diff --git a/scripts/create-account.js b/cli/create-account.js similarity index 90% rename from scripts/create-account.js rename to cli/create-account.js index c5e16198..44de9d73 100644 --- a/scripts/create-account.js +++ b/cli/create-account.js @@ -2,7 +2,7 @@ const { PrismaClient } = require('@prisma/client'); const prisma = new PrismaClient(); -const exec = async () => { +module.exports = async () => { const account = await prisma.account.findOne({ where: { username: 'admin', @@ -21,8 +21,4 @@ const exec = async () => { } else { console.log('Account already exists.'); } - - process.exit(0); }; - -exec(); diff --git a/cli/index.js b/cli/index.js new file mode 100644 index 00000000..77457f42 --- /dev/null +++ b/cli/index.js @@ -0,0 +1,25 @@ +#!/usr/bin/env node + +require('dotenv').config(); +const yargs = require('yargs'); +const chalk = require('chalk'); +const createAccount = require('./create-account'); + +const cmd = yargs.usage('Usage: umami [arguments]').help('h').alias('h', 'help'); + +const { argv } = cmd; +const { + _: [action, ...params], +} = argv; + +const exec = async () => { + if (action === 'create') { + await createAccount(); + } else { + cmd.showHelp(); + } + + process.exit(0); +}; + +exec(); diff --git a/index.js b/index.js index 85b196f9..f053ebf7 100644 --- a/index.js +++ b/index.js @@ -1,3 +1 @@ -const { name, version } = require('./package.json'); - -console.log(`${name} ${version}`); +module.exports = {}; diff --git a/lib/web.js b/lib/web.js index 02769dbc..0b8acb5a 100644 --- a/lib/web.js +++ b/lib/web.js @@ -8,3 +8,13 @@ export const post = (url, params) => }, body: JSON.stringify(params), }).then(res => (res.status === 200 ? res.json() : null)); + +export const hook = (_this, method, callback) => { + const orig = _this[method]; + + return (...args) => { + callback.apply(null, args); + + return orig.apply(_this, args); + }; +}; diff --git a/package.json b/package.json index 2bfd6741..bd27cbdd 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "umami", "version": "0.1.0", "description": "Deliciously simple website stats", - "main": "index.js", "author": "Mike Cao ", "license": "MIT", "homepage": "https://github.com/mikecao/umami", @@ -10,14 +9,18 @@ "type": "git", "url": "https://github.com/mikecao/umami.git" }, + "main": "index.js", + "bin": { + "umami": "cli/index.js" + }, "scripts": { "dev": "next dev -p 8000", "build": "next build", "start": "next start", - "build-script": "rollup -c", - "build-schema": "prisma introspect", - "build-client": "prisma generate", - "create-account": "node scripts/create-account.js" + "build-tracker": "rollup -c", + "build-schema": "dotenv prisma introspect", + "build-client": "dotenv prisma generate", + "create-account": "node cli/create-account.js" }, "lint-staged": { "**/*.js": [ @@ -36,6 +39,7 @@ "dependencies": { "@prisma/client": "2.2.2", "bcrypt": "^5.0.0", + "chalk": "^4.1.0", "chart.js": "^2.9.3", "classnames": "^2.2.6", "cookie": "^0.4.1", @@ -56,7 +60,8 @@ "react-dom": "16.13.1", "request-ip": "^2.1.3", "unfetch": "^4.1.0", - "uuid": "^8.2.0" + "uuid": "^8.2.0", + "yargs": "^15.4.1" }, "devDependencies": { "@prisma/cli": "2.2.2", @@ -64,6 +69,7 @@ "@rollup/plugin-node-resolve": "^8.4.0", "@rollup/plugin-replace": "^2.3.3", "@svgr/webpack": "^5.4.0", + "dotenv-cli": "^3.2.0", "eslint": "^7.2.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-prettier": "^3.1.3", diff --git a/public/umami.js b/public/umami.js index 5e4f674c..210f8a56 100644 --- a/public/umami.js +++ b/public/umami.js @@ -1 +1 @@ -!function(){"use strict";function e(e){var t=this.constructor;return this.then((function(n){return t.resolve(e()).then((function(){return n}))}),(function(n){return t.resolve(e()).then((function(){return t.reject(n)}))}))}var t=setTimeout;function n(e){return Boolean(e&&void 0!==e.length)}function r(){}function o(e){if(!(this instanceof o))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],f(e,this)}function i(e,t){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,o._immediateFn((function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null!==n){var r;try{r=n(e._value)}catch(e){return void s(t.promise,e)}u(t.promise,r)}else(1===e._state?u:s)(t.promise,e._value)}))):e._deferreds.push(t)}function u(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var n=t.then;if(t instanceof o)return e._state=3,e._value=t,void a(e);if("function"==typeof n)return void f((r=n,i=t,function(){r.apply(i,arguments)}),e)}e._state=1,e._value=t,a(e)}catch(t){s(e,t)}var r,i}function s(e,t){e._state=2,e._value=t,a(e)}function a(e){2===e._state&&0===e._deferreds.length&&o._immediateFn((function(){e._handled||o._unhandledRejectionFn(e._value)}));for(var t=0,n=e._deferreds.length;t { const { @@ -57,19 +57,8 @@ import { post } from 'lib/web'; pageView(); }; - const hook = (type, cb) => { - const orig = history[type]; - return (state, title, url) => { - const args = [state, title, url]; - - cb.apply(null, args); - - return orig.apply(history, args); - }; - }; - - history.pushState = hook('pushState', handlePush); - history.replaceState = hook('replaceState', handlePush); + history.pushState = hook(history, 'pushState', handlePush); + history.replaceState = hook(history, 'replaceState', handlePush); /* Handle events */ diff --git a/yarn.lock b/yarn.lock index 5f7385fe..ede20a5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2457,6 +2457,15 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-deep@^0.2.4: version "0.2.4" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" @@ -2748,7 +2757,7 @@ cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3207,7 +3216,22 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" -dotenv@^8.2.0: +dotenv-cli@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-3.2.0.tgz#002367c30992acb0b218b20fc01a8e18f13f85cf" + integrity sha512-zg/dfXISo7ntL3JKC+oj7eXEMg8LbOsARWTeypfVsmYtazDYOptmKLqA9u3LTee9x/sIPiLqmI6wskRP+89ohQ== + dependencies: + cross-spawn "^7.0.1" + dotenv "^8.1.0" + dotenv-expand "^5.1.0" + minimist "^1.1.3" + +dotenv-expand@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" + integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== + +dotenv@^8.1.0, dotenv@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== @@ -3966,6 +3990,11 @@ geolite2-redist@^1.0.7: rimraf "^3.0.2" tar "^6.0.2" +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -5357,7 +5386,7 @@ minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -7325,6 +7354,16 @@ request-ip@^2.1.3: dependencies: is_js "^0.9.0" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + require-relative@^0.8.7: version "0.8.7" resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" @@ -7593,7 +7632,7 @@ serialize-javascript@^3.0.0, serialize-javascript@^3.1.0: dependencies: randombytes "^2.1.0" -set-blocking@~2.0.0: +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -8853,6 +8892,11 @@ webpack@4.42.1: watchpack "^1.6.0" webpack-sources "^1.4.1" +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + which-pm-runs@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" @@ -8954,10 +8998,27 @@ yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== -yargs-parser@^18.1.3: +yargs-parser@^18.1.2, yargs-parser@^18.1.3: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" + +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2"