diff --git a/.eslintignore b/.eslintignore index fcba99d7ad..2b11d4eeb6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -33,8 +33,9 @@ node_modules/ ReactNativeClient/android ReactNativeClient/ios ReactNativeClient/lib/vendor/ +ReactNativeClient/lib/welcomeAssets.js ReactNativeClient/locales ReactNativeClient/node_modules readme/ Tools/node_modules -Tools/PortableAppsLauncher \ No newline at end of file +Tools/PortableAppsLauncher diff --git a/CliClient/app/command-server.js b/CliClient/app/command-server.js new file mode 100644 index 0000000000..07751bb8d8 --- /dev/null +++ b/CliClient/app/command-server.js @@ -0,0 +1,57 @@ +const { BaseCommand } = require('./base-command.js'); +const { _ } = require('lib/locale.js'); +const Setting = require('lib/models/Setting.js'); +const { Logger } = require('lib/logger.js'); +const { shim } = require('lib/shim'); + +class Command extends BaseCommand { + + usage() { + return 'server '; + } + + description() { + return _('Start, stop or check the API server. To specify on which port it should run, set the api.port config variable. Commands are (start|stop|status).') + ' This is an experimental feature - use at your own risks! It is recommended that the server runs off its own separate profile so that no two CLI instances access that profile at the same time. Use --profile to specify the profile path.'; + } + + async action(args) { + const command = args.command; + + const ClipperServer = require('lib/ClipperServer'); + const stdoutFn = (s) => this.stdout(s); + const clipperLogger = new Logger(); + clipperLogger.addTarget('file', { path: Setting.value('profileDir') + '/log-clipper.txt' }); + clipperLogger.addTarget('console', { console: { + info: stdoutFn, + warn: stdoutFn, + error: stdoutFn, + }}); + ClipperServer.instance().setDispatch(action => {}); + ClipperServer.instance().setLogger(clipperLogger); + + const pidPath = Setting.value('profileDir') + '/clipper-pid.txt'; + const runningOnPort = await ClipperServer.instance().isRunning(); + + if (command === 'start') { + if (runningOnPort) { + this.stdout(_('Server is already running on port %d', runningOnPort)); + } else { + await shim.fsDriver().writeFile(pidPath, process.pid.toString(), 'utf-8'); + await ClipperServer.instance().start(); // Never exit + } + } else if (command === 'status') { + this.stdout(runningOnPort ? _('Server is running on port %d', runningOnPort) : _('Server is not running.')); + } else if (command === 'stop') { + if (!runningOnPort) { + this.stdout(_('Server is not running')); + return; + } + const pid = await shim.fsDriver().readFile(pidPath); + if (!pid) return; + process.kill(pid, 'SIGTERM'); + } + } + +} + +module.exports = Command; diff --git a/CliClient/package-lock.json b/CliClient/package-lock.json index 53511f34f6..fc86bc59fb 100644 --- a/CliClient/package-lock.json +++ b/CliClient/package-lock.json @@ -4,6 +4,19 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@cronvel/get-pixels": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@cronvel/get-pixels/-/get-pixels-3.3.1.tgz", + "integrity": "sha512-jgDb8vGPkpjRDbiYyHTI2Bna4HJysjPNSiERzBnRJjCR/YqC3u0idTae0tmNECsaZLOpAWmlK9wiIwnLGIT9Bg==", + "requires": { + "jpeg-js": "^0.1.1", + "ndarray": "^1.0.13", + "ndarray-pack": "^1.1.1", + "node-bitmap": "0.0.1", + "omggif": "^1.0.5", + "pngjs": "^2.0.0" + } + }, "abab": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", @@ -127,22 +140,6 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, - "async-kit": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/async-kit/-/async-kit-2.2.3.tgz", - "integrity": "sha1-JkdRonndxfWbQZY4uAWuLEmFj7c=", - "requires": { - "nextgen-events": "^0.9.0", - "tree-kit": "^0.5.26" - }, - "dependencies": { - "nextgen-events": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-0.9.9.tgz", - "integrity": "sha1-OaivxKK4RTiMV+LGu5cWcRmGo6A=" - } - } - }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -169,9 +166,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, "balanced-match": { "version": "1.0.0", @@ -230,14 +227,6 @@ } } }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "requires": { - "hoek": "4.x.x" - } - }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -310,6 +299,11 @@ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" }, + "chroma-js": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.0.6.tgz", + "integrity": "sha512-IiiClbBRkRwuXNl6impq5ssEhUGpmWvc5zzImZbDUWLWcFbj6ZbtsdZEx6sIXMKes7azgYaUpnmsY1T8BL6PqQ==" + }, "clean-css": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz", @@ -433,24 +427,6 @@ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "requires": { - "boom": "5.x.x" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "requires": { - "hoek": "4.x.x" - } - } - } - }, "css": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", @@ -498,11 +474,6 @@ "assert-plus": "^1.0.0" } }, - "data-uri-to-buffer": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", - "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" - }, "data-urls": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", @@ -559,6 +530,11 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -748,6 +724,14 @@ "format": "^0.2.2" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "requires": { + "pend": "~1.2.0" + } + }, "file-type": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", @@ -891,24 +875,6 @@ } } }, - "get-pixels": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.0.tgz", - "integrity": "sha1-jZeVvq4YhQuED3SVgbrcBdPjbkE=", - "requires": { - "data-uri-to-buffer": "0.0.3", - "jpeg-js": "^0.1.1", - "mime-types": "^2.0.1", - "ndarray": "^1.0.13", - "ndarray-pack": "^1.1.1", - "node-bitmap": "0.0.1", - "omggif": "^1.0.5", - "parse-data-uri": "^0.2.0", - "pngjs": "^2.0.0", - "request": "^2.44.0", - "through": "^2.3.4" - } - }, "get-prototype-chain": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-prototype-chain/-/get-prototype-chain-1.0.1.tgz", @@ -956,12 +922,35 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "requires": { - "ajv": "^5.1.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + } } }, "has-ansi": { @@ -989,17 +978,6 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - } - }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -1010,11 +988,6 @@ "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" - }, "html-encoding-sniffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", @@ -1042,6 +1015,25 @@ "uglify-js": "3.3.x" } }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1710,6 +1702,11 @@ "graceful-fs": "^4.1.9" } }, + "lazyness": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lazyness/-/lazyness-1.1.1.tgz", + "integrity": "sha512-rYHC6l6LeRlJSt5jxpqN8z/49gZ0CqLi89HAGzJjHahCFlqEjFGFN9O15hmzSzUGFl7zN/vOWduv/+0af3r/kQ==" + }, "left-pad": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", @@ -1901,6 +1898,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "multiparty": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.2.1.tgz", + "integrity": "sha512-AvESCnNoQlZiOfP9R4mxN8M9csy2L16EIbWIkt3l4FuGti9kXBS8QVzlfyg4HEnarJhrzZilgNFlZtqmoiAIIA==", + "requires": { + "fd-slicer": "1.1.0", + "http-errors": "~1.7.0", + "safe-buffer": "5.1.2", + "uid-safe": "2.1.5" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, "nan": { "version": "2.13.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", @@ -1955,9 +1970,9 @@ } }, "nextgen-events": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-0.11.3.tgz", - "integrity": "sha512-dC4v/dOF6m8/M05eU712KXjRJ0e/187rx5CMS/fTnulv2QGPps1U/c/J1D3wtegEhK+EE7LuJc3jly3pyfV46g==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-1.3.0.tgz", + "integrity": "sha512-eBz5mrO4Hw2eenPVm0AVPHuAzg/RZetAWMI547RH8O9+a0UYhCysiZ3KoNWslnWNlHetb9kzowEshsKsmFo2YQ==" }, "no-case": { "version": "2.3.2", @@ -2074,9 +2089,9 @@ "integrity": "sha512-iGfd9Y6SFdTNldEy2L0GUhcarIutFmk+MPWIn9dmj8NMIup03G08uUF2KGbbmv/Ux4RT0VZJoP/sVbWA6d/VIw==" }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, "object-assign": { "version": "4.1.1", @@ -2120,9 +2135,9 @@ } }, "omggif": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.9.tgz", - "integrity": "sha1-3LcCTazVDFK00wPwSALJHAV8dl8=" + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" }, "once": { "version": "1.4.0", @@ -2200,14 +2215,6 @@ "no-case": "^2.2.0" } }, - "parse-data-uri": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", - "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", - "requires": { - "data-uri-to-buffer": "0.0.3" - } - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2218,6 +2225,11 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -2353,6 +2365,11 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -2416,32 +2433,82 @@ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=" }, "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "requires": { "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", + "aws4": "^1.8.0", "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "hawk": "~6.0.2", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", - "tough-cookie": "~2.3.3", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "uuid": "^3.3.2" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "requires": { + "mime-db": "1.40.0" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + } } }, "request-promise-core": { @@ -2522,6 +2589,24 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "seventh": { + "version": "0.7.28", + "resolved": "https://registry.npmjs.org/seventh/-/seventh-0.7.28.tgz", + "integrity": "sha512-WitJqSwsjLWbCP9cciaozByx4csddLQyNoaPBqOpYFMNE6iD6FK/pM8J2yqtpauSxJUUo7Wfv5KF5w1jbVov7A==", + "requires": { + "setimmediate": "^1.0.5" + } + }, "sharp": { "version": "0.22.1", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.22.1.tgz", @@ -2623,14 +2708,6 @@ "is-fullwidth-code-point": "^2.0.0" } }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "requires": { - "hoek": "4.x.x" - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -2812,6 +2889,11 @@ "tweetnacl": "~0.14.0" } }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -2823,12 +2905,9 @@ "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, "string-kit": { - "version": "0.6.14", - "resolved": "https://registry.npmjs.org/string-kit/-/string-kit-0.6.14.tgz", - "integrity": "sha512-Sz9Q98Q4JKLaOaXUYLSO8ScWhO9z/itJ53GJOLl+w/wR9XXFt82MzN4Q5pwXN9QZCN1/aCnZhOe67ANK8Vs6Vw==", - "requires": { - "xregexp": "^3.2.0" - } + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/string-kit/-/string-kit-0.9.10.tgz", + "integrity": "sha512-hcJem/u3/ddt3lSY2Xlx953XCHe3C8BX2XEWbPrByjyJ0CSR36X7kzsGFsI5lLaG94dLCQYpt8ffVwRjKpRT6g==" }, "string-padding": { "version": "1.0.2", @@ -2883,11 +2962,6 @@ } } }, - "stringstream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", - "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -3035,23 +3109,20 @@ } }, "terminal-kit": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/terminal-kit/-/terminal-kit-1.15.1.tgz", - "integrity": "sha512-nk0+wDRfcvjnBXW6b2X2SFBzCMbT5ZJX56rRvmq/CFaimMYfWHU1eooy33RmzWByXWkkI71zx17q3vlp71OUNA==", + "version": "1.31.2", + "resolved": "https://registry.npmjs.org/terminal-kit/-/terminal-kit-1.31.2.tgz", + "integrity": "sha512-qbzHgHONdyJ5SQsjMWvoV5Jivw2VGbV8uw6U8WMgEgkbjX5AZ6Irhs183z459+b6u++36+6WIFeYddIDoXKNeQ==", "requires": { - "async-kit": "^2.2.3", - "get-pixels": "^3.3.0", + "@cronvel/get-pixels": "^3.3.1", + "chroma-js": "^2.0.4", + "lazyness": "^1.1.1", "ndarray": "^1.0.18", - "nextgen-events": "^0.11.2", - "string-kit": "^0.6.9", - "tree-kit": "^0.5.26" + "nextgen-events": "^1.1.1", + "seventh": "^0.7.28", + "string-kit": "^0.9.10", + "tree-kit": "^0.6.1" } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, "tkwidgets": { "version": "0.5.26", "resolved": "https://registry.npmjs.org/tkwidgets/-/tkwidgets-0.5.26.tgz", @@ -3080,6 +3151,11 @@ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", @@ -3104,9 +3180,9 @@ } }, "tree-kit": { - "version": "0.5.26", - "resolved": "https://registry.npmjs.org/tree-kit/-/tree-kit-0.5.26.tgz", - "integrity": "sha1-hXHIb6JNHbdU5bDLOn4J9B50qN8=" + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/tree-kit/-/tree-kit-0.6.1.tgz", + "integrity": "sha512-7mV4KbsLMuA6ths3J1wpVUj2PLmLdoNEGnP9fm3kxef4UXYC/A0rL5gKsqtkUaCMuRYUMORyioy8IpBWUBQ1Ig==" }, "tunnel-agent": { "version": "0.6.0", @@ -3156,6 +3232,14 @@ } } }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -3346,11 +3430,6 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.4.tgz", "integrity": "sha1-UZy0ymhtAFqEINNJbz8MruzKWA8=" }, - "xregexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.2.0.tgz", - "integrity": "sha1-yzYBmHv+JpW1hAAMGPHEqMMih44=" - }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", diff --git a/CliClient/package.json b/CliClient/package.json index a48e7ce5ec..8508ec147d 100644 --- a/CliClient/package.json +++ b/CliClient/package.json @@ -51,6 +51,7 @@ "md5": "^2.2.1", "mime": "^2.0.3", "moment": "^2.24.0", + "multiparty": "^4.2.1", "node-emoji": "^1.8.1", "node-fetch": "^1.7.1", "node-persist": "^2.1.0", @@ -59,6 +60,7 @@ "query-string": "4.3.4", "read-chunk": "^2.1.0", "redux": "^3.7.2", + "request": "^2.88.0", "sax": "^1.2.2", "server-destroy": "^1.0.1", "sharp": "^0.22.1", diff --git a/Clipper/joplin-webclipper/popup/src/bridge.js b/Clipper/joplin-webclipper/popup/src/bridge.js index f68b88f800..2c2a95b942 100644 --- a/Clipper/joplin-webclipper/popup/src/bridge.js +++ b/Clipper/joplin-webclipper/popup/src/bridge.js @@ -1,4 +1,4 @@ -const randomClipperPort = require('./randomClipperPort'); +const { randomClipperPort } = require('./randomClipperPort'); class Bridge { diff --git a/Clipper/joplin-webclipper/popup/src/randomClipperPort.js b/Clipper/joplin-webclipper/popup/src/randomClipperPort.js index d1b38c5d55..4b5dce44c1 100644 --- a/Clipper/joplin-webclipper/popup/src/randomClipperPort.js +++ b/Clipper/joplin-webclipper/popup/src/randomClipperPort.js @@ -17,4 +17,4 @@ function randomClipperPort(state, env) { return state; } -module.exports = randomClipperPort; +module.exports = { randomClipperPort }; diff --git a/ReactNativeClient/lib/ClipperServer.js b/ReactNativeClient/lib/ClipperServer.js index 9fd106f145..a4f06bc169 100644 --- a/ReactNativeClient/lib/ClipperServer.js +++ b/ReactNativeClient/lib/ClipperServer.js @@ -1,7 +1,7 @@ const urlParser = require('url'); const Setting = require('lib/models/Setting'); const { Logger } = require('lib/logger.js'); -const randomClipperPort = require('lib/randomClipperPort'); +const { randomClipperPort, startPort } = require('lib/randomClipperPort'); const enableServerDestroy = require('server-destroy'); const Api = require('lib/services/rest/Api'); const ApiResponse = require('lib/services/rest/ApiResponse'); @@ -73,13 +73,22 @@ class ClipperServer { throw new Error('All potential ports are in use or not available.'); } + async isRunning() { + const tcpPortUsed = require('tcp-port-used'); + const port = Setting.value('api.port') ? Setting.value('api.port') : startPort(Setting.value('env')); + const inUse = await tcpPortUsed.check(port); + return inUse ? port : 0; + } + async start() { this.setPort(null); this.setStartState('starting'); + const settingPort = Setting.value('api.port'); + try { - const p = await this.findAvailablePort(); + const p = settingPort ? settingPort : await this.findAvailablePort(); this.setPort(p); } catch (error) { this.setStartState('idle'); @@ -200,6 +209,10 @@ class ClipperServer { this.server_.listen(this.port_, '127.0.0.1'); this.setStartState('started'); + + // We return an empty promise that never resolves so that it's possible to `await` the server indefinitely. + // This is used only in command-server.js + return new Promise(() => {}); } async stop() { diff --git a/ReactNativeClient/lib/logger.js b/ReactNativeClient/lib/logger.js index 5c4d1ba814..c46ef6d090 100644 --- a/ReactNativeClient/lib/logger.js +++ b/ReactNativeClient/lib/logger.js @@ -120,7 +120,8 @@ class Logger { if (level == Logger.LEVEL_ERROR) fn = 'error'; if (level == Logger.LEVEL_WARN) fn = 'warn'; if (level == Logger.LEVEL_INFO) fn = 'info'; - console[fn](line + this.objectsToString(...object)); + const consoleObj = target.console ? target.console : console; + consoleObj[fn](line + this.objectsToString(...object)); } else if (target.type == 'file') { let serializedObject = this.objectsToString(...object); Logger.fsDriver().appendFileSync(target.path, line + serializedObject + '\n'); diff --git a/ReactNativeClient/lib/models/Setting.js b/ReactNativeClient/lib/models/Setting.js index 445d19a621..c57b80a978 100644 --- a/ReactNativeClient/lib/models/Setting.js +++ b/ReactNativeClient/lib/models/Setting.js @@ -390,6 +390,7 @@ class Setting extends BaseModel { }, 'api.token': { value: null, type: Setting.TYPE_STRING, public: false }, + 'api.port': { value: null, type: Setting.TYPE_INT, public: true, appTypes: ['cli'], description: () => _('Specify the port that should be used by the API server. If not set, a default will be used.') }, 'resourceService.lastProcessedChangeId': { value: 0, type: Setting.TYPE_INT, public: false }, 'searchEngine.lastProcessedChangeId': { value: 0, type: Setting.TYPE_INT, public: false }, diff --git a/ReactNativeClient/lib/randomClipperPort.js b/ReactNativeClient/lib/randomClipperPort.js index d1b38c5d55..0ddec1b962 100644 --- a/ReactNativeClient/lib/randomClipperPort.js +++ b/ReactNativeClient/lib/randomClipperPort.js @@ -1,20 +1,22 @@ function randomClipperPort(state, env) { - const startPorts = { - prod: 41184, - dev: 27583, - }; - - const startPort = env === 'prod' ? startPorts.prod : startPorts.dev; - if (!state) { state = { offset: 0 }; } else { state.offset++; } - state.port = startPort + state.offset; + state.port = startPort(env) + state.offset; return state; } -module.exports = randomClipperPort; +function startPort(env) { + const startPorts = { + prod: 41184, + dev: 27583, + }; + + return env === 'prod' ? startPorts.prod : startPorts.dev; +} + +module.exports = { randomClipperPort, startPort }; diff --git a/ReactNativeClient/lib/time-utils.js b/ReactNativeClient/lib/time-utils.js index 3613bde056..f93f8fe20e 100644 --- a/ReactNativeClient/lib/time-utils.js +++ b/ReactNativeClient/lib/time-utils.js @@ -13,7 +13,7 @@ class Time { setLocale(v) { moment.locale(v); - this.locale_ = v + this.locale_ = v; } dateFormat() {