diff --git a/packages/.gitignore b/packages/.gitignore
new file mode 100644
index 00000000..46e7e7a5
--- /dev/null
+++ b/packages/.gitignore
@@ -0,0 +1,5 @@
+/node_modules
+/coverage
+*.log
+.DS_Store
+part-registry
diff --git a/packages/discourse/.gitignore b/packages/discourse/.gitignore
new file mode 100644
index 00000000..74490cf0
--- /dev/null
+++ b/packages/discourse/.gitignore
@@ -0,0 +1,5 @@
+/node_modules
+/coverage
+*.log
+.DS_Store
+tmp
diff --git a/packages/discourse/.npmignore b/packages/discourse/.npmignore
new file mode 100644
index 00000000..4c9addac
--- /dev/null
+++ b/packages/discourse/.npmignore
@@ -0,0 +1,4 @@
+./docs
+./scripts
+./tests
+./incoming
\ No newline at end of file
diff --git a/packages/discourse/.vscode/launch.json b/packages/discourse/.vscode/launch.json
new file mode 100644
index 00000000..a33c61b5
--- /dev/null
+++ b/packages/discourse/.vscode/launch.json
@@ -0,0 +1,178 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Import - OA-Users ",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "import-users",
+ "import",
+ "--src='${OA_ROOT}/data/latest.json'",
+ "--debug=true"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ],
+ "console": "internalConsole",
+ "outputCapture": "std",
+ "trace": true
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Update - OA-Users ",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "import-users",
+ "update",
+ "--src='${OA_ROOT}/data/latest.json'",
+ "--debug=true"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ],
+ "console": "internalConsole",
+ "outputCapture": "std"
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Index - OA-Users ",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "import-users",
+ "index",
+ "--src='${OA_ROOT}/data/latest.json'",
+ "--debug=true"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ],
+ "console": "internalConsole",
+ "outputCapture": "std"
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "Import - OA-Howtos",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "import-howtos",
+ // "--src='${OA_ROOT}/data/latest.json'",
+ "--track='${OA_ROOT}/oa-data/howtos/latest_track.json'",
+ "--debug=true"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ],
+ "outputCapture": "std"
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "test sync:fs",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "sync",
+ "file",
+ "--yaml=true",
+ "--src='./tests/**/*.md'"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ]
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "test sync:component",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "sync-component",
+ "--src='${PRODUCT_ROOT}/products/'"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ]
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "test sync:forum-pages",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "sync-component",
+ "--src='${OSR_ROOT}/osr-forum-pages/pages/kb/**/*.md'",
+ "--watch",
+ "--yaml",
+ "--sync=mine"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ]
+ },
+ {
+ "type": "node",
+ "request": "launch",
+ "name": "test sync:library",
+ "skipFiles": [
+ "/**"
+ ],
+ "program": "${workspaceFolder}\\main.js",
+ "preLaunchTask": "tsc: build - tsconfig.json",
+ "args": [
+ "sync-component",
+ "--cache=true",
+ "--skip=true",
+ "--src2='${OSR_LIBRARY_MACHINES}/injection/**/config.+(json)'",
+ "--src2='${OSR_LIBRARY_MACHINES}/extrusion/**/config.+(json)'",
+ "--src='${OSR_LIBRARY_MACHINES}/sheetpress/**/config.+(json)'",
+ "--src2='${OSR_LIBRARY_MACHINES}/shredder/**/config.+(json)'",
+ "--src2='${OSR_LIBRARY_MACHINES}/zoe/config.+(json)'",
+ // "--src='${OSR_LIBRARY_MACHINES}/combo/IntegrationUnitMonash/config.+(json)'",
+ "--src1='${OSR_LIBRARY_MACHINES}/injection/**/config.+(json)'",
+ //"--src='${OSR_LIBRARY_MACHINES}/sheetpress/cassandra-light/config.+(json)'",
+ "--root='${OSR_LIBRARY_MACHINES}'",
+ "--sync=mine",
+ "--logLevel=debug"
+ ],
+ "outFiles": [
+ "${workspaceFolder}/**/*.js"
+ ],
+ "outputCapture": "std"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/packages/discourse/.vscode/settings.json b/packages/discourse/.vscode/settings.json
new file mode 100644
index 00000000..0fe4b255
--- /dev/null
+++ b/packages/discourse/.vscode/settings.json
@@ -0,0 +1,9 @@
+{
+ "cSpell.words": [
+ "Discorse",
+ "OSRL",
+ "plastichub",
+ "Salamand"
+ ],
+ "cmake.configureOnOpen": false
+}
\ No newline at end of file
diff --git a/packages/discourse/LICENSE b/packages/discourse/LICENSE
new file mode 100644
index 00000000..b0e20f53
--- /dev/null
+++ b/packages/discourse/LICENSE
@@ -0,0 +1,9 @@
+Copyright (c) All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/discourse/README.md b/packages/discourse/README.md
new file mode 100644
index 00000000..204fe53e
--- /dev/null
+++ b/packages/discourse/README.md
@@ -0,0 +1,161 @@
+# Discourse library and CLI for OSR content
+
+## Commands
+
+### `info`
+
+#### Print configuration and commands
+
+```
+osr-discourse info
+```
+
+### `deploy`
+
+Create/Update post from directory, using OSR-Specs
+
+**usage**
+
+```sh
+
+osr-discourse deploy --src="./*"
+
+```
+
+### `sync `
+
+Sync file
+
+**usage**
+
+```sh
+
+osr-discourse sync
+
+ --src=""
+ --cat=
+ --owner="user_name|user_id"
+ --config=
+ --timestamp=
+ --download-assets=true|false
+ --tags=
+
+```
+
+### `sync-kb`
+
+Create/Update/Sync kb from directory
+
+**usage**
+
+```sh
+
+osr-discourse sync --src="./*"
+
+```
+
+### `list`
+
+List posts per category or search query
+
+**usage**
+
+```sh
+
+osr-discourse list --query="discourse-query" --dst="output.[json|xls|csv]" --fields="[post-fields]"
+
+```
+
+### `oa-user-import`
+
+Imports oa-users from dump file
+
+**usage**
+
+```sh
+
+osr-discourse oa-user --src="raw.json"
+
+```
+
+### `ig-user-sync`
+
+Imports IG users from dump file
+
+**usage**
+
+```sh
+
+osr-discourse ig-user sync --src="raw.json"
+
+```
+
+### `osr-commons-sync`
+
+Sync all osr-commons ( taxonomy )
+
+**usage**
+
+```sh
+
+osr-discourse osr-sync --src="path to commons (JSON)"
+
+```
+
+### `pm`
+
+Notify all users, using Discourse private message
+
+**usage**
+
+```sh
+
+osr-discourse pm --src="path to message (MD|HTML)" --groups="osr groups"
+
+```
+
+### `invite`
+
+Send invite to a list of users, common MC/OSR CSV format
+
+**usage**
+
+```sh
+
+osr-discourse invite --src="path to message (MD|HTML)" --src="path to CSV"
+
+```
+
+## Library / API
+
+## References
+
+- [ts-json-schema-generator - issue - functions](https://github.com/loopingz/webda.io/blob/main/packages/shell/src/code/compiler.ts#L154-243)
+
+### Todos
+
+////////////////////////
+ //
+ // 1. Fetch Tags
+ // 2. Populate Tags
+ // 3. Download (oa-bot)
+ // 4. Sync - Assets (osr-machines)
+ // 5. Ensure/Find user
+ //
+ // Content
+ //
+ // Body (descr full)
+ // each step
+ // footer (refs)
+ // set tags
+ // set ts
+ //
+ // Post
+ // -> sync lib
+ // -> translate -> lib
+ // -> digest
+ // -> notifications
+ // -> index
+ // -> update ext refs
+ // -> market place
+ // -> sync externals (git, ...)
diff --git a/packages/discourse/_cli.d.ts b/packages/discourse/_cli.d.ts
new file mode 100644
index 00000000..f700ffb5
--- /dev/null
+++ b/packages/discourse/_cli.d.ts
@@ -0,0 +1,3 @@
+import { IOptions, IOptionsSync } from './types';
+export declare const defaults: () => void;
+export declare const sanitize: (argv: any) => IOptionsSync | IOptions | boolean;
diff --git a/packages/discourse/_cli.js b/packages/discourse/_cli.js
new file mode 100644
index 00000000..290946ca
--- /dev/null
+++ b/packages/discourse/_cli.js
@@ -0,0 +1,71 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sanitize = exports.defaults = void 0;
+const exists_1 = require("@plastichub/fs/exists");
+const _1 = require("./");
+const path = require("path");
+const globBase = require('glob-base');
+const defaults = () => {
+ // default command
+ const DefaultCommand = 'info';
+ if (process.argv.length === 2) {
+ process.argv.push(DefaultCommand);
+ }
+ process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
+ // currently no default handler, display only :
+ process.on('unhandledRejection', (reason) => {
+ console.error('Unhandled rejection, reason: ', reason);
+ });
+};
+exports.defaults = defaults;
+const sanitize = (argv) => {
+ let ret = {
+ ...argv
+ };
+ ret.src = argv.src;
+ let srcInfo;
+ let variables = {};
+ /*
+ if (ret.src) {
+ ret.src = forward_slash(substitute(ret.alt,ret.src,variables))
+ // in case a file with a glob pattern is provided, strip the glob
+ // this is a special case, enabling shared scripts in Alt-Tap Salamand
+ const glob_base = globBase(ret.src)
+ const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '')
+
+ if(exists(file) && isFile(file)){
+ ret.src = file
+ }
+
+ srcInfo = pathInfo(resolve(ret.src, ret.alt, variables))
+
+ if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
+ ret.srcInfo = srcInfo
+ for (const key in srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
+ variables['SRC_' + key] = srcInfo[key];
+ }
+ }
+ } else {
+ ret.src = resolve(ret.src, ret.alt, variables)
+ }
+ }
+ */
+ if (argv.cwd) {
+ ret.cwd = path.resolve(argv.cwd);
+ if (!(0, exists_1.sync)((ret.cwd))) {
+ _1.logger.error(`Invalid working directory ${argv.cwd}`);
+ }
+ }
+ else {
+ ret.cwd = process.cwd();
+ }
+ ret = {
+ ...ret,
+ variables,
+ srcInfo
+ };
+ return ret;
+};
+exports.sanitize = sanitize;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2NsaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9fY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGtEQUFzRDtBQUV0RCx5QkFBMkI7QUFDM0IsNkJBQTRCO0FBTzVCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUU5QixNQUFNLFFBQVEsR0FBRyxHQUFHLEVBQUU7SUFDekIsa0JBQWtCO0lBQ2xCLE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQztJQUM5QixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtRQUMzQixPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztLQUNyQztJQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsOEJBQThCLENBQUMsR0FBRyxHQUFHLENBQUM7SUFFbEQsK0NBQStDO0lBQy9DLE9BQU8sQ0FBQyxFQUFFLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxNQUFjLEVBQUUsRUFBRTtRQUNoRCxPQUFPLENBQUMsS0FBSyxDQUFDLCtCQUErQixFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzNELENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFBO0FBYlksUUFBQSxRQUFRLFlBYXBCO0FBRU0sTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFTLEVBQXFDLEVBQUU7SUFFckUsSUFBSSxHQUFHLEdBQVE7UUFDWCxHQUFHLElBQUk7S0FDVixDQUFBO0lBRUQsR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFBO0lBQ2xCLElBQUksT0FBTyxDQUFBO0lBQ1gsSUFBSSxTQUFTLEdBQUcsRUFBRSxDQUFBO0lBRWxCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O01BeUJFO0lBRUYsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ1YsR0FBRyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsSUFBQSxhQUFNLEVBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRTtZQUNwQixTQUFNLENBQUMsS0FBSyxDQUFDLDZCQUE2QixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQTtTQUN4RDtLQUNKO1NBQU07UUFDSCxHQUFHLENBQUMsR0FBRyxHQUFHLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQTtLQUMxQjtJQUVELEdBQUcsR0FBRztRQUNGLEdBQUcsR0FBRztRQUNOLFNBQVM7UUFDVCxPQUFPO0tBQ1YsQ0FBQTtJQUVELE9BQU8sR0FBRyxDQUFBO0FBQ2QsQ0FBQyxDQUFBO0FBckRZLFFBQUEsUUFBUSxZQXFEcEIifQ==
\ No newline at end of file
diff --git a/packages/discourse/_cli.js.map b/packages/discourse/_cli.js.map
new file mode 100644
index 00000000..1eea15e8
--- /dev/null
+++ b/packages/discourse/_cli.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"_cli.js","sourceRoot":"","sources":["src/_cli.ts"],"names":[],"mappings":";;;AAAA,kDAAsD;AAEtD,yBAA2B;AAC3B,6BAA4B;AAE5B,sBAAsB;AACf,MAAM,QAAQ,GAAG,GAAG,EAAE;IACzB,kBAAkB;IAClB,MAAM,cAAc,GAAG,MAAM,CAAC;IAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KACrC;IAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,GAAG,GAAG,CAAC;IAElD,+CAA+C;IAC/C,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAc,EAAE,EAAE;QAChD,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAbW,QAAA,QAAQ,YAanB;AAEK,MAAM,QAAQ,GAAG,CAAC,IAAS,EAAsB,EAAE;IAEtD,IAAI,GAAG,GAAQ;QACX,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;KACpB,CAAA;IAED,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;IAEnB,IAAI,IAAI,CAAC,GAAG,EAAE;QACV,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,IAAA,aAAM,EAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE;YACpB,SAAM,CAAC,KAAK,CAAC,6BAA6B,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;SACzD;KACJ;SAAM;QACH,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;KAC3B;IAED,GAAG,mCACI,GAAG,GACH,EAAE,SAAS,EAAE,EAAE,EAAE,CACvB,CAAA;IAED,OAAO,GAAG,CAAC;AACf,CAAC,CAAC;AA/BW,QAAA,QAAQ,YA+BnB"}
\ No newline at end of file
diff --git a/packages/discourse/_package.json b/packages/discourse/_package.json
new file mode 100644
index 00000000..567a1e77
--- /dev/null
+++ b/packages/discourse/_package.json
@@ -0,0 +1,85 @@
+{
+ "name": "@plastichub/osr-discourse",
+ "description": "",
+ "version": "0.1.9",
+ "typings": "index.d.ts",
+ "publishConfig": {
+ "access": "public"
+ },
+ "module": "main.js",
+ "main": "main.js",
+ "bin": {
+ "osr-discourse": "main.js"
+ },
+ "dependencies": {
+ "@iarna/toml": "^2.2.5",
+ "@plastichub/core": "^0.2.5",
+ "@plastichub/fs": "^0.13.39",
+ "@plastichub/osr-cache": "^0.4.7",
+ "@plastichub/osr-cli-commons": "^0.5.1",
+ "@plastichub/osr-commons": "^0.3.3",
+ "@plastichub/osr-fs-utils": "^0.1.4",
+ "@plastichub/osrl": "file:../osrl",
+ "@types/markdown-it": "^12.2.3",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.11",
+ "axios": "^0.27.2",
+ "bluebird": "^3.7.2",
+ "chalk": "^2.4.1",
+ "cheerio": "^1.0.0-rc.12",
+ "chokidar": "^3.5.3",
+ "download": "^8.0.0",
+ "env-var": "^7.1.1",
+ "escape-html": "^1.0.3",
+ "fast-glob": "^3.3.0",
+ "filenamify": "^4.3.0",
+ "find-up": "^5.0.0",
+ "front-matter": "^4.0.2",
+ "generate-password": "^1.7.0",
+ "glob-base": "^0.3.0",
+ "isomorphic-unfetch": "^4.0.2",
+ "js-base64": "^3.7.2",
+ "js-beautify": "^1.14.9",
+ "json-to-pretty-yaml": "^1.2.2",
+ "markdown-it": "^13.0.1",
+ "md5": "^2.3.0",
+ "moment": "^2.29.4",
+ "native-promise-pool": "^3.19.0",
+ "pretty": "^2.0.0",
+ "querystring": "^0.2.1",
+ "request": "^2.88.2",
+ "sanitize-filename": "^1.6.3",
+ "showdown": "^2.1.0",
+ "simple-git": "^3.19.1",
+ "slugify": "^1.6.6",
+ "tslog": "^3.3.4",
+ "turndown": "^7.1.2",
+ "typescript": "^4.3.5",
+ "uri-js": "^4.4.1",
+ "yargs": "^17.5.1"
+ },
+ "scripts": {
+ "test": "tsc; mocha --full-trace mocha \"spec/**/*.spec.js\"",
+ "test-with-coverage": "istanbul cover node_modules/.bin/_mocha -- 'spec/**/*.spec.js'",
+ "lint": "tslint --project=./tsconfig.json",
+ "build": "tsc -p . --declaration",
+ "dev": "tsc -p . --declaration -w",
+ "typings": "tsc --declaration",
+ "docs": "npx typedoc src/index.ts",
+ "dev-test-watch": "mocha-typescript-watch",
+ "typesafe-i18n": "typesafe-i18n",
+ "link-dev": "sh scripts/link-dev.sh"
+ },
+ "homepage": "https://git.osr-plastic.org/plastichub/lib-content",
+ "repository": {
+ "type": "git",
+ "url": "https://git.osr-plastic.org/plastichub/lib-content.git"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "license": "BSD-3-Clause",
+ "keywords": [
+ "typescript"
+ ]
+}
diff --git a/packages/discourse/commands/category.d.ts b/packages/discourse/commands/category.d.ts
new file mode 100644
index 00000000..5ea23d05
--- /dev/null
+++ b/packages/discourse/commands/category.d.ts
@@ -0,0 +1,12 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{
+ debug: boolean;
+} & {
+ short: string | boolean;
+} & {
+ disabled: string | boolean;
+} & {
+ dry: string;
+} & {
+ env_key: string;
+}>;
diff --git a/packages/discourse/commands/category.js b/packages/discourse/commands/category.js
new file mode 100644
index 00000000..64bf7168
--- /dev/null
+++ b/packages/discourse/commands/category.js
@@ -0,0 +1,103 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const path = require("path");
+const write_1 = require("@plastichub/fs/write");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const _cli_1 = require("../_cli");
+const options_1 = require("../options");
+const __1 = require("..");
+const lib_1 = require("../lib");
+const category_1 = require("../lib/cscart/category");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('short', {
+ default: 'true',
+ describe: 'Emit short info only',
+ type: 'boolean'
+ }).option('disabled', {
+ default: 'false',
+ describe: 'Enumerate disabled products',
+ type: 'boolean'
+ }).option('dry', {
+ default: 'false',
+ describe: 'Process files for debug purposes only.'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('category ', 'Category namespace', options, (argv) => __awaiter(void 0, void 0, void 0, function* () {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ const config = (0, osr_cli_commons_1.CONFIG_DEFAULT)(args.env_key);
+ let options = (0, _cli_1.sanitize)(argv);
+ if (!options) {
+ return;
+ }
+ options.debug && __1.logger.debug(`CLI Args In`, argv);
+ let opts = (0, options_1.parse)(options, args);
+ if (!opts.verb) {
+ __1.logger.error('No verb specified');
+ return;
+ }
+ if (opts.verb == 'list') {
+ let _categories = yield (0, lib_1.categories)(config.cscart);
+ if (opts.dst) {
+ (0, category_1.writeCategories)(_categories, opts);
+ }
+ else {
+ __1.logger.debug('Categories', _categories);
+ }
+ }
+ if (opts.verb == 'get') {
+ let cat = yield (0, category_1.get_category)(opts.id, config.cscart);
+ opts.debug && __1.logger.debug(`Get category ${opts.id} `, cat);
+ if (cat && opts.dst) {
+ let _path = path.resolve(opts.dst);
+ (0, write_1.sync)(_path, cat);
+ opts.debug && __1.logger.debug(`Writing category to ${_path}`);
+ }
+ }
+ if (opts.verb == 'delete') {
+ return yield (0, category_1.delete_category)(opts.id, config.cscart);
+ }
+ if (opts.verb == 'create') {
+ const args = {
+ category: 'cat',
+ company_id: 1,
+ status: 'H',
+ parent_id: 6
+ };
+ let _item = yield (0, category_1.create_category)(args, config.cscart);
+ __1.logger.debug(`Created category ! ID:`, _item);
+ }
+ if (opts.verb == 'update') {
+ const args = {
+ category: 'renamed'
+ };
+ let _item = yield (0, category_1.update_category)(opts.id, args, config.cscart);
+ __1.logger.debug(`Updated category ! ID:${opts.id}`, _item);
+ }
+ return;
+ }));
+};
+exports.register = register;
+//# sourceMappingURL=category.js.map
\ No newline at end of file
diff --git a/packages/discourse/commands/category.js.map b/packages/discourse/commands/category.js.map
new file mode 100644
index 00000000..ae4671ed
--- /dev/null
+++ b/packages/discourse/commands/category.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"category.js","sourceRoot":"","sources":["../src/commands/category.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/discourse/commands/import-oa-howtos.d.ts b/packages/discourse/commands/import-oa-howtos.d.ts
new file mode 100644
index 00000000..443f33e5
--- /dev/null
+++ b/packages/discourse/commands/import-oa-howtos.d.ts
@@ -0,0 +1,2 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/discourse/commands/import-oa-howtos.js b/packages/discourse/commands/import-oa-howtos.js
new file mode 100644
index 00000000..817dec19
--- /dev/null
+++ b/packages/discourse/commands/import-oa-howtos.js
@@ -0,0 +1,53 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const _cli_1 = require("../_cli");
+const index_1 = require("../index");
+const discourse_1 = require("../lib/discourse");
+const commons_1 = require("../lib/oa/commons");
+const howtos_1 = require("../lib/oa/howtos");
+const path = require("path");
+const fs_1 = require("@plastichub/osr-commons");
+const KB_ROOT = '${KB_ROOT}';
+const osr_commons_1 = require("@plastichub/osr-commons");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: true,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('src', {
+ default: osr_commons_1.OA_LATEST,
+ type: 'string',
+ }).option('track', {
+ default: '${OA_ROOT}/oa-data/howtos/latest_track.json',
+ type: 'string',
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('import-howtos', 'Import oa-howtos', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ let options = argv;
+ if (!options) {
+ return;
+ }
+ options.debug && index_1.logger.debug(`CLI Args In`, argv);
+ const discourse = (0, discourse_1.Instance)();
+ const _opts = {
+ src: path.resolve((0, fs_1.resolve)(options.src)),
+ track: path.resolve((0, fs_1.resolve)(options.track))
+ };
+ let howtos = (0, commons_1.read_howtos)(_opts.src);
+ howtos = (0, commons_1.filter_valid)(howtos);
+ await (0, howtos_1.importHowtos)(discourse, _opts, howtos);
+ await (0, howtos_1.updateHowtos)(discourse, _opts, howtos);
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0LW9hLWhvd3Rvcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9pbXBvcnQtb2EtaG93dG9zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLGtDQUE0QztBQUU1QyxvQ0FBOEM7QUFFOUMsZ0RBQTJDO0FBZTNDLCtDQUswQjtBQUUxQiw2Q0FFeUI7QUFRekIsNkJBQTRCO0FBQzVCLHVEQUF3RDtBQUd4RCxNQUFNLE9BQU8sR0FBRyxZQUFZLENBQUE7QUFRNUIseURBQW1EO0FBRW5ELE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUU7SUFDdkMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUN6QixPQUFPLEVBQUUsSUFBSTtRQUNiLFFBQVEsRUFBRSxnQkFBZ0I7UUFDMUIsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDYixPQUFPLEVBQUUsdUJBQVM7UUFDbEIsSUFBSSxFQUFFLFFBQVE7S0FDakIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7UUFDZixPQUFPLEVBQUUsNkNBQTZDO1FBQ3RELElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1FBQ2pCLE9BQU8sRUFBRSxZQUFZO1FBQ3JCLFFBQVEsRUFBRSxxQ0FBcUM7S0FDbEQsQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFBO0FBRUQsSUFBSSxPQUFPLEdBQUcsQ0FBQyxLQUFlLEVBQUUsRUFBRSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQTtBQUVqRCxNQUFNLFFBQVEsR0FBRyxDQUFDLEdBQWEsRUFBRSxFQUFFO0lBQ3RDLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsa0JBQWtCLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFtQixFQUFFLEVBQUU7UUFDM0YsSUFBQSxlQUFRLEdBQUUsQ0FBQTtRQUNWLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtZQUFFLE9BQU07U0FBRTtRQUN6QixJQUFJLE9BQU8sR0FBSSxJQUF3QixDQUFBO1FBRXZDLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDVixPQUFNO1NBQ1Q7UUFDRCxPQUFPLENBQUMsS0FBSyxJQUFJLGNBQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFBO1FBRWxELE1BQU0sU0FBUyxHQUFHLElBQUEsb0JBQVEsR0FBRSxDQUFBO1FBRTVCLE1BQU0sS0FBSyxHQUFHO1lBQ1YsR0FBRyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBQSxZQUFPLEVBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZDLEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsWUFBTyxFQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztTQUNsQyxDQUFBO1FBRWIsSUFBSSxNQUFNLEdBQUcsSUFBQSxxQkFBVyxFQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUNuQyxNQUFNLEdBQUcsSUFBQSxzQkFBWSxFQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQzdCLE1BQU0sSUFBQSxxQkFBWSxFQUFDLFNBQVMsRUFBQyxLQUFLLEVBQUMsTUFBTSxDQUFDLENBQUE7UUFDMUMsTUFBTSxJQUFBLHFCQUFZLEVBQUMsU0FBUyxFQUFDLEtBQUssRUFBQyxNQUFNLENBQUMsQ0FBQTtJQUM5QyxDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQTtBQXZCWSxRQUFBLFFBQVEsWUF1QnBCIn0=
\ No newline at end of file
diff --git a/packages/discourse/commands/import-oa-users.d.ts b/packages/discourse/commands/import-oa-users.d.ts
new file mode 100644
index 00000000..443f33e5
--- /dev/null
+++ b/packages/discourse/commands/import-oa-users.d.ts
@@ -0,0 +1,2 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/discourse/commands/import-oa-users.js b/packages/discourse/commands/import-oa-users.js
new file mode 100644
index 00000000..84b3f40f
--- /dev/null
+++ b/packages/discourse/commands/import-oa-users.js
@@ -0,0 +1,88 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const _cli_1 = require("../_cli");
+const options_1 = require("../options");
+const index_1 = require("../index");
+const discourse_1 = require("../lib/discourse");
+const write_1 = require("@plastichub/fs/write");
+const users_1 = require("../lib/oa/users");
+const path = require("path");
+const fs_1 = require("@plastichub/osr-commons");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('src', {
+ default: '${OA_ROOT}/data/latest.json',
+ type: 'string',
+ }).option('track', {
+ default: '${OSR_ROOT}/osr-directory/pp/merged.json',
+ type: 'string',
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('import-users ', 'Import oa-users', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ let options = (0, _cli_1.sanitize)(argv);
+ if (!options) {
+ return;
+ }
+ options.debug && index_1.logger.debug(`CLI Args In`, argv);
+ let opts = (0, options_1.parse)(options, args);
+ const discourse = (0, discourse_1.Instance)();
+ const _opts = {
+ verb: argv.verb,
+ src: path.resolve((0, fs_1.resolve)(options.src)),
+ track: path.resolve((0, fs_1.resolve)(options.track))
+ };
+ let users = (0, users_1.read_users)(_opts.src);
+ users = (0, users_1.filter_valid)(users);
+ //////////////////////////
+ //
+ // store invalid
+ let usersInvalid = (0, users_1.read_users)(_opts.src);
+ usersInvalid = (0, users_1.filter_email_only)(usersInvalid);
+ usersInvalid = (0, users_1.filter_invalid)(usersInvalid);
+ index_1.logger.debug('write invalidUsers.json : ', (0, users_1.getDataPath)('/invalidUsers.json'));
+ (0, write_1.sync)((0, users_1.getDataPath)('/invalidUsers.json'), usersInvalid.map((u) => {
+ return {
+ ...u.detail,
+ id: u._id,
+ email: (0, users_1.oa_user_email)(u)
+ };
+ }));
+ let usersInvalidEmail = (0, users_1.read_users)(_opts.src);
+ usersInvalidEmail = (0, users_1.filter_email_missing)(usersInvalidEmail);
+ index_1.logger.debug('write invalidUsersEMail.json : ', (0, users_1.getDataPath)('/invalidUsersEMail.json'));
+ (0, write_1.sync)((0, users_1.getDataPath)('./invalidUsersEMail.json'), usersInvalidEmail.map((u) => {
+ return {
+ ...u.detail,
+ id: u._id
+ };
+ }));
+ index_1.logger.debug('invalid users email : ', usersInvalidEmail.length);
+ index_1.logger.debug('invalid users : ', usersInvalid.length);
+ if (opts.verb == 'index') {
+ await (0, users_1.indexUsers)(discourse, options, users);
+ }
+ if (opts.verb == 'import') {
+ await (0, users_1.importUsers)(discourse, options, users);
+ }
+ if (opts.verb == 'update') {
+ await (0, users_1.updateUsers)(discourse, options, users);
+ }
+ return;
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0LW9hLXVzZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmRzL2ltcG9ydC1vYS11c2Vycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxrQ0FBNEM7QUFDNUMsd0NBQWtDO0FBRWxDLG9DQUE4QztBQUU5QyxnREFBMkM7QUFFM0MsZ0RBQW9EO0FBSXBELDJDQVV3QjtBQUV4Qiw2QkFBNEI7QUFDNUIsdURBQXdEO0FBRXhELE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUU7SUFDdkMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUN6QixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSxnQkFBZ0I7UUFDMUIsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDYixPQUFPLEVBQUUsNkJBQTZCO1FBQ3RDLElBQUksRUFBRSxRQUFRO0tBQ2pCLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ2YsT0FBTyxFQUFFLDBDQUEwQztRQUNuRCxJQUFJLEVBQUUsUUFBUTtLQUNqQixDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUNqQixPQUFPLEVBQUUsWUFBWTtRQUNyQixRQUFRLEVBQUUscUNBQXFDO0tBQ2xELENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQTtBQUVELElBQUksT0FBTyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUE7QUFFakQsTUFBTSxRQUFRLEdBQUcsQ0FBQyxHQUFhLEVBQUUsRUFBRTtJQUN0QyxPQUFPLEdBQUcsQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsaUJBQWlCLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFtQixFQUFFLEVBQUU7UUFFaEcsSUFBQSxlQUFRLEdBQUUsQ0FBQTtRQUVWLElBQUksSUFBSSxDQUFDLElB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
\ No newline at end of file
diff --git a/packages/discourse/commands/import-oa.d.ts b/packages/discourse/commands/import-oa.d.ts
new file mode 100644
index 00000000..eb7ef92a
--- /dev/null
+++ b/packages/discourse/commands/import-oa.d.ts
@@ -0,0 +1,10 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{
+ debug: boolean;
+} & {
+ src: string;
+} & {
+ track: string;
+} & {
+ env_key: string;
+}>;
diff --git a/packages/discourse/commands/import-oa.js b/packages/discourse/commands/import-oa.js
new file mode 100644
index 00000000..905ccbcc
--- /dev/null
+++ b/packages/discourse/commands/import-oa.js
@@ -0,0 +1,89 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const _cli_1 = require("../_cli");
+const options_1 = require("../options");
+const index_1 = require("../index");
+const discourse_1 = require("../lib/discourse");
+const write_1 = require("@plastichub/fs/write");
+const users_1 = require("../lib/oa/users");
+const path = require("path");
+const fs_1 = require("@plastichub/osr-commons");
+const KB_ROOT = '${KB_ROOT}';
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('src', {
+ default: '${OA_ROOT}/data/latest.json',
+ type: 'string',
+ }).option('track', {
+ default: './latest_track.json',
+ type: 'string',
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('import ', 'Import oa-users', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ let options = (0, _cli_1.sanitize)(argv);
+ if (!options) {
+ return;
+ }
+ options.debug && index_1.logger.debug(`CLI Args In`, argv);
+ let opts = (0, options_1.parse)(options, args);
+ if (!opts.verb) {
+ index_1.logger.error('No verb specified');
+ return;
+ }
+ const discourse = (0, discourse_1.Instance)();
+ const _opts = {
+ verb: argv.verb,
+ src: path.resolve((0, fs_1.resolve)(options.src)),
+ track: path.resolve((0, fs_1.resolve)(options.track))
+ };
+ if (opts.verb == 'users') {
+ let users = (0, users_1.read_users)(_opts.src);
+ // users = filter_email_only(users)
+ //users = filter_accepted(users as IImportUser[])
+ users = (0, users_1.filter_valid)(users);
+ //////////////////////////
+ //
+ // store invalid
+ let usersInvalid = (0, users_1.read_users)(_opts.src);
+ usersInvalid = (0, users_1.filter_email_only)(usersInvalid);
+ usersInvalid = (0, users_1.filter_invalid)(usersInvalid);
+ (0, write_1.sync)((0, users_1.getDataPath)('/invalidUsers.json'), usersInvalid.map((u) => {
+ return {
+ ...u.detail,
+ id: u._id,
+ email: (0, users_1.oa_user_email)(u)
+ };
+ }));
+ let usersInvalidEmail = (0, users_1.read_users)(_opts.src);
+ usersInvalidEmail = (0, users_1.filter_email_missing)(usersInvalidEmail);
+ (0, write_1.sync)((0, users_1.getDataPath)('./invalidUsersEMail.json'), usersInvalidEmail.map((u) => {
+ return {
+ ...u.detail,
+ id: u._id
+ };
+ }));
+ console.log('invalid users : ', usersInvalidEmail.length);
+ await (0, users_1.importUsers)(discourse, options, users);
+ // await updateUsers(discourse, options, users)
+ // const items = await discourse.search('Sheetpress - Cell','tags:sheetpress')
+ // logger.info('items',items)
+ }
+ return;
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0LW9hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmRzL2ltcG9ydC1vYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxrQ0FBNEM7QUFDNUMsd0NBQWtDO0FBRWxDLG9DQUE4QztBQUU5QyxnREFBMkM7QUFFM0MsZ0RBQW9EO0FBRXBELDJDQVV3QjtBQUd4Qiw2QkFBNEI7QUFDNUIsdURBQXdEO0FBSXhELE1BQU0sT0FBTyxHQUFHLFlBQVksQ0FBQTtBQUU1QixNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFO0lBQ3ZDLE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7UUFDekIsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsZ0JBQWdCO1FBQzFCLElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2IsT0FBTyxFQUFFLDZCQUE2QjtRQUN0QyxJQUFJLEVBQUUsUUFBUTtLQUNqQixDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUNmLE9BQU8sRUFBRSxxQkFBcUI7UUFDOUIsSUFBSSxFQUFFLFFBQVE7S0FDakIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUU7UUFDakIsT0FBTyxFQUFFLFlBQVk7UUFDckIsUUFBUSxFQUFFLHFDQUFxQztLQUNsRCxDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBRWpELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBYSxFQUFFLEVBQUU7SUFDdEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQW1CLEVBQUUsRUFBRTtRQUUxRixJQUFBLGVBQVEsR0FBRSxDQUFBO1FBRVYs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
\ No newline at end of file
diff --git a/packages/discourse/commands/info.d.ts b/packages/discourse/commands/info.d.ts
new file mode 100644
index 00000000..443f33e5
--- /dev/null
+++ b/packages/discourse/commands/info.d.ts
@@ -0,0 +1,2 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/discourse/commands/info.js b/packages/discourse/commands/info.js
new file mode 100644
index 00000000..8efb656e
--- /dev/null
+++ b/packages/discourse/commands/info.js
@@ -0,0 +1,27 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const index_1 = require("../index");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: 'false',
+ describe: 'debug messages'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('info', 'info', options, async (argv) => {
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ const src = (0, osr_cli_commons_1.CONFIG_DEFAULT)(args.env_key);
+ index_1.logger.debug(`Reading OSR Config with key "${argv.env_key}"`, src);
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5mby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9pbmZvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGlFQUE0RDtBQUM1RCxvQ0FBaUM7QUFFakMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFlLEVBQUUsRUFBRTtJQUN2QyxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ3pCLE9BQU8sRUFBRSxPQUFPO1FBQ2hCLFFBQVEsRUFBRSxnQkFBZ0I7S0FDN0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUU7UUFDakIsT0FBTyxFQUFFLFlBQVk7UUFDckIsUUFBUSxFQUFFLG9DQUFvQztLQUNqRCxDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBRWxELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBYSxFQUFFLEVBQUU7SUFDdEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFtQixFQUFFLEVBQUU7UUFDdEUsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQUUsT0FBTTtTQUFFO1FBQ3pCLE1BQU0sSUFBSSxHQUFRLElBQUksQ0FBQTtRQUN0QixNQUFNLEdBQUcsR0FBRyxJQUFBLGdDQUFjLEVBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ3hDLGNBQU0sQ0FBQyxLQUFLLENBQUMsZ0NBQWdDLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQTtJQUN0RSxDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQTtBQVBZLFFBQUEsUUFBUSxZQU9wQiJ9
\ No newline at end of file
diff --git a/packages/discourse/commands/info.js.map b/packages/discourse/commands/info.js.map
new file mode 100644
index 00000000..34acfddc
--- /dev/null
+++ b/packages/discourse/commands/info.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"info.js","sourceRoot":"","sources":["../src/commands/info.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,iEAA6D;AAC7D,2BAA4B;AAE5B,MAAM,cAAc,GAAG,CAAC,KAAe,EAAE,EAAE;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACzB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,gBAAgB;KAC7B,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;QACjB,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,oCAAoC;KACjD,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,IAAI,OAAO,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAElD,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAO,IAAmB,EAAE,EAAE;QACtE,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO;SAAE;QAC1B,MAAM,IAAI,GAAQ,IAAI,CAAC;QACvB,MAAM,GAAG,GAAG,IAAA,gCAAc,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,UAAM,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,CAAC,CAAC;IACvE,CAAC,CAAA,CAAC,CAAC;AACP,CAAC,CAAC;AAPW,QAAA,QAAQ,YAOnB"}
\ No newline at end of file
diff --git a/packages/discourse/commands/product.d.ts b/packages/discourse/commands/product.d.ts
new file mode 100644
index 00000000..675c3fc3
--- /dev/null
+++ b/packages/discourse/commands/product.d.ts
@@ -0,0 +1,14 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{
+ debug: boolean;
+} & {
+ id: number;
+} & {
+ short: string | boolean;
+} & {
+ disabled: string | boolean;
+} & {
+ dry: string;
+} & {
+ env_key: string;
+}>;
diff --git a/packages/discourse/commands/product.js b/packages/discourse/commands/product.js
new file mode 100644
index 00000000..708c4468
--- /dev/null
+++ b/packages/discourse/commands/product.js
@@ -0,0 +1,110 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const path = require("path");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const write_1 = require("@plastichub/fs/write");
+const _cli_1 = require("../_cli");
+const options_1 = require("../options");
+const __1 = require("..");
+const product_1 = require("../lib/cscart/product");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('id', {
+ describe: 'Entity ID',
+ type: 'number'
+ }).option('short', {
+ default: 'true',
+ describe: 'Emit short info only',
+ type: 'boolean'
+ }).option('disabled', {
+ default: 'false',
+ describe: 'Enumerate disabled products',
+ type: 'boolean'
+ }).option('dry', {
+ default: 'false',
+ describe: 'Process files for debug purposes only.'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('product ', 'Product namespace', options, (argv) => __awaiter(void 0, void 0, void 0, function* () {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ const config = (0, osr_cli_commons_1.CONFIG_DEFAULT)(args.env_key);
+ let options = (0, _cli_1.sanitize)(argv);
+ if (!options) {
+ return;
+ }
+ options.debug && __1.logger.debug(`CLI Args In`, argv);
+ let opts = (0, options_1.parse)(options, args);
+ if (!opts.verb) {
+ __1.logger.error('No verb specified');
+ return;
+ }
+ if (opts.verb == 'list') {
+ let _products = yield (0, product_1.products)(config.cscart);
+ if (opts.dst) {
+ (0, product_1.writeProducts)(_products, opts);
+ }
+ }
+ if (opts.verb == 'delete') {
+ return yield (0, product_1.delete_product)(opts.id, config.cscart);
+ }
+ if (opts.verb == 'get') {
+ let _product = yield (0, product_1.get_product)(opts.id, config.cscart);
+ opts.debug && __1.logger.debug(`Get product ${opts.id} `, _product);
+ if (_product && opts.dst) {
+ let _path = path.resolve(opts.dst);
+ (0, write_1.sync)(_path, _product);
+ opts.debug && __1.logger.debug(`Writing product to ${_path}`);
+ }
+ }
+ if (opts.verb == 'create') {
+ const args = {
+ product: 'xxxx2',
+ price: 1234,
+ main_category: 22,
+ category_ids: [22],
+ status: 'A',
+ company_id: 1
+ };
+ let _product = yield (0, product_1.create_product)(args, config.cscart);
+ __1.logger.debug(`Created product ! ID:`, _product);
+ }
+ if (opts.verb == 'update') {
+ const args = {
+ price: 12342,
+ product: "cscart-api-test",
+ status: 'H',
+ full_description: "test - es>",
+ meta_keywords: "pp,hdpe",
+ category_ids: [22, 15],
+ lang_code: 'es'
+ };
+ let _product = yield (0, product_1.update_product)(opts.id, args, config.cscart);
+ __1.logger.debug(`Updated product ! ID:${opts.id}`, _product);
+ }
+ return;
+ }));
+};
+exports.register = register;
+//# sourceMappingURL=product.js.map
\ No newline at end of file
diff --git a/packages/discourse/commands/product.js.map b/packages/discourse/commands/product.js.map
new file mode 100644
index 00000000..b255d414
--- /dev/null
+++ b/packages/discourse/commands/product.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"product.js","sourceRoot":"","sources":["../src/commands/product.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/discourse/commands/query.d.ts b/packages/discourse/commands/query.d.ts
new file mode 100644
index 00000000..443f33e5
--- /dev/null
+++ b/packages/discourse/commands/query.d.ts
@@ -0,0 +1,2 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/discourse/commands/query.js b/packages/discourse/commands/query.js
new file mode 100644
index 00000000..44350480
--- /dev/null
+++ b/packages/discourse/commands/query.js
@@ -0,0 +1,56 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const _cli_1 = require("../_cli");
+const options_1 = require("../options");
+const index_1 = require("../index");
+const discourse_1 = require("../lib/discourse");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('short', {
+ default: 'true',
+ describe: 'Emit short info only',
+ type: 'boolean'
+ }).option('disabled', {
+ default: 'false',
+ describe: 'Enumerate disabled products',
+ type: 'boolean'
+ }).option('dry', {
+ default: 'false',
+ describe: 'Process files for debug purposes only.'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('query ', 'Search namespace', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ let options = (0, _cli_1.sanitize)(argv);
+ if (!options) {
+ return;
+ }
+ options.debug && index_1.logger.debug(`CLI Args In`, argv);
+ let opts = (0, options_1.parse)(options, args);
+ if (!opts.verb) {
+ index_1.logger.error('No verb specified');
+ return;
+ }
+ const discourse = (0, discourse_1.Instance)();
+ if (opts.verb == 'tags') {
+ const items = await discourse.search('Sheetpress - Cell', 'tags:sheetpress');
+ index_1.logger.info('items', items);
+ }
+ return;
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29tbWFuZHMvcXVlcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEsa0NBQTRDO0FBQzVDLHdDQUFrQztBQUVsQyxvQ0FBaUM7QUFFakMsZ0RBQTJDO0FBRTNDLE1BQU0sY0FBYyxHQUFHLENBQUMsS0FBZSxFQUFFLEVBQUU7SUFDdkMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtRQUN6QixPQUFPLEVBQUUsS0FBSztRQUNkLFFBQVEsRUFBRSxnQkFBZ0I7UUFDMUIsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7UUFDZixPQUFPLEVBQUUsTUFBTTtRQUNmLFFBQVEsRUFBRSxzQkFBc0I7UUFDaEMsSUFBSSxFQUFFLFNBQVM7S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7UUFDbEIsT0FBTyxFQUFFLE9BQU87UUFDaEIsUUFBUSxFQUFFLDZCQUE2QjtRQUN2QyxJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUNiLE9BQU8sRUFBRSxPQUFPO1FBQ2hCLFFBQVEsRUFBRSx3Q0FBd0M7S0FDckQsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUU7UUFDakIsT0FBTyxFQUFFLFlBQVk7UUFDckIsUUFBUSxFQUFFLHFDQUFxQztLQUNsRCxDQUFDLENBQUE7QUFDTixDQUFDLENBQUE7QUFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEtBQWUsRUFBRSxFQUFFLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBRWpELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBYSxFQUFFLEVBQUU7SUFDdEMsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQW1CLEVBQUUsRUFBRTtRQUMxRixJQUFBLGVBQVEsR0FBRSxDQUFDO1FBQ1gsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQUUsT0FBTTtTQUFFO1FBQ3pCLE1BQU0sSUFBSSxHQUFRLElBQUksQ0FBQTtRQUV0QixJQUFJLE9BQU8sR0FBRyxJQUFBLGVBQVEsRUFBQyxJQUFXLENBQWEsQ0FBQTtRQUUvQyxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1YsT0FBTTtTQUNUO1FBQ0QsT0FBTyxDQUFDLEtBQUssSUFBSSxjQUFNLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUNsRCxJQUFJLElBQUksR0FBRyxJQUFBLGVBQUssRUFBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUE7UUFFL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDWixjQUFNLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUE7WUFDakMsT0FBTztTQUNWO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBQSxvQkFBUSxHQUFFLENBQUE7UUFDNUIsSUFBSSxJQUFJLENBQUMsSUFBSSxJQUFJLE1BQU0sRUFBRTtZQUNyQixNQUFNLEtBQUssR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUM1RSxjQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBQyxLQUFLLENBQUMsQ0FBQTtTQUM3QjtRQUNELE9BQU07SUFDVixDQUFDLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQTtBQXpCWSxRQUFBLFFBQVEsWUF5QnBCIn0=
\ No newline at end of file
diff --git a/packages/discourse/commands/query.js.map b/packages/discourse/commands/query.js.map
new file mode 100644
index 00000000..2f4871b8
--- /dev/null
+++ b/packages/discourse/commands/query.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/commands/query.ts"],"names":[],"mappings":";;;;;;;;;;;;AAEA,kCAA4C;AAC5C,wCAAkC;AAElC,0BAA2B;AAE3B,gDAA2C;AAE3C,MAAM,cAAc,GAAG,CAAC,KAAe,EAAE,EAAE;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACzB,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,gBAAgB;QAC1B,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;QACf,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,sBAAsB;QAChC,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE;QAClB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,6BAA6B;QACvC,IAAI,EAAE,SAAS;KAClB,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE;QACb,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,wCAAwC;KACrD,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;QACjB,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,qCAAqC;KAClD,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,IAAI,OAAO,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAElD,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,kBAAkB,EAAE,OAAO,EAAE,CAAO,IAAmB,EAAE,EAAE;QAC1F,IAAA,eAAQ,GAAE,CAAC;QACX,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAO;SAAE;QAC1B,MAAM,IAAI,GAAQ,IAAI,CAAC;QACvB,IAAI,OAAO,GAAG,IAAA,eAAQ,EAAC,IAAW,CAAa,CAAC;QAEhD,IAAI,CAAC,OAAO,EAAE;YACV,OAAO;SACV;QACD,OAAO,CAAC,KAAK,IAAI,UAAM,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,IAAI,GAAG,IAAA,eAAK,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAEhC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACZ,UAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAClC,OAAO;SACV;QAED,MAAM,SAAS,GAAG,IAAA,oBAAQ,GAAE,CAAA;QAE5B,IAAI,IAAI,CAAC,IAAI,IAAI,MAAM,EAAE;YACrB,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,mBAAmB,EAAC,iBAAiB,CAAC,CAAC;YAC5E,UAAM,CAAC,IAAI,CAAC,OAAO,EAAC,KAAK,CAAC,CAAA;SAC7B;QAED,OAAO;IAEX,CAAC,CAAA,CAAC,CAAC;AACP,CAAC,CAAC;AA5BW,QAAA,QAAQ,YA4BnB"}
\ No newline at end of file
diff --git a/packages/discourse/commands/sync-component.d.ts b/packages/discourse/commands/sync-component.d.ts
new file mode 100644
index 00000000..1d55e593
--- /dev/null
+++ b/packages/discourse/commands/sync-component.d.ts
@@ -0,0 +1,4 @@
+import * as CLI from 'yargs';
+import { IOptionsSyncComponent } from '../types';
+export declare const parse: (argv: any) => IOptionsSyncComponent | boolean;
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/discourse/commands/sync-component.js b/packages/discourse/commands/sync-component.js
new file mode 100644
index 00000000..55e73f4c
--- /dev/null
+++ b/packages/discourse/commands/sync-component.js
@@ -0,0 +1,124 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = exports.parse = void 0;
+const path = require("path");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const fs_1 = require("@plastichub/osr-commons");
+const exists_1 = require("@plastichub/fs/exists");
+const constants_1 = require("../lib/discourse/constants");
+const _cli_1 = require("../_cli");
+const index_1 = require("../index");
+const component_1 = require("../lib/sync/component");
+const osr_fs_utils_1 = require("@plastichub/osr-fs-utils");
+const globBase = require('glob-base');
+const parse = (argv) => {
+ let ret = {
+ ...argv
+ };
+ let srcInfo;
+ let variables = {};
+ ret.src = argv.src;
+ ret.source = (0, fs_1.resolve)((0, osr_cli_commons_1.forward_slash)(ret.source), ret.alt, variables);
+ ret.root = (0, fs_1.resolve)((0, osr_cli_commons_1.forward_slash)(ret.root), ret.alt, variables);
+ ret.product_root = (0, fs_1.resolve)((0, osr_cli_commons_1.forward_slash)(ret.product_root), ret.alt, variables);
+ if (ret.src) {
+ ret.src = (0, fs_1.resolve)(ret.src, ret.alt, variables);
+ // in case a file with a glob pattern is provided, strip the glob
+ // this is a special case, enabling shared scripts in Alt-Tap Salamand
+ const glob_base = globBase(ret.src);
+ const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '');
+ // case : single file
+ if ((0, exists_1.sync)(file) && (0, fs_1.isFile)(file)) {
+ ret.src = file;
+ }
+ const src = (0, fs_1.resolve)((0, osr_cli_commons_1.forward_slash)(ret.src), ret.alt, variables);
+ srcInfo = (0, osr_cli_commons_1.pathInfo)(src);
+ // case : glob pattern
+ if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
+ ret.srcInfo = srcInfo;
+ for (const key in srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
+ variables['SRC_' + key] = srcInfo[key];
+ }
+ }
+ }
+ else {
+ ret.src = (0, fs_1.resolve)(ret.src, ret.alt, variables);
+ }
+ }
+ if (argv.cwd) {
+ ret.cwd = path.resolve(argv.cwd);
+ if (!(0, exists_1.sync)((ret.cwd))) {
+ index_1.logger.error(`Invalid working directory ${argv.cwd}`);
+ }
+ }
+ else {
+ ret.cwd = process.cwd();
+ }
+ ret = {
+ ...ret,
+ variables,
+ srcInfo
+ };
+ return ret;
+};
+exports.parse = parse;
+const defaultOptions = (yargs) => {
+ return yargs
+ //standard options
+ .option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
+ //discourse
+ .option('yaml', { type: 'boolean', default: false, describe: 'Parse options from YAML header' })
+ .option('skip', { type: 'boolean', default: true, describe: 'Skip existing' })
+ .option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
+ .option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
+ .option('title', { type: 'string', default: 'Title of the Discourse post' })
+ .option('cat', { default: constants_1.CAT_TEST, type: 'number' })
+ .option('timestamp', { type: 'number', default: Date.now() })
+ .option('owner', { type: 'number', default: constants_1.DEFAULT_IMPORT_OWNER })
+ .option('config', { type: 'string', default: 'discourse_admin' })
+ //osrl
+ .option('src', {
+ default: '${OSR_ROOT}/osr-machines/injection/**/config.json',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('src2', {
+ default: '${OSR_ROOT}/osr-machines/sheetpress/cassandra-light/config.json',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('env', { type: 'string', default: 'forum' })
+ .option('profile', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/base.json" })
+ .option('format', { type: 'string', default: 'md' })
+ .option('source', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/root.html" })
+ .option('language', { type: 'string', default: 'osr' })
+ .option('plugins', { type: 'string', default: '${root}/osr/plugins' })
+ .option('root', { type: 'string', default: process.cwd() })
+ .option('product_root', { type: 'string', default: '${PRODUCT_ROOT}/products' })
+ .option('cwd', { type: 'string', default: process.cwd() })
+ .option('module', { type: 'string', default: 'osr-lib-components' })
+ .option('filter', { type: 'string', default: osr_fs_utils_1.PFilterValid.library_component })
+ .option('cache', { type: 'boolean', default: true })
+ .option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('sync-component', 'Sync OSR Component', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ let options = (0, exports.parse)(argv);
+ if (!options) {
+ return;
+ }
+ index_1.logger.setSettings({ minLevel: argv.logLevel });
+ // options.debug && logger.debug(`CLI Args In`, argv)
+ index_1.logger.debug('Options', options);
+ let ret = (0, component_1.syncComponent)(options);
+ return ret;
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29tbWFuZHMvc3luYy1jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTRCO0FBRzVCLGlFQUFxRTtBQUNyRSx1REFBZ0U7QUFFaEUsa0RBQXNEO0FBRXRELDBEQUEyRTtBQUUzRSxrQ0FBa0M7QUFFbEMsb0NBQWlDO0FBQ2pDLHFEQUFxRDtBQUNyRCwyREFBdUQ7QUFDdkQsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFBO0FBRTlCLE1BQU0sS0FBSyxHQUFHLENBQUMsSUFBUyxFQUFtQyxFQUFFO0lBRWhFLElBQUksR0FBRyxHQUFRO1FBQ1gsR0FBRyxJQUFJO0tBQ1YsQ0FBQTtJQUVELElBQUksT0FBTyxDQUFBO0lBQ1gsSUFBSSxTQUFTLEdBQUcsRUFBRSxDQUFBO0lBRWxCLEdBQUcsQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQTtJQUVsQixHQUFHLENBQUMsTUFBTSxHQUFHLElBQUEsWUFBTyxFQUFDLElBQUEsK0JBQWEsRUFBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQTtJQUNuRSxHQUFHLENBQUMsSUFBSSxHQUFHLElBQUEsWUFBTyxFQUFDLElBQUEsK0JBQWEsRUFBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQTtJQUMvRCxHQUFHLENBQUMsWUFBWSxHQUFHLElBQUEsWUFBTyxFQUFDLElBQUEsK0JBQWEsRUFBQyxHQUFHLENBQUMsWUFBWSxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQTtJQUUvRSxJQUFJLEdBQUcsQ0FBQyxHQUFHLEVBQUU7UUFFVCxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUEsWUFBTyxFQUFDLEdB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
\ No newline at end of file
diff --git a/packages/discourse/commands/sync-file.d.ts b/packages/discourse/commands/sync-file.d.ts
new file mode 100644
index 00000000..443f33e5
--- /dev/null
+++ b/packages/discourse/commands/sync-file.d.ts
@@ -0,0 +1,2 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/discourse/commands/sync-file.js b/packages/discourse/commands/sync-file.js
new file mode 100644
index 00000000..e0a797ab
--- /dev/null
+++ b/packages/discourse/commands/sync-file.js
@@ -0,0 +1,55 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const _cli_1 = require("../_cli");
+const index_1 = require("../index");
+const file_1 = require("../lib/sync/file");
+const constants_1 = require("../lib/discourse/constants");
+const defaultOptions = (yargs) => {
+ return yargs
+ .option('debug', { type: 'boolean', default: true, describe: 'debug messages' })
+ .option('verbose', { type: 'boolean', default: true, describe: 'even more debug messages' })
+ .option('yaml', { type: 'boolean', default: true, describe: 'Parse options from YAML header' })
+ .option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
+ .option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
+ .option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
+ .option('src', {
+ default: './tests/**/*.md',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('title', { type: 'string', default: 'Title of the Discourse post' })
+ .option('config', { type: 'string', default: 'osr_admin' })
+ .option('cat', { default: constants_1.CAT_TEST, type: 'number' })
+ .option('timestamp', { type: 'number', default: Date.now() })
+ .option('owner', { type: 'number', default: constants_1.DEFAULT_IMPORT_OWNER })
+ .option('config', { type: 'string', default: 'discourse_admin' })
+ .option('env', { type: 'string', default: 'test-import' })
+ .option('profile', { type: 'string', default: "${OSR_ROOT}/osr-profiles/osr/base.json" })
+ .option('format', { type: 'string', default: 'html' })
+ .option('root', { type: 'string', default: process.cwd() })
+ .option('cwd', { type: 'string', default: process.cwd() })
+ .option('cache', { type: 'boolean', default: true })
+ .option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('sync ', 'Sync file', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ let options = (0, _cli_1.sanitize)(argv);
+ if (!options) {
+ return;
+ }
+ options.debug && index_1.logger.debug(`CLI Args In`, argv);
+ if (!options.verb) {
+ index_1.logger.error('No verb specified');
+ return;
+ }
+ return (0, file_1.syncYAML)(options);
+ });
+};
+exports.register = register;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3luYy1maWxlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NvbW1hbmRzL3N5bmMtZmlsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxrQ0FBNEM7QUFFNUMsb0NBQWlDO0FBU2pDLDJDQUEyQztBQUMzQywwREFBMkU7QUFFM0UsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFlLEVBQUUsRUFBRTtJQUN2QyxPQUFPLEtBQUs7U0FDUCxNQUFNLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO1NBQy9FLE1BQU0sQ0FBQyxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLDBCQUEwQixFQUFFLENBQUM7U0FDM0YsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFJLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsZ0NBQWdDLEVBQUMsQ0FBQztTQUMvRixNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUMsQ0FBQztTQUMzRSxNQUFNLENBQUMsYUFBYSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxrQ0FBa0MsRUFBQyxDQUFDO1NBQ3RHLE1BQU0sQ0FBQyxjQUFjLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLG1DQUFtQyxFQUFDLENBQUM7U0FDeEcsTUFBTSxDQUFDLEtBQUssRUFBRTtRQUNYLE9BQU8sRUFBRSxpQkFBaUI7UUFDMUIsSUFBSSxFQUFFLFFBQVE7UUFDZCxRQUFRLEVBQUUscUVB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
\ No newline at end of file
diff --git a/packages/discourse/config/machines.js b/packages/discourse/config/machines.js
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/discourse/constants.d.ts b/packages/discourse/constants.d.ts
new file mode 100644
index 00000000..ca2c1318
--- /dev/null
+++ b/packages/discourse/constants.d.ts
@@ -0,0 +1 @@
+export declare const MODULE_NAME = "OSR-DISCOURSE";
diff --git a/packages/discourse/constants.js b/packages/discourse/constants.js
new file mode 100644
index 00000000..652da578
--- /dev/null
+++ b/packages/discourse/constants.js
@@ -0,0 +1,5 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MODULE_NAME = void 0;
+exports.MODULE_NAME = `OSR-DISCOURSE`;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBYSxRQUFBLFdBQVcsR0FBRyxlQUFlLENBQUEifQ==
\ No newline at end of file
diff --git a/packages/discourse/constants.js.map b/packages/discourse/constants.js.map
new file mode 100644
index 00000000..8bb5513a
--- /dev/null
+++ b/packages/discourse/constants.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"constants.js","sourceRoot":"","sources":["src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,eAAe,CAAA"}
\ No newline at end of file
diff --git a/packages/discourse/discourse-sync.json b/packages/discourse/discourse-sync.json
new file mode 100644
index 00000000..7cf74cab
--- /dev/null
+++ b/packages/discourse/discourse-sync.json
@@ -0,0 +1,34 @@
+{
+ "./tests/image.jpg": {
+ "id": 9561,
+ "url": "https://forum.osr-plastic.org/uploads/default/original/2X/e/e501e5aa77623b161069805f5e84a4dcd5e9632a.jpeg",
+ "original_filename": "image.jpg",
+ "filesize": 130249,
+ "width": 828,
+ "height": 1472,
+ "thumbnail_width": 281,
+ "thumbnail_height": 500,
+ "extension": "jpeg",
+ "short_url": "upload://wFTp838ZYs2IcwTpTMT9g566ijU.jpeg",
+ "short_path": "/uploads/short-url/wFTp838ZYs2IcwTpTMT9g566ijU.jpeg",
+ "retain_hours": null,
+ "human_filesize": "127 KB",
+ "dominant_color": "4C4D4E"
+ },
+ "https://osr-plastic.org/machines/injection/components/304_Valve-40mm/renderings/webp/perspective.webp": {
+ "id": 9562,
+ "url": "https://forum.osr-plastic.org/uploads/default/original/2X/0/020b78cdced1bf3095da4ababa8347e2334f26dd.webp",
+ "original_filename": "perspective.webp",
+ "filesize": 14366,
+ "width": 1080,
+ "height": 864,
+ "thumbnail_width": 625,
+ "thumbnail_height": 500,
+ "extension": "webp",
+ "short_url": "upload://i5x4cSq74UrBXgc4Kw66mIf7rL.webp",
+ "short_path": "/uploads/short-url/i5x4cSq74UrBXgc4Kw66mIf7rL.webp",
+ "retain_hours": null,
+ "human_filesize": "14 KB",
+ "dominant_color": "E7E4E2"
+ }
+}
\ No newline at end of file
diff --git a/packages/discourse/docs/data.md b/packages/discourse/docs/data.md
new file mode 100644
index 00000000..4343dffd
--- /dev/null
+++ b/packages/discourse/docs/data.md
@@ -0,0 +1,22 @@
+### OA - Users
+
+cli::import-oa-users import|update
+
+src -> export const osr-commons/OA_LATEST = '${OSR_ROOT}/osr-directory/pp/${YYYY}_${MM}.json'
+
+ -> write (${OSR_ROOT}/${OSR_ROOT}/osr-directory/pp/invalidUsers.json)
+ -> write (${OSR_ROOT}/${OSR_ROOT}/osr-directory/pp/invalidUsersEMail.json)
+ -> merge to '${OSR_ROOT}/${OSR_ROOT}/osr-directory/pp/merged.json'
+
+### Discourse Directory Layout
+
+- Intro Page
+ - Continent (cat, +tags)
+ - country page (+tags, +lang)
+ - item (+tags, +lang)
+
+- External feeds
+ - social
+ - products
+ - osr content
+ - news
diff --git a/packages/discourse/index.d.ts b/packages/discourse/index.d.ts
new file mode 100644
index 00000000..4cc5bf88
--- /dev/null
+++ b/packages/discourse/index.d.ts
@@ -0,0 +1,9 @@
+export * from './constants';
+export * from './types';
+export * from './lib';
+export * from './lib/oa/types';
+import { Logger } from "tslog";
+export { Logger } from 'tslog';
+export declare const logger: Logger;
+import { IObjectLiteral } from "@plastichub/core";
+export declare const substitute: (alt: boolean, template: string, vars?: IObjectLiteral) => any;
diff --git a/packages/discourse/index.js b/packages/discourse/index.js
new file mode 100644
index 00000000..29638d69
--- /dev/null
+++ b/packages/discourse/index.js
@@ -0,0 +1,89 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.substitute = exports.logger = exports.Logger = void 0;
+__exportStar(require("./constants"), exports);
+__exportStar(require("./types"), exports);
+__exportStar(require("./lib"), exports);
+__exportStar(require("./lib/oa/types"), exports);
+const debug_1 = require("@plastichub/core/debug");
+const constants_1 = require("./constants");
+var tslog_1 = require("tslog");
+Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return tslog_1.Logger; } });
+let loggers = {};
+/*
+const _logger = new Logger({
+ prettyLogTemplate: "{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}\t{{logLevelName}}\t[{{filePathWithLine}}{{name}}]\t",
+ prettyErrorTemplate: "\n{{errorName}} {{errorMessage}}\nerror stack:\n{{errorStack}}",
+ prettyErrorStackTemplate: " • {{fileName}}\t{{method}}\n\t{{filePathWithLine}}",
+ prettyErrorParentNamesSeparator: ":",
+ prettyErrorLoggerNameDelimiter: "\t",
+ stylePrettyLogs: true,
+ prettyLogTimeZone: "UTC",
+ prettyLogStyles: {
+ logLevelName: {
+ "*": ["bold", "black", "bgWhiteBright", "dim"],
+ SILLY: ["bold", "white"],
+ TRACE: ["bold", "whiteBright"],
+ DEBUG: ["bold", "green"],
+ INFO: ["bold", "blue"],
+ WARN: ["bold", "yellow"],
+ ERROR: ["bold", "red"],
+ FATAL: ["bold", "redBright"],
+ },
+ dateIsoStr: "white",
+ filePathWithLine: "white",
+ name: ["white", "bold"],
+ nameWithDelimiterPrefix: ["white", "bold"],
+ nameWithDelimiterSuffix: ["white", "bold"],
+ errorName: ["bold", "bgRedBright", "whiteBright"],
+ fileName: ["yellow"],
+ fileNameWithLine: "white",
+ },
+ });
+ */
+/*
+export const __logger = (name: string = MODULE_NAME, options: ISettingsParam = {}): Logger => {
+ if (!loggers[name]) {
+ const logger: Logger = new Logger({
+ name: name,
+ type: 'pretty',
+ ...options
+ });
+ // const trans = (transportLogger: LogObj & ILogObjMet)
+ (logger as any).attachTransport((logObj) => {
+ debugger
+ //transports.push(logObj);
+ });
+
+ logger.debug('test')
+
+ loggers[name] = logger;
+ }
+ return loggers[name]
+}*/
+exports.logger = (0, debug_1.logger)(constants_1.MODULE_NAME);
+/*
+export const log = (msg: string, ...args: any) => logger().info(msg, ...args);
+export const info = (msg: string, ...args: any) => logger().info(msg, ...args);
+export const error = (msg: string, ...args: any) => logger().error(msg, ...args);
+export const warn = (msg: string, ...args: any) => logger().warn(msg, ...args);
+export const debug = (msg: string, ...args: any) => logger().debug(msg, ...args);
+*/
+const strings_1 = require("@plastichub/core/strings");
+const substitute = (alt, template, vars = {}) => alt ? (0, strings_1.substituteAlt)(template, vars) : (0, strings_1.substitute)(template, vars);
+exports.substitute = substitute;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw4Q0FBMkI7QUFDM0IsMENBQXVCO0FBQ3ZCLHdDQUFxQjtBQUNyQixpREFBOEI7QUFFOUIsa0RBQTBEO0FBRTFELDJDQUF5QztBQUV6QywrQkFBOEI7QUFBckIsK0ZBQUEsTUFBTSxPQUFBO0FBRWYsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0FBRWpCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7SUE4Qkk7QUFDSjs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUdVLFFBQUEsTUFBTSxHQUFHLElBQUEsY0FBTyxFQUFDLHVCQUFXLENBQUMsQ0FBQTtBQUUxQzs7Ozs7O0VBTUU7QUFHRixzREFBcUc7QUFJOUYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFZLEVBQUUsUUFBZ0IsRUFBRSxPQUF1QixFQUFFLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBQSx1QkFBYyxFQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBQSxvQkFBVyxFQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQTtBQUE5SSxRQUFBLFVBQVUsY0FBb0kifQ==
\ No newline at end of file
diff --git a/packages/discourse/index.js.map b/packages/discourse/index.js.map
new file mode 100644
index 00000000..25190a41
--- /dev/null
+++ b/packages/discourse/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,0CAAuB;AAEvB,kDAA0D;AAE1D,2CAAyC;AAI5B,QAAA,MAAM,GAAG,IAAA,cAAO,EAAC,uBAAW,CAAC,CAAA;AAE1C,2CAAgH;AAEzG,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,QAAe,EAAE,IAAmB,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAA,oBAAc,EAAC,QAAQ,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAA,iBAAW,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;AAArI,QAAA,UAAU,cAA2H"}
\ No newline at end of file
diff --git a/packages/discourse/index.md b/packages/discourse/index.md
new file mode 100644
index 00000000..751fdea7
--- /dev/null
+++ b/packages/discourse/index.md
@@ -0,0 +1,146 @@
+## Directory Index
+
+**Hidden / Censored Users** :
+
+**Total** :
+
+## Africa
+ - [Algeria (6)](/directory/users_algeria-af)
+- [Botswana (1)](/directory/users_botswana-af)
+- [Burkina Faso (2)](/directory/users_burkina-faso-af)
+- [Cabo Verde (1)](/directory/users_cabo-verde-af)
+- [Cameroon (2)](/directory/users_cameroon-af)
+- [Congo (3)](/directory/users_congo-(the-democratic-republic-of-the)-af)
+- [Egypt (7)](/directory/users_egypt-af)
+- [Eswatini (1)](/directory/users_eswatini-af)
+- [Ethiopia (2)](/directory/users_ethiopia-af)
+- [Ghana (5)](/directory/users_ghana-af)
+- [Kenya (14)](/directory/users_kenya-af)
+- [Libya (1)](/directory/users_libya-af)
+- [Madagascar (2)](/directory/users_madagascar-af)
+- [Mali (2)](/directory/users_mali-af)
+- [Mauritius (2)](/directory/users_mauritius-af)
+- [Morocco (2)](/directory/users_morocco-af)
+- [Namibia (3)](/directory/users_namibia-af)
+- [Nigeria (7)](/directory/users_nigeria-af)
+- [Reunion (1)](/directory/users_reunion-af)
+- [Senegal (1)](/directory/users_senegal-af)
+- [Somalia (1)](/directory/users_somalia-af)
+- [South Africa (16)](/directory/users_south-africa-af)
+- [Spain (58)](/directory/users_spain-af)
+- [Tanzania, the United Republic of (6)](/directory/users_tanzania-the-united-republic-of-af)
+- [Tunisia (3)](/directory/users_tunisia-af)
+- [Uganda (1)](/directory/users_uganda-af)
+- [Zambia (2)](/directory/users_zambia-af)
+## Asia
+ - [Armenia (1)](/directory/users_armenia-as)
+- [Azerbaijan (2)](/directory/users_azerbaijan-as)
+- [Bangladesh (6)](/directory/users_bangladesh-as)
+- [Cambodia (2)](/directory/users_cambodia-as)
+- [China (3)](/directory/users_china-as)
+- [Christmas Island (1)](/directory/users_christmas-island-as)
+- [Cyprus (3)](/directory/users_cyprus-as)
+- [Georgia (3)](/directory/users_georgia-as)
+- [Hong Kong (7)](/directory/users_hong-kong-as)
+- [India (42)](/directory/users_india-as)
+- [Indonesia (57)](/directory/users_indonesia-as)
+- [Iran (1)](/directory/users_iran-(islamic-republic-of)-as)
+- [Iraq (2)](/directory/users_iraq-as)
+- [Israel (1)](/directory/users_israel-as)
+- [Japan (16)](/directory/users_japan-as)
+- [Jordan (4)](/directory/users_jordan-as)
+- [Kazakhstan (1)](/directory/users_kazakhstan-as)
+- [Korea (16)](/directory/users_korea-(the-republic-of)-as)
+- [Kyrgyzstan (1)](/directory/users_kyrgyzstan-as)
+- [Lao People's Democratic Republic (1)](/directory/users_lao-people's-democratic-republic-(the)-as)
+- [Lebanon (2)](/directory/users_lebanon-as)
+- [Malaysia (13)](/directory/users_malaysia-as)
+- [Mongolia (2)](/directory/users_mongolia-as)
+- [Myanmar (1)](/directory/users_myanmar-as)
+- [Pakistan (1)](/directory/users_pakistan-as)
+- [Philippines (5)](/directory/users_philippines-(the)-as)
+- [Russian Federation (31)](/directory/users_russian-federation-(the)-as)
+- [Saudi Arabia (3)](/directory/users_saudi-arabia-as)
+- [Singapore (4)](/directory/users_singapore-as)
+- [Sri Lanka (1)](/directory/users_sri-lanka-as)
+- [Taiwan (2)](/directory/users_taiwan-(province-of-china)-as)
+- [Thailand (12)](/directory/users_thailand-as)
+- [Timor-Leste (2)](/directory/users_timor-leste-as)
+- [Turkiye (16)](/directory/users_turkiye-as)
+- [United Arab Emirates (3)](/directory/users_united-arab-emirates-(the)-as)
+- [Uzbekistan (2)](/directory/users_uzbekistan-as)
+- [Viet Nam (12)](/directory/users_viet-nam-as)
+## Australian continent
+ - [Australia (53)](/directory/users_australia-au)
+## Europe
+ - [Albania (2)](/directory/users_albania-eu)
+- [Austria (6)](/directory/users_austria-eu)
+- [Belarus (1)](/directory/users_belarus-eu)
+- [Belgium (18)](/directory/users_belgium-eu)
+- [Bosnia and Herzegovina (3)](/directory/users_bosnia-and-herzegovina-eu)
+- [Bulgaria (5)](/directory/users_bulgaria-eu)
+- [Croatia (4)](/directory/users_croatia-eu)
+- [Czechia (7)](/directory/users_czechia-eu)
+- [Denmark (4)](/directory/users_denmark-eu)
+- [Estonia (1)](/directory/users_estonia-eu)
+- [Finland (2)](/directory/users_finland-eu)
+- [France (95)](/directory/users_france-eu)
+- [Germany (66)](/directory/users_germany-eu)
+- [Greece (14)](/directory/users_greece-eu)
+- [Hungary (5)](/directory/users_hungary-eu)
+- [Iceland (1)](/directory/users_iceland-eu)
+- [Ireland (5)](/directory/users_ireland-eu)
+- [Italy (31)](/directory/users_italy-eu)
+- [Latvia (2)](/directory/users_latvia-eu)
+- [Liechtenstein (1)](/directory/users_liechtenstein-eu)
+- [Lithuania (2)](/directory/users_lithuania-eu)
+- [Malta (1)](/directory/users_malta-eu)
+- [Montenegro (1)](/directory/users_montenegro-eu)
+- [Netherlands (37)](/directory/users_netherlands-(the)-eu)
+- [Norway (7)](/directory/users_norway-eu)
+- [Poland (4)](/directory/users_poland-eu)
+- [Portugal (17)](/directory/users_portugal-eu)
+- [Romania (5)](/directory/users_romania-eu)
+- [Russian Federation (31)](/directory/users_russian-federation-(the)-eu)
+- [Serbia (6)](/directory/users_serbia-eu)
+- [Slovakia (6)](/directory/users_slovakia-eu)
+- [Slovenia (1)](/directory/users_slovenia-eu)
+- [Spain (58)](/directory/users_spain-eu)
+- [Sweden (4)](/directory/users_sweden-eu)
+- [Switzerland (15)](/directory/users_switzerland-eu)
+- [Ukraine (16)](/directory/users_ukraine-eu)
+- [United Kingdom of Great Britain and Northern Ireland (65)](/directory/users_united-kingdom-of-great-britain-and-northern-ireland-(the)-eu)
+## North America
+ - [Canada (42)](/directory/users_canada-na)
+- [Costa Rica (6)](/directory/users_costa-rica-na)
+- [Cuba (1)](/directory/users_cuba-na)
+- [Curacao (1)](/directory/users_curacao-na)
+- [Dominican Republic (9)](/directory/users_dominican-republic-(the)-na)
+- [Guatemala (2)](/directory/users_guatemala-na)
+- [Haiti (2)](/directory/users_haiti-na)
+- [Mexico (57)](/directory/users_mexico-na)
+- [Netherlands (37)](/directory/users_netherlands-(the)-na)
+- [Panama (3)](/directory/users_panama-na)
+- [Puerto Rico (3)](/directory/users_puerto-rico-na)
+- [United States of America (167)](/directory/users_united-states-of-america-(the)-na)
+## Oceania
+ - [Fiji (2)](/directory/users_fiji-oc)
+- [Guam (1)](/directory/users_guam-oc)
+- [Micronesia (1)](/directory/users_micronesia-(federated-states-of)-oc)
+- [New Caledonia (1)](/directory/users_new-caledonia-oc)
+- [New Zealand (10)](/directory/users_new-zealand-oc)
+- [United States of America (167)](/directory/users_united-states-of-america-(the)-oc)
+## South America
+ - [Argentina (34)](/directory/users_argentina-sa)
+- [Bolivia (2)](/directory/users_bolivia-(plurinational-state-of)-sa)
+- [Brazil (57)](/directory/users_brazil-sa)
+- [Chile (26)](/directory/users_chile-sa)
+- [Colombia (39)](/directory/users_colombia-sa)
+- [Ecuador (11)](/directory/users_ecuador-sa)
+- [Guyana (1)](/directory/users_guyana-sa)
+- [Paraguay (2)](/directory/users_paraguay-sa)
+- [Peru (9)](/directory/users_peru-sa)
+- [Uruguay (4)](/directory/users_uruguay-sa)
+- [Venezuela (5)](/directory/users_venezuela-(bolivarian-republic-of)-sa)
+
+
diff --git a/packages/discourse/lib/discourse/cache.d.ts b/packages/discourse/lib/discourse/cache.d.ts
new file mode 100644
index 00000000..fe047e18
--- /dev/null
+++ b/packages/discourse/lib/discourse/cache.d.ts
@@ -0,0 +1,10 @@
+///
+import { IDiscourseUser } from '../../';
+import { Discourser } from '../index';
+export declare const fileAsBuffer: (path: string) => Buffer;
+export declare const cacheCategories: (options: any, discourse: Discourser) => Promise;
+export declare const cacheTopics: (options: any, discourse: Discourser) => Promise;
+export declare const _getForumUsers: (d: Discourser, page: any, detail: any) => any;
+export declare const getForumUsers: (d: any, detail: any) => Promise;
+export declare const cacheUsers: (options: any, discourse: Discourser) => Promise;
+export declare const cacheTags: (options: any, discourse: Discourser) => Promise;
diff --git a/packages/discourse/lib/discourse/cache.js b/packages/discourse/lib/discourse/cache.js
new file mode 100644
index 00000000..6238f7d3
--- /dev/null
+++ b/packages/discourse/lib/discourse/cache.js
@@ -0,0 +1,122 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.cacheTags = exports.cacheUsers = exports.getForumUsers = exports._getForumUsers = exports.cacheTopics = exports.cacheCategories = exports.fileAsBuffer = void 0;
+const bluebird_1 = require("bluebird");
+const read_1 = require("@plastichub/fs/read");
+const exists_1 = require("@plastichub/fs/exists");
+const write_1 = require("@plastichub/fs/write");
+const fs_1 = require("@plastichub/osr-commons");
+const constants_1 = require("../discourse/constants");
+const path = require("path");
+const escapeHtml = require('escape-html');
+const pretty = require('pretty');
+const fileAsBuffer = (path) => (0, read_1.sync)(path, 'buffer') || Buffer.from("-");
+exports.fileAsBuffer = fileAsBuffer;
+const lib_1 = require("@plastichub/osr-cache/lib");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const constants_2 = require("../../constants");
+const cacheCategories = async (options, discourse) => {
+ const osr_cache = (0, osr_cli_commons_1.OSR_CACHE)();
+ const cPath = path.resolve((0, fs_1.resolve)(constants_1.DISCOURSE_CATEGORY_CACHE));
+ const cached = (0, exists_1.sync)(cPath) ? await (0, lib_1.get_cached)(cPath, {}, constants_2.MODULE_NAME) : null;
+ if (osr_cache && cached && options.cache !== false) {
+ return JSON.parse(cached);
+ }
+ let cats = await discourse.getCategories({
+ include_subcategories: true
+ });
+ (0, write_1.sync)(cPath, cats);
+ if (osr_cache && options.cache !== false) {
+ await (0, lib_1.set_cached)(cPath, {}, constants_2.MODULE_NAME, cats);
+ }
+ return cats;
+};
+exports.cacheCategories = cacheCategories;
+const cacheTopics = async (options, discourse) => {
+};
+exports.cacheTopics = cacheTopics;
+let uPage = 1;
+let usersAll = [];
+const _getForumUsers = async (d, page, detail) => {
+ const uPath = path.resolve((0, fs_1.resolve)(constants_1.DISCOURSE_USER_CACHE));
+ if (uPage == 1) {
+ usersAll = [];
+ }
+ let users = await d.getUsers(page);
+ if (users.length) {
+ usersAll = usersAll.concat(users);
+ uPage++;
+ return (0, exports._getForumUsers)(d, uPage, detail);
+ }
+ else {
+ uPage = 1;
+ (0, write_1.sync)(uPath, usersAll);
+ let fUsers = (0, read_1.sync)(uPath, 'json') || [];
+ const add = async (u) => {
+ return new Promise((resolve, reject) => {
+ let fUser = fUsers.find((fu) => u.id == fu.id);
+ if (!fUser) {
+ fUsers.push(u);
+ fUser = u;
+ }
+ if (fUser.detail) {
+ console.log('Retrieve User Detail ' + u.name);
+ setTimeout(() => {
+ d.getUser(fUser.id).then((detail) => {
+ if (detail) {
+ fUser.detail = detail;
+ }
+ (0, write_1.sync)(uPath, fUsers);
+ resolve(fUser);
+ });
+ }, 200);
+ }
+ else {
+ resolve(fUser);
+ }
+ });
+ };
+ return await bluebird_1.Promise.resolve(usersAll).map((u) => {
+ return add(u);
+ }, { concurrency: 1 });
+ }
+};
+exports._getForumUsers = _getForumUsers;
+const getForumUsers = async (d, detail) => {
+ return (0, exports._getForumUsers)(d, uPage, detail);
+};
+exports.getForumUsers = getForumUsers;
+const cacheUsers = async (options, discourse) => {
+ const osr_cache = (0, osr_cli_commons_1.OSR_CACHE)();
+ const uPath = path.resolve((0, fs_1.resolve)(constants_1.DISCOURSE_USER_CACHE));
+ const cached = (0, exists_1.sync)(uPath) ? await (0, lib_1.get_cached)(uPath, {}, constants_2.MODULE_NAME) : null;
+ if (osr_cache && options.cache !== false && (0, exists_1.sync)(uPath)) {
+ return (0, read_1.sync)(uPath, 'json');
+ }
+ if (osr_cache && cached && options.cache !== false) {
+ return JSON.parse(cached);
+ }
+ let users = await (0, exports.getForumUsers)(discourse, false);
+ (0, write_1.sync)(uPath, users);
+ if (osr_cache && options.cache !== false) {
+ await (0, lib_1.set_cached)(uPath, {}, constants_2.MODULE_NAME, users);
+ }
+ return users;
+};
+exports.cacheUsers = cacheUsers;
+const cacheTags = async (options, discourse) => {
+ const osr_cache = (0, osr_cli_commons_1.OSR_CACHE)();
+ const tPath = path.resolve((0, fs_1.resolve)(constants_1.DISCOURSE_TAGS_CACHE));
+ const cached = (0, exists_1.sync)(tPath) ? await (0, lib_1.get_cached)(tPath, {}, constants_2.MODULE_NAME) : null;
+ if (osr_cache && cached && options.cache !== false) {
+ return JSON.parse(cached);
+ }
+ let tags = await discourse.getTags();
+ (0, write_1.sync)(tPath, tags);
+ if (osr_cache && options.cache !== false) {
+ await (0, lib_1.set_cached)(tPath, {}, constants_2.MODULE_NAME, tags);
+ }
+ return tags;
+};
+exports.cacheTags = cacheTags;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2Rpc2NvdXJzZS9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSx1Q0FBOEM7QUFDOUMsOENBQWtEO0FBQ2xELGtEQUFzRDtBQUN0RCxnREFBb0Q7QUFDcEQsdURBQXdEO0FBcUJ4RCxzREFRK0I7QUFLL0IsNkJBQTRCO0FBTzVCLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQTtBQUN6QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFFekIsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDLElBQUEsV0FBSSxFQUFDLElBQUksRUFBRSxRQUFRLENBQVcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO0FBQW5GLFFBQUEsWUFBWSxnQkFBdUU7QUFFaEcsbURBQWtFO0FBQ2xFLGlFQUF1RDtBQUl2RCwrQ0FFd0I7QUFHakIsTUFBTSxlQUFlLEdBQUcsS0FBSyxFQUFFLE9BQVksRUFBRSxTQUFxQixFQUFFLEVBQUU7SUFFekUsTUFBTSxTQUFTLEdBQUcsSUFBQSwyQkFBUyxHQUFFLENBQUE7SUFFN0IsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFBLFlBQU8sRUFBQyxvQ0FBd0IsQ0FBQyxDQUFDLENBQUE7SUFFN0QsTUFBTSxNQUFNLEdBQUcsSUFBQSxhQUFNLEVBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBQSxnQkFBVSxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsdUJBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7SUFFOUUsSUFBSSxTQUFTLElBQUksTUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFO1FBQ2hELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtLQUM1QjtJQUVELElBQUksSUFBSSxHQUFHLE1BQU0sU0FBUyxDQUFDLGFBQWEsQ0FBQztRQUNyQyxxQkFBcUIsRUFBRSxJQUFJO0tBQzlCLENBQUMsQ0FBQTtJQUVGLElBQUEsWUFBSyxFQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUVsQixJQUFJLFNBQVMsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLEtBQUssRUFBRTtRQUN0QyxNQUFNLElBQUEsZ0JBQVUsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLHVCQUFXLEVBQUUsSUFBSSxDQUFDLENBQUE7S0FDakQ7SUFFRCxPQUFPLElBQUksQ0FBQTtBQUNmLENBQUMsQ0FBQTtBQXZCWSxRQUFBLGVBQWUsbUJBdUIzQjtBQUVNLE1BQU0sV0FBVyxHQUFHLEtBQUssRUFBRSxPQUFXLEVBQUUsU0FBcUIsRUFBRSxFQUFFO0FBRXhFLENBQUMsQ0FBQTtBQUZZLFFBQUEsV0FBVyxlQUV2QjtBQUVELElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQTtBQUNiLElBQUksUUFBUSxHQUFHLEVBQUUsQ0FBQTtBQUVWLE1BQU0sY0FBYyxHQUFHLEtBQUssRUFBRSxDQUFhLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBRWhFLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBQSxZQUFPLEVBQUMsZ0NBQW9CLENBQUMsQ0FBQyxDQUFBO0lBRXpELElBQUksS0FBSyxJQUFJLENBQUMsRUFBRTtRQUNaLFFBQVEsR0FBRyxFQUFFLENBQUE7S0FDaEI7SUFDRCxJQUFJLEtBQUssR0FBUSxNQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDdkMsSUFBSSxLQUFLLENBQUMsTUFBTSxFQUFFO1FBQ2QsUUFBUSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDakMsS0FBSyxFQUFFLENBQUE7UUFDUCxPQUFPLElBQUEsc0JBQWMsRUFBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0tBQzFDO1NBQU07UUFDSCxLQUFLLEdBQUcsQ0FBQyxDQUFBO1FBRVQsSUFBQSxZQUFLLEVBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFBO1FBRXRCLElBQUksTUFBTSxHQUFxQixJQUFBLFdBQUksRUFBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBUyxDQUFBO1FBRS9ELE1BQU0sR0FBRyxHQUFHLEtBQUssRUFBRSxDQUFpQixFQUFFLEVBQUU7WUFDcEMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDbkMsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUE7Z0JBQzlDLElBQUksQ0FBQyxLQUFLLEVBQUU7b0JBQ1IsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQTtvQkFDZCxLQUFLLEdBQUcsQ0FBQyxDQUFBO2lCQUNaO2dCQUVELElBQUksS0FBSyxDQUFDLE1BQU0sRUFBRTtvQkFDZCxPQUFPLENBQUMsR0FBRyxDQUFDLHVCQUF1QixHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtvQkFDN0MsVUFBVSxDQUFDLEdBQUcsRUFBRTt3QkFDWixDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTs0QkFDaEMsSUFBSSxNQUFNLEVBQUU7Z0NBQ1IsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7NkJBQ3hCOzRCQUNELElBQUEsWUFBSyxFQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQTs0QkFDcEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO3dCQUNsQixDQUFDLENBQUMsQ0FBQTtvQkFDTixDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUE7aUJBQ1Y7cUJBQU07b0JBQ0gsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO2lCQUNqQjtZQUNMLENBQUMsQ0FBQyxDQUFBO1FBQ04sQ0FBQyxDQUFBO1FBQ0QsT0FBTyxNQUFNLGtCQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQWlCLEVBQUUsRUFBRTtZQUM5RCxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNqQixDQUFDLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtLQUV6QjtBQUNMLENBQUMsQ0FBQTtBQWhEWSxRQUFBLGNBQWMsa0JBZ0QxQjtBQUNNLE1BQU0sYUFBYSxHQUFHLEtBQUssRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUE2QixFQUFFO0lBQ3hFLE9BQU8sSUFBQSxzQkFBYyxFQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUE7QUFDM0MsQ0FBQyxDQUFBO0FBRlksUUFBQSxhQUFhLGlCQUV6QjtBQUVNLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxPQUFPLEVBQUUsU0FBcUIsRUFBNkIsRUFBRTtJQUUxRixNQUFNLFNBQVMsR0FBRyxJQUFBLDJCQUFTLEdBQUUsQ0FBQTtJQUM3QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsWUFBTyxFQUFDLGdDQUFvQixDQUFDLENBQUMsQ0FBQTtJQUV6RCxNQUFNLE1BQU0sR0FBRyxJQUFBLGFBQU0sRUFBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFBLGdCQUFVLEVBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSx1QkFBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtJQUU5RSxJQUFJLFNBQVMsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLEtBQUssSUFBSSxJQUFBLGFBQU0sRUFBQyxLQUFLLENBQUMsRUFBRTtRQUN2RCxPQUFPLElBQUEsV0FBSSxFQUFDLEtBQUssRUFBRSxNQUFNLENBQVEsQ0FBQTtLQUNwQztJQUVELElBQUksU0FBUyxJQUFJLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLEtBQUssRUFBRTtRQUNoRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUE7S0FDNUI7SUFFRCxJQUFJLEtBQUssR0FBRyxNQUFNLElBQUEscUJBQWEsRUFBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFFakQsSUFBQSxZQUFLLEVBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBRW5CLElBQUksU0FBUyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFO1FBQ3RDLE1BQU0sSUFBQSxnQkFBVSxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsdUJBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQTtLQUNsRDtJQUVELE9BQU8sS0FBSyxDQUFBO0FBRWhCLENBQUMsQ0FBQTtBQXpCWSxRQUFBLFVBQVUsY0F5QnRCO0FBRU0sTUFBTSxTQUFTLEdBQUcsS0FBSyxFQUFFLE9BQU8sRUFBRSxTQUFxQixFQUFFLEVBQUU7SUFDOUQsTUFBTSxTQUFTLEdBQUcsSUFBQSwyQkFBUyxHQUFFLENBQUE7SUFDN0IsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFBLFlBQU8sRUFBQyxnQ0FBb0IsQ0FBQyxDQUFDLENBQUE7SUFFekQsTUFBTSxNQUFNLEdBQUcsSUFBQSxhQUFNLEVBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sSUFBQSxnQkFBVSxFQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsdUJBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7SUFFOUUsSUFBSSxTQUFTLElBQUksTUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLEtBQUssS0FBSyxFQUFFO1FBQ2hELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtLQUM1QjtJQUVELElBQUksSUFBSSxHQUFHLE1BQU0sU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ3BDLElBQUEsWUFBSyxFQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQTtJQUVsQixJQUFJLFNBQVMsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLEtBQUssRUFBRTtRQUN0QyxNQUFNLElBQUEsZ0JBQVUsRUFBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLHVCQUFXLEVBQUUsSUFBSSxDQUFDLENBQUE7S0FDakQ7SUFFRCxPQUFPLElBQUksQ0FBQTtBQUNmLENBQUMsQ0FBQTtBQWxCWSxRQUFBLFNBQVMsYUFrQnJCIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/constants.d.ts b/packages/discourse/lib/discourse/constants.d.ts
new file mode 100644
index 00000000..49a2ce1c
--- /dev/null
+++ b/packages/discourse/lib/discourse/constants.d.ts
@@ -0,0 +1,70 @@
+export type EDiscourseConfigKey = 'discourse' | 'discourse_admin';
+export declare const SYNC_TRACK_FILENAME = "discourse-sync.json";
+export declare const OSR_CACHE_ROOT = "${OSR_CACHE}";
+export declare const OSR_DISCOURSE_CACHE = "${OSR_CACHE}/discourse";
+export declare const DISCOURSE_CATEGORY_CACHE = "${OSR_CACHE}/discourse/cats.json";
+export declare const DISCOURSE_TOPICS_CACHE = "${OSR_CACHE}/discourse/topics.json";
+export declare const DISCOURSE_TAGS_CACHE = "${OSR_CACHE}/discourse/tags.json";
+export declare const DISCOURSE_USER_CACHE = "${OSR_CACHE}/discourse/users.json";
+export declare const OA_DIRECTORY_OVERVIEW_TOPIC = 28873;
+export declare const OA_USER_IMPORT_GROUP = 43;
+export declare const KB_USERS = "${KB_ROOT}/static/users";
+export declare const DATA_PATH = "${OSR_ROOT}/osr-directory/pp";
+export declare const LATEST_TRACK = "${OSR_ROOT}/osr-directory/pp/merged.json";
+export declare const LATEST_TEST = "./latest_test.json";
+export declare const FETCH_DUSERS = false;
+export declare const F_USERS_NOW = "./fusers.json";
+export declare const F_USERS_ALL = "./fusers-all.json";
+export declare const DEFAULT_PASSWORD: () => string;
+export declare const HOWTOS_ASSETS_URL: () => string;
+export declare const MACHINES_ASSETS_URL: () => string;
+export declare const CAT_TEST = 65;
+export declare const TAGS_TEST = "plastic, meta";
+export declare const DEFAULT_IMPORT_OWNER = 1;
+export declare const D_ROOT_CAT = 97;
+export declare const D_ROOT_AFRICA = 79;
+export declare const D_ROOT_ASIA = 60;
+export declare const D_ROOT_EUROPE = 59;
+export declare const D_ROOT_AUSTRALIA = 76;
+export declare const D_ROOT_NAMERICA = 101;
+export declare const D_ROOT_SAMERICA = 102;
+export declare const D_ROOT_OCEANIA = 103;
+export declare const HT_CAT_ROOT = 54;
+export declare const HT_CAT_GUIDES = 86;
+export declare const HT_CAT_MACHINES = 87;
+export declare const HT_CAT_PRODUCTS = 88;
+export declare const HT_CAT_MOULDS = 89;
+export declare const HT_CAT_IDS: {
+ HT_CAT_ROOT: number;
+ HT_CAT_GUIDES: number;
+ HT_CAT_MACHINES: number;
+ HT_CAT_PRODUCTS: number;
+ HT_CAT_MOULDS: number;
+};
+export declare const HT_CATS: {
+ Guides: number;
+ Machines: number;
+ Products: number;
+ Moulds: number;
+};
+export declare const MACHINE_CAT_INJECTION = 50;
+export declare const MACHINE_CAT_EXTRUSION = 51;
+export declare const MACHINE_CAT_SHREDDER = 52;
+export declare const MACHINE_CAT_SHEETPRESS = 63;
+export declare const MACHINE_CAT_3DPRINT = 70;
+export declare const MACHINE_CAT_MOULDS = 71;
+export declare const MACHINE_CAT_IDS: {
+ MACHINE_CAT_INJECTION: number;
+ MACHINE_CAT_EXTRUSION: number;
+ MACHINE_CAT_SHREDDER: number;
+ MACHINE_CAT_SHEETPRESS: number;
+ MACHINE_CAT_3DPRINT: number;
+ MACHINE_CAT_MOULDS: number;
+};
+export declare const MACHINE_CATS: {
+ Injection: number;
+ Extrusion: number;
+ Sheetpress: number;
+ '3DPrint': number;
+ Moulds: number;
+};
diff --git a/packages/discourse/lib/discourse/constants.js b/packages/discourse/lib/discourse/constants.js
new file mode 100644
index 00000000..b6d5f2f0
--- /dev/null
+++ b/packages/discourse/lib/discourse/constants.js
@@ -0,0 +1,100 @@
+"use strict";
+//////////////////////////////////////////////////////////////
+//
+// Keys
+//
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MACHINE_CATS = exports.MACHINE_CAT_IDS = exports.MACHINE_CAT_MOULDS = exports.MACHINE_CAT_3DPRINT = exports.MACHINE_CAT_SHEETPRESS = exports.MACHINE_CAT_SHREDDER = exports.MACHINE_CAT_EXTRUSION = exports.MACHINE_CAT_INJECTION = exports.HT_CATS = exports.HT_CAT_IDS = exports.HT_CAT_MOULDS = exports.HT_CAT_PRODUCTS = exports.HT_CAT_MACHINES = exports.HT_CAT_GUIDES = exports.HT_CAT_ROOT = exports.D_ROOT_OCEANIA = exports.D_ROOT_SAMERICA = exports.D_ROOT_NAMERICA = exports.D_ROOT_AUSTRALIA = exports.D_ROOT_EUROPE = exports.D_ROOT_ASIA = exports.D_ROOT_AFRICA = exports.D_ROOT_CAT = exports.DEFAULT_IMPORT_OWNER = exports.TAGS_TEST = exports.CAT_TEST = exports.MACHINES_ASSETS_URL = exports.HOWTOS_ASSETS_URL = exports.DEFAULT_PASSWORD = exports.F_USERS_ALL = exports.F_USERS_NOW = exports.FETCH_DUSERS = exports.LATEST_TEST = exports.LATEST_TRACK = exports.DATA_PATH = exports.KB_USERS = exports.OA_USER_IMPORT_GROUP = exports.OA_DIRECTORY_OVERVIEW_TOPIC = exports.DISCOURSE_USER_CACHE = exports.DISCOURSE_TAGS_CACHE = exports.DISCOURSE_TOPICS_CACHE = exports.DISCOURSE_CATEGORY_CACHE = exports.OSR_DISCOURSE_CACHE = exports.OSR_CACHE_ROOT = exports.SYNC_TRACK_FILENAME = void 0;
+//////////////////////////////////////////////////////////////
+//
+// Paths
+//
+exports.SYNC_TRACK_FILENAME = 'discourse-sync.json';
+exports.OSR_CACHE_ROOT = '${OSR_CACHE}';
+exports.OSR_DISCOURSE_CACHE = '${OSR_CACHE}/discourse';
+exports.DISCOURSE_CATEGORY_CACHE = '${OSR_CACHE}/discourse/cats.json';
+exports.DISCOURSE_TOPICS_CACHE = '${OSR_CACHE}/discourse/topics.json';
+exports.DISCOURSE_TAGS_CACHE = '${OSR_CACHE}/discourse/tags.json';
+exports.DISCOURSE_USER_CACHE = '${OSR_CACHE}/discourse/users.json';
+//////////////////////////////////////////////////////////////
+//
+// OA - User Import
+//
+exports.OA_DIRECTORY_OVERVIEW_TOPIC = 28873;
+exports.OA_USER_IMPORT_GROUP = 43;
+exports.KB_USERS = '${KB_ROOT}/static/users';
+exports.DATA_PATH = '${OSR_ROOT}/osr-directory/pp';
+exports.LATEST_TRACK = '${OSR_ROOT}/osr-directory/pp/merged.json';
+exports.LATEST_TEST = './latest_test.json';
+exports.FETCH_DUSERS = false;
+exports.F_USERS_NOW = './fusers.json';
+exports.F_USERS_ALL = './fusers-all.json';
+const DEFAULT_PASSWORD = () => '4g0&KPN$e*Un';
+exports.DEFAULT_PASSWORD = DEFAULT_PASSWORD;
+const HOWTOS_ASSETS_URL = () => `https://kb.osr-plastic.org/howtos/`;
+exports.HOWTOS_ASSETS_URL = HOWTOS_ASSETS_URL;
+const MACHINES_ASSETS_URL = () => `https://assets.osr-plastic.org/machines/`;
+exports.MACHINES_ASSETS_URL = MACHINES_ASSETS_URL;
+exports.CAT_TEST = 65;
+exports.TAGS_TEST = 'plastic, meta';
+exports.DEFAULT_IMPORT_OWNER = 1;
+//////////////////////////////////////////////////////////////
+//
+// OA - Directory Import
+//
+exports.D_ROOT_CAT = 97;
+exports.D_ROOT_AFRICA = 79;
+exports.D_ROOT_ASIA = 60;
+exports.D_ROOT_EUROPE = 59;
+exports.D_ROOT_AUSTRALIA = 76;
+exports.D_ROOT_NAMERICA = 101;
+exports.D_ROOT_SAMERICA = 102;
+exports.D_ROOT_OCEANIA = 103;
+//////////////////////////////////////////////////////////////
+//
+// OA - Howto Import
+//
+exports.HT_CAT_ROOT = 54;
+exports.HT_CAT_GUIDES = 86;
+exports.HT_CAT_MACHINES = 87;
+exports.HT_CAT_PRODUCTS = 88;
+exports.HT_CAT_MOULDS = 89;
+exports.HT_CAT_IDS = {
+ HT_CAT_ROOT: exports.HT_CAT_ROOT,
+ HT_CAT_GUIDES: exports.HT_CAT_GUIDES,
+ HT_CAT_MACHINES: exports.HT_CAT_MACHINES,
+ HT_CAT_PRODUCTS: exports.HT_CAT_PRODUCTS,
+ HT_CAT_MOULDS: exports.HT_CAT_MOULDS
+};
+exports.HT_CATS = {
+ 'Guides': exports.HT_CAT_GUIDES,
+ 'Machines': exports.HT_CAT_MACHINES,
+ 'Products': exports.HT_CAT_PRODUCTS,
+ 'Moulds': exports.HT_CAT_MOULDS
+};
+//////////////////////////////////////////////////////////////
+//
+// OA - Library Import
+//
+exports.MACHINE_CAT_INJECTION = 50;
+exports.MACHINE_CAT_EXTRUSION = 51;
+exports.MACHINE_CAT_SHREDDER = 52;
+exports.MACHINE_CAT_SHEETPRESS = 63;
+exports.MACHINE_CAT_3DPRINT = 70;
+exports.MACHINE_CAT_MOULDS = 71;
+exports.MACHINE_CAT_IDS = {
+ MACHINE_CAT_INJECTION: exports.MACHINE_CAT_INJECTION,
+ MACHINE_CAT_EXTRUSION: exports.MACHINE_CAT_EXTRUSION,
+ MACHINE_CAT_SHREDDER: exports.MACHINE_CAT_SHREDDER,
+ MACHINE_CAT_SHEETPRESS: exports.MACHINE_CAT_SHEETPRESS,
+ MACHINE_CAT_3DPRINT: exports.MACHINE_CAT_3DPRINT,
+ MACHINE_CAT_MOULDS: exports.MACHINE_CAT_MOULDS
+};
+exports.MACHINE_CATS = {
+ 'Injection': exports.MACHINE_CAT_INJECTION,
+ 'Extrusion': exports.MACHINE_CAT_EXTRUSION,
+ 'Sheetpress': exports.MACHINE_CAT_SHEETPRESS,
+ '3DPrint': exports.MACHINE_CAT_3DPRINT,
+ 'Moulds': exports.HT_CAT_MOULDS
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9kaXNjb3Vyc2UvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFDQSw4REFBOEQ7QUFDOUQsRUFBRTtBQUNGLFFBQVE7QUFDUixFQUFFOzs7QUFJRiw4REFBOEQ7QUFDOUQsRUFBRTtBQUNGLFNBQVM7QUFDVCxFQUFFO0FBRVcsUUFBQSxtQkFBbUIsR0FBRyxxQkFBcUIsQ0FBQTtBQUUzQyxRQUFBLGNBQWMsR0FBRyxjQUFjLENBQUE7QUFDL0IsUUFBQSxtQkFBbUIsR0FBRyx3QkFBd0IsQ0FBQTtBQUU5QyxRQUFBLHdCQUF3QixHQUFHLGtDQUFrQyxDQUFBO0FBQzdELFFBQUEsc0JBQXNCLEdBQUcsb0NBQW9DLENBQUE7QUFDN0QsUUFBQSxvQkFBb0IsR0FBRyxrQ0FBa0MsQ0FBQTtBQUN6RCxRQUFBLG9CQUFvQixHQUFHLG1DQUFtQyxDQUFBO0FBRXZFLDhEQUE4RDtBQUM5RCxFQUFFO0FBQ0Ysb0JBQW9CO0FBQ3BCLEVBQUU7QUFFVyxRQUFBLDJCQUEyQixHQUFHLEtBQUssQ0FBQTtBQUNuQyxRQUFBLG9CQUFvQixHQUFHLEVBQUUsQ0FBQTtBQUN6QixRQUFBLFFBQVEsR0FBRyx5QkFBeUIsQ0FBQTtBQUNwQyxRQUFBLFNBQVMsR0FBRyw4QkFBOEIsQ0FBQTtBQUUxQyxRQUFBLFlBQVksR0FBRywwQ0FBMEMsQ0FBQTtBQUN6RCxRQUFBLFdBQVcsR0FBRyxvQkFBb0IsQ0FBQTtBQUNsQyxRQUFBLFlBQVksR0FBRyxLQUFLLENBQUE7QUFDcEIsUUFBQSxXQUFXLEdBQUcsZUFBZSxDQUFBO0FBQzdCLFFBQUEsV0FBVyxHQUFHLG1CQUFtQixDQUFBO0FBRXZDLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxFQUFFLENBQUMsY0FBYyxDQUFBO0FBQXZDLFFBQUEsZ0JBQWdCLG9CQUF1QjtBQUU3QyxNQUFNLGlCQUFpQixHQUFHLEdBQUcsRUFBRSxD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
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/index.d.ts b/packages/discourse/lib/discourse/index.d.ts
new file mode 100644
index 00000000..a67155dd
--- /dev/null
+++ b/packages/discourse/lib/discourse/index.d.ts
@@ -0,0 +1,181 @@
+export declare const logger: any;
+import PromisePool from 'native-promise-pool';
+export declare const escape: (path: string) => string;
+import { TPostStatus, TPostStatusUpdate, UserPreferencesUpdate } from './types';
+import { Category, CategoriesResponse, PostsResponse, PostResponse, TopicResponse, TopicItem, CategoryResponse, PostItem, PostUpdateItem, IDiscourserConfig, Thread, PostModifier, FetchConfig, FetchOptions, ISearchResult, ICreateUserResponse, IUserDetail, TagsResponse, Tag, TopicUpdateBasicTopic } from './types';
+import { IDiscourseUser } from '@plastichub/osr-commons';
+import { EDiscourseConfigKey } from './constants';
+import { IDImage } from '../oa/index';
+/**
+ * Discourser is an API Client for the [Discourse API](https://docs.discourse.org)
+ * It special features are:
+ * - TypeScript Types
+ * - Respecting Rate Limits
+ * - Optional Heavy Caching
+ * - Post Modifiers (can be used for global find and replace across all posts on the forum)
+ */
+export declare class Discourser {
+ readonly host: string;
+ readonly key: string;
+ readonly username: string;
+ readonly cache?: string;
+ readonly useCache?: boolean;
+ readonly dry: boolean;
+ readonly pool: PromisePool;
+ /**
+ * Construct our Discourser instance
+ * See {@link IDiscourserConfig} for available configuration.
+ */
+ constructor(config: IDiscourserConfig);
+ /** Get the URL of a topic */
+ getTopicURL(topic: TopicItem | TopicResponse | number): string;
+ /** Fetch a discourse API URL, with rate limit concurrency and optional caching */
+ fetch({ url, useCache, request }: FetchConfig): Promise;
+ /** Fetch a discourse API URL, with rate limit retries */
+ private _post;
+ /** Fetch a discourse API URL, with rate limit retries */
+ private _fetch;
+ /**
+ * API Helper for {@link .search}
+ * https://docs.discourse.org/#tag/Search/operation/search
+ */
+ search(query: string, params?: string, opts?: FetchOptions): Promise;
+ /**
+ * API Helper for {@link .getTags}
+ */
+ protected getTagsResponse(opts?: FetchOptions): Promise;
+ /**
+ * Fetch the whole information, for all categories of the forum
+ */
+ getTags(opts?: FetchOptions): Promise;
+ createTag(name: any): Promise;
+ /**
+ * API Helper for {@link .getCategories}
+ */
+ protected getCategoriesResponse(opts?: FetchOptions): Promise;
+ /**
+ * Fetch the whole information, for all categories of the forum
+ */
+ getCategories(opts?: FetchOptions): Promise;
+ /**
+ * API Helper for {@link .getTopicItemsOfCategory}
+ * Discourse does not provide an API for fetching category information for a specific category.
+ * Instead, all that it provides is a way of getting the topics for a specific category.
+ */
+ protected getCategoryResponse(categoryID: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all topics of a specific category
+ */
+ getTopicItemsOfCategory(categoryID: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all topics of specific categoires
+ */
+ getTopicItemsOfCategories(categoryIDs: number[], opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all topics of the forum
+ */
+ getTopicItems(opts?: FetchOptions): Promise;
+ /**
+ * Fetch the whole information, for a specific topic of the forum
+ */
+ getTopic(id: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the whole information, for all topics, or specific topics, of the forum
+ */
+ getTopics(topicIDs?: number[] | null, opts?: FetchOptions): Promise;
+ updateTopicVisibility(topicID: number, listed?: boolean, visible?: TPostStatus): Promise;
+ updateTopicTimestamp(topicID: number, timestamp: Date | string | number, token: string): Promise;
+ /**
+ * API Helper for {@link .getPostItemsOfTopic}
+ */
+ protected getPostItemsOfTopicResponse(topicID: number, opts?: FetchOptions): Promise;
+ _createUser(name: any, email: any, pUserGroup: any): Promise;
+ getUsers(page: any): Promise;
+ getUser(id: any): Promise;
+ /**
+ * Fetch the partial information, for all posts of a specific topic
+ */
+ getPostItemsOfTopic(topicID: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of specific topics
+ */
+ getPostItemsOfTopics(topicIDs: number[], opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of a specific category
+ */
+ getPostItemsOfCategory(categoryID: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of specific categories
+ */
+ getPostItemsOfCategories(categoryIDs: number[], opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of the forum
+ */
+ getPostItems(opts?: FetchOptions): Promise;
+ /**
+ * Fetch the whole information, for a specific post of the forum
+ */
+ getPost(id: number, opts?: FetchOptions): Promise;
+ createReply(postId: any, raw: any, category: any): Promise;
+ changeOwner(postId: string | number, topicId: string | number, owner: string): Promise;
+ createUser(data: any): Promise;
+ getUserByUsername(username: any): Promise;
+ setUserAvatar(user_name: any, upload_id: any): Promise;
+ updateUser(user_name: any, args: any): Promise;
+ updateGroup(user_name: any, group: any): Promise>;
+ upload(userId: any, file: any): Promise;
+ uploadFile(userId: any, file: any): Promise;
+ /**
+ * Fetch the whole information, for all posts, or specific posts, of the forum
+ */
+ getPosts(postIDs?: number[] | null, opts?: FetchOptions): Promise;
+ createPost(title: string, raw: string, category: number): Promise;
+ /**
+ * Update a post with the content
+ * @param postID the identifier of the post to update
+ * @param content the new raw content for the post
+ * @param reason the reason, if provided, for modifying the post
+ * @param old if the old raw content is provided, then the update verified that you are working with the latest post content before applying the update
+ */
+ updatePost(postID: number, content: string, reason?: string, old?: string): Promise;
+ /**
+ * Update post meta
+ */
+ updateTopic(postId: number, category_id: number, title: string, tags?: string[]): Promise;
+ rebakePost(postID: number): Promise;
+ /**
+ * Modify a post using a modifier
+ */
+ modifyPost(post: PostResponse, modifier: PostModifier): Promise;
+ /**
+ * Modify a post (via its post identifier) using a modifier
+ */
+ modifyPostID(post: number, modifier: PostModifier): Promise;
+ /**
+ * Modify a post (via fetching the whole post from the partial post identifier) using a modifier
+ */
+ modifyPostItem(post: PostItem, modifier: PostModifier): Promise;
+ /**
+ * Run the post modifier on all specified posts
+ */
+ modifyPosts(posts: PostResponse[], modifier: PostModifier): Promise;
+ /**
+ * Fetch the partial information, for all posts of a specific topic
+ * Alias of {@link .getPostItemsOfTopic}.
+ */
+ getThread(topicID: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of specific topics, grouped by topic
+ */
+ getThreads(topicIDs: number[], opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of specific categories, grouped by topic
+ */
+ getThreadsOfCategory(categoryID: number, opts?: FetchOptions): Promise;
+ /**
+ * Fetch the partial information, for all posts of specific categories, grouped by category, then topic
+ */
+ getThreadsOfCategories(categoryIDs: number[], opts?: FetchOptions): Promise;
+ updateUserProfile(userId: any, prefs: UserPreferencesUpdate): Promise;
+}
+export declare const Instance: (config?: IDiscourseConfig, key?: EDiscourseConfigKey) => Discourser;
diff --git a/packages/discourse/lib/discourse/index.js b/packages/discourse/lib/discourse/index.js
new file mode 100644
index 00000000..335b6d90
--- /dev/null
+++ b/packages/discourse/lib/discourse/index.js
@@ -0,0 +1,936 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Instance = exports.Discourser = exports.escape = exports.logger = void 0;
+const constants_1 = require("../../constants");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const debug_1 = require("@plastichub/core/debug");
+exports.logger = (0, debug_1.logger)(constants_1.MODULE_NAME);
+const write_1 = require("@plastichub/fs/write");
+const write_2 = require("@plastichub/fs/write");
+const exists_1 = require("@plastichub/fs/exists");
+const native_promise_pool_1 = require("native-promise-pool");
+const path_1 = require("path");
+const axios_1 = require("axios");
+const fs = require("fs");
+const path = require("path");
+const FormData = require("form-data");
+const https = require('https');
+const request = require("request");
+const fetch = require('isomorphic-unfetch');
+const escape = (path) => path.replace(/[^\w]/g, '-').replace(/-+/, '-');
+exports.escape = escape;
+const generate_password_1 = require("generate-password");
+/**
+ * Discourser is an API Client for the [Discourse API](https://docs.discourse.org)
+ * It special features are:
+ * - TypeScript Types
+ * - Respecting Rate Limits
+ * - Optional Heavy Caching
+ * - Post Modifiers (can be used for global find and replace across all posts on the forum)
+ */
+class Discourser {
+ /**
+ * Construct our Discourser instance
+ * See {@link IDiscourserConfig} for available configuration.
+ */
+ constructor(config) {
+ this.host = config.host;
+ this.key = config.key;
+ this.username = config.username;
+ this.cache = config.cache;
+ this.useCache = config.useCache;
+ this.dry = config.dry || false;
+ this.pool = new native_promise_pool_1.default(config.rateLimitConcurrency || 60);
+ }
+ /** Get the URL of a topic */
+ getTopicURL(topic) {
+ if (typeof topic === 'number') {
+ return `${this.host}/t/${topic}`;
+ }
+ return `${this.host}/t/${topic.slug}/${topic.id}`;
+ }
+ /** Fetch a discourse API URL, with rate limit concurrency and optional caching */
+ async fetch({ url, useCache, request }) {
+ // check if cache is enabled
+ useCache = false;
+ const cache = this.cache &&
+ ((request === null || request === void 0 ? void 0 : request.method) || 'get') === 'get' &&
+ (0, path_1.join)(this.cache, (0, exports.escape)(url));
+ // check if we should and can read from cache
+ if (cache &&
+ this.useCache !== false &&
+ useCache !== false &&
+ ((0, exists_1.sync)(cache))) {
+ const result = (0, write_2.sync)(cache, 'json');
+ return result;
+ }
+ // fetch
+ const result = await this.pool.open(() => this._fetch({ url, request }));
+ // write to cache if cache is enabled
+ if (cache) {
+ (0, write_1.sync)(cache, result);
+ }
+ // return the result
+ return result;
+ }
+ /** Fetch a discourse API URL, with rate limit retries */
+ async _post(url, data) {
+ var _a;
+ const opts = {
+ headers: {
+ 'Api-Key': this.key,
+ 'Api-Username': this.username,
+ },
+ };
+ let d = data;
+ const res = await axios_1.default.post(url, d, {
+ headers: opts.headers
+ });
+ // fetch text then parse as json, so that when errors occur we can output what it was
+ // rather than being stuck with errors like these:
+ // FetchError: invalid json response body at https://discuss.bevry.me/posts/507.json reason: Unexpected token < in JSON at position 0
+ const text = await res.data;
+ // check if there are errors
+ if (typeof data.errors !== 'undefined') {
+ // check if the error is a rate limit
+ const wait = (_a = data.extras) === null || _a === void 0 ? void 0 : _a.wait_seconds;
+ if (wait != null) {
+ // if it was, try later
+ // return await retry(wait + 1)
+ }
+ // otherwise fail
+ // logger.debug({ data, url, opts })
+ return Promise.reject(new Error(`fetch of [${url}] received failed response:\n${data}`));
+ }
+ return text;
+ }
+ /** Fetch a discourse API URL, with rate limit retries */
+ async _fetch({ url, request }) {
+ var _a;
+ const httpsAgent = new https.Agent({
+ rejectUnauthorized: false,
+ });
+ const opts = {
+ ...request,
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username,
+ ...request === null || request === void 0 ? void 0 : request.headers
+ },
+ rejectUnauthorized: false,
+ agent: httpsAgent
+ };
+ const retry = (seconds) => {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => this._fetch({ url, request })
+ .then(resolve)
+ .catch(reject), (seconds || 60) * 1000);
+ });
+ };
+ try {
+ const res = await fetch(url, opts);
+ // fetch text then parse as json, so that when errors occur we can output what it was
+ // rather than being stuck with errors like these:
+ // FetchError: invalid json response body at https://discuss.bevry.me/posts/507.json reason: Unexpected token < in JSON at position 0
+ const text = await res.text();
+ let data;
+ try {
+ data = JSON.parse(text);
+ }
+ catch (err) {
+ // check if it was cloudflare reporting that the server has been hit too hard
+ if (text.includes('Please try again in a few minutes')) {
+ exports.logger.debug('server has stalled, trying again in a minute');
+ return await retry(60);
+ }
+ // otherwise log the error page and die
+ // logger.debug({ text, url , opts })
+ return Promise.reject(exports.logger.error(text, url, opts, err) &&
+ new Error(`fetch of [${url}] received invalid response:\n${text}`));
+ }
+ // check if there are errors
+ if (typeof data.errors !== 'undefined') {
+ // check if the error is a rate limit
+ const wait = (_a = data.extras) === null || _a === void 0 ? void 0 : _a.wait_seconds;
+ if (wait != null) {
+ // if it was, try later
+ return await retry(wait + 1);
+ }
+ // otherwise fail
+ // logger.debug({ data, url, opts })
+ return Promise.reject(new Error(`fetch of [${url}] received failed response:\n${data}`));
+ }
+ return data;
+ }
+ catch (err) {
+ // logger.debug({ err, url, opts })
+ return Promise.reject(exports.logger.error(`fetch of [${url}] failed with error`, err));
+ }
+ }
+ // =================================
+ // Search
+ /**
+ * API Helper for {@link .search}
+ * https://docs.discourse.org/#tag/Search/operation/search
+ */
+ async search(query, params = '', opts = {}) {
+ let url = `${this.host}/search.json?q=${encodeURIComponent(query)} ${encodeURIComponent(params)}`;
+ return await this.fetch({ url, ...opts });
+ }
+ // =================================
+ // Tags
+ /**
+ * API Helper for {@link .getTags}
+ */
+ async getTagsResponse(opts = {}) {
+ const url = `${this.host}/tags.json`;
+ return await this.fetch({ url, ...opts });
+ }
+ /**
+ * Fetch the whole information, for all categories of the forum
+ */
+ async getTags(opts = {}) {
+ const response = await this.getTagsResponse(opts);
+ const tags = response.tags;
+ return tags;
+ }
+ async createTag(name) {
+ const url = `${this.host}/tag_groups.json`;
+ try {
+ return await this._post(url, {
+ name
+ });
+ }
+ catch (error) {
+ debugger;
+ }
+ }
+ // =================================
+ // CATEGORIES
+ /**
+ * API Helper for {@link .getCategories}
+ */
+ async getCategoriesResponse(opts = {}) {
+ const url = `${this.host}/categories.json` +
+ (opts.include_subcategories ? '?include_subcategories=true' : '');
+ return await this.fetch({ url, ...opts });
+ }
+ /**
+ * Fetch the whole information, for all categories of the forum
+ */
+ async getCategories(opts = {}) {
+ const response = await this.getCategoriesResponse(opts);
+ const categories = response.category_list.categories;
+ return categories;
+ }
+ /**
+ * API Helper for {@link .getTopicItemsOfCategory}
+ * Discourse does not provide an API for fetching category information for a specific category.
+ * Instead, all that it provides is a way of getting the topics for a specific category.
+ */
+ async getCategoryResponse(categoryID, opts = {}) {
+ const url = `${this.host}/c/${categoryID}.json` +
+ (opts.page !== 0 ? `?page=${opts.page}` : '');
+ return await this.fetch({ url, ...opts });
+ }
+ // =================================
+ // TOPICS
+ /**
+ * Fetch the partial information, for all topics of a specific category
+ */
+ async getTopicItemsOfCategory(categoryID, opts = {}) {
+ // prepare and fetch
+ let page = opts.page || 0;
+ const response = await this.getCategoryResponse(categoryID, {
+ ...opts,
+ page,
+ });
+ let topics = response.topic_list.topics;
+ // fetch the next page
+ if (topics.length === response.topic_list.per_page) {
+ page += 1;
+ const more = await this.getTopicItemsOfCategory(categoryID, {
+ ...opts,
+ page,
+ });
+ topics.push(...more);
+ }
+ // if we are the first page, then output count as we now have all of them
+ if (page === 0) {
+ const ids = topics.map((i) => i.id);
+ }
+ topics = topics.filter((t) => t.visible === true);
+ return topics;
+ }
+ /**
+ * Fetch the partial information, for all topics of specific categoires
+ */
+ async getTopicItemsOfCategories(categoryIDs, opts = {}) {
+ // fetch topic items for specific categories
+ try {
+ const topicsOfCategories = await Promise.all(categoryIDs.map((id) => this.getTopicItemsOfCategory(id, opts)));
+ // @ts-ignore
+ return topicsOfCategories.flat();
+ }
+ catch (error) {
+ exports.logger.error(error);
+ }
+ }
+ /**
+ * Fetch the partial information, for all topics of the forum
+ */
+ async getTopicItems(opts = {}) {
+ const categories = await this.getCategories();
+ const categoryIDs = categories.map((i) => i.id);
+ return this.getTopicItemsOfCategories(categoryIDs, opts);
+ }
+ /**
+ * Fetch the whole information, for a specific topic of the forum
+ */
+ getTopic(id, opts = {}) {
+ const url = `${this.host}/t/${id}.json`;
+ return this.fetch({ url, ...opts });
+ }
+ /**
+ * Fetch the whole information, for all topics, or specific topics, of the forum
+ */
+ async getTopics(topicIDs, opts = {}) {
+ // if no topics, use all topics
+ if (!topicIDs) {
+ const topics = await this.getTopicItems(opts);
+ topicIDs = topics.map((i) => i.id);
+ }
+ // fetch whole topics
+ return Promise.all(topicIDs.map((id) => this.getTopic(id, opts)));
+ }
+ async updateTopicVisibility(topicID, listed = true, visible = 'visible') {
+ const url = `${this.host}/t/${topicID}/status`;
+ let ret = await fetch(url, {
+ "headers": {
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ "body": `status=${visible}&enabled=${listed}`,
+ "method": "PUT"
+ });
+ return ret;
+ }
+ async updateTopicTimestamp(topicID, timestamp, token) {
+ let time;
+ if (typeof timestamp === 'number') {
+ time = timestamp;
+ }
+ else if (typeof timestamp === 'number') {
+ time = Number(timestamp);
+ }
+ else if (timestamp instanceof Date) {
+ // ms to seconds
+ time = timestamp.getTime() / 1000;
+ }
+ else {
+ return Promise.reject(new Error('invalid timestamp format'));
+ }
+ const url = `${this.host}/t/${topicID}/change-timestamp`;
+ let ret = await fetch(url, {
+ "headers": {
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7,es;q=0.6,fr;q=0.5",
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ "x-csrf-token": token,
+ "x-requested-with": "XMLHttpRequest",
+ "cookie": "_bypass_cache=true; _ga_MBZGKNMDWC=GS1.1.1685892974.20.1.1685893082.0.0.0; _ga_P4SR15V1XR=GS1.1.1687459978.51.1.1687460537.0.0.0; _ga_H8W78Y3P2B=GS1.1.1687604701.23.0.1687604701.0.0.0; _ga=GA1.1.401826746.1678337758; _t=xQ05qW5JFxLM9Pq0lIwG6ez74Z1q2OLpak0DzRx8VdFYE5eI3oJXhLURPrdm2zIcHmYcBj9q%2BKdHhGz5N6j9mXitYzcMwkXHL3K9GYKdO4gJ8tBQimpmd1HFaRhB9Ml9aJ8WviqQWDZDOYwEUKFcWw3wbAalfQtbdIbUSX8gH9sG6DLFU3HiEg7tWModRy%2BoFrTm6QOalDuajRW3nBazau%2FiY8ZCVm2g30Y10CBDfqJHL1ztV8XM4kEIeulLNTzGVtSb7uuO1OcjZRSb--aDgCPEalq7SIpnH5--HWCNf5readaeij3oDl9b9w%3D%3D; __profilin=p%3Dt%2Ca%3Deef38e031f99cc8240f3518e1b8811cf; _forum_session=RkEWuzKI1QXBYCnP6KRamD8mweZ3h9%2B6G%2Fi23gAWUgy8gp8FuiyQD5lKU0Fbx3FzzaM4SiQcvnIiEAnb5P4OYjlvstqwWlfRp%2B9is7iX8StwYGiYsncHQ5LrzSbV3y9mR7sj%2F8JZ8evQOe2ZZjZB3iEkppsGrmyFrw5PsUgSphRTZm70SKIw96JrW17yK4hhLqtk%2BaQPgNu4oJl42YfXAr%2FCBldcBUKXFeHppYmv61WECV0531hCo7GcA4t06B9QpSr%2BeoiM1Ok9tpQrAlZf36Ka4lVCTyXXu3SNvbtvfd9tZMJCWDYv69jdMsezuOaEP870pk9qYPaL4x6nAY5EXO3u9usCggqQ1B1EydCK9uMy7ZUCIo9wONw7QOIgEQ%3D%3D--GMqYSb2H7xXVDky6--R9gVciBqwC0IL9LefywrFw%3D%3D; _ga_GVR8PEPG6C=GS1.1.1687710574.106.1.1687710599.0.0.0",
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ "body": `timestamp=${time}`,
+ "method": "PUT"
+ });
+ if (ret && ret.status === 200) {
+ return true;
+ }
+ return;
+ /*
+ let data = new FormData();
+ data.append('timestamp', time);
+
+ try {
+ let ret = await axios.put(url, data, {
+ headers: {
+ //'Accept-Language': 'en-US,en;q=0.8',
+ //'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ //'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ debugger
+ } catch (error) {
+ debugger
+ }
+
+
+ return
+ */
+ /*
+ var options = {
+ method: 'PUT',
+ url: url,
+ headers:
+ {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ body: `timestamp=${time}`
+ };
+
+ new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
+ */
+ /*
+ var options = {
+ method: 'POST',
+ url: url,
+ headers:
+ {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ body
+ }
+
+
+ return new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
+*/
+ // prepare the request
+ const request = {
+ timestamp: time,
+ };
+ // send the update
+ exports.logger.debug('updating', topicID, 'topic timestamp with', request);
+ //const url = `${this.host}/t/${topicID}/change-timestamp`
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put',
+ body: `timestamp=${time}`,
+ headers: {
+ 'Api-Key': this.key,
+ 'Api-Username': this.username,
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
+ }
+ }
+ });
+ // check it
+ if (response.success !== 'OK') {
+ return Promise.reject(new Error(`timestamp update of topic ${topicID} failed:\n${{
+ url,
+ request,
+ response,
+ }}`));
+ }
+ return response;
+ }
+ // =================================
+ // POSTS
+ /**
+ * API Helper for {@link .getPostItemsOfTopic}
+ */
+ async getPostItemsOfTopicResponse(topicID, opts = {}) {
+ const url = `${this.host}/t/${topicID}/posts.json`;
+ const response = await this.fetch({ url, ...opts });
+ return response;
+ }
+ async _createUser(name, email, pUserGroup) {
+ const pwd = (0, generate_password_1.generate)({
+ length: 10,
+ numbers: true
+ });
+ let user = await this.createUser({
+ "name": name,
+ "email": email,
+ "password": pwd,
+ "username": name,
+ "active": true,
+ "approved": true,
+ "user_fields[1]": true
+ });
+ if (user && user.user_id) {
+ await this.updateGroup(name, pUserGroup);
+ return { ...user, password: pwd };
+ }
+ else {
+ if (user && user.message && user.message == 'Username must be unique\nPrimary email has already been taken') {
+ return null;
+ }
+ else if (user && user.message && user.message == 'Your account is activated and ready to use.') {
+ if (user.user_id) {
+ return { ...user, password: pwd };
+ }
+ return null;
+ }
+ else {
+ console.log('cant create user ' + name, user);
+ }
+ return null;
+ }
+ }
+ async getUsers(page) {
+ const url = `${this.host}/admin/users/list/active.json?page=` + page;
+ const response = await this.fetch({ url });
+ return response;
+ }
+ async getUser(id) {
+ const url = `${this.host}/admin/users/${id}.json`;
+ const response = await this.fetch({ url });
+ return response;
+ }
+ /**
+ * Fetch the partial information, for all posts of a specific topic
+ */
+ async getPostItemsOfTopic(topicID, opts = {}) {
+ const response = await this.getPostItemsOfTopicResponse(topicID, opts);
+ const posts = response.post_stream.posts;
+ const ids = posts.map((i) => i.id);
+ return posts;
+ }
+ /**
+ * Fetch the partial information, for all posts of specific topics
+ */
+ async getPostItemsOfTopics(topicIDs, opts = {}) {
+ // fetch post items for specific topics
+ const postItemsOfTopics = await Promise.all(topicIDs.map((id) => this.getPostItemsOfTopic(id, opts)));
+ // @ts-ignore
+ return postItemsOfTopics.flat();
+ }
+ /**
+ * Fetch the partial information, for all posts of a specific category
+ */
+ async getPostItemsOfCategory(categoryID, opts = {}) {
+ // fetch topics for the category
+ const topics = await this.getTopicItemsOfCategory(categoryID, opts);
+ const topicIDs = topics.map((i) => i.id);
+ // fetch
+ const posts = await this.getPostItemsOfTopics(topicIDs);
+ const ids = posts.map((i) => i.id);
+ return posts;
+ }
+ /**
+ * Fetch the partial information, for all posts of specific categories
+ */
+ async getPostItemsOfCategories(categoryIDs, opts = {}) {
+ // fetch post items for specific categories
+ const postItemsOfCategories = await Promise.all(categoryIDs.map((id) => this.getPostItemsOfCategory(id, opts)));
+ // @ts-ignore
+ return postItemsOfCategories.flat();
+ }
+ /**
+ * Fetch the partial information, for all posts of the forum
+ */
+ async getPostItems(opts = {}) {
+ const categories = await this.getCategories();
+ const categoryIDs = categories.map((i) => i.id);
+ return this.getPostItemsOfCategories(categoryIDs, opts);
+ }
+ /**
+ * Fetch the whole information, for a specific post of the forum
+ */
+ getPost(id, opts = {}) {
+ const url = `${this.host}/posts/${id}.json`;
+ return this.fetch({ url, ...opts });
+ }
+ async createReply(postId, raw, category) {
+ const url = `${this.host}/posts.json`;
+ let data = new FormData();
+ data.append('topic_id', '' + postId);
+ data.append('raw', raw);
+ data.append('nested_post', 'true');
+ data.append('category', category);
+ var options = {
+ method: 'POST',
+ url: url,
+ headers: {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ "body": `raw=${raw}&unlist_topic=false&category=${category}&topic_id=${postId}&is_warning=false&archetype=regular&featured_link=&shared_draft=false&nested_post=true`,
+ };
+ return new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ }
+ else {
+ resolve(body);
+ }
+ });
+ });
+ }
+ async changeOwner(postId, topicId, owner) {
+ const url = `${this.host}/t/${topicId}/change-owner.json`;
+ var options = {
+ method: 'POST',
+ url: url,
+ headers: {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ body: `post_ids%5B%5D=${postId}&username=${owner}`
+ };
+ return new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ }
+ else {
+ resolve(body);
+ }
+ });
+ });
+ }
+ async createUser(data) {
+ const url = `${this.host}/users`;
+ return await this._post(url, data);
+ }
+ async getUserByUsername(username) {
+ const url = `${this.host}/u/${username}.json`;
+ const response = await this.fetch({ url });
+ return response.user;
+ }
+ async setUserAvatar(user_name, upload_id) {
+ // fetch whole posts
+ const url = `${this.host}/u/${user_name}/preferences/avatar/pick.json`;
+ return await axios_1.default.put(url, {
+ upload_id,
+ username: user_name,
+ type: 'uploaded'
+ }, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+ async updateUser(user_name, args) {
+ const url = `${this.host}/u/${user_name}.json`;
+ return await axios_1.default.put(url, {
+ ...args
+ }, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+ async updateGroup(user_name, group) {
+ // fetch whole posts
+ const url = `${this.host}/groups/${group}/members.json`;
+ const t = axios_1.default.put(url, {
+ usernames: user_name,
+ notify_users: false
+ }, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ t.then((d) => {
+ }).catch((e) => {
+ //debugger;
+ });
+ return t;
+ }
+ async upload(userId, file) {
+ // fetch whole posts
+ const url = `${this.host}/uploads.json`;
+ let data = new FormData();
+ const fsData = path.parse(file);
+ data.append('file', file, fsData.base);
+ data.append('user_id', userId);
+ data.append('upload_type', 'avatar');
+ data.append('file', fs.createReadStream(file));
+ return await axios_1.default.post(url, data, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+ async uploadFile(userId, file) {
+ // fetch whole posts
+ const url = `${this.host}/uploads.json`;
+ let data = new FormData();
+ const fsData = path.parse(file);
+ data.append('file', file, fsData.base);
+ data.append('user_id', userId);
+ data.append('upload_type', 'composer');
+ data.append('file', fs.createReadStream(file));
+ return await axios_1.default.post(url, data, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+ // =================================
+ // POSTS: UPDATING
+ /**
+ * Fetch the whole information, for all posts, or specific posts, of the forum
+ */
+ async getPosts(postIDs, opts = {}) {
+ // if no posts, use all
+ if (!postIDs) {
+ const posts = await this.getPostItems(opts);
+ postIDs = posts.map((i) => i.id);
+ }
+ // fetch whole posts
+ return await Promise.all(postIDs.map((id) => this.getPost(id, opts)));
+ }
+ async createPost(title, raw, category) {
+ // fetch whole posts
+ const url = `${this.host}/posts`;
+ return new Promise((resolve) => {
+ return this._post(url, { raw, title, category }).then((d) => {
+ resolve(d);
+ }).catch((e) => {
+ resolve(e.response.data);
+ });
+ });
+ }
+ /**
+ * Update a post with the content
+ * @param postID the identifier of the post to update
+ * @param content the new raw content for the post
+ * @param reason the reason, if provided, for modifying the post
+ * @param old if the old raw content is provided, then the update verified that you are working with the latest post content before applying the update
+ */
+ async updatePost(postID, content, reason = 'api update', old) {
+ // prepare the request
+ const data = {
+ post: {
+ raw: content,
+ edit_reason: reason,
+ },
+ };
+ if (old) {
+ data.post.raw_old = old;
+ }
+ // send the update
+ const url = `${this.host}/posts/${postID}.json`;
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put',
+ body: JSON.stringify(data),
+ },
+ });
+ // return the response
+ return response.post;
+ }
+ /**
+ * Update post meta
+ */
+ async updateTopic(postId, category_id, title, tags) {
+ const data = {
+ title,
+ tags: tags || [],
+ featuredLink: null,
+ category_id
+ };
+ const url = `${this.host}/t/${postId}.json`;
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put',
+ body: JSON.stringify(data),
+ },
+ });
+ return response.basic_topic;
+ }
+ async rebakePost(postID) {
+ const url = `${this.host}/posts/${postID}/rebake`;
+ exports.logger.debug('rebaking', postID);
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put'
+ }
+ });
+ exports.logger.debug('rebaked', postID);
+ return response;
+ }
+ /**
+ * Modify a post using a modifier
+ */
+ async modifyPost(post, modifier) {
+ // check if we received a post item, instead of a post response
+ if (post.raw == null) {
+ post = await this.getPost(post.id);
+ }
+ // check
+ if (!post.raw) {
+ return Promise.resolve(null);
+ }
+ // replace
+ const { result, reason } = modifier(post);
+ if (result === post.raw) {
+ // if (post.cooked) {
+ // const { result, reason } = modifier(post.cooked)
+ // if (result !== post.cooked) {
+ // logger.debug(
+ // 'replace did have an effect on cooked post',
+ // postID,
+ // 'so rebaking it'
+ // )
+ // return await this.rebakePost(postID)
+ // }
+ // }
+ return Promise.resolve(null);
+ }
+ // dry
+ if (this.dry) {
+ return Promise.resolve({
+ ...post,
+ result,
+ reason,
+ });
+ }
+ // update
+ try {
+ return await this.updatePost(post.id, result, reason, post.raw);
+ }
+ catch (err) {
+ if (err.message.includes('That post was edited by another user and your changes can no longer be saved.')) {
+ return this.modifyPost(await this.getPost(post.id, { useCache: false }), modifier);
+ }
+ exports.logger.error(err);
+ return Promise.reject(`modifying post ${post.id} failed`);
+ }
+ }
+ /**
+ * Modify a post (via its post identifier) using a modifier
+ */
+ async modifyPostID(post, modifier) {
+ return this.modifyPost(await this.getPost(post), modifier);
+ }
+ /**
+ * Modify a post (via fetching the whole post from the partial post identifier) using a modifier
+ */
+ async modifyPostItem(post, modifier) {
+ return this.modifyPost(await this.getPost(post.id), modifier);
+ }
+ /**
+ * Run the post modifier on all specified posts
+ */
+ async modifyPosts(posts, modifier) {
+ const updates = await Promise.all(posts.map((post) => this.modifyPost(post, modifier)));
+ const updated = updates.filter((i) => i);
+ return updated;
+ }
+ // =================================
+ // THREADS
+ /**
+ * Fetch the partial information, for all posts of a specific topic
+ * Alias of {@link .getPostItemsOfTopic}.
+ */
+ async getThread(topicID, opts = {}) {
+ const topic = await this.getTopic(topicID, opts);
+ const [post, ...replies] = await this.getPostItemsOfTopic(topicID, opts);
+ return {
+ topic,
+ post,
+ replies,
+ };
+ }
+ /**
+ * Fetch the partial information, for all posts of specific topics, grouped by topic
+ */
+ async getThreads(topicIDs, opts = {}) {
+ return await Promise.all(topicIDs.map((id) => this.getThread(id, opts)));
+ }
+ /**
+ * Fetch the partial information, for all posts of specific categories, grouped by topic
+ */
+ async getThreadsOfCategory(categoryID, opts = {}) {
+ // fetch topics for the category
+ const topics = await this.getTopicItemsOfCategory(categoryID, opts);
+ const topicIDs = topics.map((i) => i.id);
+ // return threads
+ return await this.getThreads(topicIDs);
+ }
+ /**
+ * Fetch the partial information, for all posts of specific categories, grouped by category, then topic
+ */
+ async getThreadsOfCategories(categoryIDs, opts = {}) {
+ return await Promise.all(categoryIDs.map((id) => this.getThreadsOfCategory(id, opts)));
+ }
+ async updateUserProfile(userId, prefs) {
+ const url = `${this.host}/u/${userId}.json`;
+ let data = new FormData();
+ data.append('bio_raw', prefs.bio_raw);
+ prefs.location && data.append('location', prefs.location);
+ prefs.website && data.append('website', prefs.website);
+ return await axios_1.default.put(url, data, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+}
+exports.Discourser = Discourser;
+const Instance = (config, key = 'discourse_admin') => {
+ return new Discourser(config || (0, osr_cli_commons_1.CONFIG_DEFAULT)()[key]);
+ /*
+
+ d.getTopicItemsOfCategories([cat]).then(posts => {
+ //console.log('posts', posts)
+ let content = ""
+ posts = posts.map((p) => {
+ const url = `${config.discourse.host}/t/${p.id}`;
+ const title = `${p.fancy_title}`;
+ return `${title} `;
+ }).join('\n');
+ content += posts + " ";
+ resolve(content);
+
+ });
+ */
+};
+exports.Instance = Instance;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2Rpc2NvdXJzZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwrQ0FBNkM7QUFFN0MsaUVBQTREO0FBSTVELGtEQUEwRDtBQUU3QyxRQUFBLE1BQU0sR0FBUSxJQUFBLGNBQU8sRUFBQyx1QkFBVyxDQUFDLENBQUE7QUFFL0MsZ0RBQW9EO0FBQ3BELGdEQUFtRDtBQUNuRCxrREFBc0Q7QUFFdEQsNkRBQTZDO0FBRzdDLCtCQUEyQjtBQUMzQixpQ0FBeUI7QUFDekIseUJBQXdCO0FBQ3hCLDZCQUE0QjtBQUM1QixzQ0FBcUM7QUFFckMsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBQzlCLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUNsQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtBQUVwQyxNQUFNLE1BQU0sR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFLENBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUE7QUFEbEMsUUFBQSxNQUFNLFVBQzRCO0FBRS9DLHlEQUE0QztBQXNDNUM7Ozs7Ozs7R0FPRztBQUNILE1BQWEsVUFBVTtJQVN0Qjs7O09BR0c7SUFDSCxZQUFZLE1BQXlCO1FBQ3BDLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQTtRQUN2QixJQUFJLENBQUMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUE7UUFDckIsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFBO1FBQy9CLElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQTtRQUN6QixJQUFJLENBQUMsUUFBUSxHQUFH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
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/index.js.map b/packages/discourse/lib/discourse/index.js.map
new file mode 100644
index 00000000..2cd25095
--- /dev/null
+++ b/packages/discourse/lib/discourse/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lib/discourse/index.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/types.d.ts b/packages/discourse/lib/discourse/types.d.ts
new file mode 100644
index 00000000..717972e6
--- /dev/null
+++ b/packages/discourse/lib/discourse/types.d.ts
@@ -0,0 +1,697 @@
+export interface Failure {
+ success: 'OK';
+}
+export interface Success {
+ failed: 'FAILED';
+}
+export type Response = Failure & Success;
+export interface Action {
+ can_act: boolean;
+ id: number;
+ count?: number;
+ hidden?: boolean;
+}
+export interface Poster {
+ description: string;
+ extras: string;
+ user_id: number;
+}
+export interface Person {
+ avatar_template: string;
+ id: number;
+ username: string;
+}
+export interface Participant extends Person {
+ post_count: number;
+}
+export interface Link {
+ url: string;
+ internal: boolean;
+ reflection: boolean;
+ title: string;
+ clicks: number;
+}
+/**
+ * Update a Topic Timestamp
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1change-timestamp/put
+ */
+export interface TopicUpdateTimestampRequest {
+ timestamp: number;
+}
+export type TopicUpdateTimestampResponse = Response;
+/**
+ * Update a Post
+ * https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
+ */
+export interface PostUpdateResponse {
+ post: PostUpdateItem;
+}
+export interface TopicUpdateBasicTopic {
+ fancy_title: string;
+ id: number;
+ posts_count: number;
+ slug: string;
+ title: string;
+}
+export interface TopicUpdateResponse {
+ basic_topic: TopicUpdateBasicTopic;
+}
+export interface PostUpdateItem {
+ actions_summary: Array;
+ admin: boolean;
+ avatar_template: string;
+ avg_time: object;
+ can_delete: boolean;
+ can_edit: boolean;
+ can_recover: boolean;
+ can_view_edit_history: boolean;
+ can_wiki: boolean;
+ cooked: string;
+ created_at: string;
+ deleted_at: object;
+ display_username: string;
+ draft_sequence: number;
+ edit_reason: object;
+ hidden_reason_id: object;
+ hidden: boolean;
+ id: number;
+ incoming_link_count: number;
+ moderator: boolean;
+ name: string;
+ post_number: number;
+ post_type: number;
+ primary_group_flair_bg_color: object;
+ primary_group_flair_color: object;
+ primary_group_flair_url: object;
+ primary_group_name: object;
+ quote_count: number;
+ reads: number;
+ reply_count: number;
+ reply_to_post_number: object;
+ score: number;
+ staff: boolean;
+ topic_id: number;
+ topic_slug: string;
+ trust_level: number;
+ updated_at: string;
+ user_deleted: boolean;
+ user_id: number;
+ user_title: object;
+ username: string;
+ version: number;
+ wiki: boolean;
+ yours: boolean;
+}
+export interface PostUpdateRequest {
+ post: {
+ raw: string;
+ raw_old?: string;
+ edit_reason?: string;
+ cooked?: string;
+ };
+}
+export interface TagsResponse {
+ tags: Tag[];
+ extras: TagsExtras;
+}
+export interface TagsExtras {
+ categories: any[];
+}
+export interface Tag {
+ count: number;
+ description: null;
+ id: string;
+ name: string;
+ pm_only: boolean;
+ target_tag: null;
+ text: string;
+}
+/** https://docs.discourse.org/#tag/Categories/paths/~1categories.json/get */
+export interface CategoriesResponse {
+ category_list: {
+ can_create_category: boolean;
+ can_create_topic: boolean;
+ categories: Category[];
+ draft_key: string;
+ draft_sequence: number;
+ draft: boolean;
+ };
+}
+export interface Category {
+ background_url: string;
+ can_edit: boolean;
+ color: string;
+ description_excerpt: string;
+ description_text: string;
+ description: string;
+ has_children: boolean;
+ id: number;
+ logo_url: string;
+ name: string;
+ notification_level: string;
+ permission: number;
+ position: number;
+ post_count: number;
+ read_restricted: boolean;
+ slug: string;
+ text_color: string;
+ topic_count: number;
+ topic_template: string;
+ topic_url: string;
+ topics_all_time: number;
+ topics_day: number;
+ topics_month: number;
+ topics_week: number;
+ topics_year: number;
+}
+/**
+ * Get Single Topic
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}.json/get
+ */
+export interface TopicResponse {
+ actions_summary: Array;
+ archetype: string;
+ archived: boolean;
+ bookmarked: object;
+ category_id: number;
+ chunk_size: number;
+ closed: boolean;
+ created_at: string;
+ deleted_at: object;
+ deleted_by: object;
+ details: TopicDetails;
+ draft_key: string;
+ draft_sequence: object;
+ draft: object;
+ fancy_title: string;
+ has_summary: boolean;
+ highest_post_number: number;
+ id: number;
+ last_posted_at: object;
+ like_count: number;
+ participant_count: number;
+ pinned_at: string;
+ pinned_globally: boolean;
+ pinned_until: object;
+ pinned: boolean;
+ posts_count: number;
+ reply_count: number;
+ slug: string;
+ tags: string[];
+ title: string;
+ unpinned: object;
+ user_id: number;
+ views: number;
+ visible: boolean;
+ word_count: object;
+ post_stream: {
+ posts: Array;
+ stream: Array;
+ };
+ timeline_lookup: [
+ {
+ '0': Array;
+ }
+ ];
+}
+export interface TopicDetails {
+ auto_close_at: object;
+ auto_close_based_on_last_post: boolean;
+ auto_close_hours: object;
+ can_flag_topic: boolean;
+ created_by: Person;
+ last_poster: Person;
+ notification_level: number;
+ participants: Array;
+ suggested_topics: Array;
+}
+export interface TopicItem {
+ archetype: string;
+ archived: boolean;
+ bookmarked: object;
+ bumped_at: string;
+ bumped: boolean;
+ category_id: number;
+ closed: boolean;
+ created_at: string;
+ excerpt: string;
+ fancy_title: string;
+ has_summary: boolean;
+ highest_post_number: number;
+ id: number;
+ image_url: string;
+ last_posted_at: string;
+ last_poster_username: string;
+ like_count: number;
+ liked: object;
+ pinned_globally: boolean;
+ pinned: boolean;
+ posters: Array;
+ posts_count: number;
+ reply_count: number;
+ slug: string;
+ title: string;
+ unpinned: boolean;
+ unseen: boolean;
+ views: number;
+ visible: boolean;
+}
+/**
+ * Get Topics for Category
+ * https://docs.discourse.org/#tag/Categories/paths/~1c~1{id}.json/get
+ */
+export interface CategoryResponse {
+ users: Person[];
+ topic_list: {
+ can_create_topic: boolean;
+ draft: boolean;
+ draft_key: string;
+ draft_sequence: number;
+ per_page: number;
+ topics: Array;
+ };
+}
+/**
+ * Whole Post Information
+ * As returned by getting a single Post
+ * https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/get
+ */
+export interface PostResponse {
+ actions_summary: Array;
+ admin: boolean;
+ avatar_template: string;
+ avg_time: object;
+ can_delete: boolean;
+ can_edit: boolean;
+ can_recover: boolean;
+ can_view_edit_history: boolean;
+ can_wiki: boolean;
+ cooked: string;
+ created_at: string;
+ deleted_at: object;
+ display_username: string;
+ edit_reason: object;
+ hidden_reason_id: object;
+ hidden: boolean;
+ id: number;
+ incoming_link_count: number;
+ moderator: boolean;
+ name: string;
+ post_number: number;
+ post_type: number;
+ primary_group_flair_bg_color: object;
+ primary_group_flair_color: object;
+ primary_group_flair_url: object;
+ primary_group_name: object;
+ quote_count: number;
+ raw: string;
+ reads: number;
+ reply_count: number;
+ reply_to_post_number: object;
+ score: number;
+ staff: boolean;
+ topic_id: number;
+ topic_slug: string;
+ trust_level: number;
+ updated_at: string;
+ user_deleted: boolean;
+ user_id: number;
+ user_title: object;
+ username: string;
+ version: number;
+ wiki: boolean;
+ yours: boolean;
+}
+export interface ICreateUserResponse {
+ success: boolean;
+ active: boolean;
+ message: string;
+ user_id: number;
+ password: string;
+}
+/**
+ * Get the Posts of a Topic
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1posts.json/get
+ */
+export interface PostsResponse {
+ post_stream: {
+ posts: Array;
+ };
+ id: number;
+}
+/**
+ * Partial Post Information
+ * As returned by a listing
+ */
+export interface PostItem {
+ accepted_answer: boolean;
+ actions_summary: Array;
+ admin: boolean;
+ avatar_template: string;
+ can_accept_answer: boolean;
+ can_delete: boolean;
+ can_edit: boolean;
+ can_recover: boolean;
+ can_unaccept_answer: boolean;
+ can_view_edit_history: boolean;
+ can_wiki: boolean;
+ cooked: string;
+ created_at: string;
+ deleted_at: null;
+ display_username: string;
+ edit_reason: null;
+ hidden: boolean;
+ id: number;
+ incoming_link_count: number;
+ link_counts: Array ;
+ moderator: boolean;
+ name: string;
+ post_number: number;
+ post_type: number;
+ primary_group_flair_bg_color: null | object;
+ primary_group_flair_color: null | object;
+ primary_group_flair_url: null | object;
+ primary_group_name: null | object;
+ quote_count: number;
+ read: boolean;
+ readers_count: number;
+ reads: number;
+ reply_count: number;
+ reply_to_post_number: null | number;
+ reviewable_id: number;
+ reviewable_score_count: number;
+ reviewable_score_pending_count: number;
+ score: number;
+ staff: boolean;
+ topic_id: number;
+ topic_slug: string;
+ trust_level: number;
+ updated_at: string;
+ user_deleted: boolean;
+ user_id: number;
+ user_title: null | object;
+ username: string;
+ version: number;
+ wiki: boolean;
+ yours: boolean;
+}
+export type Thread = {
+ topic: TopicResponse;
+ post: PostItem;
+ replies: PostItem[];
+};
+/** When finding and replacing, determine replacements using a method that matches this */
+export type PostModifier = (post: PostResponse) => {
+ result: string;
+ reason?: string;
+};
+/** Configuration for Discourser */
+export interface IDiscourserConfig {
+ /** the discourse hostname to connect to, including protocol */
+ host: string;
+ /** the API key to connect with */
+ key: string;
+ /** the username to behave as */
+ username: string;
+ /** the cache directory to use, if we are caching */
+ cache?: string;
+ /** Whether or not we should read from the cache */
+ useCache?: boolean;
+ /** whether or not updates should be dry (non-applying) */
+ dry?: boolean;
+ /** how many concurrency requests to send to the server at once */
+ rateLimitConcurrency?: number;
+}
+export interface FetchOptions {
+ /** Whether or not we should read from the cache */
+ useCache?: boolean;
+ /** Only applicable to fetching topics of category */
+ page?: number;
+ /** Any thing to init the fetch call with? */
+ request?: RequestInit;
+ include_subcategories?: boolean;
+}
+export interface FetchConfig extends FetchOptions {
+ url: string;
+}
+export interface PostConfig extends FetchOptions {
+ url: string;
+ data: any;
+}
+export interface ISearchPost {
+ id: number;
+ name: string;
+ username: string;
+ avatar_template: string;
+ created_at: Date;
+ like_count: number;
+ blurb: string;
+ post_number: number;
+ topic_id: number;
+}
+export interface ISearchTagsDescriptions {
+}
+export interface ISearchTopic {
+ id: number;
+ title: string;
+ fancy_title: string;
+ slug: string;
+ posts_count: number;
+ reply_count: number;
+ highest_post_number: number;
+ created_at: Date;
+ last_posted_at: Date;
+ bumped: boolean;
+ bumped_at: Date;
+ archetype: string;
+ unseen: boolean;
+ pinned: boolean;
+ unpinned?: any;
+ excerpt: string;
+ visible: boolean;
+ closed: boolean;
+ archived: boolean;
+ bookmarked?: any;
+ liked?: any;
+ tags: any[];
+ tags_descriptions: ISearchTagsDescriptions;
+ category_id: number;
+ has_accepted_answer: boolean;
+}
+export interface IGroupedSearchResult {
+ more_posts?: any;
+ more_users?: any;
+ more_categories?: any;
+ term: string;
+ search_log_id: number;
+ more_full_page_results?: any;
+ can_create_topic: boolean;
+ error?: any;
+ post_ids: number[];
+ user_ids: any[];
+ category_ids: any[];
+ tag_ids: any[];
+ group_ids: any[];
+}
+export interface ISearchResult {
+ posts: ISearchPost[];
+ topics: ISearchTopic[];
+ users: any[];
+ categories: any[];
+ tags: any[];
+ groups: any[];
+ grouped_search_result: IGroupedSearchResult;
+}
+export interface IUserDetail {
+ id: number;
+ username: string;
+ name: string;
+ avatar_template: string;
+ email: string;
+ secondary_emails: any[];
+ active: boolean;
+ admin: boolean;
+ moderator: boolean;
+ last_seen_at: string;
+ last_emailed_at: string;
+ created_at: string;
+ last_seen_age: number;
+ last_emailed_age: number;
+ created_at_age: number;
+ trust_level: number;
+ manual_locked_trust_level: any;
+ flag_level: number;
+ title: string;
+ time_read: number;
+ staged: boolean;
+ days_visited: number;
+ posts_read_count: number;
+ topics_entered: number;
+ post_count: number;
+ associated_accounts: AssociatedAccount[];
+ can_send_activation_email: boolean;
+ can_activate: boolean;
+ can_deactivate: boolean;
+ ip_address: string;
+ registration_ip_address: string;
+ can_grant_admin: boolean;
+ can_revoke_admin: boolean;
+ can_grant_moderation: boolean;
+ can_revoke_moderation: boolean;
+ can_impersonate: boolean;
+ like_count: number;
+ like_given_count: number;
+ topic_count: number;
+ post_edits_count: number;
+ flags_given_count: number;
+ flags_received_count: number;
+ private_topics_count: number;
+ can_delete_all_posts: boolean;
+ can_be_deleted: boolean;
+ can_be_anonymized: boolean;
+ can_be_merged: boolean;
+ full_suspend_reason: any;
+ silence_reason: any;
+ penalty_counts: PenaltyCounts;
+ next_penalty: string;
+ primary_group_id: any;
+ badge_count: number;
+ warnings_received_count: number;
+ user_fields: UserFields;
+ bounce_score: number;
+ reset_bounce_score_after: any;
+ can_view_action_logs: boolean;
+ can_disable_second_factor: boolean;
+ can_delete_sso_record: boolean;
+ api_key_count: number;
+ external_ids: ExternalIds;
+ single_sign_on_record: any;
+ approved_by: ApprovedBy;
+ suspended_by: any;
+ silenced_by: any;
+ tl3_requirements: Tl3Requirements;
+ groups: Group[];
+}
+export interface AssociatedAccount {
+ name: string;
+ description: string;
+}
+export interface PenaltyCounts {
+ silenced: number;
+ suspended: number;
+}
+export interface UserFields {
+ "1": string;
+ "2": string;
+ "3": string;
+ "4": string;
+ "5": string;
+}
+export interface ExternalIds {
+ google_oauth2: string;
+}
+export interface ApprovedBy {
+ id: number;
+ username: string;
+ name: string;
+ avatar_template: string;
+}
+export interface Tl3Requirements {
+ time_period: number;
+ requirements_met: boolean;
+ requirements_lost: boolean;
+ trust_level_locked: boolean;
+ on_grace_period: boolean;
+ days_visited: number;
+ min_days_visited: number;
+ num_topics_replied_to: number;
+ min_topics_replied_to: number;
+ topics_viewed: number;
+ min_topics_viewed: number;
+ posts_read: number;
+ min_posts_read: number;
+ topics_viewed_all_time: number;
+ min_topics_viewed_all_time: number;
+ posts_read_all_time: number;
+ min_posts_read_all_time: number;
+ num_flagged_posts: number;
+ max_flagged_posts: number;
+ num_flagged_by_users: number;
+ max_flagged_by_users: number;
+ num_likes_given: number;
+ min_likes_given: number;
+ num_likes_received: number;
+ min_likes_received: number;
+ num_likes_received_days: number;
+ min_likes_received_days: number;
+ num_likes_received_users: number;
+ min_likes_received_users: number;
+ penalty_counts: PenaltyCounts2;
+}
+export interface PenaltyCounts2 {
+ silenced: number;
+ suspended: number;
+ total: number;
+}
+export interface Group {
+ id: number;
+ automatic: boolean;
+ name: string;
+ display_name?: string;
+ user_count: number;
+ mentionable_level: number;
+ messageable_level: number;
+ visibility_level: number;
+ primary_group: boolean;
+ title: any;
+ grant_trust_level?: number;
+ incoming_email: any;
+ has_messages: boolean;
+ flair_url: any;
+ flair_bg_color?: string;
+ flair_color?: string;
+ bio_raw?: string;
+ bio_cooked?: string;
+ bio_excerpt?: string;
+ public_admission: boolean;
+ public_exit: boolean;
+ allow_membership_requests: boolean;
+ full_name?: string;
+ default_notification_level: number;
+ membership_request_template: any;
+ members_visibility_level: number;
+ can_see_members: boolean;
+ can_admin_group: boolean;
+ publish_read_state: boolean;
+ can_edit_group?: boolean;
+}
+export type TPostStatus = 'visible' | 'archived' | 'pinned' | 'closed';
+export interface TPostStatusUpdate {
+ success: string;
+ topic_status_update: any;
+}
+export interface UserPreferencesUpdate {
+ bio_raw?: string;
+ website?: string;
+ location?: string;
+ custom_fields?: CustomFields;
+ timezone?: string;
+ default_calendar?: string;
+ profile_background_upload_url?: string;
+ card_background_upload_url?: string;
+}
+export interface CustomFields {
+ geo_location: GeoLocation;
+}
+export interface GeoLocation {
+ lat: string;
+ lon: string;
+ address: string;
+ countrycode: string;
+ city: string;
+ state: string;
+ country: string;
+ postalcode: string;
+ boundingbox: string[];
+ type: string;
+}
diff --git a/packages/discourse/lib/discourse/types.js b/packages/discourse/lib/discourse/types.js
new file mode 100644
index 00000000..a2a22c10
--- /dev/null
+++ b/packages/discourse/lib/discourse/types.js
@@ -0,0 +1,5 @@
+"use strict";
+// Attempt at TypeScript Types for the Discourse API
+// https://docs.discourse.org
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2Rpc2NvdXJzZS90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsb0RBQW9EO0FBQ3BELDZCQUE2QiJ9
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/types.js.map b/packages/discourse/lib/discourse/types.js.map
new file mode 100644
index 00000000..b4e4ac86
--- /dev/null
+++ b/packages/discourse/lib/discourse/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/lib/discourse/types.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,6BAA6B"}
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/types/bevry.d.ts b/packages/discourse/lib/discourse/types/bevry.d.ts
new file mode 100644
index 00000000..2b0953b9
--- /dev/null
+++ b/packages/discourse/lib/discourse/types/bevry.d.ts
@@ -0,0 +1,130 @@
+import { YoutubeVideoData } from '../youtube';
+import { PostItem, TopicResponse } from './discourse';
+export interface DatabaseJSON {
+ users: {
+ [id: string]: User;
+ };
+ videos: {
+ [id: string]: VideoJSON;
+ };
+ series: {
+ [id: string]: SeriesJSON;
+ };
+ youtube: {
+ [id: string]: YoutubeVideoData;
+ };
+ transcripts: {
+ [videoID: string]: string;
+ };
+}
+export interface Database {
+ users: {
+ [id: string]: User;
+ };
+ videos: {
+ [id: string]: Video;
+ };
+ series: {
+ [id: string]: Series;
+ };
+ youtube: {
+ [id: string]: YoutubeVideoData;
+ };
+ transcripts: {
+ [videoID: string]: string;
+ };
+}
+export interface YoutubeBase {
+ youtubeID: string;
+ youtubeURL: string;
+ /** for videos, this is the video topic, for series, this is the tag, for meetings, this is null for now */
+ forumURL?: string | null;
+ studyURL?: string | null;
+ /** utc iso string */
+ datetime: string;
+ name: string;
+}
+export interface YoutubeJSON extends YoutubeBase {
+ author: string;
+}
+export interface Youtube extends YoutubeBase {
+ author: User;
+ toJSON: () => YoutubeJSON;
+}
+export interface NoteBase {
+ forumURL: string;
+ content: string;
+}
+export interface NoteJSON extends NoteBase {
+ video: string;
+ author: string;
+}
+export interface Note extends NoteBase {
+ video: Video;
+ author: User;
+ toJSON: () => NoteJSON;
+}
+export interface CommentJSON extends NoteJSON {
+ seconds: number;
+}
+export interface Comment extends Note {
+ seconds: number;
+ toJSON: () => CommentJSON;
+}
+export interface DiscussionBase {
+ forumURL: string;
+ name: string;
+ datetime: string;
+}
+export interface DiscussionJSON extends DiscussionBase {
+ video?: string | null;
+}
+export interface Discussion extends DiscussionBase {
+ video?: Video | null;
+ toJSON: () => DiscussionJSON;
+}
+export interface VideoBase {
+ notes: Note[];
+ discussions: Discussion[];
+ comments: Comment[];
+ thread: Thread;
+}
+export interface VideoJSON extends VideoBase, YoutubeJSON {
+ series?: string | null;
+ youtube: string;
+}
+export interface Video extends VideoBase, Youtube {
+ series?: Series | null;
+ youtube: YoutubeVideoData;
+ toJSON: () => VideoJSON;
+}
+export interface SeriesRaw {
+ youtubeID: string;
+ youtubeURL: string;
+ studyURL?: string | null;
+ name: string;
+ forumURL: string;
+}
+export interface SeriesJSON extends YoutubeJSON {
+ videos: SeriesRaw[];
+}
+export interface Series extends Youtube {
+ videos: Video[];
+ toJSON: () => SeriesJSON;
+}
+export interface User {
+ id: string;
+ name: string;
+ profiles: Profile[];
+}
+export interface Profile {
+ service: 'bevry' | 'youtube' | 'goodreads' | 'twitter' | 'email';
+ value: string;
+ url?: string;
+ data?: object;
+}
+export type Thread = {
+ topic: TopicResponse;
+ post: PostItem;
+ replies: PostItem[];
+};
diff --git a/packages/discourse/lib/discourse/types/bevry.js b/packages/discourse/lib/discourse/types/bevry.js
new file mode 100644
index 00000000..826ad1b4
--- /dev/null
+++ b/packages/discourse/lib/discourse/types/bevry.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=bevry.js.map
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/types/bevry.js.map b/packages/discourse/lib/discourse/types/bevry.js.map
new file mode 100644
index 00000000..501ab6f3
--- /dev/null
+++ b/packages/discourse/lib/discourse/types/bevry.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"bevry.js","sourceRoot":"","sources":["../../../src/lib/discourse/types/bevry.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/types/discourse.d.ts b/packages/discourse/lib/discourse/types/discourse.d.ts
new file mode 100644
index 00000000..6762c9d6
--- /dev/null
+++ b/packages/discourse/lib/discourse/types/discourse.d.ts
@@ -0,0 +1,364 @@
+export interface Failure {
+ success: 'OK';
+}
+export interface Success {
+ failed: 'FAILED';
+}
+export type Response = Failure & Success;
+export interface Action {
+ can_act: boolean;
+ id: number;
+ count?: number;
+ hidden?: boolean;
+}
+export interface Poster {
+ description: string;
+ extras: string;
+ user_id: number;
+}
+export interface Person {
+ avatar_template: string;
+ id: number;
+ username: string;
+}
+export interface Participant extends Person {
+ post_count: number;
+}
+export interface Link {
+ url: string;
+ internal: boolean;
+ reflection: boolean;
+ title: string;
+ clicks: number;
+}
+/**
+ * Update a Topic Timestamp
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1change-timestamp/put
+ */
+export interface TopicUpdateTimestampRequest {
+ timestamp: number;
+}
+export type TopicUpdateTimestampResponse = Response;
+/**
+ * Update a Post
+ * https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
+ */
+export interface PostUpdateResponse {
+ post: PostUpdateItem;
+}
+export interface PostUpdateItem {
+ actions_summary: Array;
+ admin: boolean;
+ avatar_template: string;
+ avg_time: object;
+ can_delete: boolean;
+ can_edit: boolean;
+ can_recover: boolean;
+ can_view_edit_history: boolean;
+ can_wiki: boolean;
+ cooked: string;
+ created_at: string;
+ deleted_at: object;
+ display_username: string;
+ draft_sequence: number;
+ edit_reason: object;
+ hidden_reason_id: object;
+ hidden: boolean;
+ id: number;
+ incoming_link_count: number;
+ moderator: boolean;
+ name: string;
+ post_number: number;
+ post_type: number;
+ primary_group_flair_bg_color: object;
+ primary_group_flair_color: object;
+ primary_group_flair_url: object;
+ primary_group_name: object;
+ quote_count: number;
+ reads: number;
+ reply_count: number;
+ reply_to_post_number: object;
+ score: number;
+ staff: boolean;
+ topic_id: number;
+ topic_slug: string;
+ trust_level: number;
+ updated_at: string;
+ user_deleted: boolean;
+ user_id: number;
+ user_title: object;
+ username: string;
+ version: number;
+ wiki: boolean;
+ yours: boolean;
+}
+export interface PostUpdateRequest {
+ post: {
+ raw: string;
+ raw_old?: string;
+ edit_reason?: string;
+ cooked?: string;
+ };
+}
+/** https://docs.discourse.org/#tag/Categories/paths/~1categories.json/get */
+export interface CategoriesResponse {
+ category_list: {
+ can_create_category: boolean;
+ can_create_topic: boolean;
+ categories: Category[];
+ draft_key: string;
+ draft_sequence: number;
+ draft: boolean;
+ };
+}
+export interface Category {
+ background_url: string;
+ can_edit: boolean;
+ color: string;
+ description_excerpt: string;
+ description_text: string;
+ description: string;
+ has_children: boolean;
+ id: number;
+ logo_url: string;
+ name: string;
+ notification_level: string;
+ permission: number;
+ position: number;
+ post_count: number;
+ read_restricted: boolean;
+ slug: string;
+ text_color: string;
+ topic_count: number;
+ topic_template: string;
+ topic_url: string;
+ topics_all_time: number;
+ topics_day: number;
+ topics_month: number;
+ topics_week: number;
+ topics_year: number;
+}
+/**
+ * Get Single Topic
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}.json/get
+ */
+export interface TopicResponse {
+ actions_summary: Array;
+ archetype: string;
+ archived: boolean;
+ bookmarked: object;
+ category_id: number;
+ chunk_size: number;
+ closed: boolean;
+ created_at: string;
+ deleted_at: object;
+ deleted_by: object;
+ details: TopicDetails;
+ draft_key: string;
+ draft_sequence: object;
+ draft: object;
+ fancy_title: string;
+ has_summary: boolean;
+ highest_post_number: number;
+ id: number;
+ last_posted_at: object;
+ like_count: number;
+ participant_count: number;
+ pinned_at: string;
+ pinned_globally: boolean;
+ pinned_until: object;
+ pinned: boolean;
+ posts_count: number;
+ reply_count: number;
+ slug: string;
+ tags: string[];
+ title: string;
+ unpinned: object;
+ user_id: number;
+ views: number;
+ visible: boolean;
+ word_count: object;
+ post_stream: {
+ posts: Array;
+ stream: Array;
+ };
+ timeline_lookup: [
+ {
+ '0': Array;
+ }
+ ];
+}
+export interface TopicDetails {
+ auto_close_at: object;
+ auto_close_based_on_last_post: boolean;
+ auto_close_hours: object;
+ can_flag_topic: boolean;
+ created_by: Person;
+ last_poster: Person;
+ notification_level: number;
+ participants: Array;
+ suggested_topics: Array;
+}
+export interface TopicItem {
+ archetype: string;
+ archived: boolean;
+ bookmarked: object;
+ bumped_at: string;
+ bumped: boolean;
+ category_id: number;
+ closed: boolean;
+ created_at: string;
+ excerpt: string;
+ fancy_title: string;
+ has_summary: boolean;
+ highest_post_number: number;
+ id: number;
+ image_url: string;
+ last_posted_at: string;
+ last_poster_username: string;
+ like_count: number;
+ liked: object;
+ pinned_globally: boolean;
+ pinned: boolean;
+ posters: Array;
+ posts_count: number;
+ reply_count: number;
+ slug: string;
+ title: string;
+ unpinned: boolean;
+ unseen: boolean;
+ views: number;
+ visible: boolean;
+}
+/**
+ * Get Topics for Category
+ * https://docs.discourse.org/#tag/Categories/paths/~1c~1{id}.json/get
+ */
+export interface CategoryResponse {
+ users: Person[];
+ topic_list: {
+ can_create_topic: boolean;
+ draft: boolean;
+ draft_key: string;
+ draft_sequence: number;
+ per_page: number;
+ topics: Array;
+ };
+}
+/**
+ * Whole Post Information
+ * As returned by getting a single Post
+ * https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/get
+ */
+export interface PostResponse {
+ actions_summary: Array;
+ admin: boolean;
+ avatar_template: string;
+ avg_time: object;
+ can_delete: boolean;
+ can_edit: boolean;
+ can_recover: boolean;
+ can_view_edit_history: boolean;
+ can_wiki: boolean;
+ cooked: string;
+ created_at: string;
+ deleted_at: object;
+ display_username: string;
+ edit_reason: object;
+ hidden_reason_id: object;
+ hidden: boolean;
+ id: number;
+ incoming_link_count: number;
+ moderator: boolean;
+ name: string;
+ post_number: number;
+ post_type: number;
+ primary_group_flair_bg_color: object;
+ primary_group_flair_color: object;
+ primary_group_flair_url: object;
+ primary_group_name: object;
+ quote_count: number;
+ raw: string;
+ reads: number;
+ reply_count: number;
+ reply_to_post_number: object;
+ score: number;
+ staff: boolean;
+ topic_id: number;
+ topic_slug: string;
+ trust_level: number;
+ updated_at: string;
+ user_deleted: boolean;
+ user_id: number;
+ user_title: object;
+ username: string;
+ version: number;
+ wiki: boolean;
+ yours: boolean;
+}
+/**
+ * Get the Posts of a Topic
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1posts.json/get
+ */
+export interface PostsResponse {
+ post_stream: {
+ posts: Array;
+ };
+ id: number;
+}
+/**
+ * Partial Post Information
+ * As returned by a listing
+ */
+export interface PostItem {
+ accepted_answer: boolean;
+ actions_summary: Array;
+ admin: boolean;
+ avatar_template: string;
+ can_accept_answer: boolean;
+ can_delete: boolean;
+ can_edit: boolean;
+ can_recover: boolean;
+ can_unaccept_answer: boolean;
+ can_view_edit_history: boolean;
+ can_wiki: boolean;
+ cooked: string;
+ created_at: string;
+ deleted_at: null;
+ display_username: string;
+ edit_reason: null;
+ hidden: boolean;
+ id: number;
+ incoming_link_count: number;
+ link_counts: Array ;
+ moderator: boolean;
+ name: string;
+ post_number: number;
+ post_type: number;
+ primary_group_flair_bg_color: null | object;
+ primary_group_flair_color: null | object;
+ primary_group_flair_url: null | object;
+ primary_group_name: null | object;
+ quote_count: number;
+ read: boolean;
+ readers_count: number;
+ reads: number;
+ reply_count: number;
+ reply_to_post_number: null | number;
+ reviewable_id: number;
+ reviewable_score_count: number;
+ reviewable_score_pending_count: number;
+ score: number;
+ staff: boolean;
+ topic_id: number;
+ topic_slug: string;
+ trust_level: number;
+ updated_at: string;
+ user_deleted: boolean;
+ user_id: number;
+ user_title: null | object;
+ username: string;
+ version: number;
+ wiki: boolean;
+ yours: boolean;
+}
diff --git a/packages/discourse/lib/discourse/types/discourse.js b/packages/discourse/lib/discourse/types/discourse.js
new file mode 100644
index 00000000..5e8d99f7
--- /dev/null
+++ b/packages/discourse/lib/discourse/types/discourse.js
@@ -0,0 +1,5 @@
+"use strict";
+// Attempt at TypeScript Types for the Discourse API
+// https://docs.discourse.org
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=discourse.js.map
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/types/discourse.js.map b/packages/discourse/lib/discourse/types/discourse.js.map
new file mode 100644
index 00000000..422d97b1
--- /dev/null
+++ b/packages/discourse/lib/discourse/types/discourse.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"discourse.js","sourceRoot":"","sources":["../../../src/lib/discourse/types/discourse.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,6BAA6B"}
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/util.d.ts b/packages/discourse/lib/discourse/util.d.ts
new file mode 100644
index 00000000..8c80c60c
--- /dev/null
+++ b/packages/discourse/lib/discourse/util.d.ts
@@ -0,0 +1,26 @@
+import { Discourser } from './index';
+export declare const uploadFile: (discourse: any, forum: any, name: any, filePath: any) => Promise;
+export declare const findReplyPage: (b: any, pages: any) => any;
+export declare const findReplyUpload: (u: any, page: any) => any;
+export declare const getPages: (topics: any, topic: any) => any;
+export declare const getReplies: (topics: any, topic: any) => any[];
+export declare const findFile: (folder: any, filename: any) => any;
+export declare const topicFolder: (forum: any, folder: any, title: any) => string;
+export declare const dOptions: {
+ host: string;
+ key: string;
+ username: string;
+ rateLimitConcurrency: number;
+};
+export declare const getFUser: (users: any, user_name: any) => any;
+export declare const getOAvatar: (index: any, user: any) => any;
+export declare const getTopics: (index: any) => any[];
+export declare const convert: (input: string) => any;
+export declare const getDiscourse: () => Discourser;
+export declare function inspect(arg: any): string;
+export declare function log(...args: any[]): void;
+export declare function mkdirp(path: string): Promise;
+export declare function readJSON(path: string): Promise;
+export declare function writeJSON(path: string, data: object): Promise;
+export declare function exists(path: string): Promise;
+export declare function escape(path: string): string;
diff --git a/packages/discourse/lib/discourse/util.js b/packages/discourse/lib/discourse/util.js
new file mode 100644
index 00000000..f55ce447
--- /dev/null
+++ b/packages/discourse/lib/discourse/util.js
@@ -0,0 +1,184 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.escape = exports.exists = exports.writeJSON = exports.readJSON = exports.mkdirp = exports.log = exports.inspect = exports.getDiscourse = exports.convert = exports.getTopics = exports.getOAvatar = exports.getFUser = exports.dOptions = exports.topicFolder = exports.findFile = exports.getReplies = exports.getPages = exports.findReplyUpload = exports.findReplyPage = exports.uploadFile = void 0;
+const fs_1 = require("fs");
+const util_1 = require("util");
+const cwd = process.cwd();
+var TurndownService = require('turndown');
+const index_1 = require("./index");
+const path = require("path");
+const fg = require('fast-glob');
+const slugify_1 = require("slugify");
+var sanitize = require("sanitize-filename");
+var mom = require('moment');
+const uploadFile = (discourse, forum, name, filePath) => __awaiter(void 0, void 0, void 0, function* () {
+ return yield discourse.upload(1, filePath);
+});
+exports.uploadFile = uploadFile;
+const findReplyPage = (b, pages) => {
+ return pages.find((p) => {
+ return p.replies.find((r) => {
+ return r.replyBody == b;
+ });
+ });
+};
+exports.findReplyPage = findReplyPage;
+const findReplyUpload = (u, page) => {
+ const f_pics = page.f_pics || [];
+ return f_pics.find((p) => {
+ return p.url === u;
+ });
+};
+exports.findReplyUpload = findReplyUpload;
+const getPages = (topics, topic) => {
+ return topics.filter((t) => {
+ return t.title == topic.title;
+ });
+};
+exports.getPages = getPages;
+const getReplies = (topics, topic) => {
+ if (topic.nextPages) {
+ const all = topics.filter((t) => {
+ return t.title == topic.title;
+ });
+ let replies = all.map((t) => t.replies);
+ replies = [].concat.apply([], replies);
+ replies = replies.sort((a, b) => {
+ const d1 = mom(a.replyDate, 'DD/MM/YYYY AT HH:mm').toDate();
+ const d2 = mom(b.replyDate, 'DD/MM/YYYY AT HH:mm').toDate();
+ return new Date(d1).getTime() > new Date(d2).getTime() ? 1 : -1;
+ });
+ return replies;
+ /*
+ const findReply = (b, pages) => {
+ return pages.find((p) => {
+ return p.replies.find((r) => {
+ return r.replyBody == b;
+ })
+ })
+ }
+ const p = findReply('\n\n\nsounds great, let me get Old Tony´s Schaeubling 13 and a surface grinder first, after that I can do the parts for the espresso machine in the best maker porn fashion possible, no seriously, every time I thought I know something, there’s just another video around the next corner making me cry like a baby, incl. the coffee machine
\n', all);
+ debugger;
+ */
+ }
+ return [];
+};
+exports.getReplies = getReplies;
+const findFile = (folder, filename) => {
+ const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: folder, absolute: true });
+ if (files.length == 0) {
+ return false;
+ }
+ return files[0];
+};
+exports.findFile = findFile;
+const topicFolder = (forum, folder, title) => {
+ const _title = sanitize((0, slugify_1.default)(title));
+ const tf = path.resolve(forum + '/' + folder + '/' + _title);
+ return tf;
+};
+exports.topicFolder = topicFolder;
+exports.dOptions = {
+ host: 'https://forum.osr-plastic.org',
+ key: 'f624b8385fb2219cb49de63d1e22883afdf7b7367a0bebf822523f49f2678031',
+ username: 'admin',
+ rateLimitConcurrency: 1
+};
+const getFUser = (users, user_name) => {
+ return users.find((u) => {
+ return u.name == user_name;
+ });
+};
+exports.getFUser = getFUser;
+const getOAvatar = (index, user) => {
+ const topics = (0, exports.getTopics)(index);
+ let topic = topics.find((t) => {
+ return t.authorName == user;
+ });
+ if (topic) {
+ return topic.authorImage;
+ }
+ for (let i = 0; i < topics.length; i++) {
+ const t = topics[i];
+ if (t.replies) {
+ const r = t.replies.find((r) => {
+ return r.user == user;
+ });
+ if (r) {
+ return r.avatar;
+ }
+ }
+ }
+ return null;
+};
+exports.getOAvatar = getOAvatar;
+const getTopics = (index) => {
+ let topics = [];
+ for (let t in index) {
+ topics.push(index[t]);
+ }
+ return topics;
+};
+exports.getTopics = getTopics;
+const convert = (input) => {
+ var turndownService = new TurndownService();
+ return turndownService.turndown(input);
+};
+exports.convert = convert;
+const getDiscourse = () => {
+ return new index_1.Discourser(exports.dOptions);
+};
+exports.getDiscourse = getDiscourse;
+function inspect(arg) {
+ return (0, util_1.inspect)(arg, {
+ depth: 5,
+ colors: true,
+ });
+}
+exports.inspect = inspect;
+function log(...args) {
+ console.log(...args.map((arg) => inspect(arg)));
+}
+exports.log = log;
+function mkdirp(path) {
+ return __awaiter(this, void 0, void 0, function* () {
+ try {
+ yield fs_1.default.promises.mkdir(path);
+ }
+ catch (err) {
+ // don't care if it already exists
+ }
+ });
+}
+exports.mkdirp = mkdirp;
+function readJSON(path) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const text = yield fs_1.default.promises.readFile(path, 'utf8');
+ return JSON.parse(text);
+ });
+}
+exports.readJSON = readJSON;
+function writeJSON(path, data) {
+ return fs_1.default.promises.writeFile(path, JSON.stringify(data));
+}
+exports.writeJSON = writeJSON;
+function exists(path) {
+ return new Promise(function (resolve) {
+ fs_1.default.exists(path, resolve);
+ });
+}
+exports.exists = exists;
+function escape(path) {
+ return path.replace(/[^\w]/g, '-').replace(/-+/, '-');
+}
+exports.escape = escape;
+//# sourceMappingURL=util.js.map
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/util.js.map b/packages/discourse/lib/discourse/util.js.map
new file mode 100644
index 00000000..72ea9c72
--- /dev/null
+++ b/packages/discourse/lib/discourse/util.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/lib/discourse/util.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/youtube.d.ts b/packages/discourse/lib/discourse/youtube.d.ts
new file mode 100644
index 00000000..305ab150
--- /dev/null
+++ b/packages/discourse/lib/discourse/youtube.d.ts
@@ -0,0 +1,260 @@
+export declare function getYoutubeVideo(videoID: string): Promise;
+export interface YoutubeVideoData {
+ playabilityStatus: PlayabilityStatus;
+ streamingData: StreamingData;
+ playbackTracking: PlaybackTracking;
+ captions: Captions;
+ videoDetails: VideoDetails;
+ playerConfig: PlayerConfig;
+ storyboards: Storyboards;
+ microformat: Microformat;
+ trackingParams: string;
+ attestation: Attestation;
+ videoQualityPromoSupportedRenderers: VideoQualityPromoSupportedRenderers;
+}
+export interface Attestation {
+ playerAttestationRenderer: PlayerAttestationRenderer;
+}
+export interface PlayerAttestationRenderer {
+ challenge: string;
+ botguardData: BotguardData;
+}
+export interface BotguardData {
+ program: string;
+ interpreterUrl: string;
+}
+export interface Captions {
+ playerCaptionsRenderer: PlayerCaptionsRenderer;
+ playerCaptionsTracklistRenderer: PlayerCaptionsTracklistRenderer;
+}
+export interface PlayerCaptionsRenderer {
+ baseUrl: string;
+ visibility: string;
+ contribute: Contribute;
+}
+export interface Contribute {
+ captionsMetadataRenderer: CaptionsMetadataRenderer;
+}
+export interface CaptionsMetadataRenderer {
+ addSubtitlesText: AddSubtitlesText;
+ noSubtitlesText: Description;
+ promoSubtitlesText: Description;
+}
+export interface AddSubtitlesText {
+ runs: AddSubtitlesTextRun[];
+}
+export interface AddSubtitlesTextRun {
+ text: string;
+ navigationEndpoint: NavigationEndpoint;
+}
+export interface NavigationEndpoint {
+ clickTrackingParams: string;
+ urlEndpoint: NavigationEndpointURLEndpoint;
+}
+export interface NavigationEndpointURLEndpoint {
+ url: string;
+}
+export interface Description {
+ simpleText: string;
+}
+export interface PlayerCaptionsTracklistRenderer {
+ captionTracks: CaptionTrack[];
+ audioTracks: AudioTrack[];
+ translationLanguages: TranslationLanguage[];
+ defaultAudioTrackIndex: number;
+ contribute: Contribute;
+}
+export interface AudioTrack {
+ captionTrackIndices: number[];
+}
+export interface CaptionTrack {
+ baseUrl: string;
+ name: Description;
+ vssId: string;
+ languageCode: string;
+ kind: string;
+ isTranslatable: boolean;
+}
+export interface TranslationLanguage {
+ languageCode: string;
+ languageName: Description;
+}
+export interface Microformat {
+ playerMicroformatRenderer: PlayerMicroformatRenderer;
+}
+export interface PlayerMicroformatRenderer {
+ thumbnail: PlayerMicroformatRendererThumbnail;
+ embed: Embed;
+ title: Description;
+ description: Description;
+ lengthSeconds: string;
+ ownerProfileUrl: string;
+ externalChannelId: string;
+ availableCountries: string[];
+ isUnlisted: boolean;
+ hasYpcMetadata: boolean;
+ viewCount: string;
+ category: string;
+ publishDate: Date;
+ ownerChannelName: string;
+ uploadDate: Date;
+}
+export interface Embed {
+ iframeUrl: string;
+ flashUrl: string;
+ width: number;
+ height: number;
+ flashSecureUrl: string;
+}
+export interface PlayerMicroformatRendererThumbnail {
+ thumbnails: ThumbnailElement[];
+}
+export interface ThumbnailElement {
+ url: string;
+ width: number;
+ height: number;
+}
+export interface PlayabilityStatus {
+ status: string;
+ playableInEmbed: boolean;
+ contextParams: string;
+}
+export interface PlaybackTracking {
+ videostatsPlaybackUrl: PtrackingURLClass;
+ videostatsDelayplayUrl: PtrackingURLClass;
+ videostatsWatchtimeUrl: PtrackingURLClass;
+ ptrackingUrl: PtrackingURLClass;
+ qoeUrl: PtrackingURLClass;
+ setAwesomeUrl: AtrURLClass;
+ atrUrl: AtrURLClass;
+}
+export interface AtrURLClass {
+ baseUrl: string;
+ elapsedMediaTimeSeconds: number;
+}
+export interface PtrackingURLClass {
+ baseUrl: string;
+}
+export interface PlayerConfig {
+ audioConfig: AudioConfig;
+ streamSelectionConfig: StreamSelectionConfig;
+ mediaCommonConfig: MediaCommonConfig;
+}
+export interface AudioConfig {
+ loudnessDb: number;
+ perceptualLoudnessDb: number;
+ enablePerFormatLoudness: boolean;
+}
+export interface MediaCommonConfig {
+ dynamicReadaheadConfig: DynamicReadaheadConfig;
+}
+export interface DynamicReadaheadConfig {
+ maxReadAheadMediaTimeMs: number;
+ minReadAheadMediaTimeMs: number;
+ readAheadGrowthRateMs: number;
+}
+export interface StreamSelectionConfig {
+ maxBitrate: string;
+}
+export interface Storyboards {
+ playerStoryboardSpecRenderer: PlayerStoryboardSpecRenderer;
+}
+export interface PlayerStoryboardSpecRenderer {
+ spec: string;
+}
+export interface StreamingData {
+ expiresInSeconds: string;
+ formats: Format[];
+ adaptiveFormats: Format[];
+}
+export interface Format {
+ itag: number;
+ url: string;
+ mimeType: string;
+ bitrate: number;
+ width?: number;
+ height?: number;
+ initRange?: Range;
+ indexRange?: Range;
+ lastModified: string;
+ contentLength?: string;
+ quality: string;
+ fps?: number;
+ qualityLabel?: string;
+ projectionType: ProjectionType;
+ averageBitrate?: number;
+ approxDurationMs: string;
+ colorInfo?: ColorInfo;
+ highReplication?: boolean;
+ audioQuality?: string;
+ audioSampleRate?: string;
+ audioChannels?: number;
+}
+export interface ColorInfo {
+ primaries: string;
+ transferCharacteristics: string;
+ matrixCoefficients: string;
+}
+export interface Range {
+ start: string;
+ end: string;
+}
+export declare enum ProjectionType {
+ Rectangular = "RECTANGULAR"
+}
+export interface VideoDetails {
+ videoId: string;
+ title: string;
+ lengthSeconds: string;
+ keywords: string[];
+ channelId: string;
+ isOwnerViewing: boolean;
+ shortDescription: string;
+ isCrawlable: boolean;
+ thumbnail: PlayerMicroformatRendererThumbnail;
+ averageRating: number;
+ allowRatings: boolean;
+ viewCount: string;
+ author: string;
+ isPrivate: boolean;
+ isUnpluggedCorpus: boolean;
+ isLiveContent: boolean;
+}
+export interface VideoQualityPromoSupportedRenderers {
+ videoQualityPromoRenderer: VideoQualityPromoRenderer;
+}
+export interface VideoQualityPromoRenderer {
+ triggerCriteria: TriggerCriteria;
+ text: Text;
+ endpoint: Endpoint;
+ trackingParams: string;
+ closeButton: CloseButton;
+}
+export interface CloseButton {
+ videoQualityPromoCloseRenderer: VideoQualityPromoCloseRenderer;
+}
+export interface VideoQualityPromoCloseRenderer {
+ trackingParams: string;
+}
+export interface Endpoint {
+ clickTrackingParams: string;
+ urlEndpoint: EndpointURLEndpoint;
+}
+export interface EndpointURLEndpoint {
+ url: string;
+ target: string;
+}
+export interface Text {
+ runs: TextRun[];
+}
+export interface TextRun {
+ text: string;
+ bold?: boolean;
+}
+export interface TriggerCriteria {
+ connectionWhitelists: string[];
+ joinLatencySeconds: number;
+ rebufferTimeSeconds: number;
+ watchTimeWindowSeconds: number;
+ refractorySeconds: number;
+}
diff --git a/packages/discourse/lib/discourse/youtube.js b/packages/discourse/lib/discourse/youtube.js
new file mode 100644
index 00000000..86abe41e
--- /dev/null
+++ b/packages/discourse/lib/discourse/youtube.js
@@ -0,0 +1,30 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.ProjectionType = exports.getYoutubeVideo = void 0;
+const isomorphic_unfetch_1 = require("isomorphic-unfetch");
+function getYoutubeVideo(videoID) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const eurl = `https://youtube.googleapis.com/v/${videoID}`;
+ const response = yield (0, isomorphic_unfetch_1.default)(`https://www.youtube.com/get_video_info?video_id=${videoID}&el=embedded&eurl=${eurl}&sts=18333`);
+ const text = yield response.text();
+ const params = new URLSearchParams(text);
+ //const data = JSON.parse(Object.fromEntries(params).player_response)
+ // return data as YoutubeVideoData
+ return {};
+ });
+}
+exports.getYoutubeVideo = getYoutubeVideo;
+var ProjectionType;
+(function (ProjectionType) {
+ ProjectionType["Rectangular"] = "RECTANGULAR";
+})(ProjectionType = exports.ProjectionType || (exports.ProjectionType = {}));
+//# sourceMappingURL=youtube.js.map
\ No newline at end of file
diff --git a/packages/discourse/lib/discourse/youtube.js.map b/packages/discourse/lib/discourse/youtube.js.map
new file mode 100644
index 00000000..3edc47f0
--- /dev/null
+++ b/packages/discourse/lib/discourse/youtube.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"youtube.js","sourceRoot":"","sources":["../../src/lib/discourse/youtube.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2DAAsC;AAEtC,SAAsB,eAAe,CACpC,OAAe;;QAEf,MAAM,IAAI,GAAG,oCAAoC,OAAO,EAAE,CAAA;QAC1D,MAAM,QAAQ,GAAG,MAAM,IAAA,4BAAK,EAC3B,mDAAmD,OAAO,qBAAqB,IAAI,YAAY,CAC/F,CAAA;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAClC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;QACxC,qEAAqE;QACrE,kCAAkC;QAClC,OAAO,EAAsB,CAAC;IAC/B,CAAC;CAAA;AAZD,0CAYC;AAiPD,IAAY,cAEX;AAFD,WAAY,cAAc;IACzB,6CAA2B,CAAA;AAC5B,CAAC,EAFW,cAAc,GAAd,sBAAc,KAAd,sBAAc,QAEzB"}
\ No newline at end of file
diff --git a/packages/discourse/lib/git/index.d.ts b/packages/discourse/lib/git/index.d.ts
new file mode 100644
index 00000000..3dd29ec2
--- /dev/null
+++ b/packages/discourse/lib/git/index.d.ts
@@ -0,0 +1,5 @@
+export declare function git_status(cwd: any, dir: any): Promise;
+export declare function git_log(cwd: any, dir: any): Promise<{
+ files: any;
+ last: any;
+}>;
diff --git a/packages/discourse/lib/git/index.js b/packages/discourse/lib/git/index.js
new file mode 100644
index 00000000..0e1c2164
--- /dev/null
+++ b/packages/discourse/lib/git/index.js
@@ -0,0 +1,39 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.git_log = exports.git_status = void 0;
+const index_1 = require("../../index");
+const GIT_CHANGELOG_MESSAGE_PREFIX = '';
+const simpleGit = require("simple-git/promise");
+const moment = require("moment");
+async function git_status(cwd, dir) {
+ const git = simpleGit(cwd);
+ let statusSummary = null;
+ try {
+ statusSummary = await git.log(['--stat', dir]);
+ }
+ catch (e) {
+ index_1.logger.error('Error Git', e);
+ }
+ return statusSummary;
+}
+exports.git_status = git_status;
+async function git_log(cwd, dir) {
+ const stats = await git_status(cwd, dir);
+ index_1.logger.info(`Reading Git log at ${cwd}/${dir}`);
+ let changelogs = stats.all.filter((e) => e.message.trim().toLowerCase().startsWith(GIT_CHANGELOG_MESSAGE_PREFIX.toLowerCase()));
+ if (!changelogs.length) {
+ return { files: [], last: stats.latest };
+ }
+ let pretty = changelogs.map((e) => {
+ return {
+ files: e.diff.files.map((f) => { return { path: f.file }; }),
+ msg: e.message.toLowerCase().replace(GIT_CHANGELOG_MESSAGE_PREFIX.toLowerCase(), '').trim(),
+ hash: e.hash,
+ date: moment(e.date).format('LLLL')
+ };
+ });
+ return { files: pretty, last: stats.latest };
+}
+exports.git_log = git_log;
+;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL2dpdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSx1Q0FBa0M7QUFFbEMsTUFBTSw0QkFBNEIsR0FBRyxFQUFFLENBQUE7QUFJdkMsZ0RBQWdEO0FBRWhELGlDQUFpQztBQUUxQixLQUFLLFVBQVUsVUFBVSxDQUFDLEdBQUcsRUFBRSxHQUFHO0lBRXJDLE1BQU0sR0FBRyxHQUFjLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN0QyxJQUFJLGFBQWEsR0FBTyxJQUFJLENBQUM7SUFDN0IsSUFBSTtRQUNBLGFBQWEsR0FBRyxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztLQUNsRDtJQUNELE9BQU8sQ0FBQyxFQUFFO1FBQ04sY0FBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDLENBQUM7S0FDaEM7SUFDRCxPQUFPLGFBQWEsQ0FBQztBQUN6QixDQUFDO0FBWEQsZ0NBV0M7QUFFTSxLQUFLLFVBQVUsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHO0lBQ2xDLE1BQU0sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUN6QyxjQUFNLENBQUMsSUFBSSxDQUFDLHNCQUFzQixHQUFHLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNoRCxJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxVQUFVLENBQUMsNEJBQTRCLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2hJLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFO1FBQ3BCLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUE7S0FDMUM7SUFDRCxJQUFJLE1BQU0sR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7UUFDOUIsT0FBTztZQUNILEtBQUssRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxHQUFHLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFBLENBQUMsQ0FBQyxDQUFDO1lBQzNELEdBQUcsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxXQUFXLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUU7WUFDM0YsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJO1lBQ1osSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztTQUN0QyxDQUFBO0lBQ0wsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBQ2pELENBQUM7QUFqQkQsMEJBaUJDO0FBQUEsQ0FBQyJ9
\ No newline at end of file
diff --git a/packages/discourse/lib/index.d.ts b/packages/discourse/lib/index.d.ts
new file mode 100644
index 00000000..f34b2558
--- /dev/null
+++ b/packages/discourse/lib/index.d.ts
@@ -0,0 +1,2 @@
+export * from './discourse';
+export * from './discourse/types';
diff --git a/packages/discourse/lib/index.js b/packages/discourse/lib/index.js
new file mode 100644
index 00000000..c0b519a1
--- /dev/null
+++ b/packages/discourse/lib/index.js
@@ -0,0 +1,19 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./discourse"), exports);
+__exportStar(require("./discourse/types"), exports);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvbGliL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw4Q0FBMkI7QUFDM0Isb0RBQWlDIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/index.js.map b/packages/discourse/lib/index.js.map
new file mode 100644
index 00000000..a7fb63af
--- /dev/null
+++ b/packages/discourse/lib/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA2B;AAC3B,oDAAiC"}
\ No newline at end of file
diff --git a/packages/discourse/lib/markdown/Pattern.d.ts b/packages/discourse/lib/markdown/Pattern.d.ts
new file mode 100644
index 00000000..dd02b1a1
--- /dev/null
+++ b/packages/discourse/lib/markdown/Pattern.d.ts
@@ -0,0 +1,7 @@
+import { RegExCallback } from './types';
+export declare class Pattern {
+ regex: RegExp;
+ replacement: RegExCallback;
+ constructor(regex: RegExp, replacement: any);
+ apply(raw: string): string;
+}
diff --git a/packages/discourse/lib/markdown/Pattern.js b/packages/discourse/lib/markdown/Pattern.js
new file mode 100644
index 00000000..09ca45bf
--- /dev/null
+++ b/packages/discourse/lib/markdown/Pattern.js
@@ -0,0 +1,14 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Pattern = void 0;
+class Pattern {
+ constructor(regex, replacement) {
+ this.regex = regex;
+ this.replacement = replacement;
+ }
+ apply(raw) {
+ return raw.replace(this.regex, this.replacement);
+ }
+}
+exports.Pattern = Pattern;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGF0dGVybi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvbWFya2Rvd24vUGF0dGVybi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxNQUFhLE9BQU87SUFHbEIsWUFBWSxLQUFhLEVBQUUsV0FBZ0I7UUFDekMsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUE7UUFDbEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUE7SUFDaEMsQ0FBQztJQUVELEtBQUssQ0FBQyxHQUFXO1FBQ2YsT0FBTyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO0lBQ2xELENBQUM7Q0FDRjtBQVhELDBCQVdDIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/markdown/Rule.d.ts b/packages/discourse/lib/markdown/Rule.d.ts
new file mode 100644
index 00000000..f19edcd8
--- /dev/null
+++ b/packages/discourse/lib/markdown/Rule.d.ts
@@ -0,0 +1,7 @@
+import { Pattern } from './Pattern';
+export declare class Rule {
+ name: string;
+ patterns: Pattern[];
+ constructor(name: string, patterns: Pattern[]);
+ apply(raw: string): string;
+}
diff --git a/packages/discourse/lib/markdown/Rule.js b/packages/discourse/lib/markdown/Rule.js
new file mode 100644
index 00000000..9d6b927a
--- /dev/null
+++ b/packages/discourse/lib/markdown/Rule.js
@@ -0,0 +1,14 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.Rule = void 0;
+class Rule {
+ constructor(name, patterns) {
+ this.name = name;
+ this.patterns = patterns;
+ }
+ apply(raw) {
+ return this.patterns.reduce((result, pattern) => pattern.apply(result), raw);
+ }
+}
+exports.Rule = Rule;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUnVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvbWFya2Rvd24vUnVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFFQSxNQUFhLElBQUk7SUFHZixZQUFZLElBQVksRUFBRSxRQUFtQjtRQUMzQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLEdBQVc7UUFDZixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUN6QixDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQzFDLEdBQUcsQ0FDSixDQUFDO0lBQ0osQ0FBQztDQUNGO0FBZEQsb0JBY0MifQ==
\ No newline at end of file
diff --git a/packages/discourse/lib/markdown/index.d.ts b/packages/discourse/lib/markdown/index.d.ts
new file mode 100644
index 00000000..32743bb1
--- /dev/null
+++ b/packages/discourse/lib/markdown/index.d.ts
@@ -0,0 +1,14 @@
+import { Rule } from './Rule';
+import { RMarkOptions } from './types';
+export declare const RE_IMAGES: RegExp;
+export declare const RE_LINKS: RegExp;
+export declare class RMark {
+ constructor(options: RMarkOptions);
+ private rules;
+ addRuleBefore(rule: Rule, before: string): RMark;
+ addRule(rule: Rule): RMark;
+ render(raw: string): string;
+}
+export { Rule } from './Rule';
+export { Pattern } from './Pattern';
+export declare const toHTML: (content: any) => string;
diff --git a/packages/discourse/lib/markdown/index.js b/packages/discourse/lib/markdown/index.js
new file mode 100644
index 00000000..ac075114
--- /dev/null
+++ b/packages/discourse/lib/markdown/index.js
@@ -0,0 +1,104 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.toHTML = exports.Pattern = exports.Rule = exports.RMark = exports.RE_LINKS = exports.RE_IMAGES = void 0;
+const Rule_1 = require("./Rule");
+const Pattern_1 = require("./Pattern");
+exports.RE_IMAGES = /\!\[([^\]]+)\]\((\S+)\)/g;
+exports.RE_LINKS = /\[([^\n]+)\]\(([^\n]+)\)/g;
+const markdown = require("markdown-it");
+const defaultRules = [
+ new Rule_1.Rule('header', [
+ new Pattern_1.Pattern(/^#{6}\s?([^\n]+)/gm, '$1 '),
+ new Pattern_1.Pattern(/^#{5}\s?([^\n]+)/gm, '$1 '),
+ new Pattern_1.Pattern(/^#{4}\s?([^\n]+)/gm, '$1 '),
+ new Pattern_1.Pattern(/^#{3}\s?([^\n]+)/gm, '$1 '),
+ new Pattern_1.Pattern(/^#{2}\s?([^\n]+)/gm, '$1 '),
+ new Pattern_1.Pattern(/^#{1}\s?([^\n]+)/gm, '$1 '),
+ ]),
+ new Rule_1.Rule('bold', [
+ new Pattern_1.Pattern(/\*\*\s?([^\n]+)\*\*/g, '$1 '),
+ new Pattern_1.Pattern(/\_\_\s?([^\n]+)\_\_/g, '$1 '),
+ ]),
+ new Rule_1.Rule('italic', [
+ new Pattern_1.Pattern(/\*\s?([^\n]+)\*/g, '$1 '),
+ new Pattern_1.Pattern(/\_\s?([^\n]+)\_/g, '$1 '),
+ ]),
+ new Rule_1.Rule('image', [
+ new Pattern_1.Pattern(/\!\[([^\]]+)\]\((\S+)\)/g, ' '),
+ ]),
+ new Rule_1.Rule('link', [
+ new Pattern_1.Pattern(/\[([^\n]+)\]\(([^\n]+)\)/g, '$1 '),
+ ]),
+ new Rule_1.Rule('paragraph', [
+ // this regex can't skip processed HTML
+ new Pattern_1.Pattern(/([^\n]+\n?)/g, '\n$1
\n'),
+ // another possible regex that can't skip processed HTML
+ // new Pattern(/(?:^|\n)([^\n\<]+(?:\n[^\n\>]+)*)(?:\n|$)/gm, '\n$1
\n'),
+ ])
+];
+const defaultRulesDiscourse = (images, links) => {
+ return [
+ new Rule_1.Rule('image', [
+ new Pattern_1.Pattern(exports.RE_LINKS, images)
+ ]) /*,
+ new Rule('link', [
+ new Pattern(
+ RE_LINKS,
+ links
+ )
+ ])*/
+ ];
+};
+class RMark {
+ constructor(options) {
+ this.rules = defaultRulesDiscourse(options.images, options.links);
+ }
+ addRuleBefore(rule, before) {
+ const index = this.rules.findIndex((r) => r.name === before);
+ if (index !== -1) {
+ this.rules.splice(index, 0, rule);
+ }
+ return this;
+ }
+ addRule(rule) {
+ this.addRuleBefore(rule, 'paragraph');
+ return this;
+ }
+ render(raw) {
+ let result = raw;
+ this.rules.forEach((rule) => {
+ result = rule.apply(result);
+ });
+ return result;
+ }
+}
+exports.RMark = RMark;
+var Rule_2 = require("./Rule");
+Object.defineProperty(exports, "Rule", { enumerable: true, get: function () { return Rule_2.Rule; } });
+var Pattern_2 = require("./Pattern");
+Object.defineProperty(exports, "Pattern", { enumerable: true, get: function () { return Pattern_2.Pattern; } });
+// export const find = (content:string, reg:RegExp) => content.match(reg)
+const toHTML = (content) => {
+ const md = new markdown({
+ html: true,
+ breaks: true
+ });
+ return md.render(content);
+};
+exports.toHTML = toHTML;
+function image_urls(input) {
+ const regex = /https?:\/\/(?:[a-z0-9\-]+\.)+[a-z]{2,}(?:\/[^\/#\s]*)*\.(?:jpe?g|gif|png|webp)/g;
+ const matches = input.match(regex);
+ return matches || [];
+}
+function image_urls_local(input) {
+ const regex = /\/(?:[^\/#\s]+\/)*[^\/#\s]+\.(?:jpe?g|gif|png|webp)/g;
+ const matches = input.match(regex);
+ return matches || [];
+}
+function findUploadImageUrls(input) {
+ const regex = /upload:\/\/[^\s]+?\.(?:jpe?g|gif|png)/gi;
+ const matches = input.match(regex);
+ return matches || [];
+}
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL21hcmtkb3duL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLGlDQUE2QjtBQUM3Qix1Q0FBbUM7QUFJdEIsUUFBQSxTQUFTLEdBQVcsMEJBQTBCLENBQUE7QUFDOUMsUUFBQSxRQUFRLEdBQVcsMkJBQTJCLENBQUE7QUFFM0Qsd0NBQXVDO0FBSXZDLE1BQU0sWUFBWSxHQUFXO0lBQzNCLElBQUksV0FBSSxDQUFDLFFBQVEsRUFBRTtRQUNqQixJQUFJLGlCQUFPLENBQUMsb0JBQW9CLEVBQUUsYUFBYSxDQUFDO1FBQ2hELElBQUksaUJBQU8sQ0FBQyxvQkFBb0IsRUFBRSxhQUFhLENBQUM7UUFDaEQsSUFBSSxpQkFBTyxDQUFDLG9CQUFvQixFQUFFLGFBQWEsQ0FBQztRQUNoRCxJQUFJLGlCQUFPLENBQUMsb0JBQW9CLEVBQUUsYUFBYSxDQUFDO1FBQ2hELElBQUksaUJBQU8sQ0FBQyxvQkFBb0IsRUFBRSxhQUFhLENBQUM7UUFDaEQsSUFBSSxpQkFBTyxDQUFDLG9CQUFvQixFQUFFLGFBQWEsQ0FBQztLQUNqRCxDQUFDO0lBQ0YsSUFBSSxXQUFJLENBQUMsTUFBTSxFQUFFO1FBQ2YsSUFBSSxpQkFBTyxDQUFDLHNCQUFzQixFQUFFLFdBQVcsQ0FBQztRQUNoRCxJQUFJLGlCQUFPLENBQUMsc0JBQXNCLEVBQUUsV0FBVyxDQUFDO0tBQ2pELENBQUM7SUFDRixJQUFJLFdBQUksQ0FBQyxRQUFRLEVBQUU7UUFDakIsSUFBSSxpQkFBTyxDQUFDLGtCQUFrQixFQUFFLFdBQVcsQ0FBQztRQUM1QyxJQUFJLGlCQUFPLENBQUMsa0JBQWtCLEVBQUUsV0FBVyxDQUFDO0tBQzdDLENBQUM7SUFDRixJQUFJLFdBQUksQ0FBQyxPQUFPLEVBQUU7UUFDaEIsSUFBSSxpQkFBTyxDQUFDLDBCQUEwQixFQUFFLDJCQUEyQixDQUFDO0tBQ3JFLENBQUM7SUFDRixJQUFJLFdBQUksQ0FBQyxNQUFNLEVBQUU7UUFDZixJQUFJLGlCQUFPLENBQ1QsMkJBQTJCLEVBQzNCLHFEQUFxRCxDQUN0RDtLQUNGLENBQUM7SUFDRixJQUFJLFdBQUksQ0FBQyxXQUFXLEVBQUU7UUFDcEIsdUNBQXVDO1FBQ3ZDLElBQUksaUJBQU8sQ0FBQyxjQUFjLEVBQUUsZUFBZSxDQUFDO1FBQzVDLHdEQUF3RDtRQUN4RCwrRUFBK0U7S0FDaEYsQ0FBQztDQUNILENBQUE7QUFFRCxNQUFNLHFCQUFxQixHQUFHLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxFQUFFO0lBQzlDLE9BQU87UUFDTCxJQUFJLFdBQUksQ0FBQyxPQUFPLEVBQUU7WUFDaEIsSUFBSSxpQkFBTyxDQUFDLGdCQUFRLEVBQUUsTUFBTSxDQUFDO1NBQzlCLENBQUMsQ0FBQTs7Ozs7O1lBTUU7S0FDTCxDQUFBO0FBQ0gsQ0FBQyxDQUFBO0FBRUQsTUFBYSxLQUFLO0lBRWhCLFlBQVksT0FBcUI7UUFDL0IsSUFBSSxDQUFDLEtBQUssR0FBRyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNuRSxDQUFDO0lBSU0sYUFBYSxDQUFDLElBQVUsRUFBRSxNQUFjO1FBQzdDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxDQUFDO1FBQzdELElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQ2hCLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7U0FDbkM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTSxPQUFPLENBQUMsSUFBVTtRQUN2QixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztRQUN0QyxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTSxNQUFNLENBQUMsR0FBVztRQUN2QixJQUFJLE1BQU0sR0FBRyxHQUFHLENBQUM7UUFDakIsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUMxQixNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7Q0FDRjtBQTVCRCxzQkE0QkM7QUFFRCwrQkFBOEI7QUFBckIsNEZBQUEsSUFBSSxPQUFBO0FBQ2IscUNBQW9DO0FBQTNCLGtHQUFBLE9BQU8sT0FBQTtBQUVoQix5RUFBeUU7QUFLbEUsTUFBTSxNQUFNLEdBQUcsQ0FBQyxPQUFPLEVBQUUsRUFBRTtJQUVoQyxNQUFNLEVBQUUsR0FBRyxJQUFJLFFBQVEsQ0FBQztRQUN0QixJQUFJLEVBQUUsSUFBSTtRQUNWLE1BQU0sRUFBQyxJQUFJO0tBQ1osQ0FBQyxDQUFBO0lBRUYsT0FBTyxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBQzNCLENBQUMsQ0FBQTtBQVJZLFFBQUEsTUFBTSxVQVFsQjtBQUVELFNBQVMsVUFBVSxDQUFDLEtBQWE7SUFDL0IsTUFBTSxLQUFLLEdBQUcsaUZBQWlGLENBQUE7SUFDL0YsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNsQyxPQUFPLE9BQU8sSUFBSSxFQUFFLENBQUE7QUFDdEIsQ0FBQztBQUVELFNBQVMsZ0JBQWdCLENBQUMsS0FBYTtJQUNyQyxNQUFNLEtBQUssR0FBRyxzREFBc0QsQ0FBQTtJQUNwRSxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ2xDLE9BQU8sT0FBTyxJQUFJLEVBQUUsQ0FBQTtBQUN0QixDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxLQUFhO0lBQ3hDLE1BQU0sS0FBSyxHQUFHLHlDQUF5QyxDQUFDO0lBQ3hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkMsT0FBTyxPQUFPLElBQUksRUFBRSxDQUFDO0FBQ3ZCLENBQUMifQ==
\ No newline at end of file
diff --git a/packages/discourse/lib/markdown/types.d.ts b/packages/discourse/lib/markdown/types.d.ts
new file mode 100644
index 00000000..912a5295
--- /dev/null
+++ b/packages/discourse/lib/markdown/types.d.ts
@@ -0,0 +1,5 @@
+export type RegExCallback = (match: any, capture: any, arg1: any, arg2: any) => string;
+export interface RMarkOptions {
+ images: RegExCallback;
+ links?: RegExCallback;
+}
diff --git a/packages/discourse/lib/markdown/types.js b/packages/discourse/lib/markdown/types.js
new file mode 100644
index 00000000..806a986f
--- /dev/null
+++ b/packages/discourse/lib/markdown/types.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL21hcmtkb3duL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/commons.d.ts b/packages/discourse/lib/oa/commons.d.ts
new file mode 100644
index 00000000..45211337
--- /dev/null
+++ b/packages/discourse/lib/oa/commons.d.ts
@@ -0,0 +1,27 @@
+import { IUploadedFileMeta } from '@plastichub/osr-commons';
+import { IImportUser, IOAHowto, IOACategory, IOATags, IOAHowtoImport } from '../../';
+export declare const DEFAULT_HT_CATEGORY: {
+ _modified: string;
+ label: string;
+ _id: string;
+ _created: string;
+ _deleted: boolean;
+};
+export declare const LATEST_TRACK = "${OSR_ROOT}/oa-data/howtos/latest_track.json";
+export declare const LATEST_TEST = "./latest_test.json";
+export declare const DEFAULT_USER = "katharinaelleke";
+export declare const getDataPath: (_path?: string) => string;
+export declare const getHowtosPath: () => string;
+export declare const getHowtos: () => IOAHowtoImport[];
+export declare const read_howtos: (src: string) => IOAHowtoImport[];
+export declare const read_categories: (src: string) => IOACategory[];
+export declare const read_tags: (src: string) => IOATags[];
+export declare const filter_valid: (users: IOAHowtoImport[]) => IOAHowtoImport[];
+export declare const kb_howto_folder: (howto: any) => string;
+export declare const kb_howto_file: (howto: any, filename: any) => string;
+export declare const getHowtoUser: (howto: IOAHowto) => IImportUser;
+export declare const toMDImage: (image: IUploadedFileMeta) => string;
+export declare const md_edit_wrap: (content: any, f: any, prefix?: string, context?: string) => any;
+export declare const removeEmojis: (string: any) => any;
+export declare const toHTML: (path: any, markdown: any) => any;
+export declare const createTextLinks_: (text: any) => any;
diff --git a/packages/discourse/lib/oa/commons.js b/packages/discourse/lib/oa/commons.js
new file mode 100644
index 00000000..d01ef525
--- /dev/null
+++ b/packages/discourse/lib/oa/commons.js
@@ -0,0 +1,106 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createTextLinks_ = exports.toHTML = exports.removeEmojis = exports.md_edit_wrap = exports.toMDImage = exports.getHowtoUser = exports.kb_howto_file = exports.kb_howto_folder = exports.filter_valid = exports.read_tags = exports.read_categories = exports.read_howtos = exports.getHowtos = exports.getHowtosPath = exports.getDataPath = exports.DEFAULT_USER = exports.LATEST_TEST = exports.LATEST_TRACK = exports.DEFAULT_HT_CATEGORY = void 0;
+const lib_1 = require("./lib");
+const path = require("path");
+const read_1 = require("@plastichub/fs/read");
+const fs_1 = require("@plastichub/osr-commons");
+const users_1 = require("./users");
+const js_beautify_1 = require("js-beautify");
+const showdown_1 = require("showdown");
+var escapeHtml = require('escape-html');
+const pretty = require('pretty');
+const TEST = false;
+exports.DEFAULT_HT_CATEGORY = {
+ "_modified": "2022-09-18T08:51:47.196Z",
+ "label": "Guides",
+ "_id": "CrZjHORWfxEl6iDrrPIO",
+ "_created": "2022-09-18T08:51:47.196Z",
+ "_deleted": false
+};
+exports.LATEST_TRACK = '${OSR_ROOT}/oa-data/howtos/latest_track.json';
+exports.LATEST_TEST = './latest_test.json';
+exports.DEFAULT_USER = 'katharinaelleke';
+const getDataPath = (_path = '') => path.resolve(path.join((0, fs_1.resolve)('${OSR_ROOT}/oa-data/howtos/'), _path));
+exports.getDataPath = getDataPath;
+const getHowtosPath = () => path.resolve((0, fs_1.resolve)(TEST ? exports.LATEST_TEST : exports.LATEST_TRACK));
+exports.getHowtosPath = getHowtosPath;
+const getHowtos = () => (0, read_1.sync)(path.resolve((0, exports.getHowtosPath)()), 'json') || [];
+exports.getHowtos = getHowtos;
+const read_howtos = (src) => {
+ const raw = (0, read_1.sync)(src, 'json');
+ return raw.v3_howtos;
+};
+exports.read_howtos = read_howtos;
+const read_categories = (src) => {
+ const raw = (0, read_1.sync)(src, 'json');
+ return raw.v3_categories;
+};
+exports.read_categories = read_categories;
+const read_tags = (src) => {
+ const raw = (0, read_1.sync)(src, 'json');
+ return raw.v3_tags;
+};
+exports.read_tags = read_tags;
+const filter_valid = (users) => {
+ return users.filter((user) => {
+ if (user.title === 'Build a Fishing Canoe') {
+ //debugger
+ }
+ if (user.moderation.toLowerCase() !== 'accepted') {
+ return false;
+ }
+ return true;
+ });
+};
+exports.filter_valid = filter_valid;
+const kb_howto_folder = (howto) => path.resolve(path.join((0, fs_1.resolve)("${KB_ROOT}/src/howtos/"), howto.slug));
+exports.kb_howto_folder = kb_howto_folder;
+const kb_howto_file = (howto, filename) => path.resolve(path.join((0, fs_1.resolve)("${KB_ROOT}/src/howtos/"), howto.slug, (0, lib_1.sanitize)(filename)));
+exports.kb_howto_file = kb_howto_file;
+const getHowtoUser = (howto) => {
+ const users = (0, users_1.getUsers)();
+ let user = users.find((u) => u._id == howto._createdBy);
+ if (user && user.f_id) {
+ return user;
+ }
+ else {
+ user = users.find((u) => u._id == exports.DEFAULT_USER);
+ if (user && user.f_id) {
+ console.error('using default user : ' + exports.DEFAULT_USER + ' : for' + howto.slug);
+ return user;
+ }
+ }
+};
+exports.getHowtoUser = getHowtoUser;
+const toMDImage = (image) => ``;
+exports.toMDImage = toMDImage;
+const md_edit_wrap = (content, f, prefix = '', context = '') => (0, js_beautify_1.html_beautify)(`${content}
`);
+exports.md_edit_wrap = md_edit_wrap;
+const removeEmojis = (string) => {
+ return string.replace(/([#0-9]\u20E3)|[\xA9\xAE\u203C\u2047-\u2049\u2122\u2139\u3030\u303D\u3297\u3299][\uFE00-\uFEFF]?|[\u2190-\u21FF][\uFE00-\uFEFF]?|[\u2300-\u23FF][\uFE00-\uFEFF]?|[\u2460-\u24FF][\uFE00-\uFEFF]?|[\u25A0-\u25FF][\uFE00-\uFEFF]?|[\u2600-\u27BF][\uFE00-\uFEFF]?|[\u2900-\u297F][\uFE00-\uFEFF]?|[\u2B00-\u2BF0][\uFE00-\uFEFF]?|(?:\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDEFF])[\uFE00-\uFEFF]?/g, '');
+};
+exports.removeEmojis = removeEmojis;
+const toHTML = (path, markdown) => {
+ const content = (0, read_1.sync)(path, 'string');
+ if (!markdown) {
+ let converter = new showdown_1.Converter({ tables: true });
+ converter.setOption('literalMidWordUnderscores', 'true');
+ return converter.makeHtml(content);
+ }
+ else {
+ return content;
+ }
+};
+exports.toHTML = toHTML;
+const createTextLinks_ = (text) => {
+ return (text || "").replace(/([^\S]|^)(((https?\:\/\/)|(www\.))(\S+))/gi, function (match, space, url) {
+ var hyperlink = url;
+ if (!hyperlink.match('^https?:\/\/')) {
+ hyperlink = 'http://' + hyperlink;
+ }
+ return space + '' + url + ' ';
+ });
+};
+exports.createTextLinks_ = createTextLinks_;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvb2EvY29tbW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUF3QkEsK0JBQXlDO0FBRXpDLDZCQUE0QjtBQUM1Qiw4Q0FBa0Q7QUFLbEQsdURBQXdEO0FBR3hELG1DQUFpRDtBQUVqRCw2Q0FBMkM7QUFDM0MsdUNBQW9DO0FBQ3BDLElBQUksVUFBVSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQUd4QyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFHaEMsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFBO0FBRUwsUUFBQSxtQkFBbUIsR0FBRztJQUMvQixXQUFXLEVBQUUsMEJBQTBCO0lBQ3ZDLE9BQU8sRUFBRSxRQUFRO0lBQ2pCLEtBQUssRUFBRSxzQkFBc0I7SUFDN0IsVUFBVSxFQUFFLDBCQUEwQjtJQUN0QyxVQUFVLEVBQUUsS0FBSztDQUNwQixDQUFBO0FBR1ksUUFBQSxZQUFZLEdBQUcsOENBQThDLENBQUE7QUFDN0QsUUFBQSxXQUFXLEdBQUcsb0JBQW9CLENBQUE7QUFFbEMsUUFBQSxZQUFZLEdBQUcsaUJBQWlCLENBQUE7QUFFdEMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxLQUFLLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBQSxZQUFPLEVBQUMsNkJBQTZCLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO0FBQXBHLFFBQUEsV0FBVyxlQUF5RjtBQUMxRyxNQUFNLGFBQWEsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsWUFBTyxFQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsbUJBQVcsQ0FBQyxDQUFDLENBQUMsb0JBQVksQ0FBQyxDQUFDLENBQUE7QUFBOUUsUUFBQSxhQUFhLGlCQUFpRTtB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
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/howtos.d.ts b/packages/discourse/lib/oa/howtos.d.ts
new file mode 100644
index 00000000..fa372fd5
--- /dev/null
+++ b/packages/discourse/lib/oa/howtos.d.ts
@@ -0,0 +1,10 @@
+import { IOptions, IOAHowtoImport } from '../../';
+import { Discourser } from '../index';
+export declare const mergeLatest: (discorse: any, options: IOptions, oa_howtos: IOAHowtoImport[]) => IOAHowtoImport[];
+export declare const read_fragments: (src: any, config: any, prefix?: string, context?: string) => any;
+export declare function howto_content(howto: IOAHowtoImport, folder: string, fragments: any, templates: any): Promise;
+export declare const createHowtoTopic: (discourse: any, howto: IOAHowtoImport, create?: boolean) => Promise;
+export declare const importHowto: (discorse: any, howto: IOAHowtoImport) => Promise;
+export declare const importHowtos: (discorse: any, options: IOptions, howtos: IOAHowtoImport[]) => Promise;
+export declare const updateHowto: (discourse: Discourser, howto: IOAHowtoImport, options: IOptions) => Promise;
+export declare const updateHowtos: (discorse: any, options: IOptions, howtos: IOAHowtoImport[]) => Promise;
diff --git a/packages/discourse/lib/oa/howtos.js b/packages/discourse/lib/oa/howtos.js
new file mode 100644
index 00000000..eb0ab03b
--- /dev/null
+++ b/packages/discourse/lib/oa/howtos.js
@@ -0,0 +1,475 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.updateHowtos = exports.updateHowto = exports.importHowtos = exports.importHowto = exports.createHowtoTopic = exports.howto_content = exports.read_fragments = exports.mergeLatest = void 0;
+const bluebird_1 = require("bluebird");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const core_1 = require("@plastichub/core");
+const strings_1 = require("@plastichub/core/strings");
+const index_1 = require("../../index");
+const constants_1 = require("../discourse/constants");
+const lib_1 = require("./lib");
+const path = require("path");
+const read_1 = require("@plastichub/fs/read");
+const exists_1 = require("@plastichub/fs/exists");
+const write_1 = require("@plastichub/fs/write");
+const fs_1 = require("@plastichub/osr-commons");
+const cheerio = require("cheerio");
+const users_1 = require("./users");
+var escapeHtml = require('escape-html');
+const dir_1 = require("@plastichub/fs/dir");
+const osr_cli_commons_2 = require("@plastichub/osr-cli-commons");
+const FUCKING_TOKEN = 'j7oYrkQe5nbnikCNHcfoP2DGtXKV4iHHzDFip8gGatS145g3B65UU6mI09KeFday9mY5HNQnU2jXUTe7LLkP-w';
+const commons_1 = require("./commons");
+const mergeLatest = (discorse, options, oa_howtos) => {
+ const howtos = (0, commons_1.getHowtos)();
+ oa_howtos.forEach((h) => {
+ const howto = howtos.find((tu) => {
+ return tu._id === h._id;
+ });
+ if (!howto) {
+ howtos.push(h);
+ }
+ });
+ (0, write_1.sync)((0, commons_1.getHowtosPath)(), howtos);
+ return howtos;
+};
+exports.mergeLatest = mergeLatest;
+const updateHowtoFile = (howto) => {
+ const howtos = (0, commons_1.getHowtos)();
+ const index = howtos.findIndex((u) => u._id == howto._id);
+ howtos[index] = howto;
+ (0, write_1.sync)((0, commons_1.getHowtosPath)(), howtos);
+};
+const uploadImage = async (discourse, user, image, localPath) => {
+ if (image.data) {
+ return image;
+ }
+ index_1.logger.debug('uploading image:', image.name);
+ const upped = await discourse.uploadFile(user.f_id, localPath);
+ const data = upped.data;
+ if (data && data.id) {
+ image.data = data;
+ }
+ else {
+ index_1.logger.error('error uploading image');
+ }
+ return image;
+};
+const read_fragments = (src, config, prefix = '', context = '') => {
+ if (!(0, exists_1.sync)(src)) {
+ (0, dir_1.sync)(src);
+ }
+ let fragments = (0, osr_cli_commons_2.files)(src, '*.html');
+ fragments.map((f) => {
+ config[path.parse(f).name] = (0, commons_1.md_edit_wrap)((0, commons_1.toHTML)(f, true), f, prefix, context);
+ });
+ fragments = (0, osr_cli_commons_2.files)(src, '*.md');
+ fragments.map((f) => {
+ config[path.parse(f).name] = (0, commons_1.md_edit_wrap)((0, commons_1.toHTML)(f, false), f, prefix, context);
+ });
+ return config;
+};
+exports.read_fragments = read_fragments;
+async function howto_content(howto, folder, fragments, templates) {
+ //const tags = data.v3_tags;
+ const howtoTags = [];
+ /*
+ for (const ht in howto.tags) {
+ const gt = tags.find((t) => t._id === ht);
+ if (gt) {
+ howtoTags.push(gt.label);
+ // logger.debug('resolved ' + ht + ' to ' + gt.label);
+ } else {
+ // logger.error('Cant resolve tag : ' + ht);
+ }
+ }
+*/
+ howto.slug = howto.slug.trim();
+ let s = '';
+ let step_template = "" + templates.step;
+ let invalid_step_images = false;
+ const step_image = (i) => {
+ if (!i.data || !i.data.short_url) {
+ index_1.logger.error('invalid image : ' + i.downloadUrl + ' : ' + howto.slug);
+ invalid_step_images = true;
+ return '\n';
+ }
+ return `\n${(0, commons_1.toMDImage)(i)}`;
+ };
+ const step_file = (i) => {
+ const image = `/howtos/${howto.slug}/${encodeURIComponent((0, lib_1.sanitize)(i.name))}`;
+ return ``;
+ };
+ const step_files = (s) => {
+ const files = s.files.map(step_file).join('\n');
+ return `
+ ${files}
+
+ `;
+ };
+ const step_images = (s) => {
+ const images = s.images.map(step_image).join('\n');
+ return `${images}`;
+ };
+ const step_images_gallery = (s) => {
+ const images = s.images.map(step_image).join('');
+ return `\n${images}
`;
+ };
+ const step = (s, i) => {
+ const t = (0, strings_1.substitute)(step_template, {
+ title: s.title,
+ text: (0, commons_1.createTextLinks_)(escapeHtml(s.text.trim()).replace(/(?:\r\n|\r|\n)/g, '\n\n')),
+ step_number: i + 1,
+ images: s.images.length > 1 ? step_images_gallery(s) : step_images(s)
+ });
+ return t;
+ };
+ const steps = howto.steps.map((s, i) => step(s, i)).join('\n\n');
+ const attachments = howto.files.map((f) => {
+ return `[${(0, lib_1.sanitize)(f.name)}](${f.downloadUrl})`;
+ });
+ howto.description = (0, commons_1.removeEmojis)(howto.description);
+ howto.description = (0, commons_1.createTextLinks_)(howto.description);
+ let authorName = (howto.user && howto.user.data && howto.user.data && howto.user.data.title) ? howto.user.data.title : (howto.user ? howto.user._id : 'OSR-Plastic');
+ if (authorName === 'Precious Plastic Headquarters') {
+ authorName = 'Precious Plastic Nantes';
+ }
+ let _3dFiles = [...(0, osr_cli_commons_2.files)(path.resolve(`${folder}`), '**/**/*.step'), ...(0, osr_cli_commons_2.files)(path.resolve(`${folder}`), '**/**/*.STEP'), ...(0, osr_cli_commons_2.files)(path.resolve(`${folder}`), '**/**/*.stp')];
+ _3dFiles = _3dFiles.map((f) => {
+ return (0, osr_cli_commons_1.forward_slash)(`${howto.slug}/${path.relative(path.resolve(folder), f)}`);
+ });
+ let previews = '';
+ if (_3dFiles.length) {
+ previews += '';
+ previews += '
';
+ _3dFiles = _3dFiles.map((f) => {
+ return `
+
+ 3D Step File: ${f.replace(howto.slug, '')} -
+
+ Preview
+
+ `;
+ });
+ previews += _3dFiles.join('');
+ previews += ' ';
+ }
+ if (invalid_step_images) {
+ return false;
+ }
+ let index = (0, strings_1.substitute)(templates.howto, {
+ ...fragments,
+ image: `/howtos/${howto.slug}/${encodeURIComponent((0, lib_1.sanitize)(howto.cover_image.name))}`,
+ title: howto.title.trim(),
+ description: escapeHtml(howto.description.trim()) || "",
+ enabled: howto.moderation == "accepted" ? true : false,
+ steps: steps,
+ keywords: ['Precious plastic', 'Preciousplastic', 'plastichub', 'osr', ...howtoTags].join(','),
+ user: howto._createdBy,
+ files: `${attachments.join('\n')}`,
+ authorName: authorName,
+ authorUrl: `https://osr-plastic.org/users/${howto.user ? howto.user._id : 'https://osr-plastic.org/users/plastichub'}.html`,
+ // short: escapeHtml(howto.description.trim()).substring(0, 100) + '....',
+ slug: howto.slug,
+ previews3D: previews
+ });
+ const $ = cheerio.load(index, {
+ xmlMode: true
+ });
+ /*
+ $('a').each(function () {
+ const url = $(this).attr("href");
+ logger.debug('url : ' + url);
+ if(url.indexOf('dropbox')){
+
+ }
+ });*/
+ //write(index_md, pretty(index, { ocd: true }));
+ return (0, commons_1.removeEmojis)(index);
+}
+exports.howto_content = howto_content;
+const createHowtoTopic = async (discourse, howto, create = true) => {
+ if (!howto.category || !howto.category.label) {
+ howto.category = commons_1.DEFAULT_HT_CATEGORY;
+ index_1.logger.error(`create howto : invalid category: ${howto.category} : ${howto.slug}`);
+ }
+ const user = (0, commons_1.getHowtoUser)(howto);
+ if (!user) {
+ index_1.logger.error(`create howto : invalid user : ${howto._createdBy} :: ${howto.title}`);
+ }
+ const howto_folder = (0, commons_1.kb_howto_folder)(howto);
+ const howto_cover_image = (0, commons_1.kb_howto_file)(howto, howto.cover_image.name);
+ if (!(0, exists_1.sync)(howto_folder)) {
+ index_1.logger.error('howto folder doesnt exists', howto.title);
+ }
+ if (!(0, exists_1.sync)(howto_cover_image)) {
+ index_1.logger.error('howto cover image doesnt exists', howto.title);
+ }
+ if (!user || !user.f_id) {
+ index_1.logger.error(`create howto : invalid user : ${howto._createdBy} :: ${howto.title}`);
+ return false;
+ }
+ howto.cover_image = await uploadImage(discourse, user, howto.cover_image, howto_cover_image);
+ updateHowtoFile(howto);
+ let invalid_images = false;
+ for (const step of howto.steps) {
+ let i = 0;
+ for await (const image of step.images) {
+ const image_name = (0, lib_1.sanitize)(image.name);
+ const imagePath = path.resolve(path.join(howto_folder, (0, lib_1.sanitize)(image_name)));
+ if (!(0, exists_1.sync)(imagePath)) {
+ index_1.logger.error('step image doesnt exists : ' + image.name + ' in ' + howto.slug);
+ invalid_images = true;
+ continue;
+ }
+ step.images[i] = await uploadImage(discourse, user, step.images[i], imagePath);
+ updateHowtoFile(howto);
+ i++;
+ }
+ }
+ if (invalid_images) {
+ index_1.logger.error('invalid images : ' + howto.slug);
+ return false;
+ }
+ const cat = constants_1.HT_CATS[howto.category.label];
+ if (!cat) {
+ index_1.logger.error('invalid kat');
+ return false;
+ }
+ const templatesRoot = path.resolve((0, fs_1.resolve)("${OSR_ROOT}/osr-templates/discourse"));
+ const cPath = path.resolve(`${templatesRoot}/base.json`);
+ index_1.logger.debug(`read config at ${cPath}`);
+ const config = (0, read_1.sync)(cPath, 'json');
+ const templates = path.resolve(`${templatesRoot}/howto`);
+ if (!(0, exists_1.sync)(templates)) {
+ index_1.logger.error(`\t Cant find templates at ${templates}, path doesn't exists`);
+ return;
+ }
+ let fragments = { ...config.variables };
+ (0, exports.read_fragments)(templates, fragments, "product_rel_path_name", "machine");
+ let template = (0, read_1.sync)(path.resolve(`${templates}/howto.md`), 'string');
+ let step = (0, read_1.sync)(path.resolve(`${templates}/step.md`), 'string');
+ (0, core_1.resolveConfig)(fragments);
+ const content = await howto_content(howto, howto_folder, fragments, {
+ howto: template,
+ step: '' + step
+ });
+ if (!content) {
+ index_1.logger.error('invalid content : ' + howto.slug);
+ return;
+ }
+ let data;
+ if (create) {
+ data = await discourse.createPost((0, lib_1.sanitize)(howto.title), content, cat);
+ if (data) {
+ index_1.logger.debug('created topic : ' + howto.title + ' : ' + data.id);
+ if (data && data.id) {
+ howto.post_id = data.id;
+ howto.topic_id = data.topic_id;
+ updateHowtoFile(howto);
+ try {
+ index_1.logger.debug('change user to ', user._id);
+ await discourse.changeOwner(howto.post_id, howto.topic_id, (0, users_1.get_user_name)(user));
+ }
+ catch (e) {
+ index_1.logger.debug('changing owner ' + howto.title + ' failed!');
+ howto.oF = true;
+ updateHowtoFile(howto);
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + howto.title + ' failed!', data.errors);
+ howto.post_id = 'failed';
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + howto.slug);
+ howto.post_id = 'already';
+ }
+ }
+ updateHowtoFile(howto);
+ }
+ }
+ }
+ else {
+ data = await discourse.updatePost(howto.post_id, content);
+ howto._updatedContent1 = true;
+ updateHowtoFile(howto);
+ }
+};
+exports.createHowtoTopic = createHowtoTopic;
+const importHowto = async (discorse, howto) => {
+ //const howtos = getHowtos()
+ //const index = howtos.findIndex((u) => u._id == howto._id)
+ const ret = await (0, exports.createHowtoTopic)(discorse, howto);
+ return ret;
+};
+exports.importHowto = importHowto;
+const importHowtos = async (discorse, options, howtos) => {
+ index_1.logger.debug('read howtos from ', path.resolve((0, commons_1.getHowtosPath)()));
+ howtos = (0, exports.mergeLatest)(discorse, options, howtos);
+ howtos = howtos.filter((h) => {
+ if (h.title === 'Build a Fishing Canoe') {
+ //debugger
+ }
+ if (h.post_id || h.post_id < 0) {
+ return false;
+ }
+ if (h.post_id === 'failed') {
+ index_1.logger.debug('skip failed : ' + h.slug);
+ return false;
+ }
+ //if (u.alreadyExists || u.invalidData) {
+ // return false;
+ //}
+ return true;
+ });
+ return await bluebird_1.Promise.resolve(howtos).map((h) => {
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = (0, exports.importHowto)(discorse, h);
+ if (d) {
+ d.then(resolve);
+ }
+ else {
+ reject();
+ }
+ }, 500);
+ });
+ }
+ catch (e) {
+ debugger;
+ index_1.logger.error('error creating howto ' + h._id, e);
+ }
+ }, { concurrency: 1 });
+};
+exports.importHowtos = importHowtos;
+/////////////////////////////////////////////////////////////////////////
+//
+// Update Howtos
+//
+let _discorseTags;
+const getDiscourseTags = async (discourse) => {
+ if (!_discorseTags) {
+ _discorseTags = await discourse.getTags();
+ }
+ return _discorseTags;
+};
+const updateHowto = async (discourse, howto, options) => {
+ const tags = (0, commons_1.read_tags)(options.src);
+ let howtoTags = [];
+ for (const ht in howto.tags) {
+ const t = ht;
+ const gt = tags.find((t) => {
+ return t._id === ht;
+ });
+ if (gt) {
+ howtoTags.push(gt.label);
+ }
+ else {
+ // logger.error('Cant resolve tag : ' + ht);
+ }
+ }
+ howtoTags.push('oa-import');
+ let discorseTags = await getDiscourseTags(discourse);
+ const cat = constants_1.HT_CATS[howto.category.label];
+ if (howtoTags && howtoTags.length) {
+ try {
+ const ret = await discourse.updateTopic(howto.topic_id, cat, (0, lib_1.sanitize)(howto.title), howtoTags);
+ index_1.logger.debug('Updating howto tags : ' + howto.title);
+ }
+ catch (error) {
+ index_1.logger.error('Error updating post' + howto.title, howto.topic_id, cat, howtoTags, error);
+ howto['updateFailed1'] = 1;
+ updateHowtoFile(howto);
+ //debugger
+ }
+ }
+ howto.updatedTags = true;
+ updateHowtoFile(howto);
+ const _date = howto._modified || howto._created;
+ if (_date) {
+ let date = new Date(_date);
+ index_1.logger.debug('update ts ' + howto.slug + ' : ' + new Date(date).toLocaleDateString());
+ let offset = 0;
+ const valueOf = date.valueOf() - (offset) * 60000;
+ let ts = Math.floor(valueOf / 1000);
+ const tUpdate = await discourse.updateTopicTimestamp(howto.topic_id, ts, FUCKING_TOKEN);
+ if (tUpdate) {
+ howto.updatedTime8 = true;
+ updateHowtoFile(howto);
+ return true;
+ }
+ }
+ else {
+ index_1.logger.error('Have no ts : ' + howto.slug);
+ }
+};
+exports.updateHowto = updateHowto;
+const updateHowtos = async (discorse, options, howtos) => {
+ index_1.logger.debug('update howtos from ', path.resolve((0, commons_1.getHowtosPath)()));
+ howtos = (0, exports.mergeLatest)(discorse, options, howtos);
+ const forceUpdateContent = true;
+ const forceUpdateMeta = true;
+ const updateContent = true;
+ const updateMeta = true;
+ howtos = howtos.filter((h) => {
+ if (!h.post_id || !h.topic_id) {
+ return false;
+ }
+ if (h.post_id === 'failed') {
+ index_1.logger.debug('skip failed : ' + h.slug);
+ return false;
+ }
+ if (forceUpdateContent || forceUpdateMeta) {
+ return true;
+ }
+ if (!h._updatedContent1) {
+ return true;
+ }
+ if (h.updatedTags && h.updatedTime8) {
+ return false;
+ }
+ if (!h.updatedTags || !h.updatedTime8) {
+ return true;
+ }
+ return true;
+ });
+ return await bluebird_1.Promise.resolve(howtos).map((h) => {
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ if (updateContent) {
+ index_1.logger.debug('\t recook howto content', h.title);
+ let d = (0, exports.createHowtoTopic)(discorse, h, false);
+ d.then(() => {
+ if (updateMeta) {
+ d = (0, exports.updateHowto)(discorse, h, options);
+ if (d) {
+ d.then(resolve);
+ }
+ else {
+ reject();
+ }
+ }
+ else {
+ resolve(1);
+ }
+ });
+ }
+ }, 500);
+ });
+ }
+ catch (e) {
+ debugger;
+ index_1.logger.error('error creating howto ' + h._id, e);
+ }
+ }, { concurrency: 1 });
+};
+exports.updateHowtos = updateHowtos;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaG93dG9zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9vYS9ob3d0b3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdUNBQThDO0FBRTlDLGlFQUEyRDtBQUMzRCwyQ0FBZ0Q7QUFDaEQsc0RBQXFEO0FBV3JELHVDQUVvQjtBQUVwQixzREFFK0I7QUFJL0IsK0JBQXlDO0FBRXpDLDZCQUE0QjtBQUM1Qiw4Q0FBa0Q7QUFDbEQsa0RBQXNEO0FBRXRELGdEQUFvRDtBQUVwRCx1REFBd0Q7QUFFeEQsbUNBQWtDO0FBQ2xDLG1DQUFpRDtBQUVqRCxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDeEMsNENBQWtEO0FBQ2xELGlFQUFtRDtBQUluRCxNQUFNLGFBQWEsR0FBRyx3RkFBd0YsQ0FBQTtBQUU5Ryx1Q0Fja0I7QUFFWCxNQUFNLFdBQVcsR0FBRyxDQUFDLFFBQVEsRUFBRSxPQUFpQixFQUFFLFNBQTJCLEVBQW9CLEVBQUU7SUFFdEcsTUFBTSxNQUFNLEdBQVUsSUFBQSxtQkFBUyxHQUFFLENBQUE7SUFDakMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3BCLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRTtZQUM3QixPQUFPLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQTtRQUMzQixDQUFDLENBQUMsQ0FBQTtRQUNGLElBQUksQ0FBQyxLQUFLLEVBQUU7WUFDUixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQ2pCO0lBRUwsQ0FBQyxDQUFDLENBQUE7SUFDRixJQUFBLFlBQUssRUFBQyxJQUFBLHVCQUFhLEdBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUM5QixPQUFPLE1BQU0sQ0FBQTtBQUNqQixDQUFDLENBQUE7QUFkWSxRQUFBLFdBQVcsZUFj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
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/index.d.ts b/packages/discourse/lib/oa/index.d.ts
new file mode 100644
index 00000000..7966de83
--- /dev/null
+++ b/packages/discourse/lib/oa/index.d.ts
@@ -0,0 +1,3 @@
+export * from './lib';
+export * from './users';
+export * from './types';
diff --git a/packages/discourse/lib/oa/index.js b/packages/discourse/lib/oa/index.js
new file mode 100644
index 00000000..c854f1a4
--- /dev/null
+++ b/packages/discourse/lib/oa/index.js
@@ -0,0 +1,20 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./lib"), exports);
+__exportStar(require("./users"), exports);
+__exportStar(require("./types"), exports);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL29hL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSx3Q0FBcUI7QUFDckIsMENBQXVCO0FBQ3ZCLDBDQUF1QiJ9
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/lib.d.ts b/packages/discourse/lib/oa/lib.d.ts
new file mode 100644
index 00000000..49c99ad8
--- /dev/null
+++ b/packages/discourse/lib/oa/lib.d.ts
@@ -0,0 +1,3 @@
+export declare const sanitize: (f: any) => string;
+export declare const getImageName: (url: any) => string;
+export declare const convert: (input: string) => any;
diff --git a/packages/discourse/lib/oa/lib.js b/packages/discourse/lib/oa/lib.js
new file mode 100644
index 00000000..696cd8ee
--- /dev/null
+++ b/packages/discourse/lib/oa/lib.js
@@ -0,0 +1,197 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.convert = exports.getImageName = exports.sanitize = void 0;
+const _sanitize = require("sanitize-filename");
+const URI = require("uri-js");
+const path = require("path");
+const filenamify = require('filenamify');
+var TurndownService = require('turndown');
+const sanitize = (f) => {
+ let str = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "");
+ if (str.startsWith('_')) {
+ str = str.substring(1);
+ }
+ return str;
+};
+exports.sanitize = sanitize;
+const getImageName = (url) => {
+ const parsed = URI.parse(decodeURIComponent(url));
+ const pParsed = path.parse(parsed.path);
+ const fileName = (0, exports.sanitize)(decodeURIComponent(pParsed.base));
+ return fileName;
+};
+exports.getImageName = getImageName;
+const convert = (input) => {
+ var turndownService = new TurndownService();
+ return turndownService.turndown(input);
+};
+exports.convert = convert;
+/*
+
+
+const getFUser = (users, user_name) => {
+ return users.find((u) => {
+ return u.name == user_name
+ })
+}
+
+
+const indexUsers = async (d, forum: string, detail) => {
+
+ const forumUsers = await getForumUsers(d, detail)
+ const raw = (read(path.resolve(forum + '/index.json'), 'json') as any)
+ const users_raw = raw.users
+ let users = []
+ for (let u in users_raw) {
+ const user = users_raw[u];
+ const avatar = getOAvatar(raw, u);
+ let aFileName = '';
+ let fUser = getFUser(forumUsers, u);
+ if (avatar) {
+ const parsed = URI.parse(avatar);
+ const pParsed = path.parse(parsed.path);
+ aFileName = pParsed.base;
+ }
+ users.push({
+ name: u,
+ avatar: avatar,
+ avatarFileName: aFileName,
+ user_id: fUser ? fUser.id : -1
+ });
+ }
+ write(path.resolve(forum + '/user.json'), users);
+}
+
+const _createUser = async (discorse, forum, name, email) => {
+
+ const users = getUsers()
+ const index = users.findIndex((u) => u.detail.name == name)
+ let user = await createUser(discorse, null)
+
+
+ if (user && users[index].upload_id) {
+ await discorse.setUserAvatar(name, users[index].upload_id);
+ //return users;
+ }
+
+ if (user > 0 && index) {
+ users[index].f_id = user;
+ console.log('created ' + name + ' ' + user);
+ write(getUsersPath(), users);
+ } else {
+ console.error('cant create user - error', name, user)
+ }
+}
+
+
+const _updateGroup = async (discorse, forum, name, id, forumUsers) => {
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const index = users.findIndex((u) => u.name == name);
+ try {
+ const d = await discorse.updateGroup(name, pUserGroup);
+ console.log('updated user group for ' + name);
+ users[index].g_id = pUserGroup;
+ write(path.resolve(forum + '/user.json'), users);
+ if (users[index].upload_id) {
+ //await discorse.setUserAvatar(name, users[index].upload_id);
+ }
+ } catch (e) {
+ if (e.data && e.data.status == 422) {
+ users[index].g_id = pUserGroup;
+ write(path.resolve(forum + '/user.json'), users);
+ console.log('updated user group for ' + name);
+ }
+ }
+}
+
+const _updateAvatar = async (discorse, forum, name) => {
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const index = users.findIndex((u) => u.name == name);
+ return new Promise((resolve, reject) => {
+ try {
+ setTimeout(() => {
+ discorse.setUserAvatar(name, users[index].upload_id).then(() => {
+ console.log('updated avatar for ' + name);
+ users[index].avatarSet = true;
+ write(path.resolve(forum + '/user.json'), users);
+ resolve(1);
+ });
+ }, 200);
+ } catch (e) {
+ console.error('-error setting avatar', e);
+ debugger;
+ }
+ });
+}
+
+
+const createUsers = async (d, forum) => {
+
+ const forumUsers = await getForumUsers(d, true)
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const toBeCreated = users.filter((u) => {
+ if (u.f_id || u.f_id < 0) {
+ return false;
+ }
+ if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
+ return false
+ }
+ return true;
+ });
+
+ console.log('Create Users ' + users.length + ' Total | Left: ' + toBeCreated.length);
+
+ return await BPromise.resolve(toBeCreated).map((u: any) => {
+ const t = _createUser(d, forum, u.name, u.email);
+ return t;
+ }, { concurrency: 1 })
+
+}
+
+const updateUserGroups = async (forum) => {
+ const forumUsers = (read(path.resolve(forum + '/fusers.json'), 'json') as any);
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const toBeUpdated = users.filter((u) => {
+ if (u.g_id) {
+ return false;
+ }
+ if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
+ return false
+ }
+ return true;
+ });
+ const d = getDiscourse();
+ console.log('Update Users ' + users.length + ' Total | Left: ' + toBeUpdated.length);
+ return await BPromise.resolve(toBeUpdated).map((u: any) => {
+ const t = _updateGroup(d, forum, u.name, u.f_id, forumUsers);
+ return t;
+ }, { concurrency: 1 })
+
+}
+
+const updateUserAvatars = async (forum) => {
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const toBeUpdated = users.filter((u) => {
+ if (!u.upload_id) {
+ return false;
+ }
+
+ if (u.avatarSet) {
+ return false;
+ }
+
+ if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
+ return false
+ }
+ return true;
+ });
+ const d = getDiscourse();
+ console.log('Update User Avatar ' + users.length + ' Total | Left: ' + toBeUpdated.length);
+ return await BPromise.resolve(toBeUpdated).map((u: any) => {
+ const t = _updateAvatar(d, forum, u.name);
+ return t;
+ }, { concurrency: 1 })
+
+}
+*/
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGliLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9vYS9saWIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUE7QUFDOUMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQzdCLDZCQUE0QjtBQUM1QixNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUE7QUFDeEMsSUFBSSxlQUFlLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ25DLE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUU7SUFDMUIsSUFBSSxHQUFHLEdBQVcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDeEUsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ3JCLEdBQUcsR0FBRyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFBO0tBQ3pCO0lBQ0QsT0FBTyxHQUFHLENBQUE7QUFDZCxDQUFDLENBQUE7QUFOWSxRQUFBLFFBQVEsWUFNcEI7QUFHTSxNQUFNLFlBQVksR0FBSSxDQUFDLEdBQUcsRUFBRSxFQUFFO0lBQ2pDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNsRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QyxNQUFNLFFBQVEsR0FBRyxJQUFBLGdCQUFRLEVBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7SUFDM0QsT0FBTyxRQUFRLENBQUE7QUFDbkIsQ0FBQyxDQUFBO0FBTFksUUFBQSxZQUFZLGdCQUt4QjtBQUVNLE1BQU0sT0FBTyxHQUFHLENBQUMsS0FBYSxFQUFFLEVBQUU7SUFDeEMsSUFBSSxlQUFlLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQTtJQUMzQyxPQUFPLGVBQWUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDeEMsQ0FBQyxDQUFBO0FBSFksUUFBQSxPQUFPLFdBR25CO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBdUtFIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/types.d.ts b/packages/discourse/lib/oa/types.d.ts
new file mode 100644
index 00000000..836543ee
--- /dev/null
+++ b/packages/discourse/lib/oa/types.d.ts
@@ -0,0 +1,91 @@
+import { IUploadedFileMeta, I_OSR_USER } from '@plastichub/osr-commons';
+export interface IOACategory {
+ _created: string;
+ _id: string;
+ _deleted: boolean;
+ label: string;
+ _modified: string;
+}
+export interface IOATag {
+ categories: string[];
+ image: string;
+ _created: string;
+ _deleted: boolean;
+ label: string;
+ _createdBy: string;
+ _modified: string;
+ _id: string;
+}
+export type IOADifficultyLevel = 'Easy' | 'Medium' | 'Hard' | 'Very Hard';
+export interface IDImage {
+ id: number;
+ url: string;
+ original_filename: string;
+ filesize: number;
+ width: number;
+ height: number;
+ thumbnail_width: number;
+ thumbnail_height: number;
+ extension: string;
+ short_url: string;
+ short_path: string;
+ retain_hours: any;
+ human_filesize: string;
+}
+export interface IOAHowto {
+ moderation: string;
+ category: IOACategory;
+ previousSlugs: string[];
+ total_downloads: number;
+ _createdBy: string;
+ slug: string;
+ cover_image: IUploadedFileMeta;
+ _modified: string;
+ files: any[];
+ description: string;
+ mentions: any[];
+ time: string;
+ _created: string;
+ fileLink: string;
+ steps: IOAStep[];
+ creatorCountry: string;
+ title: string;
+ tags: IOATags;
+ _id: string;
+ _deleted: boolean;
+ total_views: number;
+ difficulty_level: IOADifficultyLevel;
+ comments: any[];
+ user: IImportUser;
+ pics?: string[];
+}
+export interface IOAStep {
+ _animationKey: string;
+ images: IUploadedFileMeta[];
+ text: string;
+ title: string;
+}
+export interface IOATags {
+ [key: string]: boolean;
+}
+export type IOAHowtoImport = IOAHowto & {
+ post_id?: number | string;
+ topic_id?: number;
+ oF?: boolean;
+ updatedTags?: boolean;
+ updatedTime8?: boolean;
+ _updatedContent1?: boolean;
+};
+export interface IImportUser extends I_OSR_USER {
+ f_id: number;
+ upload_id: number;
+ avatar: string;
+ _didSetAvatar: boolean;
+ _didSetGroup: boolean;
+ alreadyExists: boolean;
+ invalidData: boolean;
+ didUpdateName: boolean;
+ profileHeader?: IDImage;
+ cardBackground?: IDImage;
+ avatarImage?: IDImage;
+}
diff --git a/packages/discourse/lib/oa/types.js b/packages/discourse/lib/oa/types.js
new file mode 100644
index 00000000..b1a4cd6c
--- /dev/null
+++ b/packages/discourse/lib/oa/types.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL29hL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/users.d.ts b/packages/discourse/lib/oa/users.d.ts
new file mode 100644
index 00000000..b6b09b40
--- /dev/null
+++ b/packages/discourse/lib/oa/users.d.ts
@@ -0,0 +1,30 @@
+import { I_OSR_USER } from '@plastichub/osr-commons';
+import { IOptions, IImportUser, IDiscourseUser } from '../../';
+import { Discourser } from '../index';
+export declare const read_users: (src: string) => I_OSR_USER[];
+export declare const filter_valid: (users: IImportUser[]) => IImportUser[];
+export declare const filter_email_only: (users: any[]) => any[];
+export declare const filter_invalid: (users: any[]) => any[];
+export declare const filter_email_missing: (users: any[]) => any[];
+export declare const filter_accepted: (users: IImportUser[]) => IImportUser[];
+export declare const oa_user_email: (user: I_OSR_USER) => string | false;
+export declare const get_user_name: (user: IImportUser) => string;
+export declare const get_user_display_name: (user: IImportUser) => string;
+export declare const getDataPath: (_path?: string) => string;
+export declare const getUsersPath: () => string;
+export declare const getUsers: () => IImportUser[];
+export declare const _getForumUsers: (d: Discourser, page: any, detail: any) => any;
+export declare const getForumUsers: (d: any, detail: any) => Promise;
+export declare const createUser: (discourse: Discourser, oa_user: IImportUser) => Promise;
+export declare const uploadAvatar: (discourse: any, name: any, filePath: any) => Promise;
+export declare const updateUser: (discorse: Discourser, oa_user: IImportUser) => Promise;
+export declare const importUser: (discorse: Discourser, oa_user: IImportUser) => Promise;
+export declare const mergeLatestUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => IImportUser[];
+export declare const mergeLatestUsersTest: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => IImportUser[];
+export declare const importUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => Promise;
+export declare const updateUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => Promise;
+export declare const md_edit_wrap: (content: any, f: any, prefix?: string, context?: string) => any;
+export declare const toHTML: (path: any, markdown: any) => any;
+export declare const imageName: (url: any) => string;
+export declare const read_fragments: (src: any, config: any, prefix?: string, context?: string) => any;
+export declare const indexUsers: (discorse: any, options: IOptions, oa_users: I_OSR_USER[]) => Promise;
diff --git a/packages/discourse/lib/oa/users.js b/packages/discourse/lib/oa/users.js
new file mode 100644
index 00000000..399e4d4a
--- /dev/null
+++ b/packages/discourse/lib/oa/users.js
@@ -0,0 +1,936 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.indexUsers = exports.read_fragments = exports.imageName = exports.toHTML = exports.md_edit_wrap = exports.updateUsers = exports.importUsers = exports.mergeLatestUsersTest = exports.mergeLatestUsers = exports.importUser = exports.updateUser = exports.uploadAvatar = exports.createUser = exports.getForumUsers = exports._getForumUsers = exports.getUsers = exports.getUsersPath = exports.getDataPath = exports.get_user_display_name = exports.get_user_name = exports.oa_user_email = exports.filter_accepted = exports.filter_email_missing = exports.filter_invalid = exports.filter_email_only = exports.filter_valid = exports.read_users = void 0;
+const bluebird_1 = require("bluebird");
+const lib_1 = require("./lib");
+const utils_1 = require("@plastichub/core/utils");
+const path = require("path");
+const read_1 = require("@plastichub/fs/read");
+const exists_1 = require("@plastichub/fs/exists");
+const write_1 = require("@plastichub/fs/write");
+const fs_1 = require("@plastichub/osr-commons");
+const index_1 = require("../../index");
+const slugify = require('slugify');
+const core_1 = require("@plastichub/core");
+const js_beautify_1 = require("js-beautify");
+const dir_1 = require("@plastichub/fs/dir");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const showdown_1 = require("showdown");
+const URI = require("uri-js");
+const constants_1 = require("../discourse/constants");
+const filenamify = require('filenamify');
+const fg = require('fast-glob');
+const TEST = false;
+const read_users = (src) => {
+ const raw = (0, read_1.sync)(src, 'json');
+ return raw.v3_mappins.filter((f) => f.data != null);
+};
+exports.read_users = read_users;
+const filter_valid = (users) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (!user.data.title) {
+ return false;
+ }
+ if (!user.detail) {
+ return false;
+ }
+ if (!user.detail.heroImageUrl) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ if (user.moderation !== 'accepted') {
+ //return false
+ }
+ return true;
+ });
+};
+exports.filter_valid = filter_valid;
+const filter_email_only = (users) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ if (!user.detail) {
+ return false;
+ }
+ if (!user.detail.name) {
+ return false;
+ }
+ if (user.data.urls.find((l) => l.name == 'Email') == undefined) {
+ return false;
+ }
+ return true;
+ });
+};
+exports.filter_email_only = filter_email_only;
+const filter_invalid = (users) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ if (!user.detail.name) {
+ return true;
+ }
+ if (user.data.urls.find((l) => l.name == 'Email') == undefined) {
+ return true;
+ }
+ if (user.moderation !== 'accepted') {
+ return true;
+ }
+ return false;
+ });
+};
+exports.filter_invalid = filter_invalid;
+const filter_email_missing = (users) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ if (!user.detail) {
+ return false;
+ }
+ if (!user.detail.name) {
+ return false;
+ }
+ if (user.moderation !== 'accepted') {
+ return false;
+ }
+ if (!user.data.urls.find((l) => l.name == 'Email')) {
+ return true;
+ }
+ return false;
+ });
+};
+exports.filter_email_missing = filter_email_missing;
+const filter_accepted = (users) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (!user.detail.heroImageUrl) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ if (user.moderation !== 'accepted') {
+ return false;
+ }
+ return true;
+ });
+};
+exports.filter_accepted = filter_accepted;
+const oa_user_email = (user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ let u = user.data.urls.find((l) => l.name == 'Email');
+ if (u) {
+ return u.url.replace('mailto:', '');
+ }
+};
+exports.oa_user_email = oa_user_email;
+const get_user_name = (user) => {
+ let ret = (0, utils_1.replaceAll)('--', '-', (0, lib_1.sanitize)(filenamify(user._id)).replace(/^\-+/g, '').replace(/\-$/, ''));
+ ret = ret.replace(/\-$/, '');
+ ret = ret.replace(/\_$/, '');
+ if (!(0, exports.oa_user_email)(user)) {
+ ret += '-uc';
+ }
+ return ret;
+};
+exports.get_user_name = get_user_name;
+const get_user_display_name = (user) => (0, utils_1.replaceAll)('--', '-', (0, lib_1.sanitize)(filenamify(user.data.title)).replace(/^\-+/g, '').replace(/\-$/, ''));
+exports.get_user_display_name = get_user_display_name;
+const getDataPath = (_path = '') => path.resolve(path.join((0, fs_1.resolve)(constants_1.DATA_PATH), _path));
+exports.getDataPath = getDataPath;
+const getUsersPath = () => path.resolve((0, fs_1.resolve)(TEST ? constants_1.LATEST_TEST : constants_1.LATEST_TRACK));
+exports.getUsersPath = getUsersPath;
+const getUsers = () => (0, read_1.sync)(path.resolve((0, exports.getUsersPath)()), 'json') || [];
+exports.getUsers = getUsers;
+let uPage = 1;
+let usersAll = [];
+const _getForumUsers = async (d, page, detail) => {
+ if (uPage == 1) {
+ usersAll = [];
+ }
+ let users = await d.getUsers(page);
+ if (users.length) {
+ usersAll = usersAll.concat(users);
+ uPage++;
+ return (0, exports._getForumUsers)(d, uPage, detail);
+ }
+ else {
+ uPage = 1;
+ (0, write_1.sync)(path.resolve(constants_1.F_USERS_NOW), usersAll);
+ let fUsers = (0, read_1.sync)(path.resolve(constants_1.F_USERS_ALL), 'json') || [];
+ const add = async (u) => {
+ return new Promise((resolve, reject) => {
+ let fUser = fUsers.find((fu) => u.id == fu.id);
+ if (!fUser) {
+ fUsers.push(u);
+ fUser = u;
+ }
+ if (!fUser.detail) {
+ index_1.logger.debug('Retrieve User Detail ' + u.name);
+ setTimeout(() => {
+ d.getUser(fUser.id).then((detail) => {
+ if (detail) {
+ fUser.detail = detail;
+ }
+ (0, write_1.sync)(path.resolve('./fusers-all.json'), fUsers);
+ resolve(fUser);
+ });
+ }, 200);
+ }
+ else {
+ resolve(fUser);
+ }
+ });
+ };
+ return await bluebird_1.Promise.resolve(usersAll).map((u) => {
+ return add(u);
+ }, { concurrency: 1 });
+ }
+};
+exports._getForumUsers = _getForumUsers;
+const getForumUsers = async (d, detail) => {
+ if (!constants_1.FETCH_DUSERS) {
+ return (0, read_1.sync)((0, exports.getDataPath)(constants_1.F_USERS_ALL), 'json') || [];
+ }
+ return (0, exports._getForumUsers)(d, uPage, detail);
+};
+exports.getForumUsers = getForumUsers;
+const createUser = async (discourse, oa_user) => {
+ /*
+ Bazar
+ https://shop.osr-plastic.org
+ Website
+ website2
+ Instagram
+ https://www.instagram.com/osr_plastic/
+ Directory / Map Url
+ https://www.google.com/maps/contrib/117674167598277014013
+ OSR - Marketplace Url
+ https://shop.osr-plastic.org/plastichub/
+ */
+ if (!oa_user.data.title) {
+ return -120;
+ }
+ let name = (0, utils_1.replaceAll)('--', '-', (0, exports.get_user_display_name)(oa_user).replace(/^\-+/g, '').replace(/\-$/, ''));
+ let user_name = (0, exports.get_user_name)(oa_user);
+ name = user_name.replace(/\-$/, '');
+ name = user_name.replace(/\_$/, '');
+ let opts = {
+ "name": name,
+ "email": (0, exports.oa_user_email)(oa_user) || `${user_name}_uc@osr-plastic.org`,
+ "password": (0, constants_1.DEFAULT_PASSWORD)(),
+ "username": user_name,
+ "active": true,
+ "approved": true,
+ "user_fields[1]": true
+ };
+ let user = await discourse.createUser(opts);
+ if (name.length < 4) {
+ return -120;
+ }
+ if (user_name.length > 50) {
+ return -120;
+ }
+ if (user && user.errors) {
+ if (user.message === "Username must be no more than 50 characters" ||
+ user.message === 'Username must not contain a sequence of 2 or more special chars (.-_)') {
+ return -120;
+ }
+ if (user.message === "Username must be unique" || user.message === "Primary email has already been taken") {
+ return -100;
+ }
+ if (user.errors.email && user.errors.username) {
+ user = await discourse.getUserByUsername(user_name);
+ if (user && user.id && !oa_user._didSetGroup) {
+ try {
+ let gret = await discourse.updateGroup(user_name, constants_1.OA_USER_IMPORT_GROUP);
+ }
+ catch (e) {
+ index_1.logger.error('error adding to group', user_name);
+ }
+ return user.id;
+ }
+ ;
+ }
+ index_1.logger.error('Error creating user ' + user_name, user.errors);
+ }
+ if (user && user.user_id) {
+ try {
+ await discourse.updateGroup(user_name, constants_1.OA_USER_IMPORT_GROUP);
+ return user.user_id;
+ }
+ catch (e) {
+ index_1.logger.error('error adding to group', user_name);
+ return user.user_id;
+ }
+ }
+ else {
+ if (user && user.message && user.message == 'Username must be unique\nPrimary email has already been taken') {
+ index_1.logger.error('already created', oa_user.detail.name);
+ return -10;
+ }
+ else if (user && user.message && user.message == 'Your account is activated and ready to use.') {
+ if (user.user_id) {
+ return user.user_id;
+ }
+ return -10;
+ }
+ else {
+ index_1.logger.debug('cant create user ' + oa_user.detail.name, user);
+ }
+ return null;
+ }
+ return null;
+};
+exports.createUser = createUser;
+const uploadAvatar = async (discourse, name, filePath) => {
+ const users = (0, exports.getUsers)();
+ const index = users.findIndex((u) => u.detail.name == name);
+ try {
+ const upped = await discourse.upload(1, filePath);
+ const data = upped.data;
+ if (data && data.id) {
+ users[index].upload_id = data.id;
+ index_1.logger.debug('uploaded avatar ' + name + ' ' + data.id);
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ }
+ else {
+ index_1.logger.error('upload - error', name);
+ }
+ return users;
+ }
+ catch (error) {
+ users[index].upload_id = -1;
+ index_1.logger.error('error uploading avatar', name);
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ }
+};
+exports.uploadAvatar = uploadAvatar;
+const uploadAvatars = async (discourse, users) => {
+ const toBeUploaded = users.filter((u) => {
+ if (u.upload_id) {
+ return false;
+ }
+ const hero = (0, lib_1.getImageName)(u.detail.heroImageUrl);
+ const avatar = findAvatar(u, hero);
+ if (!avatar) {
+ index_1.logger.error('cant find avatar : ', u._id, hero);
+ return false;
+ }
+ u.avatar = avatar;
+ return true;
+ });
+ return await bluebird_1.Promise.resolve(toBeUploaded).map((u) => {
+ if (!u.detail.name) {
+ return;
+ }
+ index_1.logger.debug('upload avatar : ' + u._id);
+ const t = (0, exports.uploadAvatar)(discourse, u.detail.name, u.avatar);
+ return t;
+ }, { concurrency: 1 });
+};
+const findAvatar = (user, filename) => {
+ const root = path.resolve((0, fs_1.resolve)(constants_1.DATA_PATH));
+ const _path = path.resolve(`${root}/${user._id}/${filename}`);
+ if ((0, exists_1.sync)(_path)) {
+ return _path;
+ }
+ const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: root, absolute: true });
+ if (files.length == 0) {
+ return false;
+ }
+ return files[0];
+};
+/////////////////////////////////////////////////////
+//
+// users
+//
+const updateUser = async (discorse, oa_user) => {
+ const users = (0, exports.getUsers)();
+ const index = users.findIndex((u) => u.detail.name == oa_user.detail.name);
+ const user_name = (0, utils_1.replaceAll)('--', '-', (0, exports.get_user_name)(oa_user).replace(/^\-+/g, '').replace(/\-$/, ''));
+ let ret = null;
+ try {
+ ret = await discorse.updateUser(user_name, {
+ name: oa_user.data.title
+ });
+ try {
+ let location;
+ if (oa_user.geo) {
+ location = `${oa_user.geo.continent} / ${oa_user.geo.countryName} / ${oa_user.geo.city} `;
+ }
+ let website;
+ if (oa_user.data) {
+ website = oa_user.data.urls.find((l) => l.name == 'Website');
+ if (website) {
+ website = website.url;
+ }
+ }
+ let description;
+ if (oa_user.data) {
+ if (oa_user.data.description) {
+ description += oa_user.data.description;
+ }
+ description += '\n';
+ if (oa_user.data.services) {
+ let services = `### Services \n`;
+ let hasServices = false;
+ for (let s in oa_user.data.services[0]) {
+ if (oa_user.data.services[0][s]) {
+ services += `- [x] ${(0, utils_1.capitalize)(s)}\n`;
+ hasServices = true;
+ }
+ }
+ if (hasServices) {
+ description += services;
+ }
+ }
+ }
+ let links = '';
+ if (oa_user.data.urls) {
+ links = oa_user.data.urls.filter((r) => r.name !== 'Bazar' && r.name !== 'sponsor the work').map((l) => {
+ let label = '' + l.name;
+ if (label === 'Social media') {
+ if (l.url.indexOf('facebook') !== -1) {
+ label = 'Facebook';
+ }
+ if (l.url.indexOf('instagram') !== -1) {
+ label = 'Instagram';
+ }
+ }
+ label += " - " + l.url;
+ label = label.replace("https://", "");
+ label = label.replace("http://", "");
+ label = label.replace("mailto:", "");
+ return `${label} `;
+ }).join(" \n");
+ description += '\n### Links\n';
+ description += links;
+ }
+ if (oa_user.location) {
+ description += `\n\n Get Directions \n`;
+ }
+ let updatePrefs = await discorse.updateUserProfile(user_name, {
+ bio_raw: (0, utils_1.replaceAll)('undefined', '', description),
+ location,
+ website
+ });
+ }
+ catch (error) {
+ index_1.logger.error(`Error updating user prefs : ${user_name}`);
+ }
+ }
+ catch (error) {
+ index_1.logger.error('error updating user', oa_user._id, error.message);
+ return;
+ }
+ if (ret.status === 200) {
+ users[index].didUpdateName = true;
+ index_1.logger.debug('did update user', oa_user._id, ' # ', oa_user.data.title);
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ }
+ else {
+ index_1.logger.error('did update user failed ', oa_user._id);
+ }
+};
+exports.updateUser = updateUser;
+const importUser = async (discorse, oa_user) => {
+ const users = (0, exports.getUsers)();
+ const index = users.findIndex((u) => u._id == oa_user._id);
+ let user = null;
+ try {
+ user = await (0, exports.createUser)(discorse, oa_user);
+ }
+ catch (error) {
+ debugger;
+ index_1.logger.error('error creating user', error);
+ return false;
+ }
+ if (user === -100) {
+ users[index].alreadyExists = true;
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ return;
+ }
+ if (user === -120) {
+ users[index].invalidData = true;
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ return;
+ }
+ if (user && users[index].upload_id && !users[index]._didSetAvatar) {
+ try {
+ await discorse.setUserAvatar((0, exports.get_user_name)(oa_user), users[index].upload_id);
+ }
+ catch (e) {
+ index_1.logger.error('error setting avatar', (0, exports.get_user_name)(oa_user));
+ }
+ }
+ const _t = users[index];
+ if (user > 0) {
+ users[index].f_id = user;
+ users[index]._didSetAvatar = true;
+ users[index]._didSetGroup = true;
+ index_1.logger.debug('\t created ' + oa_user.data.title);
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ }
+ else {
+ index_1.logger.error('cant create user - error', oa_user.detail.name, user);
+ }
+ return users[index];
+};
+exports.importUser = importUser;
+const mergeLatestUsers = (discorse, options, oa_users) => {
+ const users = (0, exports.getUsers)();
+ oa_users.forEach((u) => {
+ const tUser = users.find((tu) => {
+ return tu._id === u._id;
+ });
+ if (!tUser) {
+ users.push(u);
+ }
+ });
+ index_1.logger.debug(`Merged users to ${(0, exports.getUsersPath)()}`);
+ (0, write_1.sync)((0, exports.getUsersPath)(), users);
+ return users;
+};
+exports.mergeLatestUsers = mergeLatestUsers;
+const mergeLatestUsersTest = (discorse, options, oa_users) => {
+ const users = ((0, read_1.sync)(constants_1.LATEST_TEST, 'json') || []);
+ oa_users.forEach((u) => {
+ const tUser = users.find((u) => {
+ return u._id === u._id;
+ });
+ if (!tUser) {
+ users.push(u);
+ }
+ });
+ (0, write_1.sync)(options.track, users);
+ return users;
+};
+exports.mergeLatestUsersTest = mergeLatestUsersTest;
+const importUsers = async (discorse, options, oa_users) => {
+ index_1.logger.debug('read users from ', path.resolve((0, exports.getUsersPath)()));
+ let users = (0, exports.mergeLatestUsers)(discorse, options, oa_users);
+ //const users = mergeLatestUsersTest(discorse, options, oa_users)
+ users = users.filter((u) => {
+ if (u.f_id || u.f_id < 0) {
+ return false;
+ }
+ if (u.detail.name === 'plastichub' || u.detail.name === 'lu' || u.detail.name === 'timberstar' || u.detail.name === 'nickname') {
+ return false;
+ }
+ if (u.alreadyExists || u.invalidData) {
+ return false;
+ }
+ return true;
+ });
+ index_1.logger.debug('Create Users ' + users.length + ' Total | Left: ' + users.length);
+ await uploadAvatars(discorse, users);
+ return await bluebird_1.Promise.resolve(users).map((u) => {
+ index_1.logger.debug('import user ' + (0, exports.get_user_name)(u));
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = (0, exports.importUser)(discorse, u);
+ if (d) {
+ d.then(resolve);
+ }
+ else {
+ reject();
+ }
+ }, 500);
+ });
+ }
+ catch (e) {
+ debugger;
+ index_1.logger.error('error creating user ' + u._id, e);
+ }
+ }, { concurrency: 1 });
+};
+exports.importUsers = importUsers;
+const updateUsers = async (discorse, options, oa_users) => {
+ // https://forum.osr-plastic.org/u/easymoulds/preferences/profile
+ const users = (0, exports.mergeLatestUsers)(discorse, options, oa_users);
+ //const users = mergeLatestUsersTest(discorse, options, oa_users)
+ let toBeCreated = users.filter((u) => {
+ if (u.f_id || u.f_id < 0) {
+ return true;
+ }
+ if (u.didUpdateName) {
+ return false;
+ }
+ return true;
+ });
+ const testUser = 'easymoulds';
+ const test = toBeCreated.find((u) => {
+ return u._id === testUser;
+ });
+ // toBeCreated = [test]
+ return await bluebird_1.Promise.resolve(toBeCreated).map((u) => {
+ /*
+ if (u.didUpdateName) {
+ return false
+ }
+ */
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = (0, exports.updateUser)(discorse, u);
+ if (d) {
+ d.then(resolve);
+ }
+ else {
+ reject();
+ }
+ }, 200);
+ });
+ }
+ catch (e) {
+ debugger;
+ index_1.logger.error('error creating user ' + u._id, e);
+ }
+ }, { concurrency: 1 });
+};
+exports.updateUsers = updateUsers;
+const md_edit_wrap = (content, f, prefix = '', context = '') => {
+ return (0, js_beautify_1.html_beautify)(`${content}
`);
+};
+exports.md_edit_wrap = md_edit_wrap;
+const toHTML = (path, markdown) => {
+ const content = (0, read_1.sync)(path, 'string');
+ if (!markdown) {
+ let converter = new showdown_1.Converter({ tables: true });
+ converter.setOption('literalMidWordUnderscores', 'true');
+ return converter.makeHtml(content);
+ }
+ else {
+ return content;
+ }
+};
+exports.toHTML = toHTML;
+const imageName = (url) => {
+ if (!url) {
+ return "";
+ }
+ try {
+ const parsed = URI.parse(decodeURIComponent(url));
+ const pParsed = path.parse(parsed.path);
+ return (0, lib_1.sanitize)(decodeURIComponent(pParsed.base));
+ }
+ catch (error) {
+ index_1.logger.error('error image name : ', url);
+ return "";
+ }
+};
+exports.imageName = imageName;
+const read_fragments = (src, config, prefix = '', context = '') => {
+ if (!(0, exists_1.sync)(src)) {
+ //debug.warn(`Create template folder ${src}`);
+ (0, dir_1.sync)(src);
+ }
+ let fragments = (0, osr_cli_commons_1.files)(src, '*.html');
+ fragments.map((f) => {
+ config[path.parse(f).name] = (0, exports.md_edit_wrap)((0, exports.toHTML)(f, true), f, prefix, context);
+ });
+ fragments = (0, osr_cli_commons_1.files)(src, '*.md');
+ fragments.map((f) => {
+ config[path.parse(f).name] = (0, exports.md_edit_wrap)((0, exports.toHTML)(f, false), f, prefix, context);
+ });
+ return config;
+};
+exports.read_fragments = read_fragments;
+const indexUsers = async (discorse, options, oa_users) => {
+ let users = (0, exports.mergeLatestUsers)(discorse, options, oa_users);
+ users = users.filter((u) => {
+ if (u.f_id && u.data && u.geo) {
+ return true;
+ }
+ return false;
+ });
+ const continents = [];
+ const countries = [];
+ const navIndex = [];
+ users.forEach((u) => {
+ if (!u.geo || !u.data || u.data.jsError || !u.detail || !u.detail.heroImageUrl) {
+ return;
+ }
+ if (!u.detail.heroImageUrl) {
+ return;
+ }
+ let code = null;
+ if (u.geo.continent && continents.indexOf(u.geo.continent) == -1) {
+ continents.push(u.geo.continent);
+ navIndex.push({
+ title: u.geo.continent,
+ url: `/users/${slugify(u.geo.continent)}.html`,
+ children: [],
+ code: u.geo.continentCode
+ // code:u.geo.continentCode
+ });
+ }
+ if (countries.indexOf(u.geo.countryName) == -1) {
+ countries.push(u.geo.countryName);
+ }
+ const c = navIndex.find((c) => c.title === u.geo.continent);
+ if (c) {
+ const cc = c.children.find((i) => i.title == u.geo.countryName);
+ if (!cc) {
+ c.children.push({
+ title: u.geo.countryName,
+ url: `/users/${slugify(c.title)}.html#${slugify(u.geo.countryName.toLocaleLowerCase())}`,
+ postTitle: `Directory - ${u.geo.countryName}`
+ });
+ }
+ }
+ });
+ navIndex.sort((a, b) => {
+ if (a.title < b.title) {
+ return -1;
+ }
+ if (a.title > b.title) {
+ return 1;
+ }
+ return 0;
+ });
+ navIndex.forEach((c) => {
+ c.children.sort((a, b) => {
+ if (a.title < b.title) {
+ return -1;
+ }
+ if (a.title > b.title) {
+ return 1;
+ }
+ return 0;
+ });
+ });
+ const directoryRoot = path.resolve((0, fs_1.resolve)('${OSR_ROOT}/osr-directory/pp'));
+ const createContinentPage = (continent) => {
+ const templates_path = path.resolve(`${directoryRoot}/templates`);
+ if (!(0, exists_1.sync)(templates_path)) {
+ index_1.logger.error(`\t Cant find templates at ${templates_path}, path doesn't exists`);
+ return;
+ }
+ const cPath = path.resolve(`${directoryRoot}/templates/config.json`);
+ const config = (0, read_1.sync)(cPath, 'json');
+ let fragments = { ...config };
+ (0, exports.read_fragments)(templates_path, fragments, "product_rel_path_name", "machine");
+ let templateCountry = (0, read_1.sync)(path.resolve(`${templates_path}/country_users.md`), 'string');
+ const ccountries = {};
+ let code = null;
+ users.forEach((u) => {
+ if (!u.geo || !u.data || u.data.jsError || !u.detail || !u.detail.heroImageUrl) {
+ return;
+ }
+ if (!u.detail.heroImageUrl) {
+ return;
+ }
+ if (u.geo.continent && u.geo.continent === continent) {
+ if (!code) {
+ code = u.geo.continentCode;
+ }
+ if (!ccountries[u.geo.countryName]) {
+ ccountries[u.geo.countryName] = [];
+ }
+ ccountries[u.geo.countryName].push(u);
+ }
+ });
+ if (continent === 'Africa') {
+ //debugger;
+ }
+ let weight = 100;
+ for (var country in ccountries) {
+ let cPage = "";
+ if (country === 'Kenya') {
+ //debugger;
+ }
+ cPage += `\n#### ${slugify(country)}\n\n`;
+ if (country === 'undefined' || country === 'unknown' || !country) {
+ return;
+ }
+ cPage += '';
+ cPage += '
';
+ let cusers = ccountries[country];
+ cusers = cusers.sort((a, b) => a.type === b.type ? 1 : -1);
+ const cUsersC = cusers.map((u) => {
+ const prefix = u.moderation === 'rejected' ? "
Censored " : "";
+ const image = `/users/${u._id}/${encodeURIComponent((0, lib_1.sanitize)((0, exports.imageName)(u.detail.heroImageUrl)))}`;
+ const title = u.data && u.data.title ? u.data.title : u._id;
+ const uUrl = `/directory/users/${u._id}`;
+ let censored = u.moderation === 'rejected' ? '
Yes ' : 'No';
+ return `
+
+
+
+
${title}
+
Type: ${u.type}
+
Censored: ${censored}
+
+
${u.geo.principalSubdivision} / ${u.geo.locality} - ${u.geo.principalSubdivisionCode} - ${u.geo.postcode}
+
+
`;
+ });
+ cPage += cUsersC.join('');
+ cPage += '
';
+ country = country.replace(' (the)', '');
+ /*
+ const cPagePath = path.resolve(`${kb}/src/directory/users_${sanitize(slugify(country))}-${code}.md`)
+
+ const title = 'Users - ' + country;
+
+ cPage = substitute(templateCountry, {
+ ...fragments,
+ title: title,
+ keywords: 'Precious Plastic, Precious Plastic Users - ' + country,
+ content: html_beautify(cPage),
+ continent: slugify(continent),
+ country: slugify(country),
+ identifier: country + "-" + continent,
+ weight: weight
+ });
+
+ weight++;
+ write(cPagePath, cPage);
+ console.log('write ' + cPagePath);
+ */
+ }
+ /*
+ content = substitute(template, {
+ ...fragments,
+ title: 'Precious Plastic - Users ' + continent,
+ keywords: 'Precious Plastic, Precious Plastic Users - ' + continent,
+ content: content,
+ continent: slugify(continent)
+ });
+ */
+ //const index_md = path.resolve(`${root}/_pages/users_${code}.md`);
+ //write(index_md, content);
+ };
+ const templates_path = path.resolve(`${directoryRoot}/templates`);
+ const createCountryPages = async (index, indexPath) => {
+ let i = 0;
+ for await (const continent of index) {
+ const countries = continent.children;
+ for await (const country of countries) {
+ const d = 0;
+ }
+ }
+ };
+ await createCountryPages(navIndex, './');
+ const createIntroPage = async (users, index, dst) => {
+ let template = (0, read_1.sync)(path.resolve(`${templates_path}/intro_users.md`));
+ let content = "";
+ const usersPerCountry = (country) => {
+ return users.filter((u) => u.geo.countryName === country);
+ };
+ index.forEach((i) => {
+ const heading = `## ${i.title}`;
+ let countries = '';
+ i.children.forEach((c) => {
+ let title = c.title.replace(/ *\([^)]*\) */g, "");
+ const nb = usersPerCountry(c.title).length;
+ title = `${title} \(${nb}\)`;
+ const cPagePath = `/directory/users_${(0, lib_1.sanitize)(slugify(c.title))}-${i.code}`;
+ countries += `- [${(title)}](${cPagePath.toLowerCase()})\n`;
+ });
+ content += `${heading}\n ${countries}`;
+ });
+ (0, write_1.sync)(dst, (0, core_1.substitute)(template, {
+ content: content,
+ /*hidden: data.v3_mappins.filter((u) => u.moderation !== "accepted").length,
+ total: data.v3_mappins.length*/
+ }));
+ let data;
+ try {
+ data = await discorse.updatePost(constants_1.OA_DIRECTORY_OVERVIEW_TOPIC, content);
+ debugger;
+ //logger.debug('update post : ' + options.title + ' : ' + data.id + ' | topic id ' + data.topic_id)
+ }
+ catch (e) {
+ return false;
+ }
+ };
+ // await createIntroPage(users, navIndex, './index.md')
+ /*
+
+ return await BPromise.resolve(users).map((u: IImportUser) => {
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = updateUser(discorse, u)
+ if (d) {
+ d.then(resolve)
+ } else {
+ reject()
+ }
+ }, 200)
+
+ })
+
+ } catch (e) {
+ debugger;
+ logger.error('error creating user ' + u._id, e)
+ }
+ }, { concurrency: 1 })
+
+ */
+};
+exports.indexUsers = indexUsers;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL29hL3VzZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHVDQUE4QztBQUs5QywrQkFBOEM7QUFFOUMsa0RBQXdFO0FBQ3hFLDZCQUE0QjtBQUM1Qiw4Q0FBa0Q7QUFDbEQsa0RBQXNEO0FBQ3RELGdEQUFvRDtBQUVwRCx1REFBd0Q7QUFFeEQsdUNBQW9DO0FBRXBDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUVsQywyQ0FBNEQ7QUFFNUQsNkNBQTJDO0FBQzNDLDRDQUFrRDtBQUNsRCxpRUFBa0U7QUFDbEUsdUNBQW9DO0FBQ3BDLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUU3QixzREFXK0I7QUFLL0IsTUFBTSxVQUFVLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO0FBQ3hDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUcvQixNQUFNLElBQUksR0FBRyxLQUFLLENBQUE7QUFJWCxNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQVcsRUFBZ0IsRUFBRTtJQUNwRCxNQUFNLEdBQUcsR0FBRyxJQUFBLFdBQUksRUFBQyxHQUFHLEVBQUUsTUFBTSxDQUFRLENBQUE7SUFDcEMsT0FBTyxHQUFHLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsQ0FBQTtBQUN2RCxDQUFDLENBQUE7QUFIWSxRQUFBLFVBQVUsY0FHdEI7QUFFTSxNQUFNLFlBQVksR0FBRyxDQUFDLEtBQW9CLEVBQUUsRUFBRTtJQUNqRCxPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtRQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNaLE9BQU8s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
\ No newline at end of file
diff --git a/packages/discourse/lib/oa/utils.d.ts b/packages/discourse/lib/oa/utils.d.ts
new file mode 100644
index 00000000..90a40b1e
--- /dev/null
+++ b/packages/discourse/lib/oa/utils.d.ts
@@ -0,0 +1,26 @@
+import { Discourser } from '../index';
+export declare const uploadFile: (discourse: any, forum: any, name: any, filePath: any) => Promise;
+export declare const findReplyPage: (b: any, pages: any) => any;
+export declare const findReplyUpload: (u: any, page: any) => any;
+export declare const getPages: (topics: any, topic: any) => any;
+export declare const getReplies: (topics: any, topic: any) => any[];
+export declare const findFile: (folder: any, filename: any) => any;
+export declare const topicFolder: (forum: any, folder: any, title: any) => string;
+export declare const getFUser: (users: any, user_name: any) => any;
+export declare const dOptions: {
+ host: string;
+ key: string;
+ username: string;
+ rateLimitConcurrency: number;
+};
+export declare const getOAvatar: (index: any, user: any) => any;
+export declare const getTopics: (index: any) => any[];
+export declare const convert: (input: string) => any;
+export declare const getDiscourse: () => Discourser;
+export declare function inspect(arg: any): string;
+export declare function log(...args: any[]): void;
+export declare function mkdirp(path: string): Promise;
+export declare function readJSON(path: string): Promise;
+export declare function writeJSON(path: string, data: object): Promise;
+export declare function exists(path: string): Promise;
+export declare function escape(path: string): string;
diff --git a/packages/discourse/lib/oa/utils.js b/packages/discourse/lib/oa/utils.js
new file mode 100644
index 00000000..f553ad16
--- /dev/null
+++ b/packages/discourse/lib/oa/utils.js
@@ -0,0 +1,172 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.escape = exports.exists = exports.writeJSON = exports.readJSON = exports.mkdirp = exports.log = exports.inspect = exports.getDiscourse = exports.convert = exports.getTopics = exports.getOAvatar = exports.dOptions = exports.getFUser = exports.topicFolder = exports.findFile = exports.getReplies = exports.getPages = exports.findReplyUpload = exports.findReplyPage = exports.uploadFile = void 0;
+const fs_1 = require("fs");
+const util_1 = require("util");
+const cwd = process.cwd();
+var TurndownService = require('turndown');
+const index_1 = require("../index");
+const path = require("path");
+const fg = require('fast-glob');
+const slugify_1 = require("slugify");
+var sanitize = require("sanitize-filename");
+//import { replaceAll } from '../../lib';
+var mom = require('moment');
+const uploadFile = async (discourse, forum, name, filePath) => {
+ return await discourse.upload(1, filePath);
+};
+exports.uploadFile = uploadFile;
+const findReplyPage = (b, pages) => {
+ return pages.find((p) => {
+ return p.replies.find((r) => {
+ return r.replyBody == b;
+ });
+ });
+};
+exports.findReplyPage = findReplyPage;
+const findReplyUpload = (u, page) => {
+ const f_pics = page.f_pics || [];
+ return f_pics.find((p) => {
+ return p.url === u;
+ });
+};
+exports.findReplyUpload = findReplyUpload;
+const getPages = (topics, topic) => {
+ return topics.filter((t) => {
+ return t.title == topic.title;
+ });
+};
+exports.getPages = getPages;
+const getReplies = (topics, topic) => {
+ if (topic.nextPages) {
+ const all = topics.filter((t) => {
+ return t.title == topic.title;
+ });
+ let replies = all.map((t) => t.replies);
+ replies = [].concat.apply([], replies);
+ replies = replies.sort((a, b) => {
+ const d1 = mom(a.replyDate, 'DD/MM/YYYY AT HH:mm').toDate();
+ const d2 = mom(b.replyDate, 'DD/MM/YYYY AT HH:mm').toDate();
+ return new Date(d1).getTime() > new Date(d2).getTime() ? 1 : -1;
+ });
+ return replies;
+ /*
+ const findReply = (b, pages) => {
+ return pages.find((p) => {
+ return p.replies.find((r) => {
+ return r.replyBody == b;
+ })
+ })
+ }
+ const p = findReply('\n\n\nsounds great, let me get Old Tony´s Schaeubling 13 and a surface grinder first, after that I can do the parts for the espresso machine in the best maker porn fashion possible, no seriously, every time I thought I know something, there’s just another video around the next corner making me cry like a baby, incl. the coffee machine
\n', all);
+ debugger;
+ */
+ }
+ return [];
+};
+exports.getReplies = getReplies;
+const findFile = (folder, filename) => {
+ const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: folder, absolute: true });
+ if (files.length == 0) {
+ return false;
+ }
+ return files[0];
+};
+exports.findFile = findFile;
+const topicFolder = (forum, folder, title) => {
+ const _title = sanitize((0, slugify_1.default)(title));
+ const tf = path.resolve(forum + '/' + folder + '/' + _title);
+ return tf;
+};
+exports.topicFolder = topicFolder;
+const getFUser = (users, user_name) => {
+ return users.find((u) => {
+ return u.name == user_name;
+ });
+};
+exports.getFUser = getFUser;
+exports.dOptions = {
+ host: 'https://forum.osr-plastic.org',
+ key: 'f624b8385fb2219cb49de63d1e22883afdf7b7367a0bebf822523f49f2678031',
+ username: 'admin',
+ rateLimitConcurrency: 1
+};
+const getOAvatar = (index, user) => {
+ const topics = (0, exports.getTopics)(index);
+ let topic = topics.find((t) => {
+ return t.authorName == user;
+ });
+ if (topic) {
+ return topic.authorImage;
+ }
+ for (let i = 0; i < topics.length; i++) {
+ const t = topics[i];
+ if (t.replies) {
+ const r = t.replies.find((r) => {
+ return r.user == user;
+ });
+ if (r) {
+ return r.avatar;
+ }
+ }
+ }
+ return null;
+};
+exports.getOAvatar = getOAvatar;
+const getTopics = (index) => {
+ let topics = [];
+ for (let t in index) {
+ topics.push(index[t]);
+ }
+ return topics;
+};
+exports.getTopics = getTopics;
+const convert = (input) => {
+ var turndownService = new TurndownService();
+ return turndownService.turndown(input);
+};
+exports.convert = convert;
+const getDiscourse = () => {
+ return new index_1.Discourser(exports.dOptions);
+};
+exports.getDiscourse = getDiscourse;
+function inspect(arg) {
+ return (0, util_1.inspect)(arg, {
+ depth: 5,
+ colors: true,
+ });
+}
+exports.inspect = inspect;
+function log(...args) {
+ console.log(...args.map((arg) => inspect(arg)));
+}
+exports.log = log;
+async function mkdirp(path) {
+ try {
+ await fs_1.default.promises.mkdir(path);
+ }
+ catch (err) {
+ // don't care if it already exists
+ }
+}
+exports.mkdirp = mkdirp;
+async function readJSON(path) {
+ const text = await fs_1.default.promises.readFile(path, 'utf8');
+ return JSON.parse(text);
+}
+exports.readJSON = readJSON;
+function writeJSON(path, data) {
+ return fs_1.default.promises.writeFile(path, JSON.stringify(data));
+}
+exports.writeJSON = writeJSON;
+function exists(path) {
+ return new Promise(function (resolve) {
+ fs_1.default.exists(path, resolve);
+ });
+}
+exports.exists = exists;
+function escape(path) {
+ return path.replace(/[^\w]/g, '-').replace(/-+/, '-');
+}
+exports.escape = escape;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL29hL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJCQUFtQjtBQUNuQiwrQkFBNkM7QUFFN0MsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFBO0FBQ3pCLElBQUksZUFBZSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQTtBQUN6QyxvQ0FBcUM7QUFHckMsNkJBQTRCO0FBQzVCLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUMvQixxQ0FBNkI7QUFFN0IsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUE7QUFLM0MseUNBQXlDO0FBR3pDLElBQUksR0FBRyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUVwQixNQUFNLFVBQVUsR0FBRyxLQUFLLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUU7SUFDcEUsT0FBTyxNQUFNLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQzVDLENBQUMsQ0FBQTtBQUZZLFFBQUEsVUFBVSxjQUV0QjtBQUVNLE1BQU0sYUFBYSxHQUFHLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFO0lBQ3pDLE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3ZCLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtZQUMzQixPQUFPLENBQUMsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDO1FBQ3pCLENBQUMsQ0FBQyxDQUFBO0lBQ0gsQ0FBQyxDQUFDLENBQUE7QUFDSCxDQUFDLENBQUE7QUFOWSxRQUFBLGFBQWEsaUJBTXpCO0FBRU0sTUFBTSxlQUFlLEdBQUcsQ0FB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
\ No newline at end of file
diff --git a/packages/discourse/lib/osr/index.d.ts b/packages/discourse/lib/osr/index.d.ts
new file mode 100644
index 00000000..ffd16f3f
--- /dev/null
+++ b/packages/discourse/lib/osr/index.d.ts
@@ -0,0 +1 @@
+export * from './urls';
diff --git a/packages/discourse/lib/osr/index.js b/packages/discourse/lib/osr/index.js
new file mode 100644
index 00000000..8811f26b
--- /dev/null
+++ b/packages/discourse/lib/osr/index.js
@@ -0,0 +1,18 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./urls"), exports);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL29zci9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEseUNBQXNCIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/osr/urls.d.ts b/packages/discourse/lib/osr/urls.d.ts
new file mode 100644
index 00000000..84d162bd
--- /dev/null
+++ b/packages/discourse/lib/osr/urls.d.ts
@@ -0,0 +1 @@
+export declare const marketplaceUrl: (store: any, product_id: any) => string;
diff --git a/packages/discourse/lib/osr/urls.js b/packages/discourse/lib/osr/urls.js
new file mode 100644
index 00000000..e70e6a6b
--- /dev/null
+++ b/packages/discourse/lib/osr/urls.js
@@ -0,0 +1,6 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.marketplaceUrl = void 0;
+const marketplaceUrl = (store, product_id) => `${store}/dispatch=products.view&product_id=${product_id}`;
+exports.marketplaceUrl = marketplaceUrl;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXJscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvb3NyL3VybHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQU8sTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLEVBQUUsQ0FDaEQsR0FBRyxLQUFLLHNDQUFzQyxVQUFVLEVBQUUsQ0FBQTtBQURqRCxRQUFBLGNBQWMsa0JBQ21DIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/commons.d.ts b/packages/discourse/lib/sync/commons.d.ts
new file mode 100644
index 00000000..252f5882
--- /dev/null
+++ b/packages/discourse/lib/sync/commons.d.ts
@@ -0,0 +1,12 @@
+///
+import { IOptionsSync, IOptionsSyncComponent } from '../../';
+export declare const fileAsBuffer: (path: string) => Buffer;
+export declare const images_urls: (content: string) => any[];
+export declare const adjustUrls: (content: string, options: IOptionsSync) => string;
+export declare const fromJSON: (content: string, file: string, options: IOptionsSyncComponent) => void;
+export declare const fromYAML: (content: string, options: IOptionsSync) => {
+ attributes: any;
+ body: any;
+};
+export declare const option: (option: string, taskOptions: any, col: any, _default?: any) => any;
+export declare const createContent: (file: any, _options: any) => Promise;
diff --git a/packages/discourse/lib/sync/commons.js b/packages/discourse/lib/sync/commons.js
new file mode 100644
index 00000000..42a4c364
--- /dev/null
+++ b/packages/discourse/lib/sync/commons.js
@@ -0,0 +1,174 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createContent = exports.option = exports.fromYAML = exports.fromJSON = exports.adjustUrls = exports.images_urls = exports.fileAsBuffer = void 0;
+const path = require("path");
+const Engine_1 = require("@plastichub/osrl/Engine");
+const options_1 = require("@plastichub/osrl/options");
+const glob_1 = require("@plastichub/osr-cli-commons/glob");
+const fs_1 = require("@plastichub/osr-commons");
+const __1 = require("../../");
+const exists_1 = require("@plastichub/fs/exists");
+const read_1 = require("@plastichub/fs/read");
+const write_1 = require("@plastichub/fs/write");
+const bluebird_1 = require("bluebird");
+const constants_1 = require("../../constants");
+const chokidar = require("chokidar");
+const cheerio = require('cheerio');
+const frontMatter = require('front-matter');
+const fileAsBuffer = (path) => (0, read_1.sync)(path, 'buffer') || Buffer.from("-");
+exports.fileAsBuffer = fileAsBuffer;
+const lib_1 = require("@plastichub/osr-cache/lib");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const md5 = require("md5");
+const markdown_1 = require("../markdown");
+const images_urls = (content) => {
+ const html = (0, markdown_1.toHTML)(content);
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+ const images = [];
+ const links = [];
+ $('img').each(function () {
+ images.push($(this).attr('src'));
+ });
+ return images;
+};
+exports.images_urls = images_urls;
+const adjustUrls = (content, options) => {
+ let ret = new markdown_1.RMark({
+ images: (match, capture, arg1, arg2) => ``,
+ //links: (match, capture, arg1, arg2) => `[${capture}](${arg1})`
+ }).render(content);
+ return ret;
+};
+exports.adjustUrls = adjustUrls;
+const fromJSON = (content, file, options) => {
+};
+exports.fromJSON = fromJSON;
+const fromYAML = (content, options) => {
+ if (frontMatter.test(content)) {
+ const fm = frontMatter(content);
+ return {
+ attributes: fm.attributes,
+ body: fm.body
+ };
+ }
+ else {
+ return {
+ attributes: {},
+ body: content
+ };
+ }
+};
+exports.fromYAML = fromYAML;
+// to be changed to osr-defaults
+const option = (option, taskOptions, col, _default) => {
+ // support grunt or yargs
+ const val = col.option ? col.option : (option) => col[option];
+ let ret = taskOptions[option] !== undefined ? taskOptions[option] : _default;
+ if (val(option) !== undefined) {
+ ret = val(option);
+ }
+ return ret;
+};
+exports.option = option;
+const createContent = async (file, _options) => {
+ const parts = path.parse(file);
+ const rel = path.relative(_options.root, file);
+ let output = _options.output;
+ let outputInfo = (0, glob_1.pathInfo)(_options.output);
+ const variables = {
+ root: '.',
+ cwd: _options.cwd || path.resolve('.'),
+ ..._options.variables
+ };
+ if (!outputInfo.FILE_EXT) {
+ output = path.resolve(`${_options.output}/${path.parse(rel).dir}/${parts.name}.md`);
+ }
+ else {
+ output = path.resolve((0, fs_1.resolve)(output, false, variables));
+ }
+ const defaults = {
+ language: _options.lang,
+ debug: _options.debug,
+ profile: _options.profile,
+ output: output,
+ plugins: _options.plugins,
+ env: _options.env || 'library',
+ cwd: _options.cwd || path.resolve('.'),
+ source: file,
+ variables
+ };
+ const options = (0, options_1.parse)(defaults, defaults);
+ const eOptions = {
+ ...options,
+ root: [
+ ...options.profile.includes,
+ path.parse(file).dir
+ ],
+ toHTML: false,
+ cache: false,
+ keepOutputType: true,
+ trimTagRight: false,
+ trimTagLeft: false,
+ trimOutputRight: false,
+ trimOutputLeft: false,
+ greedy: false
+ };
+ const Engine = new Engine_1.Engine(eOptions);
+ options.source = path.resolve(options.source);
+ const osr_cache = (0, osr_cli_commons_1.OSR_CACHE)();
+ const cached = await (0, lib_1.get_cached)(options.source, eOptions, _options.module || constants_1.MODULE_NAME);
+ if (osr_cache && cached && _options.cache !== false) {
+ options.debug && __1.logger.info('Compile file serving from cache: ' + options.source);
+ let md5Src = md5(Buffer.from(cached));
+ let md5Dst = md5((0, exports.fileAsBuffer)(options.output));
+ if (!(0, exists_1.sync)(options.output) || md5Src !== md5Dst) {
+ (0, write_1.sync)(options.output, cached);
+ }
+ return cached;
+ }
+ options.debug && __1.logger.info('Compile file ' + file, eOptions);
+ let content = await Engine.render(options.source, options.variables);
+ if (_options.onCompiled) {
+ content = await _options.onCompiled(options.source, output, content);
+ }
+ if (osr_cache && _options.cache !== false) {
+ options.debug && __1.logger.info('Write output to cache', output);
+ await (0, lib_1.set_cached)(options.source, eOptions, _options.module || constants_1.MODULE_NAME, content);
+ }
+ let dst = path.resolve((0, fs_1.resolve)(output, false, options.variables));
+ _options.debug && __1.logger.info('Write output to: ', dst);
+ (0, write_1.sync)(dst, content);
+ if (_options.onCompileDone) {
+ await _options.onCompileDone(options.source, dst, options, content);
+ }
+ return content;
+};
+exports.createContent = createContent;
+const watch = async (src, options) => {
+ src = path.resolve(src);
+ const watcher = chokidar.watch(`${src}`, {
+ ignored: /(^|[\/\\])\../,
+ persistent: true
+ });
+ watcher.on('change', async (path) => {
+ await (0, exports.createContent)(path, options);
+ });
+ return watcher;
+};
+const compileAll = async (files, options) => {
+ return await bluebird_1.Promise.resolve(files).map((f) => {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ (0, exports.createContent)(f, options).then(() => resolve(true));
+ }, 50);
+ });
+ }, { concurrency: 1 });
+};
+const compileAllEx = async (files, options) => {
+ return await bluebird_1.Promise.resolve(files).map((f) => {
+ return (0, exports.createContent)(f, options);
+ }, { concurrency: 1 });
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvc3luYy9jb21tb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE0QjtBQUU1QixvREFBMEQ7QUFDMUQsc0RBQWdEO0FBRWhELDJEQUEyRDtBQUMzRCx1REFBd0Q7QUFDeEQsOEJBQW9FO0FBQ3BFLGtEQUFzRDtBQUN0RCw4Q0FBa0Q7QUFDbEQsZ0RBQW9EO0FBRXBELHVDQUE4QztBQUU5QywrQ0FFd0I7QUFFeEIsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0FBQ3BDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUNsQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUE7QUFHcEMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDLElBQUEsV0FBSSxFQUFDLElBQUksRUFBRSxRQUFRLENBQVcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO0FBQW5GLFFBQUEsWUFBWSxnQkFBdUU7QUFFaEcsbURBQWtFO0FBQ2xFLGlFQUF1RDtBQUV2RCwyQkFBMEI7QUFFMUIsMENBQTJDO0FBQ3BDLE1BQU0sV0FBVyxHQUFHLENBQUMsT0FBZSxFQUFFLEVBQUU7SUFFM0MsTUFBTSxJQUFJLEdBQUcsSUFBQSxpQkFBTSxFQUFDLE9BQU8sQ0FBQyxDQUFBO0lBQzVCLE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ3pCLE9BQU8sRUFBRSxJQUFJO0tBQ2hCLENBQUMsQ0FBQztJQUVILE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQTtJQUNqQixNQUFNLEtBQUssR0FBRyxFQUFFLENBQUE7SUFDaEIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNWLE1BQU0sQ0FBQyxJQUFJLENB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
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/component.d.ts b/packages/discourse/lib/sync/component.d.ts
new file mode 100644
index 00000000..1d3c8b71
--- /dev/null
+++ b/packages/discourse/lib/sync/component.d.ts
@@ -0,0 +1,6 @@
+import { IOptionsSync } from '../../types';
+import { Discourser } from '../discourse';
+export declare const createPost: (discourse: Discourser, options: IOptionsSync, content: any) => Promise;
+export declare const updatePost: (discourse: Discourser, options: IOptionsSync, topic_id: any, content: any) => Promise;
+export declare const syncComponent: (options: IOptionsSync) => Promise;
+export declare const sync: (options: IOptionsSync) => Promise;
diff --git a/packages/discourse/lib/sync/component.js b/packages/discourse/lib/sync/component.js
new file mode 100644
index 00000000..21b2eadf
--- /dev/null
+++ b/packages/discourse/lib/sync/component.js
@@ -0,0 +1,373 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sync = exports.syncComponent = exports.updatePost = exports.createPost = void 0;
+const path = require("path");
+const exists_1 = require("@plastichub/fs/exists");
+const dir_1 = require("@plastichub/fs/dir");
+const write_1 = require("@plastichub/fs/write");
+const fs_1 = require("@plastichub/osr-commons");
+const bluebird_1 = require("bluebird");
+const osrl_1 = require("./osrl");
+const YAML = require('json-to-pretty-yaml');
+const cheerio = require('cheerio');
+const findUp = require('find-up');
+const frontMatter = require('front-matter');
+const md5 = require('md5');
+const download_1 = require("./download");
+const markdown_1 = require("../markdown");
+const primitives_1 = require("@plastichub/core/primitives");
+const _1 = require("./");
+const cache_1 = require("../discourse/cache");
+const discourse_1 = require("../discourse");
+const commons_1 = require("./commons");
+const osr_fs_utils_1 = require("@plastichub/osr-fs-utils");
+const index_1 = require("../../index");
+const osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+const CONTENT_TEST = false;
+const SKIP_EXISTING = false;
+const createPost = async (discourse, options, content) => {
+ if (!(0, primitives_1.isNumber)(options.cat)) {
+ index_1.logger.error(`category not a number! ${options.title} `);
+ }
+ let data;
+ try {
+ data = await discourse.createPost(options.title, content, options.cat);
+ }
+ catch (e) {
+ debugger;
+ }
+ if (data) {
+ if (data && data.id) {
+ try {
+ options.post_id = data.id;
+ options.topic_id = data.topic_id;
+ await discourse.changeOwner(options.post_id, options.topic_id, options.user_name);
+ index_1.logger.debug('created topic : ' + options.title + ' : ' + data.id + ' | topic id :' + data.topic_id);
+ return true;
+ }
+ catch (e) {
+ index_1.logger.error('changing owner ' + options.title + ' failed!', e);
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + options.title + ' failed!', data.errors, data);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + options.title);
+ }
+ }
+ }
+ }
+ else {
+ return false;
+ }
+};
+exports.createPost = createPost;
+const updatePost = async (discourse, options, topic_id, content) => {
+ let data;
+ try {
+ data = await discourse.updatePost(topic_id, content);
+ index_1.logger.debug('update post : ' + options.title + ' : ' + data.id + ' | topic id ' + data.topic_id);
+ }
+ catch (e) {
+ return false;
+ }
+ if (data) {
+ if (data && data.id) {
+ try {
+ // logger.debug('change user to ', options.owner);
+ options.post_id = data.id;
+ options.topic_id = data.topic_id;
+ await new Promise(f => setTimeout(f, 1000));
+ await discourse.changeOwner(topic_id, topic_id, options.user_name);
+ return true;
+ }
+ catch (e) {
+ index_1.logger.debug('changing owner ' + options.title + ' failed!');
+ return false;
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + options.title);
+ }
+ return false;
+ }
+ }
+ }
+};
+exports.updatePost = updatePost;
+const uploadImages = async (content, discourse, options) => {
+ const root = path.resolve((0, fs_1.resolve)(options.root));
+ if (!(0, exists_1.sync)(root)) {
+ return false;
+ }
+ const track_path = (0, _1.trackingPath)(root);
+ const track = (0, _1.tracking)(root);
+ const html = (0, markdown_1.toHTML)(content);
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+ const images = (0, commons_1.images_urls)(content);
+ $('img').each(function () {
+ if ($(this).attr('src') && $(this).attr('src').length > 5) {
+ images.push($(this).attr('src'));
+ }
+ });
+ for await (const image of Object.entries(images)) {
+ const url = image[1];
+ if (url.length < 10) {
+ continue;
+ }
+ if (url.startsWith('upload:')) {
+ continue;
+ }
+ if (options.uploadRemote && url.startsWith('http')) {
+ const contentHash = md5(content).substring(0, 5);
+ const cache_path = path.resolve((0, fs_1.resolve)('${OSR_CACHE}/discourse-downloads/' + contentHash));
+ if (!(0, exists_1.sync)(cache_path)) {
+ (0, dir_1.sync)(cache_path);
+ }
+ const image_name = (0, download_1.imageName)(url);
+ const image_local = path.join(cache_path, image_name);
+ if (!(0, exists_1.sync)(image_local)) {
+ try {
+ await (0, download_1.downloadFile)(url, cache_path);
+ }
+ catch (e) {
+ continue;
+ }
+ }
+ if (!(0, exists_1.sync)(image_local)) {
+ continue;
+ }
+ if (!track[url]) {
+ const upped = await discourse.uploadFile(options.owner, image_local);
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data;
+ (0, write_1.sync)(track_path, track);
+ }
+ else {
+ console.error('error uploading image');
+ }
+ }
+ continue;
+ }
+ if (options.uploadLocal) {
+ const image_path = path.join(root, url);
+ if ((0, exists_1.sync)(image_path) && (!track[url] || options.cache === false)) {
+ const upped = await discourse.uploadFile(options.owner, image_path);
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data;
+ (0, write_1.sync)(track_path, track);
+ }
+ else {
+ console.error('error uploading image');
+ }
+ }
+ }
+ }
+ return track;
+};
+const syncFile = async (file, options) => {
+ const discourse = (0, discourse_1.Instance)(null, options.config);
+ let config = (0, _1.fromJSON)(file, options) || {};
+ const componentDir = path.parse(file).dir;
+ // ph3 back sync
+ const rel = (0, osr_cli_commons_1.forward_slash)(path.relative(options.root, componentDir));
+ const productConfigPath = path.join(options.product_root, rel, 'config.json');
+ let body = await (0, osrl_1.createContent)(componentDir, options);
+ let images_track;
+ if (options.uploadLocal || options.uploadRemote) {
+ images_track = await uploadImages(body, discourse, options);
+ const image_urls = (0, commons_1.images_urls)(body);
+ image_urls.forEach((i) => {
+ if (images_track[i]) {
+ body = body.replace(i, images_track[i].short_url);
+ }
+ else {
+ index_1.logger.warn(`Cant resolve image url : ${i} - ${componentDir} ! Image Upload track invalid`);
+ }
+ });
+ }
+ index_1.logger.debug(`Processing ${componentDir}`);
+ const output = path.join(componentDir, '.osr/discourse_raw.md');
+ let dst = path.resolve((0, fs_1.resolve)(output));
+ options.debug && index_1.logger.info('Write output to: ', dst);
+ (0, write_1.sync)(dst, body);
+ let post_id, topic_id;
+ let dOpts = {
+ ...options,
+ cat: config.forumCategory,
+ id: options.id,
+ owner: config.forumUserId || 1,
+ tags: config.forumTags,
+ title: config.name,
+ topic_id: config.forumTopicId,
+ post_id: config.forumPostId
+ };
+ options = {
+ ...options,
+ ...dOpts
+ };
+ const hash = md5(JSON.stringify({
+ cat: dOpts.cat,
+ tags: dOpts.tags,
+ owner: dOpts.owner,
+ body,
+ title: dOpts.title
+ }, null));
+ // const cats = await cacheCategories(options, discourse)
+ // const tags = await cacheTags(options, discourse)
+ const users = await (0, cache_1.cacheUsers)(options, discourse);
+ await new Promise(f => setTimeout(f, 1000));
+ let search = await discourse.search(dOpts.title);
+ await new Promise(f => setTimeout(f, 2000));
+ let dTopic;
+ let dPost;
+ if (search && search.posts && search.topics) {
+ search.topics.forEach((t, i) => {
+ if (t.title === dOpts.title) {
+ dTopic = t;
+ dPost = search.posts[i];
+ topic_id = dTopic.id;
+ post_id = dPost.id;
+ }
+ });
+ }
+ if (!dTopic || !dPost) {
+ console.error('!dTopic || !dPost : cant find ' + dOpts.title);
+ // return
+ }
+ const user = users.find((u) => {
+ return u.id === dOpts.owner;
+ });
+ if (!user) {
+ index_1.logger.error('Invalid user : ', dOpts.owner);
+ return false;
+ }
+ options.user_name = user.username;
+ if (SKIP_EXISTING && hash === config.forumPostHash &&
+ config.forumTopicId && config.forumPostId) {
+ return;
+ }
+ if (CONTENT_TEST) {
+ return;
+ }
+ if (post_id) {
+ if (await (0, exports.updatePost)(discourse, options, post_id, body)) {
+ if (topic_id) {
+ await new Promise(f => setTimeout(f, 2000));
+ await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
+ }
+ }
+ else {
+ index_1.logger.error(`Error updating post ${dOpts.title}`);
+ }
+ }
+ else {
+ if (await (0, exports.createPost)(discourse, options, body)) {
+ await new Promise(f => setTimeout(f, 1000));
+ await discourse.updateTopic(options.topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
+ }
+ else {
+ index_1.logger.error('Creating post failed !', dOpts.title);
+ }
+ }
+ // const visStatus = await discourse.updateTopicVisibility(topic_id, true)
+ // re-read without defaults
+ config = (0, osr_fs_utils_1.readOSRConfig)(file);
+ config.forumPostHash = hash;
+ if (dTopic) {
+ config.forumTopicId = dTopic.id;
+ }
+ else if (topic_id) {
+ config.forumTopicId = topic_id;
+ }
+ if (dPost) {
+ config.forumPostId = dPost.id;
+ }
+ else if (post_id) {
+ config.forumPostId = post_id;
+ }
+ (0, write_1.sync)(file, config);
+ //ph3 products
+ if ((0, exists_1.sync)(productConfigPath)) {
+ let pConfig = (0, osr_fs_utils_1.readOSRConfig)(productConfigPath);
+ index_1.logger.debug(`Updating product config ${productConfigPath}`);
+ pConfig = {
+ ...config
+ //...pConfig,
+ //...
+ /*
+ forumTopicId:config.forumTopicId,
+ forumPostId:config.forumPostId,
+ forumPostHash: config.forumPostHash
+ */
+ };
+ (0, write_1.sync)(productConfigPath, pConfig);
+ }
+ return body;
+};
+const syncComponent = async (options) => {
+ let components = options.srcInfo.FILES.filter(osr_fs_utils_1.isValidLibraryComponent);
+ //let components = options.srcInfo.FILES.filter((c) => {
+ //components = components.filter((c) => {
+ /*
+try {
+ const config = readOSRConfig(c) as IComponentConfig
+ if (config) {
+ if (config.forum === false) {
+ return false
+ }
+ // return !config.code && !config.cscartId && !config.steps
+ return !!config.name
+ }
+ return false
+} catch (error) {
+ logger.error(`Invalid config : ${c}`)
+}
+})*/
+ const skipExisting = options.skip;
+ /*
+ [
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/asterix-pp/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/asterix-sm-morren/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/bicycle-shredder/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/idefix/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/obelix/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/pp-v3.3/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/components/shredder_v21-light-ex/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/components/shredder_v31-light/config.json",
+ ]
+ */
+ if (skipExisting) {
+ components = components.filter((f) => {
+ const config = (0, osr_fs_utils_1.readOSRConfig)(f);
+ if (config.forumPostId && config.forumTopicId) {
+ return false;
+ }
+ return true;
+ });
+ }
+ //components = [components[0]]
+ index_1.logger.info(`Syncing ${components.length} components`, components);
+ await bluebird_1.Promise.resolve(components).map((f) => {
+ try {
+ return syncFile(f, options);
+ }
+ catch (error) {
+ debugger;
+ }
+ }, { concurrency: 1 });
+};
+exports.syncComponent = syncComponent;
+const sync = async (options) => {
+ return (0, exports.syncComponent)(options);
+};
+exports.sync = sync;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9zeW5jL2NvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2QkFBNEI7QUFDNUIsa0RBQXNEO0FBRXRELDRDQUFnRDtBQUNoRCxnREFBb0Q7QUFHcEQsdURBQXdEO0FBRXhELHVDQUE4QztBQUc5QyxpQ0FBc0M7QUFFdEMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUE7QUFDM0MsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFBO0FBQ2xDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUNqQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUE7QUFDM0MsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBRTFCLHlDQUFvRDtBQUVwRCwwQ0FBb0M7QUFDcEMsNERBQXNEO0FBRXRELHlCQUFvRTtBQU9wRSw4Q0FLMkI7QUFHM0IsNENBR3FCO0FBRXJCLHVDQUVrQjtBQVVsQiwyREFBaUY7QUFFakYsdUNBQW9DO0FBQ3BDLGlFQUEyRDtBQUUzRCxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUE7QUFDMUIsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFBO0FBRXBCLE1BQU0sVUFBVSxHQUFHLEtBQUssRUFBRSxTQUFxQixFQUFFLE9BQXFCLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFFdEYsSUFBSSxDQUFDLElBQUEscUJBQVEsRUFBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDeEIsY0FBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsT0FBTyxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUE7S0FDM0Q7SUFFRCxJQUFJLElBQVMsQ0FBQTtJQUNiLElBQUk7UUFDQSxJQUFJLEdBQUcsTUFBTSxTQUFTLENBQUMsVUFBVSxDQUFD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
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/download.d.ts b/packages/discourse/lib/sync/download.d.ts
new file mode 100644
index 00000000..668cfd3d
--- /dev/null
+++ b/packages/discourse/lib/sync/download.d.ts
@@ -0,0 +1,5 @@
+export declare const sanitize: (f: any) => string;
+export declare const sanitize_ex: (f: any) => string;
+export declare const filename: (_url: any) => string;
+export declare const imageName: (url: any) => string;
+export declare const downloadFile: (_url: string, dir: string) => Promise;
diff --git a/packages/discourse/lib/sync/download.js b/packages/discourse/lib/sync/download.js
new file mode 100644
index 00000000..61e62fd7
--- /dev/null
+++ b/packages/discourse/lib/sync/download.js
@@ -0,0 +1,48 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.downloadFile = exports.imageName = exports.filename = exports.sanitize_ex = exports.sanitize = void 0;
+const path = require("path");
+const _sanitize = require("sanitize-filename");
+const filenamify = require('filenamify');
+const download = require("download");
+const URI = require("uri-js");
+const url = require("url");
+const sanitize = (f) => {
+ let str = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "");
+ if (str.startsWith('_')) {
+ str = str.substring(1);
+ }
+ return str;
+};
+exports.sanitize = sanitize;
+const sanitize_ex = (f) => {
+ let str = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "").replace('_', '');
+ return str;
+};
+exports.sanitize_ex = sanitize_ex;
+const filename = (_url) => {
+ return path.basename(url.parse(_url).path);
+};
+exports.filename = filename;
+const imageName = (url) => {
+ if (!url) {
+ return "";
+ }
+ try {
+ const parsed = URI.parse(decodeURIComponent(url));
+ const pParsed = path.parse(parsed.path);
+ return (0, exports.sanitize)(decodeURIComponent(pParsed.base));
+ }
+ catch (error) {
+ console.error('error image name : ', url);
+ return "";
+ }
+};
+exports.imageName = imageName;
+const downloadFile = async (_url, dir) => {
+ return download(_url, dir, {
+ filename: (0, exports.imageName)(_url)
+ });
+};
+exports.downloadFile = downloadFile;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG93bmxvYWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3N5bmMvZG93bmxvYWQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTRCO0FBRTVCLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFBO0FBRTlDLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUN4QyxxQ0FBb0M7QUFDcEMsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBRTdCLDJCQUEwQjtBQUVuQixNQUFNLFFBQVEsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFO0lBQzFCLElBQUksR0FBRyxHQUFXLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3hFLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUNyQixHQUFHLEdBQUcsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUMxQjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2YsQ0FBQyxDQUFBO0FBTlksUUFBQSxRQUFRLFlBTXBCO0FBRU0sTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDLEVBQUUsRUFBRTtJQUM3QixJQUFJLEdBQUcsR0FBVyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLE9BQU8sR0FBRyxDQUFDO0FBQ2YsQ0FBQyxDQUFBO0FBSFksUUFBQSxXQUFXLGVBR3ZCO0FBRU0sTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRTtJQUM3QixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMvQyxDQUFDLENBQUE7QUFGWSxRQUFBLFFBQVEsWUFFcEI7QUFHTSxNQUFNLFNBQVMsR0FBRyxDQUFDLEdBQUcsRUFBRSxFQUFFO0lBQzdCLElBQUcsQ0FBQyxHQUFHLEVBQUM7UUFDSixPQUFPLEVBQUUsQ0FBQTtLQUNaO0lBQ0QsSUFBSTtRQUNBLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNsRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QyxPQUFPLElBQUEsZ0JBQVEsRUFBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztLQUNyRDtJQUFDLE9BQU8sS0FBSyxFQUFFO1FBQ1osT0FBTyxDQUFDLEtBQUssQ0FBQyxxQkFBcUIsRUFBQyxHQUFHLENBQUMsQ0FBQTtRQUN4QyxPQUFPLEVBQUUsQ0FBQTtLQUNaO0FBQ0wsQ0FBQyxDQUFBO0FBWlksUUFBQSxTQUFTLGFBWXJCO0FBQ00sTUFBTSxZQUFZLEdBQUcsS0FBSyxFQUFFLElBQVcsRUFBRSxHQUFVLEVBQUUsRUFBRTtJQUMxRCxPQUFPLFFBQVEsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFO1FBQ3ZCLFFBQVEsRUFBRSxJQUFBLGlCQUFTLEVBQUMsSUFBSSxDQUFDO0tBQzVCLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQTtBQUpZLFFBQUEsWUFBWSxnQkFJeEIifQ==
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/file.d.ts b/packages/discourse/lib/sync/file.d.ts
new file mode 100644
index 00000000..b06a049b
--- /dev/null
+++ b/packages/discourse/lib/sync/file.d.ts
@@ -0,0 +1,6 @@
+import { IOptionsSync } from '../../types';
+import { Discourser } from '../discourse';
+export declare const createTopic: (discourse: Discourser, options: IOptionsSync, content: any) => Promise;
+export declare const updateTopic: (discourse: Discourser, options: IOptionsSync, topic_id: any, content: any) => Promise;
+export declare const syncYAML: (options: IOptionsSync) => Promise;
+export declare const sync: (options: IOptionsSync) => Promise;
diff --git a/packages/discourse/lib/sync/file.js b/packages/discourse/lib/sync/file.js
new file mode 100644
index 00000000..1cfbdc3a
--- /dev/null
+++ b/packages/discourse/lib/sync/file.js
@@ -0,0 +1,253 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sync = exports.syncYAML = exports.updateTopic = exports.createTopic = void 0;
+const path = require("path");
+const exists_1 = require("@plastichub/fs/exists");
+const dir_1 = require("@plastichub/fs/dir");
+const write_1 = require("@plastichub/fs/write");
+const read_1 = require("@plastichub/fs/read");
+const fs_1 = require("@plastichub/osr-commons");
+const bluebird_1 = require("bluebird");
+const download_1 = require("./download");
+const YAML = require('json-to-pretty-yaml');
+const cheerio = require('cheerio');
+const markdown_1 = require("../markdown");
+const constants_1 = require("../discourse/constants");
+const cache_1 = require("../discourse/cache");
+const discourse_1 = require("../discourse");
+const commons_1 = require("./commons");
+const index_1 = require("../../index");
+const md5 = require("md5");
+const createTopic = async (discourse, options, content) => {
+ let data;
+ try {
+ data = await discourse.createPost(options.title, content, options.cat);
+ }
+ catch (e) {
+ debugger;
+ }
+ if (data) {
+ index_1.logger.debug('created topic : ' + options.title + ' : ' + data.id);
+ if (data && data.id) {
+ try {
+ options.post_id = data.id;
+ options.topic_id = data.topic_id;
+ await discourse.changeOwner(options.post_id, options.topic_id, options.user_name);
+ }
+ catch (e) {
+ index_1.logger.error('changing owner ' + options.title + ' failed!', e);
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + options.title);
+ }
+ }
+ }
+ }
+};
+exports.createTopic = createTopic;
+const updateTopic = async (discourse, options, topic_id, content) => {
+ let data;
+ try {
+ data = await discourse.updatePost(topic_id, content);
+ }
+ catch (e) {
+ }
+ if (data) {
+ index_1.logger.debug('created topic : ' + options.title + ' : ' + data.id);
+ if (data && data.id) {
+ try {
+ index_1.logger.debug('change user to ', options.owner);
+ options.post_id = data.id;
+ options.topic_id = data.topic_id;
+ await discourse.changeOwner(topic_id, topic_id, options.user_name);
+ }
+ catch (e) {
+ index_1.logger.debug('changing owner ' + options.title + ' failed!');
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + options.title);
+ }
+ }
+ }
+ }
+};
+exports.updateTopic = updateTopic;
+const images_urls = (content) => {
+ const html = (0, markdown_1.toHTML)(content);
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+ const images = [];
+ const links = [];
+ $('img').each(function () {
+ images.push($(this).attr('src'));
+ });
+ return images;
+};
+const uploadImages = async (content, discourse, options) => {
+ const root = path.resolve((0, fs_1.resolve)(options.root));
+ if (!(0, exists_1.sync)(root)) {
+ return false;
+ }
+ const track_path = path.join(root, constants_1.SYNC_TRACK_FILENAME);
+ const track = (0, read_1.sync)(track_path, 'json') || {};
+ const html = (0, markdown_1.toHTML)(content);
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+ const images = images_urls(content);
+ $('img').each(function () {
+ images.push($(this).attr('src'));
+ });
+ for await (const image of Object.entries(images)) {
+ const url = image[1];
+ if (url.startsWith('upload:')) {
+ continue;
+ }
+ if (options.uploadRemote && url.startsWith('http')) {
+ const contentHash = md5(content).substring(0, 5);
+ const cache_path = path.resolve((0, fs_1.resolve)('${OSR_CACHE}/discourse-downloads/' + contentHash));
+ if (!(0, exists_1.sync)(cache_path)) {
+ (0, dir_1.sync)(cache_path);
+ }
+ const image_name = (0, download_1.imageName)(url);
+ const image_local = path.join(cache_path, image_name);
+ if (!(0, exists_1.sync)(image_local)) {
+ await (0, download_1.downloadFile)(url, cache_path);
+ }
+ if ((0, exists_1.sync)(image_local)) {
+ const upped = await discourse.uploadFile(options.owner, image_local);
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data;
+ (0, write_1.sync)(track_path, track);
+ }
+ else {
+ console.error('error uploading image');
+ }
+ }
+ continue;
+ }
+ if (options.uploadLocal) {
+ const image_path = path.join(root, url);
+ if ((0, exists_1.sync)(image_path) && !track[url]) {
+ const upped = await discourse.uploadFile(options.owner, image_path);
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data;
+ (0, write_1.sync)(track_path, track);
+ }
+ else {
+ console.error('error uploading image');
+ }
+ }
+ }
+ }
+ return track;
+};
+const syncFile = async (file, options) => {
+ const discourse = (0, discourse_1.Instance)(null, options.config);
+ let content = (0, read_1.sync)(file);
+ const fm = (0, commons_1.fromYAML)(content, options) || {};
+ let body = "" + fm.body;
+ let images_track;
+ if (options.uploadLocal || options.uploadRemote) {
+ images_track = await uploadImages(body, discourse, options);
+ const image_urls = images_urls(body);
+ image_urls.forEach((i) => {
+ if (images_track[i])
+ body = body.replace(i, images_track[i].short_url);
+ });
+ }
+ (0, write_1.sync)('./out/md.md', body);
+ let dOpts = options.yaml ? fm.attributes : {
+ cat: options.cat,
+ id: options.id,
+ owner: options.owner,
+ tags: options.tags,
+ title: options.title
+ };
+ options = {
+ ...options,
+ ...dOpts
+ };
+ const cats = await (0, cache_1.cacheCategories)(options, discourse);
+ const tags = await (0, cache_1.cacheTags)(options, discourse);
+ const users = await (0, cache_1.cacheUsers)(options, discourse);
+ const search = await discourse.search(dOpts.title);
+ let post_id, topic_id;
+ if (options.yaml) {
+ post_id = dOpts.post_id;
+ topic_id = dOpts.topic_id;
+ }
+ let dTopic;
+ let dPost;
+ if (search.posts && search.topics
+ && search.posts[0] && search.topics[0]
+ && search.topics[0].title === dOpts.title) {
+ dPost = search.posts[0];
+ dTopic = search.topics[0];
+ topic_id = dTopic.id;
+ post_id = dPost.id;
+ }
+ else if (post_id && topic_id) {
+ }
+ const user = users.find((u) => {
+ return u.id === dOpts.owner;
+ });
+ if (!user) {
+ index_1.logger.error('Invalid user : ', dOpts.owner);
+ return false;
+ }
+ options.user_name = user.username;
+ let topic = null;
+ if (post_id) {
+ topic = await (0, exports.updateTopic)(discourse, options, post_id, body);
+ if (topic_id) {
+ topic = await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
+ }
+ }
+ else {
+ await (0, exports.createTopic)(discourse, options, body);
+ topic_id = options.topic_id;
+ post_id = options.post_id;
+ await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
+ }
+ if (dTopic) {
+ options.topic_id = dTopic.id;
+ }
+ if (dPost) {
+ options.post_id = dPost.id;
+ }
+ if (options.yaml) {
+ let contentOut = `---\n`;
+ contentOut += YAML.stringify({
+ ...fm.attributes,
+ topic_id: topic_id,
+ post_id: post_id
+ });
+ contentOut += `---\n`;
+ contentOut += fm.body;
+ (0, write_1.sync)(file, contentOut);
+ }
+ return content;
+};
+const syncYAML = async (options) => {
+ await bluebird_1.Promise.resolve(options.srcInfo.FILES).map((f) => {
+ return syncFile(f, options);
+ }, { concurrency: 1 });
+};
+exports.syncYAML = syncYAML;
+const sync = async (options) => {
+ return (0, exports.syncYAML)(options);
+};
+exports.sync = sync;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvc3luYy9maWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE0QjtBQUM1QixrREFBc0Q7QUFFdEQsNENBQWdEO0FBQ2hELGdEQUFvRDtBQUNwRCw4Q0FBa0Q7QUFFbEQsdURBQXdEO0FBRXhELHVDQUE4QztBQUU5Qyx5Q0FBb0Q7QUFHcEQsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUE7QUFDM0MsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBRW5DLDBDQUFvQztBQUVwQyxzREFFK0I7QUFFL0IsOENBSzJCO0FBRTNCLDRDQUdxQjtBQUVyQix1Q0FFa0I7QUFHbEIsdUNBQStEO0FBRS9ELDJCQUEwQjtBQUVuQixNQUFNLFdBQVcsR0FBRyxLQUFLLEVBQUUsU0FBcUIsRUFBRSxPQUFxQixFQUFFLE9BQU8sRUFBRSxFQUFFO0lBRXZGLElBQUksSUFBUyxDQUFBO0lBQ2IsSUFBSTtRQUNBLElBQUksR0FBRyxNQUFNLFNBQVMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQWEsQ0FBQyxDQUFBO0tBQ25GO0lBQUMsT0FBTyxDQUFDLEVBQUU7UUFDUixRQUFRLENBQUE7S0FDWDtJQUVELElBQUksSUFBSSxFQUFFO1FBQ04sY0FBTSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsR0FBRyxPQUFPLENBQUMsS0FBSyxHQUFHLE1BQU0sR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDbkUsSUFBSSxJQUFJLElBQUksSUFBSSxDQUFDLEVBQUUsRUFBRTtZQUVqQixJQUFJO2dCQUNBLE9BQU8sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDMUIsT0FBTyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFBO2dC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
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/fs.d.ts b/packages/discourse/lib/sync/fs.d.ts
new file mode 100644
index 00000000..b06a049b
--- /dev/null
+++ b/packages/discourse/lib/sync/fs.d.ts
@@ -0,0 +1,6 @@
+import { IOptionsSync } from '../../types';
+import { Discourser } from '../discourse';
+export declare const createTopic: (discourse: Discourser, options: IOptionsSync, content: any) => Promise;
+export declare const updateTopic: (discourse: Discourser, options: IOptionsSync, topic_id: any, content: any) => Promise;
+export declare const syncYAML: (options: IOptionsSync) => Promise;
+export declare const sync: (options: IOptionsSync) => Promise;
diff --git a/packages/discourse/lib/sync/fs.js b/packages/discourse/lib/sync/fs.js
new file mode 100644
index 00000000..2a3279fa
--- /dev/null
+++ b/packages/discourse/lib/sync/fs.js
@@ -0,0 +1,275 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sync = exports.syncYAML = exports.updateTopic = exports.createTopic = void 0;
+const path = require("path");
+const exists_1 = require("@plastichub/fs/exists");
+const dir_1 = require("@plastichub/fs/dir");
+const write_1 = require("@plastichub/fs/write");
+const read_1 = require("@plastichub/fs/read");
+const fs_1 = require("@plastichub/osr-commons");
+const bluebird_1 = require("bluebird");
+const YAML = require('json-to-pretty-yaml');
+const cheerio = require('cheerio');
+const download_1 = require("./download");
+const markdown_1 = require("../markdown");
+const constants_1 = require("../discourse/constants");
+const cache_1 = require("../discourse/cache");
+const discourse_1 = require("../discourse");
+const index_1 = require("../../index");
+const md5 = require("md5");
+const frontMatter = require('front-matter');
+const fromYAML = (content, options) => {
+ if (frontMatter.test(content)) {
+ const fm = frontMatter(content);
+ return {
+ attributes: fm.attributes,
+ body: fm.body
+ };
+ }
+ else {
+ return {
+ attributes: {},
+ body: content
+ };
+ }
+};
+const adjustUrls = (content, options) => {
+ let ret = new markdown_1.RMark({
+ images: (match, capture, arg1, arg2) => ``,
+ //links: (match, capture, arg1, arg2) => `[${capture}](${arg1})`
+ }).render(content);
+ return ret;
+};
+const createTopic = async (discourse, options, content) => {
+ let data;
+ try {
+ data = await discourse.createPost(options.title, content, options.cat);
+ }
+ catch (e) {
+ debugger;
+ }
+ if (data) {
+ index_1.logger.debug('created topic : ' + options.title + ' : ' + data.id);
+ if (data && data.id) {
+ try {
+ options.post_id = data.id;
+ options.topic_id = data.topic_id;
+ await discourse.changeOwner(options.post_id, options.topic_id, options.user_name);
+ }
+ catch (e) {
+ index_1.logger.error('changing owner ' + options.title + ' failed!', e);
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + options.title);
+ }
+ }
+ }
+ }
+};
+exports.createTopic = createTopic;
+const updateTopic = async (discourse, options, topic_id, content) => {
+ let data;
+ try {
+ data = await discourse.updatePost(topic_id, content);
+ }
+ catch (e) {
+ }
+ if (data) {
+ index_1.logger.debug('created topic : ' + options.title + ' : ' + data.id);
+ if (data && data.id) {
+ try {
+ index_1.logger.debug('change user to ', options.owner);
+ options.post_id = data.id;
+ options.topic_id = data.topic_id;
+ await discourse.changeOwner(topic_id, topic_id, options.user_name);
+ }
+ catch (e) {
+ index_1.logger.debug('changing owner ' + options.title + ' failed!');
+ }
+ }
+ else {
+ index_1.logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ index_1.logger.error('title already used : ' + options.title);
+ }
+ }
+ }
+ }
+};
+exports.updateTopic = updateTopic;
+const images_urls = (content) => {
+ const html = (0, markdown_1.toHTML)(content);
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+ const images = [];
+ const links = [];
+ $('img').each(function () {
+ images.push($(this).attr('src'));
+ });
+ return images;
+};
+const uploadImages = async (content, discourse, options) => {
+ const root = path.resolve((0, fs_1.resolve)(options.root));
+ if (!(0, exists_1.sync)(root)) {
+ return false;
+ }
+ const track_path = path.join(root, constants_1.SYNC_TRACK_FILENAME);
+ const track = (0, read_1.sync)(track_path, 'json') || {};
+ const html = (0, markdown_1.toHTML)(content);
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+ const images = images_urls(content);
+ $('img').each(function () {
+ images.push($(this).attr('src'));
+ });
+ for await (const image of Object.entries(images)) {
+ const url = image[1];
+ if (url.startsWith('upload:')) {
+ continue;
+ }
+ if (options.uploadRemote && url.startsWith('http')) {
+ const contentHash = md5(content).substring(0, 5);
+ const cache_path = path.resolve((0, fs_1.resolve)('${OSR_CACHE}/discourse-downloads/' + contentHash));
+ if (!(0, exists_1.sync)(cache_path)) {
+ (0, dir_1.sync)(cache_path);
+ }
+ const image_name = (0, download_1.imageName)(url);
+ const image_local = path.join(cache_path, image_name);
+ if (!(0, exists_1.sync)(image_local)) {
+ await (0, download_1.downloadFile)(url, cache_path);
+ }
+ if ((0, exists_1.sync)(image_local)) {
+ const upped = await discourse.uploadFile(options.owner, image_local);
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data;
+ (0, write_1.sync)(track_path, track);
+ }
+ else {
+ console.error('error uploading image');
+ }
+ }
+ continue;
+ }
+ if (options.uploadLocal) {
+ const image_path = path.join(root, url);
+ if ((0, exists_1.sync)(image_path) && !track[url]) {
+ const upped = await discourse.uploadFile(options.owner, image_path);
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data;
+ (0, write_1.sync)(track_path, track);
+ }
+ else {
+ console.error('error uploading image');
+ }
+ }
+ }
+ }
+ return track;
+};
+const syncFile = async (file, options) => {
+ const discourse = (0, discourse_1.Instance)(null, options.config);
+ let content = (0, read_1.sync)(file);
+ const fm = fromYAML(content, options) || {};
+ let body = "" + fm.body;
+ let images_track;
+ if (options.uploadLocal || options.uploadRemote) {
+ images_track = await uploadImages(body, discourse, options);
+ const image_urls = images_urls(body);
+ image_urls.forEach((i) => {
+ if (images_track[i])
+ body = body.replace(i, images_track[i].short_url);
+ });
+ }
+ (0, write_1.sync)('./out/md.md', body);
+ let dOpts = options.yaml ? fm.attributes : {
+ cat: options.cat,
+ id: options.id,
+ owner: options.owner,
+ tags: options.tags,
+ title: options.title
+ };
+ options = {
+ ...options,
+ ...dOpts
+ };
+ const cats = await (0, cache_1.cacheCategories)(options, discourse);
+ const tags = await (0, cache_1.cacheTags)(options, discourse);
+ const users = await (0, cache_1.cacheUsers)(options, discourse);
+ const search = await discourse.search(dOpts.title);
+ let post_id, topic_id;
+ if (options.yaml) {
+ post_id = dOpts.post_id;
+ topic_id = dOpts.topic_id;
+ }
+ let dTopic;
+ let dPost;
+ if (search.posts && search.topics
+ && search.posts[0] && search.topics[0]
+ && search.topics[0].title === dOpts.title) {
+ dPost = search.posts[0];
+ dTopic = search.topics[0];
+ topic_id = dTopic.id;
+ post_id = dPost.id;
+ }
+ else if (post_id && topic_id) {
+ }
+ const user = users.find((u) => {
+ return u.id === dOpts.owner;
+ });
+ if (!user) {
+ index_1.logger.error('Invalid user : ', dOpts.owner);
+ return false;
+ }
+ options.user_name = user.username;
+ let topic = null;
+ if (post_id) {
+ topic = await (0, exports.updateTopic)(discourse, options, post_id, body);
+ if (topic_id) {
+ topic = await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
+ }
+ }
+ else {
+ await (0, exports.createTopic)(discourse, options, body);
+ topic_id = options.topic_id;
+ post_id = options.post_id;
+ await discourse.updateTopic(topic_id, dOpts.cat, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : []);
+ }
+ if (dTopic) {
+ options.topic_id = dTopic.id;
+ }
+ if (dPost) {
+ options.post_id = dPost.id;
+ }
+ if (options.yaml) {
+ let contentOut = `---\n`;
+ contentOut += YAML.stringify({
+ ...fm.attributes,
+ topic_id: topic_id,
+ post_id: post_id
+ });
+ contentOut += `---\n`;
+ contentOut += fm.body;
+ (0, write_1.sync)(file, contentOut);
+ }
+ return content;
+};
+const syncYAML = async (options) => {
+ await bluebird_1.Promise.resolve(options.srcInfo.FILES).map((f) => {
+ return syncFile(f, options);
+ }, { concurrency: 1 });
+};
+exports.syncYAML = syncYAML;
+const sync = async (options) => {
+ return (0, exports.syncYAML)(options);
+};
+exports.sync = sync;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3N5bmMvZnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTRCO0FBQzVCLGtEQUFzRDtBQUV0RCw0Q0FBZ0Q7QUFDaEQsZ0RBQW9EO0FBQ3BELDhDQUFrRDtBQUVsRCx1REFBd0Q7QUFFeEQsdUNBQThDO0FBSzlDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFBO0FBQzNDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztBQUduQyx5Q0FBb0Q7QUFFcEQsMENBQTJDO0FBRTNDLHNEQUUrQjtBQUUvQiw4Q0FLMkI7QUFHM0IsNENBR3FCO0FBSXJCLHVDQUErRDtBQUUvRCwyQkFBMEI7QUFFMUIsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFBO0FBRTNDLE1BQU0sUUFBUSxHQUFHLENBQUMsT0FBZSxFQUFFLE9BQXFCLEVBQUUsRUFBRTtJQUN4RCxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDM0IsTUFBTSxFQUFFLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQy9CLE9BQU87WUFDSCxVQUFVLEVBQUUsRUFBRSxDQUFDLFVBQVU7WUFDekIsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJO1NBQ2hCLENBQUE7S0FDSjtTQUFNO1FBQ0gsT0FBTztZQUNILFVBQVUsRUFBRSxFQUFFO1lBQ2QsSUFBSSxFQUFFLE9BQU87U0FDaEIsQ0FBQTtLQUNKO0FBQ0wsQ0FBQyxDQUFBO0FBRUQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxPQUFlLEVBQUUsT0FBcUIsRUFBRSxFQUFFO0lBQzFELElBQUksR0FBRyxHQUFHLElBQUksZ0JBQUssQ0FDZjtRQUNJLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxFQUFF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
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/index.d.ts b/packages/discourse/lib/sync/index.d.ts
new file mode 100644
index 00000000..05bc6d93
--- /dev/null
+++ b/packages/discourse/lib/sync/index.d.ts
@@ -0,0 +1,6 @@
+import { IOptionsSync } from '../../types';
+import { IComponentConfig } from '@plastichub/osr-commons';
+export declare const trackingPath: (root: any) => string;
+export declare const tracking: (root: any) => import("@plastichub/fs/interfaces").ReadWriteDataType;
+export declare const defaultConfig: (configFile: string, options: IOptionsSync) => IComponentConfig;
+export declare const fromJSON: (configFile: string, options: IOptionsSync) => IComponentConfig;
diff --git a/packages/discourse/lib/sync/index.js b/packages/discourse/lib/sync/index.js
new file mode 100644
index 00000000..9fd4ea29
--- /dev/null
+++ b/packages/discourse/lib/sync/index.js
@@ -0,0 +1,36 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.fromJSON = exports.defaultConfig = exports.tracking = exports.trackingPath = void 0;
+const path = require("path");
+const read_1 = require("@plastichub/fs/read");
+const constants_1 = require("../discourse/constants");
+const YAML = require('json-to-pretty-yaml');
+const cheerio = require('cheerio');
+const findUp = require('find-up');
+const frontMatter = require('front-matter');
+const osr_fs_utils_1 = require("@plastichub/osr-fs-utils");
+const trackingPath = (root) => path.join(root, constants_1.SYNC_TRACK_FILENAME);
+exports.trackingPath = trackingPath;
+const tracking = (root) => (0, read_1.sync)((0, exports.trackingPath)(root), 'json') || {};
+exports.tracking = tracking;
+const defaultConfig = (configFile, options) => {
+ let defaultsJSON = findUp.sync('defaults.json', {
+ cwd: path.parse(configFile).dir,
+ stopAt: options.root
+ });
+ if (defaultsJSON) {
+ return (0, osr_fs_utils_1.readOSRConfig)(defaultsJSON);
+ }
+ return {};
+};
+exports.defaultConfig = defaultConfig;
+const fromJSON = (configFile, options) => {
+ const defaults = (0, exports.defaultConfig)(configFile, options);
+ const config = (0, osr_fs_utils_1.readOSRConfig)(configFile);
+ return {
+ ...defaults,
+ ...config
+ };
+};
+exports.fromJSON = fromJSON;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbGliL3N5bmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkJBQTRCO0FBQzVCLDhDQUFrRDtBQUNsRCxzREFFK0I7QUFjL0IsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUE7QUFDM0MsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFBO0FBQ2xDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQTtBQUNqQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUE7QUFJM0MsMkRBQWlGO0FBRTFFLE1BQU0sWUFBWSxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDakMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsK0JBQW1CLENBQUMsQ0FBQTtBQUQzQixRQUFBLFlBQVksZ0JBQ2U7QUFHakMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUM3QixJQUFBLFdBQUksRUFBQyxJQUFBLG9CQUFZLEVBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO0FBRDdCLFFBQUEsUUFBUSxZQUNxQjtBQUVuQyxNQUFNLGFBQWEsR0FBRyxDQUFDLFVBQWtCLEVBQUUsT0FBcUIsRUFBb0IsRUFBRTtJQUN6RixJQUFJLFlBQVksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRTtRQUM1QyxHQUFHLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHO1FBQy9CLE1BQU0sRUFBRSxPQUFPLENBQUMsSUFBSTtLQUN2QixDQUFDLENBQUE7SUFDRixJQUFJLFlBQVksRUFBRTtRQUNkLE9BQU8sSUFBQSw0QkFBYSxFQUFDLFlBQVksQ0FBQyxDQUFBO0tBQ3JDO0lBQ0QsT0FBTyxFQUVjLENBQUE7QUFDekIsQ0FBQyxDQUFBO0FBWFksUUFBQSxhQUFhLGlCQVd6QjtBQUVNLE1BQU0sUUFBUSxHQUFHLENBQUMsVUFBa0IsRUFBRSxPQUFxQixFQUFvQixFQUFFO0lBQ3BGLE1BQU0sUUFBUSxHQUFHLElBQUEscUJBQWEsRUFBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDbkQsTUFBTSxNQUFNLEdBQUcsSUFBQSw0QkFBYSxFQUFDLFVBQVUsQ0FBQyxDQUFBO0lBQ3hDLE9BQU87UUFDSCxHQUFHLFFBQVE7UUFDWCxHQUFHLE1BQU07S0FDWixDQUFBO0FBQ0wsQ0FBQyxDQUFBO0FBUFksUUFBQSxRQUFRLFlBT3BCIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/sync/osrl.d.ts b/packages/discourse/lib/sync/osrl.d.ts
new file mode 100644
index 00000000..14a939a0
--- /dev/null
+++ b/packages/discourse/lib/sync/osrl.d.ts
@@ -0,0 +1,4 @@
+///
+import { IOptionsSyncComponent } from '../../';
+export declare const fileAsBuffer: (path: string) => Buffer;
+export declare const createContent: (component: any, _options: IOptionsSyncComponent) => Promise;
diff --git a/packages/discourse/lib/sync/osrl.js b/packages/discourse/lib/sync/osrl.js
new file mode 100644
index 00000000..9b848a5e
--- /dev/null
+++ b/packages/discourse/lib/sync/osrl.js
@@ -0,0 +1,75 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.createContent = exports.fileAsBuffer = void 0;
+const path = require("path");
+const Engine_1 = require("@plastichub/osrl/Engine");
+const options_1 = require("@plastichub/osrl/options");
+const glob_1 = require("@plastichub/osr-cli-commons/glob");
+const fs_1 = require("@plastichub/osr-commons");
+const index_1 = require("../../index");
+const git_1 = require("../git");
+const moment = require("moment");
+const read_1 = require("@plastichub/fs/read");
+const fileAsBuffer = (path) => (0, read_1.sync)(path, 'buffer') || Buffer.from("-");
+exports.fileAsBuffer = fileAsBuffer;
+const variable_extras = async (component, rel, options) => {
+ const root = path.resolve((0, fs_1.resolve)('${OSR_LIBRARY_MACHINES}'));
+ const gitStats = await (0, git_1.git_status)(root, rel);
+ const latest = gitStats.latest;
+ return {
+ "GIT_LAST": moment(latest.date).format('LLLL'),
+ "GIT_AUTHOR": latest.author_name,
+ "GIT_MESSAGE": latest.message,
+ "GIT_COMMIT": latest.hash
+ };
+};
+const createContent = async (component, _options) => {
+ const parts = path.parse(component);
+ const rel = (0, glob_1.forward_slash)(path.relative(_options.root, component));
+ const extras = await variable_extras(component, rel, _options);
+ const variables = {
+ root: _options.root,
+ cwd: _options.cwd,
+ ..._options.variables,
+ product: rel,
+ product_rel: rel,
+ product_rel_min: rel,
+ ...extras
+ };
+ const defaults = {
+ language: _options.language,
+ debug: false,
+ profile: _options.profile,
+ // output: output,
+ plugins: [],
+ env: _options.env || 'forum',
+ cwd: _options.cwd,
+ source: _options.src,
+ variables
+ };
+ const options = (0, options_1.parse)(defaults, defaults);
+ const eOptions = {
+ ...options,
+ root: [
+ ...options.profile.includes,
+ component
+ ],
+ toHTML: false,
+ cache: false,
+ keepOutputType: true,
+ trimTagRight: false,
+ trimTagLeft: false,
+ trimOutputRight: false,
+ trimOutputLeft: false,
+ greedy: false
+ };
+ const Engine = new Engine_1.Engine(eOptions);
+ options.debug && index_1.logger.info('Compile file ' + component, eOptions);
+ let content = await Engine.render(options.source, {
+ ...options.variables,
+ ...extras
+ });
+ return content;
+};
+exports.createContent = createContent;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3NybC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9saWIvc3luYy9vc3JsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZCQUE0QjtBQUU1QixvREFBMEQ7QUFDMUQsc0RBQWdEO0FBRWhELDJEQUFnRTtBQUVoRSx1REFBd0Q7QUFHeEQsdUNBQW9DO0FBQ3BDLGdDQUFtQztBQUNuQyxpQ0FBZ0M7QUFDaEMsOENBQWtEO0FBRTNDLE1BQU0sWUFBWSxHQUFHLENBQUMsSUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFBLFdBQUksRUFBQyxJQUFJLEVBQUUsUUFBUSxDQUFXLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtBQUFuRixRQUFBLFlBQVksZ0JBQXVFO0FBQ2hHLE1BQU0sZUFBZSxHQUFHLEtBQUssRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE9BQThCLEVBQUUsRUFBRTtJQUM3RSxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUEsWUFBTyxFQUFDLHlCQUF5QixDQUFDLENBQUMsQ0FBQTtJQUM3RCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUEsZ0JBQVUsRUFBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUE7SUFDNUMsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQTtJQUM5QixPQUFPO1FBQ0gsVUFBVSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUMvQyxZQUFZLEVBQUcsTUFBTSxDQUFDLFdBQVc7UUFDakMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxPQUFPO1FBQzdCLFlBQVksRUFBRyxNQUFNLENBQUMsSUFBSTtLQUM3QixDQUFBO0FBQ0wsQ0FBQyxDQUFBO0FBRU0sTUFBTSxhQUFhLEdBQUcsS0FBSyxFQUFFLFNBQVMsRUFBRSxRQUErQixFQUFFLEVBQUU7SUFFOUUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQTtJQUNuQyxNQUFNLEdBQUcsR0FBRyxJQUFBLG9CQUFhLEVBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUE7SUFDbEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxlQUFlLENBQUMsU0FBUyxFQUFDLEdBQUcsRUFBRSxRQUFRLENBQUMsQ0FBQTtJQUM3RCxNQUFNLFNBQVMsR0FBRztRQUNkLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtRQUNuQixHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUc7UUFDakIsR0FBRyxRQUFRLENBQUMsU0FBUztRQUNyQixPQUFPLEVBQUUsR0FBRztRQUNaLFdBQVcsRUFBRSxHQUFHO1FBQ2hCLGVBQWUsRUFBRSxHQUFHO1FBQ3BCLEdBQUcsTUFBTTtLQUNaLENBQUE7SUFDRCxNQUFNLFFBQVEsR0FBUTtRQUNsQixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVE7UUFDM0IsS0FBSyxFQUFFLEtBQUs7UUFDWixPQUFPLEVBQUUsUUFBUSxDQUFDLE9BQU87UUFDN0IscUJBQXFCO1FBQ2pCLE9BQU8sRUFBRSxFQUFFO1FBQ1gsR0FBRyxFQUFFLFFBQVEsQ0FBQyxHQUFHLElBQUksT0FBTztRQUM1QixHQUFHLEVBQUUsUUFBUSxDQUFDLEdBQUc7UUFDakIsTUFBTSxFQUFFLFFBQVEsQ0FBQyxHQUFHO1FBQ3BCLFNBQVM7S0FDWixDQUFBO0lBQ0QsTUFBTSxPQUFPLEdBQUcsSUFBQSxlQUFLLEVBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzFDLE1BQU0sUUFBUSxHQUFHO1FBQ2IsR0FBRyxPQUFPO1FBQ1YsSUFBSSxFQUFFO1lBQ0YsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVE7WUFDM0IsU0FBUztTQUNaO1FBQ0QsTUFBTSxFQUFFLEtBQUs7UUFDYixLQUFLLEVBQUUsS0FBSztRQUNaLGNBQWMsRUFBRSxJQUFJO1FBQ3BCLFlBQVksRUFBRSxLQUFLO1FBQ25CLFdBQVcsRUFBRSxLQUFLO1FBQ2xCLGVBQWUsRUFBRSxLQUFLO1FBQ3RCLGNBQWMsRUFBRSxLQUFLO1FBQ3JCLE1BQU0sRUFBRSxLQUFLO0tBQ0osQ0FBQTtJQUViLE1BQU0sTUFBTSxHQUFHLElBQUksZUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRXBDLE9BQU8sQ0FBQyxLQUFLLElBQUksY0FBTSxDQUFDLElBQUksQ0FBQyxlQUFlLEdBQUcsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFBO0lBRW5FLElBQUksT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFO1FBQzlDLEdBQUcsT0FBTyxDQUFDLFNBQVM7UUFDcEIsR0FBRyxNQUFNO0tBQ1osQ0FBQyxDQUFBO0lBQ0YsT0FBTyxPQUFPLENBQUE7QUFDbEIsQ0FBQyxDQUFBO0FBbkRZLFFBQUEsYUFBYSxpQkFtRHpCIn0=
\ No newline at end of file
diff --git a/packages/discourse/lib/types.d.ts b/packages/discourse/lib/types.d.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/discourse/lib/types.js b/packages/discourse/lib/types.js
new file mode 100644
index 00000000..61fa7256
--- /dev/null
+++ b/packages/discourse/lib/types.js
@@ -0,0 +1,2 @@
+"use strict";
+//# sourceMappingURL=types.js.map
\ No newline at end of file
diff --git a/packages/discourse/lib/types.js.map b/packages/discourse/lib/types.js.map
new file mode 100644
index 00000000..247b4c7e
--- /dev/null
+++ b/packages/discourse/lib/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/lib/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/discourse/main.d.ts b/packages/discourse/main.d.ts
new file mode 100644
index 00000000..d1ebc9c7
--- /dev/null
+++ b/packages/discourse/main.d.ts
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+export {};
diff --git a/packages/discourse/main.js b/packages/discourse/main.js
new file mode 100644
index 00000000..0d4817fd
--- /dev/null
+++ b/packages/discourse/main.js
@@ -0,0 +1,28 @@
+#!/usr/bin/env node
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
+const _cli_1 = require("./_cli");
+(0, _cli_1.defaults)();
+const cli = require("yargs");
+const info_1 = require("./commands/info");
+(0, info_1.register)(cli);
+const query_1 = require("./commands/query");
+(0, query_1.register)(cli);
+const import_oa_users_1 = require("./commands/import-oa-users");
+(0, import_oa_users_1.register)(cli);
+const import_oa_howtos_1 = require("./commands/import-oa-howtos");
+(0, import_oa_howtos_1.register)(cli);
+const sync_file_1 = require("./commands/sync-file");
+(0, sync_file_1.register)(cli);
+const sync_component_1 = require("./commands/sync-component");
+(0, sync_component_1.register)(cli);
+const argv = cli.argv;
+if (argv.help) {
+ cli.showHelp();
+ process.exit();
+}
+else if (argv.v || argv.version) {
+ process.exit();
+}
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLE9BQU8sQ0FBQyxHQUFHLENBQUMsOEJBQThCLENBQUMsR0FBRyxHQUFHLENBQUM7QUFFbEQsaUNBQWtDO0FBQUMsSUFBQSxlQUFRLEdBQUUsQ0FBQztBQUM5Qyw2QkFBNkI7QUFDN0IsMENBQTJEO0FBQUMsSUFBQSxlQUFZLEVBQUMsR0FBRyxDQUFDLENBQUE7QUFDN0UsNENBQTZEO0FBQUMsSUFBQSxnQkFBYSxFQUFDLEdBQUcsQ0FBQyxDQUFBO0FBRWhGLGdFQUEwRTtBQUFDLElBQUEsMEJBQWdCLEVBQUMsR0FBRyxDQUFDLENBQUE7QUFDaEcsa0VBQWlGO0FBQUMsSUFBQSwyQkFBc0IsRUFBQyxHQUFHLENBQUMsQ0FBQTtBQUU3RyxvREFBZ0U7QUFBQyxJQUFBLG9CQUFZLEVBQUMsR0FBRyxDQUFDLENBQUE7QUFDbEYsOERBQThFO0FBQUMsSUFBQSx5QkFBcUIsRUFBQyxHQUFHLENBQUMsQ0FBQTtBQUV6RyxNQUFNLElBQUksR0FBUSxHQUFHLENBQUMsSUFBSSxDQUFDO0FBRTNCLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtJQUNYLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNmLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztDQUNsQjtLQUFNLElBQUksSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO0lBQy9CLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQztDQUNsQiJ9
\ No newline at end of file
diff --git a/packages/discourse/main.js.map b/packages/discourse/main.js.map
new file mode 100644
index 00000000..c060d445
--- /dev/null
+++ b/packages/discourse/main.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"main.js","sourceRoot":"","sources":["src/main.ts"],"names":[],"mappings":";;;AACA,iCAAkC;AAAC,IAAA,eAAQ,GAAE,CAAC;AAC9C,6BAA6B;AAC7B,0CAA2D;AAAC,IAAA,eAAY,EAAC,GAAG,CAAC,CAAC;AAC9E,4CAA6D;AAAC,IAAA,gBAAa,EAAC,GAAG,CAAC,CAAC;AACjF;;;;EAIE;AACF,MAAM,IAAI,GAAQ,GAAG,CAAC,IAAI,CAAC;AAE3B,IAAI,IAAI,CAAC,IAAI,EAAE;IACX,GAAG,CAAC,QAAQ,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,EAAE,CAAC;CAClB;KAAM,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE;IAC/B,OAAO,CAAC,IAAI,EAAE,CAAC;CAClB"}
\ No newline at end of file
diff --git a/packages/discourse/options.d.ts b/packages/discourse/options.d.ts
new file mode 100644
index 00000000..c6ac043b
--- /dev/null
+++ b/packages/discourse/options.d.ts
@@ -0,0 +1,3 @@
+export * from './lib';
+import { IOptions } from './types';
+export declare const parse: (options: IOptions, argv: any) => IOptions;
diff --git a/packages/discourse/options.js b/packages/discourse/options.js
new file mode 100644
index 00000000..54c45415
--- /dev/null
+++ b/packages/discourse/options.js
@@ -0,0 +1,39 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.parse = void 0;
+const core_1 = require("@plastichub/core");
+__exportStar(require("./lib"), exports);
+const parse = (options, argv) => {
+ for (const k in argv) {
+ if (!(k in options.variables) && k !== '_'
+ && k !== '$0'
+ && k !== 'variables'
+ && k !== 'src'
+ && k !== 'format'
+ && k !== 'profile'
+ && k !== 'output') {
+ options.variables[k] = argv[k];
+ }
+ }
+ options.variables['cwd'] = options.variables['cwd'] ? options.variables['cwd'] : options.cwd;
+ (0, core_1.resolveConfig)(options.variables);
+ let variables = {};
+ options.pathVariables = variables;
+ return options;
+};
+exports.parse = parse;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3B0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9vcHRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUEsMkNBQWdEO0FBTWhELHdDQUFxQjtBQUtkLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBaUIsRUFBRSxJQUFTLEVBQVksRUFBRTtJQUU1RCxLQUFLLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFBRTtRQUNsQixJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHO2VBQ25DLENBQUMsS0FBSyxJQUFJO2VBQ1YsQ0FBQyxLQUFLLFdBQVc7ZUFDakIsQ0FBQyxLQUFLLEtBQUs7ZUFDWCxDQUFDLEtBQUssUUFBUTtlQUNkLENBQUMsS0FBSyxTQUFTO2VBQ2YsQ0FBQyxLQUFLLFFBQVEsRUFBRTtZQUNuQixPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNsQztLQUNKO0lBRUQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFBO0lBQzVGLElBQUEsb0JBQWEsRUFBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUE7SUFDaEMsSUFBSSxTQUFTLEdBQUcsRUFBRSxDQUFBO0lBQ2xCLE9BQU8sQ0FBQyxhQUFhLEdBQUcsU0FBUyxDQUFBO0lBQ2pDLE9BQU8sT0FBTyxDQUFBO0FBQ2xCLENBQUMsQ0FBQTtBQW5CWSxRQUFBLEtBQUssU0FtQmpCIn0=
\ No newline at end of file
diff --git a/packages/discourse/options.js.map b/packages/discourse/options.js.map
new file mode 100644
index 00000000..c33ab0a6
--- /dev/null
+++ b/packages/discourse/options.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"options.js","sourceRoot":"","sources":["src/options.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAEA,2CAA4D;AAC5D,wCAAqB;AAId,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,EAAE;IAEzB,IAAI,IAAI,IAAI,GAAG,IAAI,QAAQ,IAAI,OAAO,GAAG;QAAE,OAAO,GAAG,CAAC;IACtD,IAAI,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC7B,KAAK,IAAI,IAAI,IAAI,GAAG,EAAE;QAClB,IAAI,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC;YAAE,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;KACxD;IACD,OAAO,IAAI,CAAC;AAChB,CAAC,CAAA;AARY,QAAA,KAAK,SAQjB;AAEM,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,OAAiB,EAAE,EAAE;AAExD,CAAC,CAAA;AAFY,QAAA,OAAO,WAEnB;AAGM,MAAM,KAAK,GAAG,CAAC,OAAiB,EAAE,IAAS,EAAY,EAAE;IAE5D,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE;QAClB,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,GAAG;eACnC,CAAC,KAAK,IAAI;eACV,CAAC,KAAK,WAAW;eACjB,CAAC,KAAK,QAAQ;eACd,CAAC,KAAK,UAAU;eAChB,CAAC,KAAK,cAAc;eACpB,CAAC,KAAK,eAAe;eACrB,CAAC,KAAK,QAAQ;eACd,CAAC,KAAK,SAAS;eACf,CAAC,KAAK,QAAQ;eACd,CAAC,KAAK,SAAS;eACf,CAAC,KAAK,KAAK;eACX,CAAC,KAAK,QAAQ;eACd,CAAC,KAAK,WAAW,EAAE;YACtB,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;SAClC;KACJ;IAED,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;IAE7F,IAAA,oBAAa,EAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEjC,IAAI,SAAS,GAAG,EAAE,CAAC;IAEnB,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAClC,OAAO,OAAO,CAAC;AACnB,CAAC,CAAA;AA7BY,QAAA,KAAK,SA6BjB"}
\ No newline at end of file
diff --git a/packages/discourse/package-lock.json b/packages/discourse/package-lock.json
new file mode 100644
index 00000000..99be53f0
--- /dev/null
+++ b/packages/discourse/package-lock.json
@@ -0,0 +1,5849 @@
+{
+ "name": "@plastichub/osr-discourse",
+ "version": "0.1.9",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@plastichub/osr-discourse",
+ "version": "0.1.9",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@iarna/toml": "^2.2.5",
+ "@plastichub/core": "^0.2.5",
+ "@plastichub/fs": "^0.13.39",
+ "@plastichub/osr-cache": "^0.4.7",
+ "@plastichub/osr-cli-commons": "^0.5.1",
+ "@plastichub/osr-commons": "^0.3.3",
+ "@plastichub/osr-fs-utils": "^0.1.4",
+ "@plastichub/osrl": "file:../osrl",
+ "@types/markdown-it": "^12.2.3",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.11",
+ "axios": "^0.27.2",
+ "bluebird": "^3.7.2",
+ "chalk": "^2.4.1",
+ "cheerio": "^1.0.0-rc.12",
+ "chokidar": "^3.5.3",
+ "download": "^8.0.0",
+ "env-var": "^7.1.1",
+ "escape-html": "^1.0.3",
+ "fast-glob": "^3.3.0",
+ "filenamify": "^4.3.0",
+ "find-up": "^5.0.0",
+ "front-matter": "^4.0.2",
+ "generate-password": "^1.7.0",
+ "glob-base": "^0.3.0",
+ "isomorphic-unfetch": "^4.0.2",
+ "js-base64": "^3.7.2",
+ "js-beautify": "^1.14.9",
+ "json-to-pretty-yaml": "^1.2.2",
+ "markdown-it": "^13.0.1",
+ "md5": "^2.3.0",
+ "moment": "^2.29.4",
+ "native-promise-pool": "^3.19.0",
+ "pretty": "^2.0.0",
+ "querystring": "^0.2.1",
+ "request": "^2.88.2",
+ "sanitize-filename": "^1.6.3",
+ "showdown": "^2.1.0",
+ "simple-git": "^3.19.1",
+ "slugify": "^1.6.6",
+ "tslog": "^3.3.4",
+ "turndown": "^7.1.2",
+ "typescript": "^4.3.5",
+ "uri-js": "^4.4.1",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-discourse": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "../osr-cli-commons": {
+ "name": "@plastichub/osr-cli-commons",
+ "version": "0.4.1",
+ "extraneous": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-commons": "^0.2.0",
+ "@types/cacache": "^15.0.1",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.2",
+ "cacache": "^16.1.2",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "fast-glob": "^3.2.11",
+ "glob-base": "^0.3.0",
+ "is-glob": "^4.0.3",
+ "parse-glob": "^3.0.4",
+ "rage-edit": "^1.2.0",
+ "typescript": "^4.3.5",
+ "yargs": "^17.5.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "../osrl": {
+ "name": "@plastichub/osrl",
+ "version": "0.5.4",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@elastic/elasticsearch": "^7.13.0",
+ "@google-cloud/local-auth": "^2.1.0",
+ "@iarna/toml": "^2.2.5",
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.39",
+ "@plastichub/osr-ai": "file:../osr-ai",
+ "@plastichub/osr-cache": "^0.3.9",
+ "@plastichub/osr-cli-commons": "file:../osr-cli-commons",
+ "@plastichub/osr-i18n": "file:../osr-i18n",
+ "@plastichub/osr-tasks": "file:../osr-tasks",
+ "@plastichub/osr-vcs": "^0.0.3",
+ "@types/cacache": "^15.0.1",
+ "@types/download": "^8.0.1",
+ "@types/get-stdin": "^7.0.0",
+ "@types/inquirer": "^7.3.3",
+ "@types/is-glob": "^4.0.2",
+ "@types/js-beautify": "^1.13.2",
+ "@types/jsonpath": "^0.2.0",
+ "@types/moment": "^2.13.0",
+ "@types/node": "^20.14.2",
+ "@types/yargs": "^17.0.2",
+ "axios": "^0.21.1",
+ "bluebird": "^3.7.2",
+ "cacache": "^15.2.0",
+ "chalk": "^2.4.1",
+ "cheerio": "^1.0.0-rc.10",
+ "convert-units": "^2.3.4",
+ "download": "^8.0.0",
+ "env-var": "^7.3.0",
+ "errlop": "^4.5.0",
+ "exception-formatter": "^2.1.2",
+ "fast-glob": "^3.2.7",
+ "find-up": "4.0",
+ "front-matter": "^4.0.2",
+ "get-stdin": "^9.0.0",
+ "gitea-js": "^1.20.1",
+ "glob-base": "^0.3.0",
+ "googleapis": "^105.0.0",
+ "gray-matter": "^4.0.3",
+ "grunt": "^1.6.1",
+ "grunt-cli": "^1.4.3",
+ "grunt-contrib-clean": "^2.0.0",
+ "grunt-extend-config": "^0.9.7",
+ "grunt-parallel": "^0.5.1",
+ "grunt-shell": "^3.0.1",
+ "highlight.js": "^11.1.0",
+ "inquirer": "^8.1.2",
+ "is-glob": "^4.0.1",
+ "is-url": "^1.2.4",
+ "isomorphic-unfetch": "^3.1.0",
+ "js-base64": "^3.7.2",
+ "js-beautify": "^1.14.0",
+ "jsdom": "^16.7.0",
+ "jsome": "^2.3.24",
+ "json-format-highlight": "^1.0.4",
+ "json-pretty-html": "^1.1.6",
+ "json-to-pretty-yaml": "^1.2.2",
+ "jsonpath": "^1.1.1",
+ "keyv": "^4.5.4",
+ "keyv-file": "^0.3.1",
+ "lodash": "^4.17.21",
+ "markdown-table": "^3.0.3",
+ "moment": "^2.29.1",
+ "native-promise-pool": "^3.19.0",
+ "node-xlsx": "^0.24.0",
+ "npm-run-all": "^4.1.5",
+ "open-graph-scraper": "^5.0.5",
+ "ora": "^1.3.0",
+ "parse-glob": "^3.0.4",
+ "pretty": "^2.0.0",
+ "query-string": "^7.1.3",
+ "readline": "^1.3.0",
+ "require-like": "^0.1.2",
+ "rotating-file-stream": "^3.2.3",
+ "sharp": "^0.33.4",
+ "showdown": "^2.1.0",
+ "turndown": "^7.2.0",
+ "typescript": "^4.9.4",
+ "uri-js": "^4.4.1",
+ "yaml": "^2.4.2",
+ "yargs": "^14.2.3",
+ "yargs-parser": "^15.0.3"
+ },
+ "bin": {
+ "osrl": "main.js"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "optionalDependencies": {
+ "@img/sharp-win32-x64": "^0.33.4"
+ }
+ },
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="
+ },
+ "node_modules/@iarna/toml": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz",
+ "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@kwsites/file-exists": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
+ "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
+ "dependencies": {
+ "debug": "^4.1.1"
+ }
+ },
+ "node_modules/@kwsites/promise-deferred": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
+ "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dependencies": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@npmcli/fs/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/fs/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "deprecated": "This functionality has been moved to @npmcli/fs",
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@one-ini/wasm": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
+ "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@plastichub/core": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@plastichub/core/-/core-0.2.6.tgz",
+ "integrity": "sha512-DF2IUZu6cw8+iVnFv2BFvd+s/7DYfrfXh7o3Uhg0IjbZ/QOIXY21URarnMQoTl9NEwUKN8ZZIHJmOIulT8helg==",
+ "dependencies": {
+ "deepmerge": "^4.3.1",
+ "tslog": "^3.3.3"
+ }
+ },
+ "node_modules/@plastichub/fs": {
+ "version": "0.13.39",
+ "resolved": "https://registry.npmjs.org/@plastichub/fs/-/fs-0.13.39.tgz",
+ "integrity": "sha512-Q96zN5LAlTmtj6gIbHbVM0erp2NgP+P4izRzdhqnMz/WopAvD7ZJxjQ/J44e67R6WKQuvcxt/eXPNaFBB5ehlg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.1",
+ "@types/denodeify": "^1.2.31",
+ "@types/glob": "^8.1.0",
+ "@types/minimatch": "^3.0.3",
+ "@types/node": "^14.18.63",
+ "denodeify": "^1.2.1",
+ "errno": "^0.1.4",
+ "glob": "^10.4.1",
+ "mime": "^2.0.3",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "progress-stream": "^1.2.0",
+ "q": "^1.4.1",
+ "rimraf": "^2.7.1",
+ "throttle": "^1.0.3",
+ "trash": "^4.3.0",
+ "typescript": "^4.0.3",
+ "write-file-atomic": "^1.3.1",
+ "yargs": "^17.7.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/glob": {
+ "version": "10.4.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz",
+ "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/osr-cache": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-cache/-/osr-cache-0.4.7.tgz",
+ "integrity": "sha512-uSuU+4xefo0+mX+Nft0QP4UZsp1y3afwGPOvcuRDusiMB+ShnVybUJs3T15M3JEuWSG32fViQfZnexVNiSCLLg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-cli-commons": "^0.5.1",
+ "@types/node": "^20.14.9",
+ "@types/yargs": "^17.0.32",
+ "cacache": "^18.0.3",
+ "md5": "^2.3.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "osr-cache": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/@npmcli/fs": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz",
+ "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==",
+ "license": "ISC",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/@types/node": {
+ "version": "20.16.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz",
+ "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/cacache": {
+ "version": "18.0.4",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz",
+ "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==",
+ "license": "ISC",
+ "dependencies": {
+ "@npmcli/fs": "^3.1.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^10.0.1",
+ "minipass": "^7.0.3",
+ "minipass-collect": "^2.0.1",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "p-map": "^4.0.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^3.0.0"
+ },
+ "engines": {
+ "node": "^16.14.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/fs-minipass": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz",
+ "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/minipass-collect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz",
+ "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "license": "MIT",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/ssri": {
+ "version": "10.0.6",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz",
+ "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/unique-filename": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+ "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+ "license": "ISC",
+ "dependencies": {
+ "unique-slug": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/unique-slug": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+ "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-cli-commons/-/osr-cli-commons-0.5.1.tgz",
+ "integrity": "sha512-qEhCgnLsQ5xHivRL1/lfWGb7sBZSKYnjhvN9bdh8bA/qvIHbUa4azoFbC+wKMX6DxMZNlnzRUqH3fQvTQ8kkoQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-commons": "^0.3.3",
+ "@types/cacache": "^15.0.1",
+ "@types/node": "^20.14.9",
+ "@types/which": "^3.0.4",
+ "@types/yargs": "^17.0.2",
+ "bluebird": "^3.7.2",
+ "cacache": "^16.1.2",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "fast-glob": "^3.2.11",
+ "glob": "^10.4.1",
+ "glob-base": "github:justin-caribou/glob-base",
+ "is-glob": "^4.0.3",
+ "parse-glob": "^3.0.4",
+ "rage-edit": "^1.2.0",
+ "typescript": "^4.3.5",
+ "which": "^4.0.0",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-cli": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@types/node": {
+ "version": "20.16.5",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz",
+ "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/glob": {
+ "version": "10.4.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.2.tgz",
+ "integrity": "sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/isexe": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
+ "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/which": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "dependencies": {
+ "isexe": "^3.1.1"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-commons": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-commons/-/osr-commons-0.3.3.tgz",
+ "integrity": "sha512-NW2XBeeD7AdFh5HkKOGDEMxJf6E8rS8cr8LdaY8JfM1DDae+VeX+H2wOMsSY8dgJy0VYU9ci21yuGWbEWHjGVA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.1",
+ "@plastichub/fs": "^0.13.32",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "filenamify": "^4.3.0",
+ "querystring": "^0.2.1",
+ "sanitize-filename": "^1.6.3",
+ "shell-escape": "^0.2.0",
+ "tslog": "^3.3.3",
+ "typescript": "^4.3.5",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-commons": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-fs-utils/-/osr-fs-utils-0.1.4.tgz",
+ "integrity": "sha512-MRIhPDv9m6eEcignsWN2738CZp1HOkxCKDAv39O8HivUbop5jK17LKSj8egHScHFWsajojlaYFRb0KjPyB1Fqg==",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.39",
+ "@plastichub/osr-cli-commons": "^0.4.9",
+ "@plastichub/osr-commons": "^0.3.3",
+ "@schemastore/package": "^0.0.8",
+ "@types/tar": "^6.1.5",
+ "bluebird": "^3.7.2",
+ "csv-generate": "^4.2.6",
+ "live-plugin-manager": "^0.17.1",
+ "node-xlsx": "^0.24.0",
+ "simple-git": "^3.18.0"
+ },
+ "bin": {
+ "osr-fs": "main.js"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/@plastichub/osr-cli-commons": {
+ "version": "0.4.9",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-cli-commons/-/osr-cli-commons-0.4.9.tgz",
+ "integrity": "sha512-/cVXEqMp1T4n8njCnzzSqchTdSyPmzcqiucjCiR8Jc27uvzNAtTE+8pOxnmyibUqjkKijFV2CoJ2jVGguthAyA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-commons": "^0.3.3",
+ "@types/cacache": "^15.0.1",
+ "@types/node": "^14.17.5",
+ "@types/which": "^3.0.3",
+ "@types/yargs": "^17.0.2",
+ "bluebird": "^3.7.2",
+ "cacache": "^16.1.2",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "fast-glob": "^3.2.11",
+ "glob": "^10.4.1",
+ "glob-base": "github:justin-caribou/glob-base",
+ "is-glob": "^4.0.3",
+ "parse-glob": "^3.0.4",
+ "rage-edit": "^1.2.0",
+ "typescript": "^4.3.5",
+ "which": "^4.0.0",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-cli": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/isexe": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
+ "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/osr-fs-utils/node_modules/which": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^3.1.1"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osrl": {
+ "resolved": "../osrl",
+ "link": true
+ },
+ "node_modules/@schemastore/package": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/@schemastore/package/-/package-0.0.8.tgz",
+ "integrity": "sha512-1jMrmFLUZBeQ7zdxe3ez1LSLYrUH4eY3gAPisW1rbNZ62zoYy8sudo9fXSS182s8f7p6TRy7wD6ybZvz9SUT1Q=="
+ },
+ "node_modules/@sindresorhus/df": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-2.1.0.tgz",
+ "integrity": "sha512-yozEsK3X8sEjh9fiolh3JntMUuGKe2n2t8gtE3yZ1PqAFFeaSxTrSiEVORy/YkPzUsxQ85RzLcGqmqSOgiFhtg==",
+ "dependencies": {
+ "execa": "^0.2.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/execa": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz",
+ "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==",
+ "dependencies": {
+ "cross-spawn-async": "^2.1.1",
+ "npm-run-path": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "path-key": "^1.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/npm-run-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz",
+ "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==",
+ "dependencies": {
+ "path-key": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/path-key": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz",
+ "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
+ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@types/cacache": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@types/cacache/-/cacache-15.0.1.tgz",
+ "integrity": "sha512-JhL2GFJuHMx4RMg4z0XfXB4ZkKdyiOaOLpjoYMXcyKfrkF3IBXNZBj6/Peo9zX/7PPHyfI63NWVD589cI2YTzg==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/debug": {
+ "version": "4.1.12",
+ "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+ "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+ "dependencies": {
+ "@types/ms": "*"
+ }
+ },
+ "node_modules/@types/denodeify": {
+ "version": "1.2.35",
+ "resolved": "https://registry.npmjs.org/@types/denodeify/-/denodeify-1.2.35.tgz",
+ "integrity": "sha512-5ixm6RMZKJUMlFKPZj378M/NOCGdodVVzvkYKlYbGp6mQ/r1C7C5KVroSTsZTI75qqmczZeOhhGywcWVURPMMw=="
+ },
+ "node_modules/@types/fs-extra": {
+ "version": "9.0.13",
+ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
+ "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==",
+ "dependencies": {
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob/node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA=="
+ },
+ "node_modules/@types/linkify-it": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz",
+ "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA=="
+ },
+ "node_modules/@types/lockfile": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@types/lockfile/-/lockfile-1.0.4.tgz",
+ "integrity": "sha512-Q8oFIHJHr+htLrTXN2FuZfg+WXVHQRwU/hC2GpUu+Q8e3FUM9EDkS2pE3R2AO1ZGu56f479ybdMCNF1DAu8cAQ=="
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "12.2.3",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
+ "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
+ "dependencies": {
+ "@types/linkify-it": "*",
+ "@types/mdurl": "*"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
+ "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA=="
+ },
+ "node_modules/@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
+ },
+ "node_modules/@types/minipass": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@types/minipass/-/minipass-3.3.5.tgz",
+ "integrity": "sha512-M2BLHQdEmDmH671h0GIlOQQJrgezd1vNqq7PVj1VOsHZ2uQQb4iPiQIl0SlMdhxZPUsLIfEklmeEHXg8DJRewA==",
+ "deprecated": "This is a stub types definition. minipass provides its own type definitions, so you do not need this installed.",
+ "dependencies": {
+ "minipass": "*"
+ }
+ },
+ "node_modules/@types/ms": {
+ "version": "0.7.34",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz",
+ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g=="
+ },
+ "node_modules/@types/node": {
+ "version": "14.18.63",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
+ "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.9.tgz",
+ "integrity": "sha512-bQVlnMLFJ2d35DkPNjEPmd9ueO/rh5EiaZt2bhqiSarPjZIuIV6bPQVqcrEyvNo+AfTrRGVazle1tl597w3gfA==",
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.6",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz",
+ "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A=="
+ },
+ "node_modules/@types/tar": {
+ "version": "6.1.10",
+ "resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.10.tgz",
+ "integrity": "sha512-60ZO+W0tRKJ3ggdzJKp75xKVlNogKYMqGvr2bMH/+k3T0BagfYTnbmVDFMJB1BFttz6yRgP5MDGP27eh7brrqw==",
+ "dependencies": {
+ "@types/node": "*",
+ "minipass": "^4.0.0"
+ }
+ },
+ "node_modules/@types/tar/node_modules/minipass": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
+ "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@types/url-join": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/url-join/-/url-join-4.0.1.tgz",
+ "integrity": "sha512-wDXw9LEEUHyV+7UWy7U315nrJGJ7p1BzaCxDpEoLr789Dk1WDVMMlf3iBfbG2F8NdWnYyFbtTxUn2ZNbm1Q4LQ=="
+ },
+ "node_modules/@types/which": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz",
+ "integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w=="
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
+ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/archive-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz",
+ "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==",
+ "dependencies": {
+ "file-type": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/archive-type/node_modules/file-type": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz",
+ "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+ "dependencies": {
+ "array-uniq": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws4": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
+ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
+ },
+ "node_modules/axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "dependencies": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bl": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
+ "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
+ "dependencies": {
+ "readable-stream": "^2.3.5",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/bl/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/bl/node_modules/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=="
+ },
+ "node_modules/bl/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-alloc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+ "dependencies": {
+ "buffer-alloc-unsafe": "^1.1.0",
+ "buffer-fill": "^1.0.0"
+ }
+ },
+ "node_modules/buffer-alloc-unsafe": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-fill": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+ "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ=="
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ },
+ "node_modules/cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "dependencies": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cacache/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cacache/node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cacache/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/rimraf/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/cacache/node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/rimraf/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cacheable-request": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz",
+ "integrity": "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==",
+ "dependencies": {
+ "clone-response": "1.0.2",
+ "get-stream": "3.0.0",
+ "http-cache-semantics": "3.8.1",
+ "keyv": "3.0.0",
+ "lowercase-keys": "1.0.0",
+ "normalize-url": "2.0.1",
+ "responselike": "1.0.2"
+ }
+ },
+ "node_modules/cacheable-request/node_modules/lowercase-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz",
+ "integrity": "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
+ "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "htmlparser2": "^8.0.1",
+ "parse5": "^7.0.0",
+ "parse5-htmlparser2-tree-adapter": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/clone-response": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
+ "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==",
+ "dependencies": {
+ "mimic-response": "^1.0.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/condense-newlines": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/condense-newlines/-/condense-newlines-0.2.1.tgz",
+ "integrity": "sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==",
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-whitespace": "^0.3.0",
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-units": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/convert-units/-/convert-units-2.3.4.tgz",
+ "integrity": "sha512-ERHfdA0UhHJp1IpwE6PnFJx8LqG7B1ZjJ20UvVCmopEnVCfER68Tbe3kvN63dLbYXDA2xFWRE6zd4Wsf0w7POg==",
+ "dependencies": {
+ "lodash.foreach": "2.3.x",
+ "lodash.keys": "2.3.x"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/cross-spawn-async": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
+ "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==",
+ "deprecated": "cross-spawn no longer requires a build toolchain, use it instead",
+ "dependencies": {
+ "lru-cache": "^4.0.0",
+ "which": "^1.2.8"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
+ },
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cryptr": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/cryptr/-/cryptr-6.2.0.tgz",
+ "integrity": "sha512-jYi8SxvOFebTT7EYOABiPpHKY6lwWaP9IVcvT/aIVJUVoFdzTgi0ySPCL78q1ig8w2kwfXFCZACXoCXaye57aw=="
+ },
+ "node_modules/css-select": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+ "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/csv-generate": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-4.3.0.tgz",
+ "integrity": "sha512-7KdVId/2RgwPIKfWHaHtjBq7I9mgdi8ICzsUyIhP8is6UwpwVGGSC/aPnrZ8/SkgBcCP20lXrdPuP64Irs1VBg=="
+ },
+ "node_modules/dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
+ "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decode-uri-component": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+ "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/decompress": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz",
+ "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==",
+ "dependencies": {
+ "decompress-tar": "^4.0.0",
+ "decompress-tarbz2": "^4.0.0",
+ "decompress-targz": "^4.0.0",
+ "decompress-unzip": "^4.0.1",
+ "graceful-fs": "^4.1.10",
+ "make-dir": "^1.0.0",
+ "pify": "^2.3.0",
+ "strip-dirs": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
+ "dependencies": {
+ "mimic-response": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-tar": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz",
+ "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==",
+ "dependencies": {
+ "file-type": "^5.2.0",
+ "is-stream": "^1.1.0",
+ "tar-stream": "^1.5.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-tar/node_modules/file-type": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+ "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-tarbz2": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz",
+ "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==",
+ "dependencies": {
+ "decompress-tar": "^4.1.0",
+ "file-type": "^6.1.0",
+ "is-stream": "^1.1.0",
+ "seek-bzip": "^1.0.5",
+ "unbzip2-stream": "^1.0.9"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-tarbz2/node_modules/file-type": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz",
+ "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-targz": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz",
+ "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==",
+ "dependencies": {
+ "decompress-tar": "^4.1.1",
+ "file-type": "^5.2.0",
+ "is-stream": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-targz/node_modules/file-type": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz",
+ "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-unzip": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz",
+ "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==",
+ "dependencies": {
+ "file-type": "^3.8.0",
+ "get-stream": "^2.2.0",
+ "pify": "^2.3.0",
+ "yauzl": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress-unzip/node_modules/file-type": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
+ "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decompress-unzip/node_modules/get-stream": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz",
+ "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==",
+ "dependencies": {
+ "object-assign": "^4.0.1",
+ "pinkie-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decompress/node_modules/make-dir": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz",
+ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/decompress/node_modules/make-dir/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/denodeify": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
+ "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg=="
+ },
+ "node_modules/dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dependencies": {
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domino": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
+ "integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
+ },
+ "node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/download": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/download/-/download-8.0.0.tgz",
+ "integrity": "sha512-ASRY5QhDk7FK+XrQtQyvhpDKanLluEEQtWl/J7Lxuf/b+i8RYh997QeXvL85xitrmRKVlx9c7eTrcRdq2GS4eA==",
+ "dependencies": {
+ "archive-type": "^4.0.0",
+ "content-disposition": "^0.5.2",
+ "decompress": "^4.2.1",
+ "ext-name": "^5.0.0",
+ "file-type": "^11.1.0",
+ "filenamify": "^3.0.0",
+ "get-stream": "^4.1.0",
+ "got": "^8.3.1",
+ "make-dir": "^2.1.0",
+ "p-event": "^2.1.0",
+ "pify": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/download/node_modules/filenamify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-3.0.0.tgz",
+ "integrity": "sha512-5EFZ//MsvJgXjBAFJ+Bh2YaCTRF/VP1YOmGrgt+KJ4SFRLjI87EIdwLLuT6wQX0I4F9W41xutobzczjsOKlI/g==",
+ "dependencies": {
+ "filename-reserved-regex": "^2.0.0",
+ "strip-outer": "^1.0.0",
+ "trim-repeated": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/download/node_modules/get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/download/node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/duplexer3": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
+ "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA=="
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+ },
+ "node_modules/ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
+ "dependencies": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/editorconfig": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
+ "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
+ "dependencies": {
+ "@one-ini/wasm": "0.1.1",
+ "commander": "^10.0.0",
+ "minimatch": "9.0.1",
+ "semver": "^7.5.3"
+ },
+ "bin": {
+ "editorconfig": "bin/editorconfig"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/editorconfig/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/editorconfig/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/editorconfig/node_modules/minimatch": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
+ "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/editorconfig/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/env-var": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/env-var/-/env-var-7.3.0.tgz",
+ "integrity": "sha512-qwtwYJ9d3XFxXRDudPEAMszaggpDgcfb1ZGYb9/cNyMugN2/a8EtviopnRL6c+petj2vp6/gxwYd9ExL1/iPcw==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/errno": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
+ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+ "dependencies": {
+ "prr": "~1.0.1"
+ },
+ "bin": {
+ "errno": "cli.js"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ },
+ "node_modules/escape-string-applescript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-applescript/-/escape-string-applescript-2.0.0.tgz",
+ "integrity": "sha512-Z7OsRJUi5+OHT89RRJlkS8cKxIh9AyPmgtEevsSQFCx5WLIiS3hy/HRiiQZzYQMsn6MWyCDZ5elBFa/9dxT0BA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/execa": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+ "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "dependencies": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ext-list": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz",
+ "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==",
+ "dependencies": {
+ "mime-db": "^1.28.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ext-name": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz",
+ "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==",
+ "dependencies": {
+ "ext-list": "^2.0.0",
+ "sort-keys-length": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
+ "engines": [
+ "node >=0.6.0"
+ ]
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
+ "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/file-type": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-11.1.0.tgz",
+ "integrity": "sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/filename-reserved-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
+ "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/filenamify": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
+ "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
+ "dependencies": {
+ "filename-reserved-regex": "^2.0.0",
+ "strip-outer": "^1.0.1",
+ "trim-repeated": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-up/node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz",
+ "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "node_modules/from2/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
+ "node_modules/from2/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/from2/node_modules/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=="
+ },
+ "node_modules/from2/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/front-matter": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz",
+ "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==",
+ "dependencies": {
+ "js-yaml": "^3.13.1"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+ },
+ "node_modules/fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0",
+ "path-is-absolute": "^1.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/generate-password": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/generate-password/-/generate-password-1.7.0.tgz",
+ "integrity": "sha512-WPCtlfy0jexf7W5IbwxGUgpIDvsZIohbI2DAq2Q6TSlKKis+G4GT9sxvPxrZUGL8kP6WUXMWNqYnxY6DDKAdFA=="
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-base": {
+ "version": "0.3.0",
+ "resolved": "git+ssh://git@github.com/justin-caribou/glob-base.git#d4fe4313e55988a902a3940127cb946a7defbb50",
+ "dependencies": {
+ "glob-parent": "^6.0.2",
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/glob-parent/node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/is-glob/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/got": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz",
+ "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==",
+ "dependencies": {
+ "@sindresorhus/is": "^0.7.0",
+ "cacheable-request": "^2.1.1",
+ "decompress-response": "^3.3.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "into-stream": "^3.1.0",
+ "is-retry-allowed": "^1.1.0",
+ "isurl": "^1.0.0-alpha5",
+ "lowercase-keys": "^1.0.0",
+ "mimic-response": "^1.0.0",
+ "p-cancelable": "^0.4.0",
+ "p-timeout": "^2.0.1",
+ "pify": "^3.0.0",
+ "safe-buffer": "^5.1.1",
+ "timed-out": "^4.0.1",
+ "url-parse-lax": "^3.0.0",
+ "url-to-options": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/got/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
+ },
+ "node_modules/har-schema": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+ "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/har-validator": {
+ "version": "5.1.5",
+ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
+ "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
+ "deprecated": "this library is no longer supported",
+ "dependencies": {
+ "ajv": "^6.12.3",
+ "har-schema": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-symbol-support-x": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz",
+ "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/has-to-string-tag-x": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz",
+ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==",
+ "dependencies": {
+ "has-symbol-support-x": "^1.4.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
+ "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1",
+ "entities": "^4.4.0"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz",
+ "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w=="
+ },
+ "node_modules/http-signature": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+ "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.8",
+ "npm": ">=1.3.7"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+ },
+ "node_modules/into-stream": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz",
+ "integrity": "sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==",
+ "dependencies": {
+ "from2": "^2.1.1",
+ "p-is-promise": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "node_modules/is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-natural-number": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz",
+ "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ=="
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-object": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
+ "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-retry-allowed": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
+ "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
+ },
+ "node_modules/is-whitespace": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/is-whitespace/-/is-whitespace-0.3.0.tgz",
+ "integrity": "sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/isomorphic-unfetch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-4.0.2.tgz",
+ "integrity": "sha512-1Yd+CF/7al18/N2BDbsLBcp6RO3tucSW+jcLq24dqdX5MNbCNTw1z4BsGsp4zNmjr/Izm2cs/cEqZPp4kvWSCA==",
+ "dependencies": {
+ "node-fetch": "^3.2.0",
+ "unfetch": "^5.0.0"
+ }
+ },
+ "node_modules/isomorphic-unfetch/node_modules/node-fetch": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
+ "integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
+ },
+ "node_modules/isurl": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz",
+ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==",
+ "dependencies": {
+ "has-to-string-tag-x": "^1.2.0",
+ "is-object": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/js-base64": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.4.tgz",
+ "integrity": "sha512-wpM/wi20Tl+3ifTyi0RdDckS4YTD4Lf953mBRrpG8547T7hInHNPEj8+ck4gB8VDcGyeAWFK++Wb/fU1BeavKQ=="
+ },
+ "node_modules/js-beautify": {
+ "version": "1.14.9",
+ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.9.tgz",
+ "integrity": "sha512-coM7xq1syLcMyuVGyToxcj2AlzhkDjmfklL8r0JgJ7A76wyGMpJ1oA35mr4APdYNO/o/4YY8H54NQIJzhMbhBg==",
+ "dependencies": {
+ "config-chain": "^1.1.13",
+ "editorconfig": "^1.0.3",
+ "glob": "^8.1.0",
+ "nopt": "^6.0.0"
+ },
+ "bin": {
+ "css-beautify": "js/bin/css-beautify.js",
+ "html-beautify": "js/bin/html-beautify.js",
+ "js-beautify": "js/bin/js-beautify.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/js-beautify/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/js-beautify/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/js-beautify/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ=="
+ },
+ "node_modules/json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
+ },
+ "node_modules/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=="
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
+ },
+ "node_modules/json-to-pretty-yaml": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz",
+ "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==",
+ "dependencies": {
+ "remedial": "^1.0.7",
+ "remove-trailing-spaces": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.2.0"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsprim": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
+ "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz",
+ "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==",
+ "dependencies": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
+ "node_modules/linkify-it": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz",
+ "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==",
+ "dependencies": {
+ "uc.micro": "^1.0.1"
+ }
+ },
+ "node_modules/live-plugin-manager": {
+ "version": "0.17.1",
+ "resolved": "https://registry.npmjs.org/live-plugin-manager/-/live-plugin-manager-0.17.1.tgz",
+ "integrity": "sha512-gWAjojKD8AWkK8psxpm73q6JiSPeHJwwXjoSJL23CPwp/PejuetQjBWe0hGYBPb9kNYs6s6LA4SZVYuJwXDldg==",
+ "dependencies": {
+ "@types/debug": "^4.1.7",
+ "@types/fs-extra": "^9.0.12",
+ "@types/lockfile": "^1.0.2",
+ "@types/node-fetch": "^2.5.12",
+ "@types/semver": "^7.3.8",
+ "@types/tar": "^4.0.5",
+ "@types/url-join": "4.0.1",
+ "debug": "^4.3.2",
+ "fs-extra": "^10.0.0",
+ "lockfile": "^1.0.4",
+ "node-fetch": "^2.6.1",
+ "semver": "^7.3.5",
+ "tar": "^6.1.10",
+ "url-join": "^4.0.1"
+ }
+ },
+ "node_modules/live-plugin-manager/node_modules/@types/tar": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.5.tgz",
+ "integrity": "sha512-cgwPhNEabHaZcYIy5xeMtux2EmYBitfqEceBUi2t5+ETy4dW6kswt6WX4+HqLeiiKOo42EXbGiDmVJ2x+vi37Q==",
+ "dependencies": {
+ "@types/minipass": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/live-plugin-manager/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/live-plugin-manager/node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/live-plugin-manager/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/live-plugin-manager/node_modules/semver": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
+ "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lockfile": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz",
+ "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==",
+ "dependencies": {
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/lodash._basebind": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.3.0.tgz",
+ "integrity": "sha512-SHqM7YCuJ+BeGTs7lqpWnmdHEeF4MWxS3dksJctHFNxR81FXPOzA4bS5Vs5CpcGTkBpM8FCl+YEbQEblRw8ABg==",
+ "dependencies": {
+ "lodash._basecreate": "~2.3.0",
+ "lodash._setbinddata": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreate": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.3.0.tgz",
+ "integrity": "sha512-vwZaWldZwS2y9b99D8i9+WtgiZXbHKsBsMrpxJEqTsNW20NhJo5W8PBQkeQO9CmxuqEYn8UkMnfEM2MMT4cVrw==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash.isobject": "~2.3.0",
+ "lodash.noop": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreatecallback": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.3.0.tgz",
+ "integrity": "sha512-Ev+pDzzfVfgbiucpXijconLGRBar7/+KNCf05kSnk4CmdDVhAy1RdbU9efCJ/o9GXI08JdUGwZ+5QJ3QX3kj0g==",
+ "dependencies": {
+ "lodash._setbinddata": "~2.3.0",
+ "lodash.bind": "~2.3.0",
+ "lodash.identity": "~2.3.0",
+ "lodash.support": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreatewrapper": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.3.0.tgz",
+ "integrity": "sha512-YLycQ7k8AB9Wc1EOvLNxuRWcqipDkMXq2GCgnLWQR6qtgTb3gY3LELzEpnFshrEO4LOLs+R2EpcY+uCOZaLQ8Q==",
+ "dependencies": {
+ "lodash._basecreate": "~2.3.0",
+ "lodash._setbinddata": "~2.3.0",
+ "lodash._slice": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._createwrapper": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.3.0.tgz",
+ "integrity": "sha512-XjaI/rzg9W+WO4WJDQ+PRlHD5sAMJ1RhJLuT65cBxLCb1kIYs4U20jqvTDGAWyVT3c34GYiLd9AreHYuB/8yJA==",
+ "dependencies": {
+ "lodash._basebind": "~2.3.0",
+ "lodash._basecreatewrapper": "~2.3.0",
+ "lodash.isfunction": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._objecttypes": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.3.0.tgz",
+ "integrity": "sha512-jbA6QyHt9cw3BzvbWzIcnU3Z12jSneT6xBgz3Y782CJsN1tV5aTBKrFo2B4AkeHBNaxSrbPYZZpi1Lwj3xjdtg=="
+ },
+ "node_modules/lodash._renative": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._renative/-/lodash._renative-2.3.0.tgz",
+ "integrity": "sha512-v44MRirqYqZGK/h5UKoVqXWF2L+LUiLTU+Ogu5rHRVWJUA1uWIlHaMpG8f/OA8j++BzPMQij9+erXHtgFcbuwg=="
+ },
+ "node_modules/lodash._setbinddata": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.3.0.tgz",
+ "integrity": "sha512-xMFfbF7dL+sFtrdE49uHFmfpBAEwlFtfgMp86nQRlAF6aizYL+3MTbnYMKJSkP1W501PhsgiBED5kBbZd8kR2g==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash.noop": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._shimkeys": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.3.0.tgz",
+ "integrity": "sha512-9Iuyi7TiWMGa/9+2rqEE+Zwye4b/U2w7Saw6UX1h6Xs88mEER+uz9FZcEBPKMVKsad9Pw5GNAcIBRnW2jNpneQ==",
+ "dependencies": {
+ "lodash._objecttypes": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._slice": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.3.0.tgz",
+ "integrity": "sha512-7C61GhzRUv36gTafr+RIb+AomCAYsSATEoK4OP0VkNBcwvsM022Z22AVgqjjzikeNO1U29LzsJZDvLbiNPUYvA=="
+ },
+ "node_modules/lodash.bind": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.3.0.tgz",
+ "integrity": "sha512-goakyOo+FMN8lttMPnZ0UNlr5RlzX4IrUXyTJPT2A0tGCMXySupond9wzvDqTvVmYTcQjIKGrj8naJDS2xWAlQ==",
+ "dependencies": {
+ "lodash._createwrapper": "~2.3.0",
+ "lodash._renative": "~2.3.0",
+ "lodash._slice": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.foreach": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-2.3.0.tgz",
+ "integrity": "sha512-yLnyptVRJd0//AbGp480grgQG9iaDIV5uOgSbpurRy1dYybPbjNTLQ3FyLEQ84buVLPG7jyaiyvpzgfOutRB3Q==",
+ "dependencies": {
+ "lodash._basecreatecallback": "~2.3.0",
+ "lodash.forown": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.forown": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-2.3.0.tgz",
+ "integrity": "sha512-dUnCsuQTtq3Y7bxPNoEEqjJjPL2ftLtcz2PTeRKvhbpdM514AvnqCjewHGsm/W+dwspIwa14KoWEZeizJ7smxA==",
+ "dependencies": {
+ "lodash._basecreatecallback": "~2.3.0",
+ "lodash._objecttypes": "~2.3.0",
+ "lodash.keys": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.identity": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.3.0.tgz",
+ "integrity": "sha512-NYJ2r2cwy3tkx/saqbIZEX6oQUzjWTnGRu7d/zmBjMCZos3eHBxCpbvWFWSetv8jFVrptsp6EbWjzNgBKhUoOA=="
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.3.0.tgz",
+ "integrity": "sha512-X5lteBYlCrVO7Qc00fxP8W90fzRp6Ax9XcHANmU3OsZHdSyIVZ9ZlX5QTTpRq8aGY+9I5Rmd0UTzTIIyWPugEQ=="
+ },
+ "node_modules/lodash.isobject": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.3.0.tgz",
+ "integrity": "sha512-jo1pfV61C4TE8BfEzqaHj6EIKiSkFANJrB6yscwuCJMSRw5tbqjk4Gv7nJzk4Z6nFKobZjGZ8Qd41vmnwgeQqQ==",
+ "dependencies": {
+ "lodash._objecttypes": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.keys": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.3.0.tgz",
+ "integrity": "sha512-c0UW0ffqMxSCtoVbmVt2lERJLkEqgoOn2ejPsWXzr0ZrqRbl3uruGgwHzhtqXxi6K/ei3Ey7zimOqSwXgzazPg==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash._shimkeys": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.noop": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.3.0.tgz",
+ "integrity": "sha512-NpSm8HRm1WkBBWHUveDukLF4Kfb5P5E3fjHc9Qre9A11nNubozLWD2wH3UBTZbu+KSuX8aSUvy9b+PUyEceJ8g=="
+ },
+ "node_modules/lodash.support": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.3.0.tgz",
+ "integrity": "sha512-etc7VWbB0U3Iya8ixj2xy4sDBN3jvPX7ODi8iXtn4KkkjNpdngrdc7Vlt5jub/Vgqx6/dWtp7Ml9awhCQPYKGQ==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0"
+ }
+ },
+ "node_modules/lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dependencies": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/make-dir/node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/markdown-it": {
+ "version": "13.0.1",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz",
+ "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "~3.0.1",
+ "linkify-it": "^4.0.1",
+ "mdurl": "^1.0.1",
+ "uc.micro": "^1.0.5"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.js"
+ }
+ },
+ "node_modules/markdown-it/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/markdown-it/node_modules/entities": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
+ "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "dependencies": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
+ "node_modules/mdurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g=="
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
+ "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mount-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mount-point/-/mount-point-3.0.0.tgz",
+ "integrity": "sha512-jAhfD7ZCG+dbESZjcY1SdFVFqSJkh/yGbdsifHcPkvuLRO5ugK0Ssmd9jdATu29BTd4JiN+vkpMzVvsUgP3SZA==",
+ "dependencies": {
+ "@sindresorhus/df": "^1.0.1",
+ "pify": "^2.3.0",
+ "pinkie-promise": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mount-point/node_modules/@sindresorhus/df": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-1.0.1.tgz",
+ "integrity": "sha512-1Hyp7NQnD/u4DSxR2DGW78TF9k7R0wZ8ev0BpMAIzA6yTQSHqNb5wTuvtcPYf4FWbVse2rW7RgDsyL8ua2vXHw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/native-promise-pool": {
+ "version": "3.19.0",
+ "resolved": "https://registry.npmjs.org/native-promise-pool/-/native-promise-pool-3.19.0.tgz",
+ "integrity": "sha512-Clf1xJ/qBGZrWeuu1qJ2Ta79L0CC0pANvh5cq2RIwCu4ehcc8W5COA4fwgnaU5a+Cg/QFOBGEuM/5naa9LF+og==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-xlsx": {
+ "version": "0.24.0",
+ "resolved": "https://registry.npmjs.org/node-xlsx/-/node-xlsx-0.24.0.tgz",
+ "integrity": "sha512-1olwK48XK9nXZsyH/FCltvGrQYvXXZuxVitxXXv2GIuRm51aBi1+5KwR4rWM4KeO61sFU+00913WLZTD+AcXEg==",
+ "dependencies": {
+ "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
+ },
+ "bin": {
+ "node-xlsx": "dist/bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/node-xlsx/node_modules/xlsx": {
+ "version": "0.20.2",
+ "resolved": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz",
+ "integrity": "sha512-+nKZ39+nvK7Qq6i0PvWWRA4j/EkfWOtkP/YhMtupm+lJIiHxUrgTr1CcKv1nBk1rHtkRRQ3O2+Ih/q/sA+FXZA==",
+ "bin": {
+ "xlsx": "bin/xlsx.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
+ "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
+ "dependencies": {
+ "abbrev": "^1.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-url": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz",
+ "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==",
+ "dependencies": {
+ "prepend-http": "^2.0.0",
+ "query-string": "^5.0.1",
+ "sort-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
+ "dependencies": {
+ "path-key": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/oauth-sign": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
+ "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
+ "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw=="
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-cancelable": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz",
+ "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-event": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz",
+ "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==",
+ "dependencies": {
+ "p-timeout": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-is-promise": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz",
+ "integrity": "sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate/node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-timeout": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz",
+ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==",
+ "dependencies": {
+ "p-finally": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
+ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw=="
+ },
+ "node_modules/parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==",
+ "dependencies": {
+ "glob-base": "^0.3.0",
+ "is-dotfile": "^1.0.0",
+ "is-extglob": "^1.0.0",
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
+ "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+ "dependencies": {
+ "entities": "^4.4.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
+ "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
+ "dependencies": {
+ "domhandler": "^5.0.2",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz",
+ "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==",
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/path-scurry/node_modules/minipass": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz",
+ "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-type/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+ "dependencies": {
+ "pinkie": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pretty": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pretty/-/pretty-2.0.0.tgz",
+ "integrity": "sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==",
+ "dependencies": {
+ "condense-newlines": "^0.2.1",
+ "extend-shallow": "^2.0.1",
+ "js-beautify": "^1.6.12"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/progress-stream": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz",
+ "integrity": "sha512-MIBPjZz6oGNSw5rn2mSp+nP9FGoaVo6QsPyPVEaD4puilz5hZNa3kfnrlqRNYFsugslbU3An4mnkLLtZOaWvrA==",
+ "dependencies": {
+ "speedometer": "~0.1.2",
+ "through2": "~0.2.3"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="
+ },
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="
+ },
+ "node_modules/prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag=="
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
+ "engines": {
+ "node": ">=0.6.0",
+ "teleport": ">=0.2.0"
+ }
+ },
+ "node_modules/query-string": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz",
+ "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==",
+ "dependencies": {
+ "decode-uri-component": "^0.2.0",
+ "object-assign": "^4.1.0",
+ "strict-uri-encode": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/querystring": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
+ "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/rage-edit": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/rage-edit/-/rage-edit-1.2.0.tgz",
+ "integrity": "sha512-0RspBRc2s6We4g7hRCvT5mu7YPEnfjvQK8Tt354a2uUNJCMC7MKLvo/1mLvHUCQ/zbP6siQyp5VRZN7UCpMFZg=="
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/remedial": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz",
+ "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/remove-trailing-spaces": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz",
+ "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA=="
+ },
+ "node_modules/request": {
+ "version": "2.88.2",
+ "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
+ "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
+ "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "har-validator": "~5.1.3",
+ "http-signature": "~1.2.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "oauth-sign": "~0.9.0",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.3.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/request/node_modules/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==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/request/node_modules/qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/request/node_modules/tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dependencies": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/request/node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==",
+ "dependencies": {
+ "lowercase-keys": "^1.0.0"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-3.2.0.tgz",
+ "integrity": "sha512-Ep0RsvAjnRcBX1p5vogbaBdAGu/8j/ewpvGqnQYunnLd9SM0vWcPJewPKNnWFggf0hF0pwIgwV5XK7qQ7UZ8Qg==",
+ "dependencies": {
+ "execa": "^0.10.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/sanitize-filename": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
+ "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
+ "dependencies": {
+ "truncate-utf8-bytes": "^1.0.0"
+ }
+ },
+ "node_modules/seek-bzip": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz",
+ "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==",
+ "dependencies": {
+ "commander": "^2.8.1"
+ },
+ "bin": {
+ "seek-bunzip": "bin/seek-bunzip",
+ "seek-table": "bin/seek-bzip-table"
+ }
+ },
+ "node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shell-escape": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz",
+ "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw=="
+ },
+ "node_modules/showdown": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/showdown/-/showdown-2.1.0.tgz",
+ "integrity": "sha512-/6NVYu4U819R2pUIk79n67SYgJHWCce0a5xTP979WbNp0FL9MN1I1QK662IDU1b6JzKTvmhgI7T7JYIxBi3kMQ==",
+ "dependencies": {
+ "commander": "^9.0.0"
+ },
+ "bin": {
+ "showdown": "bin/showdown.js"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://www.paypal.me/tiviesantos"
+ }
+ },
+ "node_modules/showdown/node_modules/commander": {
+ "version": "9.5.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
+ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
+ "engines": {
+ "node": "^12.20.0 || >=14"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/simple-git": {
+ "version": "3.19.1",
+ "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.1.tgz",
+ "integrity": "sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w==",
+ "dependencies": {
+ "@kwsites/file-exists": "^1.1.1",
+ "@kwsites/promise-deferred": "^1.1.1",
+ "debug": "^4.3.4"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/steveukx/git-js?sponsor=1"
+ }
+ },
+ "node_modules/slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/slide": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+ "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/slugify": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
+ "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/sort-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz",
+ "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==",
+ "dependencies": {
+ "is-plain-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/sort-keys-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz",
+ "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==",
+ "dependencies": {
+ "sort-keys": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sort-keys-length/node_modules/sort-keys": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
+ "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==",
+ "dependencies": {
+ "is-plain-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/speedometer": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz",
+ "integrity": "sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q=="
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+ },
+ "node_modules/sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/stream-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
+ "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
+ "dependencies": {
+ "debug": "2"
+ }
+ },
+ "node_modules/stream-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/stream-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/strict-uri-encode": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
+ "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-dirs": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz",
+ "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==",
+ "dependencies": {
+ "is-natural-number": "^4.0.1"
+ }
+ },
+ "node_modules/strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-outer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
+ "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
+ "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
+ "dependencies": {
+ "bl": "^1.0.0",
+ "buffer-alloc": "^1.2.0",
+ "end-of-stream": "^1.0.0",
+ "fs-constants": "^1.0.0",
+ "readable-stream": "^2.3.0",
+ "to-buffer": "^1.1.1",
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/tar-stream/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
+ "node_modules/tar-stream/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/tar-stream/node_modules/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=="
+ },
+ "node_modules/tar-stream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/tar-stream/node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/throttle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/throttle/-/throttle-1.0.3.tgz",
+ "integrity": "sha512-VYINSQFQeFdmhCds0tTqvQmLmdAjzGX1D6GnRQa4zlq8OpTtWSMddNyRq8Z4Snw/d6QZrWt9cM/cH8xTiGUkYA==",
+ "dependencies": {
+ "readable-stream": ">= 0.3.0",
+ "stream-parser": ">= 0.0.2"
+ },
+ "engines": {
+ "node": ">= v0.8.0"
+ }
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+ },
+ "node_modules/through2": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
+ "integrity": "sha512-mLa8Bn2mZurjyomGKWRu3Bo2mvoQojFks9NvOK8H+k4kDJNkdEqG522KFZsEFBEl6rKkxTgFbE5+OPcgfvPEHA==",
+ "dependencies": {
+ "readable-stream": "~1.1.9",
+ "xtend": "~2.1.1"
+ }
+ },
+ "node_modules/through2/node_modules/readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "node_modules/through2/node_modules/string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ },
+ "node_modules/timed-out": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz",
+ "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-buffer": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
+ "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/trash": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/trash/-/trash-4.3.0.tgz",
+ "integrity": "sha512-f36TKwIaBiXm63xSrn8OTNghg5CYHBsFVJvcObMo76LRpgariuRi2CqXQHw1VzfeximD0igdGaonOG6N760BtQ==",
+ "dependencies": {
+ "escape-string-applescript": "^2.0.0",
+ "fs-extra": "^0.30.0",
+ "globby": "^7.1.1",
+ "p-map": "^1.2.0",
+ "p-try": "^1.0.0",
+ "pify": "^3.0.0",
+ "run-applescript": "^3.0.0",
+ "uuid": "^3.1.0",
+ "xdg-trashdir": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
+ "dependencies": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/trim-repeated": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
+ "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/truncate-utf8-bytes": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
+ "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==",
+ "dependencies": {
+ "utf8-byte-length": "^1.0.1"
+ }
+ },
+ "node_modules/tslog": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.3.4.tgz",
+ "integrity": "sha512-N0HHuHE0e/o75ALfkioFObknHR5dVchUad4F0XyFf3gXJYB++DewEzwGI/uIOM216E5a43ovnRNEeQIq9qgm4Q==",
+ "dependencies": {
+ "source-map-support": "^0.5.21"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/turndown": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.1.2.tgz",
+ "integrity": "sha512-ntI9R7fcUKjqBP6QU8rBK2Ehyt8LAzt3UBT9JR9tgo6GtuKvyUzpayWmeMKJw1DPdXzktvtIT8m2mVXz+bL/Qg==",
+ "dependencies": {
+ "domino": "^2.1.6"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
+ },
+ "node_modules/typescript": {
+ "version": "4.9.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
+ "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/uc.micro": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
+ },
+ "node_modules/unbzip2-stream": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
+ "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
+ "dependencies": {
+ "buffer": "^5.2.1",
+ "through": "^2.3.8"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
+ },
+ "node_modules/unfetch": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-5.0.0.tgz",
+ "integrity": "sha512-3xM2c89siXg0nHvlmYsQ2zkLASvVMBisZm5lF3gFDqfF2xonNStDJyMpvaOBe0a1Edxmqrf2E0HBdmy9QyZaeg=="
+ },
+ "node_modules/unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "dependencies": {
+ "unique-slug": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-join": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
+ },
+ "node_modules/url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==",
+ "dependencies": {
+ "prepend-http": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/url-to-options": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz",
+ "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/user-home": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
+ "integrity": "sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==",
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/utf8-byte-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
+ "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA=="
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "node_modules/verror/node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
+ "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/write-file-atomic": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz",
+ "integrity": "sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "slide": "^1.1.5"
+ }
+ },
+ "node_modules/xdg-basedir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz",
+ "integrity": "sha512-NF1pPn594TaRSUO/HARoB4jK8I+rWgcpVlpQCK6/6o5PHyLUt2CSiDrpUZbQ6rROck+W2EwF8mBJcTs+W98J9w==",
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/xdg-trashdir": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/xdg-trashdir/-/xdg-trashdir-2.1.1.tgz",
+ "integrity": "sha512-KcVhPaOu2ZurYNHSRTf1+ZHORkTZGCQ+u0JHN17QixRISJq4pXOnjt/lQcehvtHL5QAKhSzKgyjrcNnPdkPBHA==",
+ "dependencies": {
+ "@sindresorhus/df": "^2.1.0",
+ "mount-point": "^3.0.0",
+ "pify": "^2.2.0",
+ "user-home": "^2.0.0",
+ "xdg-basedir": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
+ "integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==",
+ "dependencies": {
+ "object-keys": "~0.4.0"
+ },
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/packages/discourse/scripts/link-dev.sh b/packages/discourse/scripts/link-dev.sh
new file mode 100644
index 00000000..8ba121ce
--- /dev/null
+++ b/packages/discourse/scripts/link-dev.sh
@@ -0,0 +1 @@
+npm i ../osr-cli-commons/
diff --git a/packages/discourse/scripts/sync-components.sh b/packages/discourse/scripts/sync-components.sh
new file mode 100644
index 00000000..f958e057
--- /dev/null
+++ b/packages/discourse/scripts/sync-components.sh
@@ -0,0 +1 @@
+node ./main.js sync-component --skip=false --src="${OSR_LIBRARY_MACHINES}/extrusion/**/config.+(json)"
diff --git a/packages/discourse/scripts/test.sh b/packages/discourse/scripts/test.sh
new file mode 100644
index 00000000..1a4fe1bb
--- /dev/null
+++ b/packages/discourse/scripts/test.sh
@@ -0,0 +1,14 @@
+curl 'https://forum.osr-plastic.org/t/10028/change-timestamp' \
+ -X 'PUT' \
+ -H 'accept: */*' \
+ -H 'accept-language: en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7,es;q=0.6,fr;q=0.5' \
+ -H 'content-type: application/x-www-form-urlencoded; charset=UTF-8' \
+ -H 'cookie: _bypass_cache=true; _ga_MBZGKNMDWC=GS1.1.1685892974.20.1.1685893082.0.0.0; _ga_P4SR15V1XR=GS1.1.1687459978.51.1.1687460537.0.0.0; _ga_H8W78Y3P2B=GS1.1.1687604701.23.0.1687604701.0.0.0; _ga=GA1.1.401826746.1678337758; _t=xQ05qW5JFxLM9Pq0lIwG6ez74Z1q2OLpak0DzRx8VdFYE5eI3oJXhLURPrdm2zIcHmYcBj9q%2BKdHhGz5N6j9mXitYzcMwkXHL3K9GYKdO4gJ8tBQimpmd1HFaRhB9Ml9aJ8WviqQWDZDOYwEUKFcWw3wbAalfQtbdIbUSX8gH9sG6DLFU3HiEg7tWModRy%2BoFrTm6QOalDuajRW3nBazau%2FiY8ZCVm2g30Y10CBDfqJHL1ztV8XM4kEIeulLNTzGVtSb7uuO1OcjZRSb--aDgCPEalq7SIpnH5--HWCNf5readaeij3oDl9b9w%3D%3D; __profilin=p%3Dt%2Ca%3Deef38e031f99cc8240f3518e1b8811cf; _forum_session=RkEWuzKI1QXBYCnP6KRamD8mweZ3h9%2B6G%2Fi23gAWUgy8gp8FuiyQD5lKU0Fbx3FzzaM4SiQcvnIiEAnb5P4OYjlvstqwWlfRp%2B9is7iX8StwYGiYsncHQ5LrzSbV3y9mR7sj%2F8JZ8evQOe2ZZjZB3iEkppsGrmyFrw5PsUgSphRTZm70SKIw96JrW17yK4hhLqtk%2BaQPgNu4oJl42YfXAr%2FCBldcBUKXFeHppYmv61WECV0531hCo7GcA4t06B9QpSr%2BeoiM1Ok9tpQrAlZf36Ka4lVCTyXXu3SNvbtvfd9tZMJCWDYv69jdMsezuOaEP870pk9qYPaL4x6nAY5EXO3u9usCggqQ1B1EydCK9uMy7ZUCIo9wONw7QOIgEQ%3D%3D--GMqYSb2H7xXVDky6--R9gVciBqwC0IL9LefywrFw%3D%3D; _ga_GVR8PEPG6C=GS1.1.1687710574.106.1.1687710599.0.0.0' \
+ -H 'origin: https://forum.osr-plastic.org' \
+ -H 'Api-Key: 61b2d970483b8dc2d24d5358ce3ec28e6916f5daf4df20074caf18fe8c74096f' \
+ -H 'Api-Username: jerome' \
+ -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \
+ -H 'x-2csrf-token: j7oYrkQe5nbnikCNHcfoP2DGtXKV4iHHzDFip8gGatS145g3B65UU6mI09KeFday9mY5HNQnU2jXUTe7LLkP-w' \
+ -H 'x-requested-with: XMLHttpRequest' \
+ --data-raw 'timestamp=1667430000'
+
diff --git a/packages/discourse/src/_cli.ts b/packages/discourse/src/_cli.ts
new file mode 100644
index 00000000..ec697913
--- /dev/null
+++ b/packages/discourse/src/_cli.ts
@@ -0,0 +1,81 @@
+import { sync as exists } from '@plastichub/fs/exists'
+import { IOptions, IOptionsSync } from './types'
+import { logger } from './'
+import * as path from 'path'
+
+import { forward_slash, pathInfo } from "@plastichub/osr-cli-commons"
+import { isFile, resolve } from "@plastichub/osr-commons"
+
+import { substitute } from './index'
+
+const globBase = require('glob-base')
+
+export const defaults = () => {
+ // default command
+ const DefaultCommand = 'info';
+ if (process.argv.length === 2) {
+ process.argv.push(DefaultCommand);
+ }
+
+ process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
+
+ // currently no default handler, display only :
+ process.on('unhandledRejection', (reason: string) => {
+ console.error('Unhandled rejection, reason: ', reason);
+ });
+}
+
+export const sanitize = (argv: any): IOptionsSync | IOptions | boolean => {
+
+ let ret: any = {
+ ...argv
+ }
+
+ ret.src = argv.src
+ let srcInfo
+ let variables = {}
+
+ /*
+ if (ret.src) {
+ ret.src = forward_slash(substitute(ret.alt,ret.src,variables))
+ // in case a file with a glob pattern is provided, strip the glob
+ // this is a special case, enabling shared scripts in Alt-Tap Salamand
+ const glob_base = globBase(ret.src)
+ const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '')
+
+ if(exists(file) && isFile(file)){
+ ret.src = file
+ }
+
+ srcInfo = pathInfo(resolve(ret.src, ret.alt, variables))
+
+ if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
+ ret.srcInfo = srcInfo
+ for (const key in srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
+ variables['SRC_' + key] = srcInfo[key];
+ }
+ }
+ } else {
+ ret.src = resolve(ret.src, ret.alt, variables)
+ }
+ }
+ */
+
+ if (argv.cwd) {
+ ret.cwd = path.resolve(argv.cwd);
+ if (!exists((ret.cwd))) {
+ logger.error(`Invalid working directory ${argv.cwd}`)
+ }
+ } else {
+ ret.cwd = process.cwd()
+ }
+
+ ret = {
+ ...ret,
+ variables,
+ srcInfo
+ }
+
+ return ret
+}
\ No newline at end of file
diff --git a/packages/discourse/src/commands/import-oa-howtos.ts b/packages/discourse/src/commands/import-oa-howtos.ts
new file mode 100644
index 00000000..2c6bc677
--- /dev/null
+++ b/packages/discourse/src/commands/import-oa-howtos.ts
@@ -0,0 +1,95 @@
+import * as CLI from 'yargs'
+
+import { defaults, sanitize } from '../_cli'
+import { IOptions } from '../types'
+import { logger, IImportUser } from '../index'
+
+import { Instance } from '../lib/discourse'
+
+import { sync as write } from '@plastichub/fs/write'
+
+import {
+ read_users, filter_invalid,
+ filter_email_missing,
+ updateUsers,
+ filter_email_only,
+ importUsers,
+ filter_accepted,
+ oa_user_email,
+ getDataPath
+} from '../lib/oa/users'
+
+import {
+ read_categories,
+ read_howtos,
+ read_tags,
+ filter_valid
+} from '../lib/oa/commons'
+
+import {
+ importHowtos, updateHowtos
+} from '../lib/oa/howtos'
+
+import {
+ IOAHowtoImport
+} from '../'
+
+import { IUserPP } from '@plastichub/osr-commons'
+
+import * as path from 'path'
+import { resolve } from '@plastichub/osr-commons'
+import { CONFIG_DEFAULT, DEFAULT_ROOTS } from '@plastichub/osr-cli-commons'
+
+const KB_ROOT = '${KB_ROOT}'
+
+import {
+ IOACategory,
+ IOATag,
+ IOAStep
+} from '../lib/oa/types'
+
+import { OA_LATEST } from '@plastichub/osr-commons'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs.option('debug', {
+ default: true,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('src', {
+ default: OA_LATEST,
+ type: 'string',
+ }).option('track', {
+ default: '${OA_ROOT}/oa-data/howtos/latest_track.json',
+ type: 'string',
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs)
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('import-howtos', 'Import oa-howtos', options, async (argv: CLI.Arguments) => {
+ defaults()
+ if (argv.help) { return }
+ let options = (argv as any) as IOptions
+
+ if (!options) {
+ return
+ }
+ options.debug && logger.debug(`CLI Args In`, argv)
+
+ const discourse = Instance()
+
+ const _opts = {
+ src: path.resolve(resolve(options.src)),
+ track: path.resolve(resolve(options.track))
+ } as IOptions
+
+ let howtos = read_howtos(_opts.src)
+ howtos = filter_valid(howtos)
+ await importHowtos(discourse,_opts,howtos)
+ await updateHowtos(discourse,_opts,howtos)
+ })
+}
diff --git a/packages/discourse/src/commands/import-oa-users.ts b/packages/discourse/src/commands/import-oa-users.ts
new file mode 100644
index 00000000..0cefac53
--- /dev/null
+++ b/packages/discourse/src/commands/import-oa-users.ts
@@ -0,0 +1,118 @@
+import * as CLI from 'yargs'
+
+import { defaults, sanitize } from '../_cli'
+import { parse } from '../options'
+import { IOptions } from '../types'
+import { logger, IImportUser } from '../index'
+
+import { Instance } from '../lib/discourse'
+
+import { sync as write } from '@plastichub/fs/write'
+
+import { OA_LATEST, OA_LATEST_MERGED } from '@plastichub/osr-commons'
+
+import {
+ read_users, filter_invalid,
+ filter_email_missing,
+ filter_email_only,
+ importUsers,
+ filter_valid,
+ oa_user_email,
+ getDataPath,
+ updateUsers,
+ indexUsers
+} from '../lib/oa/users'
+
+import * as path from 'path'
+import { resolve } from '@plastichub/osr-commons'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('src', {
+ default: '${OA_ROOT}/data/latest.json',
+ type: 'string',
+ }).option('track', {
+ default: '${OSR_ROOT}/osr-directory/pp/merged.json',
+ type: 'string',
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs)
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('import-users ', 'Import oa-users', options, async (argv: CLI.Arguments) => {
+
+ defaults()
+
+ if (argv.help) { return }
+ const args: any = argv
+ let options = sanitize(argv as any) as IOptions;
+
+ if (!options) {
+ return
+ }
+ options.debug && logger.debug(`CLI Args In`, argv)
+ let opts = parse(options, args)
+
+ const discourse = Instance()
+
+ const _opts = {
+ verb: argv.verb,
+ src: path.resolve(resolve(options.src)),
+ track: path.resolve(resolve(options.track))
+ }
+
+
+ let users = read_users(_opts.src)
+ users = filter_valid(users as IImportUser[])
+
+ //////////////////////////
+ //
+ // store invalid
+
+ let usersInvalid = read_users(_opts.src)
+ usersInvalid = filter_email_only(usersInvalid)
+ usersInvalid = filter_invalid(usersInvalid)
+
+ logger.debug('write invalidUsers.json : ', getDataPath('/invalidUsers.json'))
+ write(getDataPath('/invalidUsers.json'), usersInvalid.map((u) => {
+ return {
+ ...u.detail,
+ id: u._id,
+ email: oa_user_email(u)
+ }
+ }))
+
+ let usersInvalidEmail = read_users(_opts.src)
+ usersInvalidEmail = filter_email_missing(usersInvalidEmail)
+ logger.debug('write invalidUsersEMail.json : ', getDataPath('/invalidUsersEMail.json'))
+ write(getDataPath('./invalidUsersEMail.json'), usersInvalidEmail.map((u) => {
+ return {
+ ...u.detail,
+ id: u._id
+ }
+ }))
+
+ logger.debug('invalid users email : ', usersInvalidEmail.length)
+ logger.debug('invalid users : ', usersInvalid.length)
+
+ if (opts.verb == 'index') {
+ await indexUsers(discourse, options, users)
+ }
+
+ if (opts.verb == 'import') {
+ await importUsers(discourse, options, users)
+ }
+
+ if (opts.verb == 'update') {
+ await updateUsers(discourse, options, users)
+ }
+ return
+ })
+}
diff --git a/packages/discourse/src/commands/info.ts b/packages/discourse/src/commands/info.ts
new file mode 100644
index 00000000..473c70e8
--- /dev/null
+++ b/packages/discourse/src/commands/info.ts
@@ -0,0 +1,24 @@
+import * as CLI from 'yargs'
+import { CONFIG_DEFAULT } from '@plastichub/osr-cli-commons'
+import { logger } from '../index'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs.option('debug', {
+ default: 'false',
+ describe: 'debug messages'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path'
+ })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs);
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('info', 'info', options, async (argv: CLI.Arguments) => {
+ if (argv.help) { return }
+ const args: any = argv
+ const src = CONFIG_DEFAULT(args.env_key)
+ logger.debug(`Reading OSR Config with key "${argv.env_key}"`, src)
+ })
+}
diff --git a/packages/discourse/src/commands/query.ts b/packages/discourse/src/commands/query.ts
new file mode 100644
index 00000000..5af23c01
--- /dev/null
+++ b/packages/discourse/src/commands/query.ts
@@ -0,0 +1,59 @@
+import * as CLI from 'yargs'
+
+import { defaults, sanitize } from '../_cli'
+import { parse } from '../options'
+import { IOptions } from '../types'
+import { logger } from '../index'
+
+import { Instance } from '../lib/discourse'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs.option('debug', {
+ default: false,
+ describe: 'debug messages',
+ type: 'boolean'
+ }).option('short', {
+ default: 'true',
+ describe: 'Emit short info only',
+ type: 'boolean'
+ }).option('disabled', {
+ default: 'false',
+ describe: 'Enumerate disabled products',
+ type: 'boolean'
+ }).option('dry', {
+ default: 'false',
+ describe: 'Process files for debug purposes only.'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path.'
+ })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs)
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('query ', 'Search namespace', options, async (argv: CLI.Arguments) => {
+ defaults();
+ if (argv.help) { return }
+ const args: any = argv
+
+ let options = sanitize(argv as any) as IOptions
+
+ if (!options) {
+ return
+ }
+ options.debug && logger.debug(`CLI Args In`, argv)
+ let opts = parse(options, args)
+
+ if (!opts.verb) {
+ logger.error('No verb specified')
+ return;
+ }
+ const discourse = Instance()
+ if (opts.verb == 'tags') {
+ const items = await discourse.search('Sheetpress - Cell','tags:sheetpress');
+ logger.info('items',items)
+ }
+ return
+ })
+}
diff --git a/packages/discourse/src/commands/sync-component.ts b/packages/discourse/src/commands/sync-component.ts
new file mode 100644
index 00000000..32a354a9
--- /dev/null
+++ b/packages/discourse/src/commands/sync-component.ts
@@ -0,0 +1,137 @@
+import * as path from 'path'
+import * as CLI from 'yargs'
+
+import { forward_slash, pathInfo } from "@plastichub/osr-cli-commons"
+import { resolve, isFile } from '@plastichub/osr-commons'
+
+import { sync as exists } from '@plastichub/fs/exists'
+
+import { CAT_TEST, DEFAULT_IMPORT_OWNER } from '../lib/discourse/constants'
+
+import { defaults } from '../_cli'
+import { IOptionsSyncComponent } from '../types'
+import { logger } from '../index'
+import { syncComponent } from '../lib/sync/component'
+import { PFilterValid } from '@plastichub/osr-fs-utils'
+const globBase = require('glob-base')
+
+export const parse = (argv: any): IOptionsSyncComponent | boolean => {
+
+ let ret: any = {
+ ...argv
+ }
+
+ let srcInfo
+ let variables = {}
+
+ ret.src = argv.src
+
+ ret.source = resolve(forward_slash(ret.source), ret.alt, variables)
+ ret.root = resolve(forward_slash(ret.root), ret.alt, variables)
+ ret.product_root = resolve(forward_slash(ret.product_root), ret.alt, variables)
+
+ if (ret.src) {
+
+ ret.src = resolve(ret.src, ret.alt, variables)
+ // in case a file with a glob pattern is provided, strip the glob
+ // this is a special case, enabling shared scripts in Alt-Tap Salamand
+ const glob_base = globBase(ret.src)
+ const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '')
+
+ // case : single file
+ if (exists(file) && isFile(file)) {
+ ret.src = file
+ }
+ const src = resolve(forward_slash(ret.src), ret.alt, variables)
+ srcInfo = pathInfo(src)
+
+ // case : glob pattern
+ if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
+ ret.srcInfo = srcInfo
+ for (const key in srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
+ variables['SRC_' + key] = srcInfo[key];
+ }
+ }
+ } else {
+ ret.src = resolve(ret.src, ret.alt, variables)
+ }
+ }
+
+ if (argv.cwd) {
+ ret.cwd = path.resolve(argv.cwd);
+ if (!exists((ret.cwd))) {
+ logger.error(`Invalid working directory ${argv.cwd}`)
+ }
+ } else {
+ ret.cwd = process.cwd()
+ }
+
+ ret = {
+ ...ret,
+ variables,
+ srcInfo
+ }
+
+ return ret
+}
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs
+
+ //standard options
+ .option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
+ //discourse
+ .option('yaml', { type: 'boolean', default: false, describe: 'Parse options from YAML header' })
+ .option('skip', { type: 'boolean', default: true, describe: 'Skip existing' })
+ .option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
+ .option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
+ .option('title', { type: 'string', default: 'Title of the Discourse post' })
+ .option('cat', { default: CAT_TEST, type: 'number' })
+ .option('timestamp', { type: 'number', default: Date.now() })
+ .option('owner', { type: 'number', default: DEFAULT_IMPORT_OWNER })
+ .option('config', { type: 'string', default: 'discourse_admin' })
+
+ //osrl
+ .option('src', {
+ default: '${OSR_ROOT}/osr-machines/injection/**/config.json',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('src2', {
+ default: '${OSR_ROOT}/osr-machines/sheetpress/cassandra-light/config.json',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('env', { type: 'string', default: 'forum' })
+ .option('profile', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/base.json" })
+ .option('format', { type: 'string', default: 'md' })
+ .option('source', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/root.html" })
+ .option('language', { type: 'string', default: 'osr' })
+ .option('plugins', { type: 'string', default: '${root}/osr/plugins' })
+ .option('root', { type: 'string', default: process.cwd() })
+ .option('product_root', { type: 'string', default: '${PRODUCT_ROOT}/products' })
+ .option('cwd', { type: 'string', default: process.cwd() })
+ .option('module', { type: 'string', default: 'osr-lib-components' })
+ .option('filter', { type: 'string', default: PFilterValid.library_component })
+ .option('cache', { type: 'boolean', default: true })
+ .option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs)
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('sync-component', 'Sync OSR Component', options, async (argv: CLI.Arguments) => {
+ defaults()
+ if (argv.help) { return }
+ let options = parse(argv as any) as IOptionsSyncComponent
+ if (!options) {
+ return
+ }
+ logger.setSettings({ minLevel: argv.logLevel as any })
+ // options.debug && logger.debug(`CLI Args In`, argv)
+ logger.debug('Options', options)
+ let ret = syncComponent(options)
+ return ret
+ })
+}
diff --git a/packages/discourse/src/commands/sync-directory.ts b/packages/discourse/src/commands/sync-directory.ts
new file mode 100644
index 00000000..d61a2bd4
--- /dev/null
+++ b/packages/discourse/src/commands/sync-directory.ts
@@ -0,0 +1,142 @@
+import * as path from 'path'
+import * as CLI from 'yargs'
+
+import { forward_slash, pathInfo } from "@plastichub/osr-cli-commons"
+import { resolve, isFile } from '@plastichub/osr-commons'
+
+import { sync as exists } from '@plastichub/fs/exists'
+
+import { CAT_TEST, DEFAULT_IMPORT_OWNER } from '../lib/discourse/constants'
+
+import { defaults } from '../_cli'
+import { IOptions, IOptionsSyncComponent } from '../types'
+import { logger } from '../index'
+import { syncComponent } from '../lib/sync/component'
+
+import { isValidLibraryComponent, PFilterValid } from '@plastichub/osr-fs-utils'
+
+import { first } from 'ramda'
+
+const globBase = require('glob-base')
+
+export const parse = (argv: any): IOptionsSyncComponent | boolean => {
+
+ let ret: any = {
+ ...argv
+ }
+
+ ret.src = argv.src
+ let srcInfo
+ let variables = {}
+
+ ret.source = resolve(forward_slash(ret.source), ret.alt, variables)
+ ret.root = resolve(forward_slash(ret.root), ret.alt, variables)
+
+ if (ret.src) {
+
+ ret.src = resolve(ret.src, ret.alt, variables)
+ // in case a file with a glob pattern is provided, strip the glob
+ // this is a special case, enabling shared scripts in Alt-Tap Salamand
+ const glob_base = globBase(ret.src)
+ const file = ret.src.replace(glob_base.glob, '').replace(/\/$/, '')
+
+ // case : single file
+ if (exists(file) && isFile(file)) {
+ ret.src = file
+ }
+ const src = resolve(forward_slash(ret.src), ret.alt, variables)
+ srcInfo = pathInfo(src)
+
+ // case : glob pattern
+ if (srcInfo && srcInfo.FILES && srcInfo.FILES.length) {
+ ret.srcInfo = srcInfo
+ for (const key in srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(srcInfo, key)) {
+ variables['SRC_' + key] = srcInfo[key];
+ }
+ }
+ } else {
+ ret.src = resolve(ret.src, ret.alt, variables)
+ }
+ }
+
+ if (argv.cwd) {
+ ret.cwd = path.resolve(argv.cwd);
+ if (!exists((ret.cwd))) {
+ logger.error(`Invalid working directory ${argv.cwd}`)
+ }
+ } else {
+ ret.cwd = process.cwd()
+ }
+
+ ret = {
+ ...ret,
+ variables,
+ srcInfo
+ }
+
+ return ret
+}
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs
+
+ //standard options
+ .option('debug', { type: 'boolean', default: true, describe: 'debug messages' })
+ .option('verbose', { type: 'boolean', default: true, describe: 'even more debug messages' })
+ .option('alt', { type: 'boolean', default: false, describe: 'alt token (%)' })
+
+ //discourse
+ .option('yaml', { type: 'boolean', default: false, describe: 'Parse options from YAML header' })
+ .option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse' })
+ .option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse' })
+
+ .option('title', { type: 'string', default: 'Title of the Discourse post' })
+
+ .option('cat', { default: CAT_TEST, type: 'number' })
+ .option('timestamp', { type: 'number', default: Date.now() })
+ .option('owner', { type: 'number', default: DEFAULT_IMPORT_OWNER })
+ .option('config', { type: 'string', default: 'discourse_admin' })
+
+ //osrl
+ .option('src2', {
+ default: '${OSR_ROOT}/osr-machines/injection/**/config.json',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('src', {
+ default: '${OSR_ROOT}/osr-machines/sheetpress/cassandra-light/config.json',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('env', { type: 'string', default: 'forum' })
+ .option('profile', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/base.json" })
+ .option('format', { type: 'string', default: 'md' })
+ .option('source', { type: 'string', default: "${OSR_ROOT}/osr-templates/discourse/root.html" })
+ .option('language', { type: 'string', default: 'osr' })
+ .option('plugins', { type: 'string', default: '${root}/osr/plugins' })
+ .option('root', { type: 'string', default: process.cwd() })
+ .option('product_root', { type: 'string', default: '${PRODUCT_ROOT}/products' })
+ .option('cwd', { type: 'string', default: process.cwd() })
+ .option('module', { type: 'string', default: 'osr-lib-components' })
+ .option('filter', { type: 'string', default: PFilterValid.library_component })
+ .option('cache', { type: 'boolean', default: true })
+ .option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs)
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('sync-component', 'Sync OSR Component', options, async (argv: CLI.Arguments) => {
+ defaults()
+ if (argv.help) { return }
+ let options = parse(argv as any) as IOptionsSyncComponent
+ if (!options) {
+ return
+ }
+ // options.debug && logger.debug(`CLI Args In`, argv)
+ // logger.debug('Options', options)
+ let ret = syncComponent(options)
+ return ret
+ })
+}
diff --git a/packages/discourse/src/commands/sync-file.ts b/packages/discourse/src/commands/sync-file.ts
new file mode 100644
index 00000000..68c1fff6
--- /dev/null
+++ b/packages/discourse/src/commands/sync-file.ts
@@ -0,0 +1,64 @@
+import * as CLI from 'yargs'
+
+import { defaults, sanitize } from '../_cli'
+import { IOptions, IOptionsSync } from '../types'
+import { logger } from '../index'
+
+import { Instance } from '../lib/discourse'
+
+import { sync as write } from '@plastichub/fs/write'
+
+import * as path from 'path'
+import { resolve } from '@plastichub/osr-commons'
+
+import { syncYAML } from '../lib/sync/file'
+import { CAT_TEST, DEFAULT_IMPORT_OWNER } from '../lib/discourse/constants'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs
+ .option('debug', { type: 'boolean', default: true, describe: 'debug messages' })
+ .option('verbose', { type: 'boolean', default: true, describe: 'even more debug messages' })
+ .option('yaml', { type: 'boolean', default: true, describe: 'Parse options from YAML header'})
+ .option('alt', {type: 'boolean', default: false, describe: 'alt token (%)'})
+ .option('uploadLocal', { type: 'boolean', default: true, describe: 'Upload local images to Discourse'})
+ .option('uploadRemote', { type: 'boolean', default: true, describe: 'Upload remote images to Discourse'})
+ .option('src', {
+ default: './tests/**/*.md',
+ type: 'string',
+ describe: 'Source : Path|Glob. Supported: HTML|MD|OSR(Options via YAML header)'
+ })
+ .option('title', { type: 'string', default: 'Title of the Discourse post' })
+ .option('config', { type: 'string', default: 'osr_admin' })
+ .option('cat', { default: CAT_TEST, type: 'number' })
+ .option('timestamp', { type: 'number', default: Date.now() })
+ .option('owner', { type: 'number', default: DEFAULT_IMPORT_OWNER })
+ .option('config', { type: 'string', default: 'discourse_admin' })
+ .option('env', { type: 'string', default: 'test-import' })
+ .option('profile', { type: 'string', default: "${OSR_ROOT}/osr-profiles/osr/base.json" })
+ .option('format', { type: 'string', default: 'html' })
+ .option('root', { type: 'string', default: process.cwd() })
+ .option('cwd', { type: 'string', default: process.cwd() })
+ .option('cache', { type: 'boolean', default: true })
+ .option('env_key', { type: 'string', default: 'OSR-CONFIG', describe: 'Environment key to the config path.' })
+}
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs)
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('sync ', 'Sync file', options, async (argv: CLI.Arguments) => {
+ defaults()
+ if (argv.help) { return }
+ let options = sanitize(argv as any) as IOptionsSync
+
+ if (!options) {
+ return
+ }
+ options.debug && logger.debug(`CLI Args In`, argv)
+
+ if (!options.verb) {
+ logger.error('No verb specified')
+ return;
+ }
+ return syncYAML(options)
+ })
+}
diff --git a/packages/discourse/src/constants.ts b/packages/discourse/src/constants.ts
new file mode 100644
index 00000000..2f24aa3a
--- /dev/null
+++ b/packages/discourse/src/constants.ts
@@ -0,0 +1 @@
+export const MODULE_NAME = `OSR-DISCOURSE`
diff --git a/packages/discourse/src/index.ts b/packages/discourse/src/index.ts
new file mode 100644
index 00000000..7054c193
--- /dev/null
+++ b/packages/discourse/src/index.ts
@@ -0,0 +1,82 @@
+export * from './constants'
+export * from './types'
+export * from './lib'
+export * from './lib/oa/types'
+
+import { logger as _logger } from '@plastichub/core/debug'
+
+import { MODULE_NAME } from './constants'
+import { ISettingsParam, Logger, ILogObject } from "tslog"
+export { Logger } from 'tslog'
+
+let loggers = {};
+
+/*
+const _logger = new Logger({
+ prettyLogTemplate: "{{yyyy}}.{{mm}}.{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}\t{{logLevelName}}\t[{{filePathWithLine}}{{name}}]\t",
+ prettyErrorTemplate: "\n{{errorName}} {{errorMessage}}\nerror stack:\n{{errorStack}}",
+ prettyErrorStackTemplate: " • {{fileName}}\t{{method}}\n\t{{filePathWithLine}}",
+ prettyErrorParentNamesSeparator: ":",
+ prettyErrorLoggerNameDelimiter: "\t",
+ stylePrettyLogs: true,
+ prettyLogTimeZone: "UTC",
+ prettyLogStyles: {
+ logLevelName: {
+ "*": ["bold", "black", "bgWhiteBright", "dim"],
+ SILLY: ["bold", "white"],
+ TRACE: ["bold", "whiteBright"],
+ DEBUG: ["bold", "green"],
+ INFO: ["bold", "blue"],
+ WARN: ["bold", "yellow"],
+ ERROR: ["bold", "red"],
+ FATAL: ["bold", "redBright"],
+ },
+ dateIsoStr: "white",
+ filePathWithLine: "white",
+ name: ["white", "bold"],
+ nameWithDelimiterPrefix: ["white", "bold"],
+ nameWithDelimiterSuffix: ["white", "bold"],
+ errorName: ["bold", "bgRedBright", "whiteBright"],
+ fileName: ["yellow"],
+ fileNameWithLine: "white",
+ },
+ });
+ */
+/*
+export const __logger = (name: string = MODULE_NAME, options: ISettingsParam = {}): Logger => {
+ if (!loggers[name]) {
+ const logger: Logger = new Logger({
+ name: name,
+ type: 'pretty',
+ ...options
+ });
+ // const trans = (transportLogger: LogObj & ILogObjMet)
+ (logger as any).attachTransport((logObj) => {
+ debugger
+ //transports.push(logObj);
+ });
+
+ logger.debug('test')
+
+ loggers[name] = logger;
+ }
+ return loggers[name]
+}*/
+
+
+export const logger = _logger(MODULE_NAME)
+
+/*
+export const log = (msg: string, ...args: any) => logger().info(msg, ...args);
+export const info = (msg: string, ...args: any) => logger().info(msg, ...args);
+export const error = (msg: string, ...args: any) => logger().error(msg, ...args);
+export const warn = (msg: string, ...args: any) => logger().warn(msg, ...args);
+export const debug = (msg: string, ...args: any) => logger().debug(msg, ...args);
+*/
+
+
+import { substitute as _substitute, substituteAlt as _substituteAlt } from "@plastichub/core/strings"
+
+import { IObjectLiteral } from "@plastichub/core"
+
+export const substitute = (alt: boolean, template: string, vars: IObjectLiteral = {}) => alt ? _substituteAlt(template, vars) : _substitute(template, vars)
diff --git a/packages/discourse/src/lib/discourse/cache.ts b/packages/discourse/src/lib/discourse/cache.ts
new file mode 100644
index 00000000..abcb4542
--- /dev/null
+++ b/packages/discourse/src/lib/discourse/cache.ts
@@ -0,0 +1,192 @@
+
+import { Promise as BPromise } from 'bluebird'
+import { sync as read } from '@plastichub/fs/read'
+import { sync as exists } from '@plastichub/fs/exists'
+import { sync as write } from '@plastichub/fs/write'
+import { resolve } from '@plastichub/osr-commons'
+import { sync as mkdir } from '@plastichub/fs/dir'
+import { files } from '@plastichub/osr-cli-commons'
+
+import { IUploadedFileMeta } from '@plastichub/osr-commons'
+import { forward_slash } from '@plastichub/osr-cli-commons'
+
+import {
+ IOptions,
+ IImportUser,
+ IOAHowto,
+ IOACategory,
+ IOATags,
+ IOAHowtoImport,
+ IDiscourseUser
+} from '../../'
+
+import {
+ logger
+} from '../../index'
+
+import {
+ HT_CATS,
+ DISCOURSE_CATEGORY_CACHE,
+ DISCOURSE_TAGS_CACHE,
+ DISCOURSE_TOPICS_CACHE,
+ DISCOURSE_USER_CACHE,
+ OSR_CACHE_ROOT,
+ OSR_DISCOURSE_CACHE,
+} from '../discourse/constants'
+
+
+import { Discourser } from '../index'
+
+import * as path from 'path'
+
+import * as cheerio from 'cheerio'
+
+import { html_beautify } from 'js-beautify'
+import { Converter } from 'showdown'
+
+const escapeHtml = require('escape-html')
+const pretty = require('pretty')
+
+export const fileAsBuffer = (path: string) => read(path, 'buffer') as Buffer || Buffer.from("-")
+
+import { get_cached, set_cached } from '@plastichub/osr-cache/lib'
+import { OSR_CACHE } from '@plastichub/osr-cli-commons'
+
+import * as md5 from 'md5'
+
+import {
+ MODULE_NAME
+} from '../../constants'
+
+
+export const cacheCategories = async (options: any, discourse: Discourser) => {
+
+ const osr_cache = OSR_CACHE()
+
+ const cPath = path.resolve(resolve(DISCOURSE_CATEGORY_CACHE))
+
+ const cached = exists(cPath) ? await get_cached(cPath, {}, MODULE_NAME) : null
+
+ if (osr_cache && cached && options.cache !== false) {
+ return JSON.parse(cached)
+ }
+
+ let cats = await discourse.getCategories({
+ include_subcategories: true
+ })
+
+ write(cPath, cats)
+
+ if (osr_cache && options.cache !== false) {
+ await set_cached(cPath, {}, MODULE_NAME, cats)
+ }
+
+ return cats
+}
+
+export const cacheTopics = async (options:any, discourse: Discourser) => {
+
+}
+
+let uPage = 1
+let usersAll = []
+
+export const _getForumUsers = async (d: Discourser, page, detail) => {
+
+ const uPath = path.resolve(resolve(DISCOURSE_USER_CACHE))
+
+ if (uPage == 1) {
+ usersAll = []
+ }
+ let users: any = await d.getUsers(page)
+ if (users.length) {
+ usersAll = usersAll.concat(users)
+ uPage++
+ return _getForumUsers(d, uPage, detail)
+ } else {
+ uPage = 1
+
+ write(uPath, usersAll)
+
+ let fUsers: IDiscourseUser[] = read(uPath, 'json') || [] as any
+
+ const add = async (u: IDiscourseUser) => {
+ return new Promise((resolve, reject) => {
+ let fUser = fUsers.find((fu) => u.id == fu.id)
+ if (!fUser) {
+ fUsers.push(u)
+ fUser = u
+ }
+
+ if (fUser.detail) {
+ console.log('Retrieve User Detail ' + u.name)
+ setTimeout(() => {
+ d.getUser(fUser.id).then((detail) => {
+ if (detail) {
+ fUser.detail = detail
+ }
+ write(uPath, fUsers)
+ resolve(fUser)
+ })
+ }, 200)
+ } else {
+ resolve(fUser)
+ }
+ })
+ }
+ return await BPromise.resolve(usersAll).map((u: IDiscourseUser) => {
+ return add(u)
+ }, { concurrency: 1 })
+
+ }
+}
+export const getForumUsers = async (d, detail): Promise => {
+ return _getForumUsers(d, uPage, detail)
+}
+
+export const cacheUsers = async (options, discourse: Discourser): Promise => {
+
+ const osr_cache = OSR_CACHE()
+ const uPath = path.resolve(resolve(DISCOURSE_USER_CACHE))
+
+ const cached = exists(uPath) ? await get_cached(uPath, {}, MODULE_NAME) : null
+
+ if (osr_cache && options.cache !== false && exists(uPath)) {
+ return read(uPath, 'json') as any
+ }
+
+ if (osr_cache && cached && options.cache !== false) {
+ return JSON.parse(cached)
+ }
+
+ let users = await getForumUsers(discourse, false)
+
+ write(uPath, users)
+
+ if (osr_cache && options.cache !== false) {
+ await set_cached(uPath, {}, MODULE_NAME, users)
+ }
+
+ return users
+
+}
+
+export const cacheTags = async (options, discourse: Discourser) => {
+ const osr_cache = OSR_CACHE()
+ const tPath = path.resolve(resolve(DISCOURSE_TAGS_CACHE))
+
+ const cached = exists(tPath) ? await get_cached(tPath, {}, MODULE_NAME) : null
+
+ if (osr_cache && cached && options.cache !== false) {
+ return JSON.parse(cached)
+ }
+
+ let tags = await discourse.getTags()
+ write(tPath, tags)
+
+ if (osr_cache && options.cache !== false) {
+ await set_cached(tPath, {}, MODULE_NAME, tags)
+ }
+
+ return tags
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/discourse/constants.ts b/packages/discourse/src/lib/discourse/constants.ts
new file mode 100644
index 00000000..2560a124
--- /dev/null
+++ b/packages/discourse/src/lib/discourse/constants.ts
@@ -0,0 +1,119 @@
+
+//////////////////////////////////////////////////////////////
+//
+// Keys
+//
+
+export type EDiscourseConfigKey = 'discourse' | 'discourse_admin'
+
+//////////////////////////////////////////////////////////////
+//
+// Paths
+//
+
+export const SYNC_TRACK_FILENAME = 'discourse-sync.json'
+
+export const OSR_CACHE_ROOT = '${OSR_CACHE}'
+export const OSR_DISCOURSE_CACHE = '${OSR_CACHE}/discourse'
+
+export const DISCOURSE_CATEGORY_CACHE = '${OSR_CACHE}/discourse/cats.json'
+export const DISCOURSE_TOPICS_CACHE = '${OSR_CACHE}/discourse/topics.json'
+export const DISCOURSE_TAGS_CACHE = '${OSR_CACHE}/discourse/tags.json'
+export const DISCOURSE_USER_CACHE = '${OSR_CACHE}/discourse/users.json'
+
+//////////////////////////////////////////////////////////////
+//
+// OA - User Import
+//
+
+export const OA_DIRECTORY_OVERVIEW_TOPIC = 28873
+export const OA_USER_IMPORT_GROUP = 43
+export const KB_USERS = '${KB_ROOT}/static/users'
+export const DATA_PATH = '${OSR_ROOT}/osr-directory/pp'
+
+export const LATEST_TRACK = '${OSR_ROOT}/osr-directory/pp/merged.json'
+export const LATEST_TEST = './latest_test.json'
+export const FETCH_DUSERS = false
+export const F_USERS_NOW = './fusers.json'
+export const F_USERS_ALL = './fusers-all.json'
+
+export const DEFAULT_PASSWORD = () => '4g0&KPN$e*Un'
+
+export const HOWTOS_ASSETS_URL = () => `https://kb.osr-plastic.org/howtos/`
+export const MACHINES_ASSETS_URL = () => `https://assets.osr-plastic.org/machines/`
+
+export const CAT_TEST = 65
+export const TAGS_TEST = 'plastic, meta'
+export const DEFAULT_IMPORT_OWNER = 1
+
+//////////////////////////////////////////////////////////////
+//
+// OA - Directory Import
+//
+export const D_ROOT_CAT = 97
+
+export const D_ROOT_AFRICA = 79
+export const D_ROOT_ASIA = 60
+export const D_ROOT_EUROPE = 59
+export const D_ROOT_AUSTRALIA = 76
+export const D_ROOT_NAMERICA = 101
+export const D_ROOT_SAMERICA = 102
+export const D_ROOT_OCEANIA = 103
+
+//////////////////////////////////////////////////////////////
+//
+// OA - Howto Import
+//
+export const HT_CAT_ROOT = 54
+export const HT_CAT_GUIDES = 86
+export const HT_CAT_MACHINES = 87
+export const HT_CAT_PRODUCTS = 88
+export const HT_CAT_MOULDS = 89
+
+export const HT_CAT_IDS = {
+ HT_CAT_ROOT,
+ HT_CAT_GUIDES,
+ HT_CAT_MACHINES,
+ HT_CAT_PRODUCTS,
+ HT_CAT_MOULDS
+}
+
+
+export const HT_CATS = {
+ 'Guides': HT_CAT_GUIDES,
+ 'Machines': HT_CAT_MACHINES,
+ 'Products': HT_CAT_PRODUCTS,
+ 'Moulds': HT_CAT_MOULDS
+}
+
+//////////////////////////////////////////////////////////////
+//
+// OA - Library Import
+//
+
+export const MACHINE_CAT_INJECTION = 50
+export const MACHINE_CAT_EXTRUSION = 51
+export const MACHINE_CAT_SHREDDER = 52
+export const MACHINE_CAT_SHEETPRESS = 63
+export const MACHINE_CAT_3DPRINT = 70
+export const MACHINE_CAT_MOULDS = 71
+
+export const MACHINE_CAT_IDS = {
+ MACHINE_CAT_INJECTION,
+ MACHINE_CAT_EXTRUSION,
+ MACHINE_CAT_SHREDDER,
+ MACHINE_CAT_SHEETPRESS,
+ MACHINE_CAT_3DPRINT,
+ MACHINE_CAT_MOULDS
+}
+
+export const MACHINE_CATS = {
+ 'Injection': MACHINE_CAT_INJECTION,
+ 'Extrusion': MACHINE_CAT_EXTRUSION,
+ 'Sheetpress': MACHINE_CAT_SHEETPRESS,
+ '3DPrint': MACHINE_CAT_3DPRINT,
+ 'Moulds': HT_CAT_MOULDS
+}
+
+
+
diff --git a/packages/discourse/src/lib/discourse/index.ts b/packages/discourse/src/lib/discourse/index.ts
new file mode 100644
index 00000000..10c0e01b
--- /dev/null
+++ b/packages/discourse/src/lib/discourse/index.ts
@@ -0,0 +1,1295 @@
+import { MODULE_NAME } from '../../constants'
+
+import { CONFIG_DEFAULT } from '@plastichub/osr-cli-commons'
+
+import { IOSRConfig, IDiscourseConfig } from '@plastichub/osr-cli-commons/types'
+
+import { logger as _logger } from '@plastichub/core/debug'
+
+export const logger: any = _logger(MODULE_NAME)
+
+import { sync as write } from '@plastichub/fs/write'
+import { sync as read } from '@plastichub/fs/write'
+import { sync as exists } from '@plastichub/fs/exists'
+
+import PromisePool from 'native-promise-pool'
+
+
+import { join } from 'path'
+import axios from 'axios'
+import * as fs from 'fs'
+import * as path from 'path'
+import * as FormData from 'form-data'
+
+const https = require('https')
+const request = require("request")
+const fetch = require('isomorphic-unfetch')
+
+export const escape = (path: string) =>
+ path.replace(/[^\w]/g, '-').replace(/-+/, '-')
+
+import { generate } from 'generate-password'
+
+import { TPostStatus, TPostStatusUpdate, UserPreferencesUpdate } from './types'
+
+// types
+import {
+ PostUpdateRequest,
+ Category,
+ CategoriesResponse,
+ PostsResponse,
+ PostResponse,
+ TopicResponse,
+ TopicItem,
+ CategoryResponse,
+ PostItem,
+ PostUpdateResponse,
+ PostUpdateItem,
+ TopicUpdateTimestampRequest,
+ TopicUpdateTimestampResponse,
+ IDiscourserConfig,
+ Thread,
+ PostModifier,
+ FetchConfig,
+ FetchOptions,
+ PostConfig,
+ ISearchResult,
+ ICreateUserResponse,
+ IUserDetail,
+ TagsResponse,
+ Tag,
+ TopicUpdateBasicTopic
+} from './types';
+import { IDiscourseUser } from '@plastichub/osr-commons'
+import { EDiscourseConfigKey } from './constants'
+import { IDImage } from '../oa/index'
+
+
+
+/**
+ * Discourser is an API Client for the [Discourse API](https://docs.discourse.org)
+ * It special features are:
+ * - TypeScript Types
+ * - Respecting Rate Limits
+ * - Optional Heavy Caching
+ * - Post Modifiers (can be used for global find and replace across all posts on the forum)
+ */
+export class Discourser {
+ readonly host: string
+ readonly key: string
+ readonly username: string
+ readonly cache?: string
+ readonly useCache?: boolean
+ readonly dry: boolean
+ readonly pool: PromisePool
+
+ /**
+ * Construct our Discourser instance
+ * See {@link IDiscourserConfig} for available configuration.
+ */
+ constructor(config: IDiscourserConfig) {
+ this.host = config.host
+ this.key = config.key
+ this.username = config.username
+ this.cache = config.cache
+ this.useCache = config.useCache
+ this.dry = config.dry || false
+ this.pool = new PromisePool(config.rateLimitConcurrency || 60)
+ }
+
+ /** Get the URL of a topic */
+ getTopicURL(topic: TopicItem | TopicResponse | number): string {
+ if (typeof topic === 'number') {
+ return `${this.host}/t/${topic}`
+ }
+ return `${this.host}/t/${topic.slug}/${topic.id}`
+ }
+
+ /** Fetch a discourse API URL, with rate limit concurrency and optional caching */
+ async fetch({ url, useCache, request }: FetchConfig): Promise {
+ // check if cache is enabled
+ useCache = false
+ const cache =
+ this.cache &&
+ (request?.method || 'get') === 'get' &&
+ join(this.cache, escape(url))
+ // check if we should and can read from cache
+ if (
+ cache &&
+ this.useCache !== false &&
+ useCache !== false &&
+ (exists(cache))
+ ) {
+ const result = read(cache, 'json')
+ return (result as unknown) as T
+ }
+ // fetch
+ const result = await this.pool.open(() => this._fetch({ url, request }))
+ // write to cache if cache is enabled
+ if (cache) {
+ write(cache, result as any)
+ }
+ // return the result
+ return result
+ }
+
+
+ /** Fetch a discourse API URL, with rate limit retries */
+ private async _post(url, data): Promise {
+ const opts: RequestInit = {
+ headers: {
+ 'Api-Key': this.key,
+ 'Api-Username': this.username,
+ },
+ }
+ let d = data;
+ const res = await axios.post(url, d, {
+ headers: opts.headers as any
+ });
+
+ // fetch text then parse as json, so that when errors occur we can output what it was
+ // rather than being stuck with errors like these:
+ // FetchError: invalid json response body at https://discuss.bevry.me/posts/507.json reason: Unexpected token < in JSON at position 0
+ const text = await res.data;
+ // check if there are errors
+ if (typeof (data as any).errors !== 'undefined') {
+ // check if the error is a rate limit
+ const wait: number = (data as any).extras?.wait_seconds
+ if (wait != null) {
+ // if it was, try later
+ // return await retry(wait + 1)
+ }
+
+ // otherwise fail
+ // logger.debug({ data, url, opts })
+ return Promise.reject(
+ new Error(
+ `fetch of [${url}] received failed response:\n${data}`
+ )
+ )
+ }
+ return text;
+ }
+
+
+
+ /** Fetch a discourse API URL, with rate limit retries */
+ private async _fetch({ url, request }: FetchConfig): Promise {
+
+ const httpsAgent = new https.Agent({
+ rejectUnauthorized: false,
+ });
+ const opts = {
+ ...request,
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username,
+ ...request?.headers
+ },
+ rejectUnauthorized: false,
+ agent: httpsAgent
+ }
+
+ const retry = (seconds: number) => {
+ return new Promise((resolve, reject) => {
+ setTimeout(
+ () =>
+ this._fetch({ url, request })
+ .then(resolve)
+ .catch(reject),
+ (seconds || 60) * 1000
+ )
+ })
+ }
+
+ try {
+ const res = await fetch(url, opts);
+ // fetch text then parse as json, so that when errors occur we can output what it was
+ // rather than being stuck with errors like these:
+ // FetchError: invalid json response body at https://discuss.bevry.me/posts/507.json reason: Unexpected token < in JSON at position 0
+ const text = await res.text()
+ let data: T
+
+ try {
+ data = JSON.parse(text) as T
+ } catch (err) {
+ // check if it was cloudflare reporting that the server has been hit too hard
+ if (text.includes('Please try again in a few minutes')) {
+ logger.debug('server has stalled, trying again in a minute')
+ return await retry(60)
+ }
+ // otherwise log the error page and die
+ // logger.debug({ text, url , opts })
+ return Promise.reject(
+ logger.error(text, url, opts, err) &&
+ new Error(`fetch of [${url}] received invalid response:\n${text}`)
+ )
+ }
+
+ // check if there are errors
+ if (typeof (data as any).errors !== 'undefined') {
+ // check if the error is a rate limit
+ const wait: number = (data as any).extras?.wait_seconds
+ if (wait != null) {
+ // if it was, try later
+ return await retry(wait + 1)
+ }
+
+ // otherwise fail
+ // logger.debug({ data, url, opts })
+ return Promise.reject(
+ new Error(
+ `fetch of [${url}] received failed response:\n${data}`
+ )
+ )
+ }
+ return data
+ } catch (err) {
+ // logger.debug({ err, url, opts })
+ return Promise.reject(
+ logger.error(`fetch of [${url}] failed with error`, err)
+ )
+ }
+ }
+
+ // =================================
+ // Search
+
+ /**
+ * API Helper for {@link .search}
+ * https://docs.discourse.org/#tag/Search/operation/search
+ */
+ public async search(
+ query: string,
+ params: string = '',
+ opts: FetchOptions = {}
+ ): Promise {
+ let url = `${this.host}/search.json?q=${encodeURIComponent(query)} ${encodeURIComponent(params)}`;
+ return await this.fetch({ url, ...opts })
+ }
+ // =================================
+ // Tags
+
+ /**
+ * API Helper for {@link .getTags}
+ */
+ protected async getTagsResponse(
+ opts: FetchOptions = {}
+ ): Promise {
+ const url = `${this.host}/tags.json`
+ return await this.fetch({ url, ...opts })
+ }
+
+ /**
+ * Fetch the whole information, for all categories of the forum
+ */
+ async getTags(opts: FetchOptions = {}): Promise {
+ const response = await this.getTagsResponse(opts)
+ const tags = response.tags
+ return tags
+ }
+
+ async createTag(name): Promise {
+ const url = `${this.host}/tag_groups.json`
+ try {
+ return await this._post(url, {
+ name
+ });
+ } catch (error) {
+ debugger
+ }
+
+ }
+
+ // =================================
+ // CATEGORIES
+
+ /**
+ * API Helper for {@link .getCategories}
+ */
+ protected async getCategoriesResponse(
+ opts: FetchOptions = {}
+ ): Promise {
+ const url = `${this.host}/categories.json` +
+ (opts.include_subcategories ? '?include_subcategories=true' : '')
+ return await this.fetch({ url, ...opts })
+ }
+
+ /**
+ * Fetch the whole information, for all categories of the forum
+ */
+ async getCategories(opts: FetchOptions = {}): Promise {
+ const response = await this.getCategoriesResponse(opts)
+ const categories = response.category_list.categories
+ return categories
+ }
+
+ /**
+ * API Helper for {@link .getTopicItemsOfCategory}
+ * Discourse does not provide an API for fetching category information for a specific category.
+ * Instead, all that it provides is a way of getting the topics for a specific category.
+ */
+ protected async getCategoryResponse(
+ categoryID: number,
+ opts: FetchOptions = {}
+ ): Promise {
+ const url =
+ `${this.host}/c/${categoryID}.json` +
+ (opts.page !== 0 ? `?page=${opts.page}` : '')
+ return await this.fetch({ url, ...opts })
+ }
+
+ // =================================
+ // TOPICS
+
+ /**
+ * Fetch the partial information, for all topics of a specific category
+ */
+ async getTopicItemsOfCategory(
+ categoryID: number,
+ opts: FetchOptions = {}
+ ): Promise {
+ // prepare and fetch
+ let page = opts.page || 0
+ const response = await this.getCategoryResponse(categoryID, {
+ ...opts,
+ page,
+ })
+
+ let topics: TopicItem[] = response.topic_list.topics
+
+ // fetch the next page
+ if (topics.length === response.topic_list.per_page) {
+ page += 1
+ const more = await this.getTopicItemsOfCategory(categoryID, {
+ ...opts,
+ page,
+ })
+ topics.push(...more)
+ }
+
+ // if we are the first page, then output count as we now have all of them
+ if (page === 0) {
+ const ids = topics.map((i: TopicItem) => i.id)
+ }
+
+ topics = topics.filter((t) => t.visible === true);
+
+ return topics
+ }
+
+ /**
+ * Fetch the partial information, for all topics of specific categoires
+ */
+ async getTopicItemsOfCategories(
+ categoryIDs: number[],
+ opts: FetchOptions = {}
+ ): Promise {
+ // fetch topic items for specific categories
+ try {
+ const topicsOfCategories = await Promise.all(
+ categoryIDs.map((id) => this.getTopicItemsOfCategory(id, opts))
+ )
+ // @ts-ignore
+ return topicsOfCategories.flat()
+ } catch (error) {
+ logger.error(error);
+ }
+ }
+
+ /**
+ * Fetch the partial information, for all topics of the forum
+ */
+ async getTopicItems(opts: FetchOptions = {}) {
+ const categories = await this.getCategories()
+ const categoryIDs = categories.map((i) => i.id)
+ return this.getTopicItemsOfCategories(categoryIDs, opts)
+ }
+
+ /**
+ * Fetch the whole information, for a specific topic of the forum
+ */
+ getTopic(id: number, opts: FetchOptions = {}): Promise {
+ const url = `${this.host}/t/${id}.json`
+ return this.fetch({ url, ...opts })
+ }
+
+ /**
+ * Fetch the whole information, for all topics, or specific topics, of the forum
+ */
+ async getTopics(
+ topicIDs?: number[] | null,
+ opts: FetchOptions = {}
+ ): Promise {
+ // if no topics, use all topics
+ if (!topicIDs) {
+ const topics = await this.getTopicItems(opts)
+ topicIDs = topics.map((i) => i.id)
+ }
+
+ // fetch whole topics
+ return Promise.all(topicIDs.map((id) => this.getTopic(id, opts)))
+ }
+
+ async updateTopicVisibility(
+ topicID: number,
+ listed: boolean = true,
+ visible: TPostStatus = 'visible'
+ ): Promise {
+ const url = `${this.host}/t/${topicID}/status`
+ let ret = await fetch(url, {
+ "headers": {
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ "body": `status=${visible}&enabled=${listed}`,
+ "method": "PUT"
+ });
+
+ return ret
+ }
+
+ async updateTopicTimestamp(
+ topicID: number,
+ timestamp: Date | string | number,
+ token: string
+ ): Promise {
+ let time: number
+ if (typeof timestamp === 'number') {
+ time = timestamp
+ } else if (typeof timestamp === 'number') {
+ time = Number(timestamp)
+ } else if (timestamp instanceof Date) {
+ // ms to seconds
+ time = timestamp.getTime() / 1000
+ } else {
+ return Promise.reject(new Error('invalid timestamp format'))
+ }
+
+ const url = `${this.host}/t/${topicID}/change-timestamp`
+
+ let ret = await fetch(url, {
+ "headers": {
+
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8,de;q=0.7,es;q=0.6,fr;q=0.5",
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ "x-csrf-token": token,
+ "x-requested-with": "XMLHttpRequest",
+ "cookie": "_bypass_cache=true; _ga_MBZGKNMDWC=GS1.1.1685892974.20.1.1685893082.0.0.0; _ga_P4SR15V1XR=GS1.1.1687459978.51.1.1687460537.0.0.0; _ga_H8W78Y3P2B=GS1.1.1687604701.23.0.1687604701.0.0.0; _ga=GA1.1.401826746.1678337758; _t=xQ05qW5JFxLM9Pq0lIwG6ez74Z1q2OLpak0DzRx8VdFYE5eI3oJXhLURPrdm2zIcHmYcBj9q%2BKdHhGz5N6j9mXitYzcMwkXHL3K9GYKdO4gJ8tBQimpmd1HFaRhB9Ml9aJ8WviqQWDZDOYwEUKFcWw3wbAalfQtbdIbUSX8gH9sG6DLFU3HiEg7tWModRy%2BoFrTm6QOalDuajRW3nBazau%2FiY8ZCVm2g30Y10CBDfqJHL1ztV8XM4kEIeulLNTzGVtSb7uuO1OcjZRSb--aDgCPEalq7SIpnH5--HWCNf5readaeij3oDl9b9w%3D%3D; __profilin=p%3Dt%2Ca%3Deef38e031f99cc8240f3518e1b8811cf; _forum_session=RkEWuzKI1QXBYCnP6KRamD8mweZ3h9%2B6G%2Fi23gAWUgy8gp8FuiyQD5lKU0Fbx3FzzaM4SiQcvnIiEAnb5P4OYjlvstqwWlfRp%2B9is7iX8StwYGiYsncHQ5LrzSbV3y9mR7sj%2F8JZ8evQOe2ZZjZB3iEkppsGrmyFrw5PsUgSphRTZm70SKIw96JrW17yK4hhLqtk%2BaQPgNu4oJl42YfXAr%2FCBldcBUKXFeHppYmv61WECV0531hCo7GcA4t06B9QpSr%2BeoiM1Ok9tpQrAlZf36Ka4lVCTyXXu3SNvbtvfd9tZMJCWDYv69jdMsezuOaEP870pk9qYPaL4x6nAY5EXO3u9usCggqQ1B1EydCK9uMy7ZUCIo9wONw7QOIgEQ%3D%3D--GMqYSb2H7xXVDky6--R9gVciBqwC0IL9LefywrFw%3D%3D; _ga_GVR8PEPG6C=GS1.1.1687710574.106.1.1687710599.0.0.0",
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ "body": `timestamp=${time}`,
+ "method": "PUT"
+ });
+
+ if (ret && ret.status === 200) {
+ return true
+ }
+ return
+
+ /*
+ let data = new FormData();
+ data.append('timestamp', time);
+
+ try {
+ let ret = await axios.put(url, data, {
+ headers: {
+ //'Accept-Language': 'en-US,en;q=0.8',
+ //'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ //'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ debugger
+ } catch (error) {
+ debugger
+ }
+
+
+ return
+ */
+
+ /*
+ var options = {
+ method: 'PUT',
+ url: url,
+ headers:
+ {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ body: `timestamp=${time}`
+ };
+
+ new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
+ */
+
+ /*
+ var options = {
+ method: 'POST',
+ url: url,
+ headers:
+ {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ body
+ }
+
+
+ return new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
+*/
+
+
+ // prepare the request
+ const request: TopicUpdateTimestampRequest = {
+ timestamp: time,
+ }
+
+ // send the update
+ logger.debug('updating', topicID, 'topic timestamp with', request)
+ //const url = `${this.host}/t/${topicID}/change-timestamp`
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put',
+ body: `timestamp=${time}`,
+ headers: {
+ 'Api-Key': this.key,
+ 'Api-Username': this.username,
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8"
+
+ }
+ }
+ })
+
+ // check it
+ if (response.success !== 'OK') {
+ return Promise.reject(
+ new Error(
+ `timestamp update of topic ${topicID} failed:\n${{
+ url,
+ request,
+ response,
+ }}`
+ )
+ )
+ }
+
+ return response
+ }
+
+ // =================================
+ // POSTS
+
+ /**
+ * API Helper for {@link .getPostItemsOfTopic}
+ */
+ protected async getPostItemsOfTopicResponse(
+ topicID: number,
+ opts: FetchOptions = {}
+ ): Promise {
+ const url = `${this.host}/t/${topicID}/posts.json`
+ const response = await this.fetch({ url, ...opts })
+ return response
+ }
+
+ async _createUser(name, email, pUserGroup): Promise {
+
+ const pwd = generate({
+ length: 10,
+ numbers: true
+ })
+
+ let user = await this.createUser({
+ "name": name,
+ "email": email,
+ "password": pwd,
+ "username": name,
+ "active": true,
+ "approved": true,
+ "user_fields[1]": true
+ }) satisfies ICreateUserResponse;
+
+ if (user && user.user_id) {
+ await this.updateGroup(name, pUserGroup);
+ return { ...user, password: pwd };
+ } else {
+ if (user && user.message && user.message == 'Username must be unique\nPrimary email has already been taken') {
+ return null;
+ } else if (user && user.message && user.message == 'Your account is activated and ready to use.') {
+ if (user.user_id) {
+ return { ...user, password: pwd };
+ }
+ return null;
+ } else {
+ console.log('cant create user ' + name, user);
+ }
+ return null;
+ }
+ }
+
+ async getUsers(page): Promise {
+ const url = `${this.host}/admin/users/list/active.json?page=` + page
+ const response = await this.fetch({ url })
+ return response
+ }
+
+ async getUser(id): Promise {
+ const url = `${this.host}/admin/users/${id}.json`
+ const response = await this.fetch({ url })
+ return response;
+ }
+
+ /**
+ * Fetch the partial information, for all posts of a specific topic
+ */
+ async getPostItemsOfTopic(
+ topicID: number,
+ opts: FetchOptions = {}
+ ): Promise {
+ const response = await this.getPostItemsOfTopicResponse(topicID, opts)
+ const posts: PostItem[] = response.post_stream.posts
+ const ids = posts.map((i) => i.id)
+ return posts
+ }
+
+ /**
+ * Fetch the partial information, for all posts of specific topics
+ */
+ async getPostItemsOfTopics(
+ topicIDs: number[],
+ opts: FetchOptions = {}
+ ): Promise {
+ // fetch post items for specific topics
+ const postItemsOfTopics = await Promise.all(
+ topicIDs.map((id) => this.getPostItemsOfTopic(id, opts))
+ )
+
+ // @ts-ignore
+ return postItemsOfTopics.flat()
+ }
+
+ /**
+ * Fetch the partial information, for all posts of a specific category
+ */
+ async getPostItemsOfCategory(
+ categoryID: number,
+ opts: FetchOptions = {}
+ ): Promise {
+ // fetch topics for the category
+ const topics = await this.getTopicItemsOfCategory(categoryID, opts)
+ const topicIDs = topics.map((i) => i.id)
+
+ // fetch
+ const posts = await this.getPostItemsOfTopics(topicIDs)
+ const ids = posts.map((i) => i.id)
+ return posts
+ }
+
+ /**
+ * Fetch the partial information, for all posts of specific categories
+ */
+ async getPostItemsOfCategories(
+ categoryIDs: number[],
+ opts: FetchOptions = {}
+ ): Promise {
+ // fetch post items for specific categories
+ const postItemsOfCategories = await Promise.all(
+ categoryIDs.map((id) => this.getPostItemsOfCategory(id, opts))
+ )
+
+ // @ts-ignore
+ return postItemsOfCategories.flat()
+ }
+
+ /**
+ * Fetch the partial information, for all posts of the forum
+ */
+ async getPostItems(opts: FetchOptions = {}): Promise {
+ const categories = await this.getCategories()
+ const categoryIDs = categories.map((i) => i.id)
+ return this.getPostItemsOfCategories(categoryIDs, opts)
+ }
+
+ /**
+ * Fetch the whole information, for a specific post of the forum
+ */
+ getPost(id: number, opts: FetchOptions = {}): Promise {
+ const url = `${this.host}/posts/${id}.json`
+ return this.fetch({ url, ...opts })
+ }
+
+ async createReply(postId, raw, category) {
+
+ const url = `${this.host}/posts.json`;
+
+ let data: any = new FormData();
+ data.append('topic_id', '' + postId);
+ data.append('raw', raw);
+ data.append('nested_post', 'true');
+ data.append('category', category);
+ var options = {
+ method: 'POST',
+ url: url,
+ headers:
+ {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ "body": `raw=${raw}&unlist_topic=false&category=${category}&topic_id=${postId}&is_warning=false&archetype=regular&featured_link=&shared_draft=false&nested_post=true`,
+ };
+
+ return new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
+
+ }
+
+ async changeOwner(postId: string | number, topicId: string | number, owner: string
+ ) {
+ const url = `${this.host}/t/${topicId}/change-owner.json`;
+ var options = {
+ method: 'POST',
+ url: url,
+ headers:
+ {
+ 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ },
+ body: `post_ids%5B%5D=${postId}&username=${owner}`
+ };
+
+
+ return new Promise((resolve, reject) => {
+ request(options, function (error, response, body) {
+ if (error) {
+ throw new Error(error);
+ } else {
+ resolve(body);
+ }
+ });
+ });
+ }
+
+ async createUser(data): Promise {
+ const url = `${this.host}/users`
+ return await this._post(url, data);
+ }
+
+ async getUserByUsername(username): Promise {
+ const url = `${this.host}/u/${username}.json`
+ const response = await this.fetch({ url })
+ return (response as any).user
+ }
+
+ async setUserAvatar(user_name, upload_id): Promise {
+ // fetch whole posts
+ const url = `${this.host}/u/${user_name}/preferences/avatar/pick.json`;
+ return await axios.put(url, {
+ upload_id,
+ username: user_name,
+ type: 'uploaded'
+ }, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+
+ async updateUser(user_name, args): Promise {
+
+ const url = `${this.host}/u/${user_name}.json`;
+ return await axios.put(url, {
+ ...args
+ }, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+
+ async updateGroup(user_name, group) {
+ // fetch whole posts
+ const url = `${this.host}/groups/${group}/members.json`;
+ const t = axios.put(url, {
+ usernames: user_name,
+ notify_users: false
+ }, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ t.then((d) => {
+
+ }).catch((e) => {
+ //debugger;
+ })
+ return t;
+ }
+
+
+
+ async upload(userId, file): Promise {
+ // fetch whole posts
+ const url = `${this.host}/uploads.json`;
+
+ let data: any = new FormData();
+ const fsData = path.parse(file);
+ data.append('file', file, fsData.base);
+ data.append('user_id', userId);
+ data.append('upload_type', 'avatar');
+ data.append('file', fs.createReadStream(file));
+
+ return await axios.post(url, data, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+
+ async uploadFile(userId, file): Promise {
+ // fetch whole posts
+ const url = `${this.host}/uploads.json`;
+ let data: any = new FormData();
+ const fsData = path.parse(file);
+ data.append('file', file, fsData.base);
+ data.append('user_id', userId);
+ data.append('upload_type', 'composer');
+ data.append('file', fs.createReadStream(file));
+
+ return await axios.post(url, data, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ 'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ });
+ }
+
+ // =================================
+ // POSTS: UPDATING
+
+ /**
+ * Fetch the whole information, for all posts, or specific posts, of the forum
+ */
+ async getPosts(
+ postIDs?: number[] | null,
+ opts: FetchOptions = {}
+ ): Promise {
+ // if no posts, use all
+ if (!postIDs) {
+ const posts = await this.getPostItems(opts)
+ postIDs = posts.map((i) => i.id)
+ }
+
+ // fetch whole posts
+ return await Promise.all(postIDs.map((id) => this.getPost(id, opts)))
+ }
+
+ async createPost(
+ title: string,
+ raw: string,
+ category: number
+ ) {
+ // fetch whole posts
+ const url = `${this.host}/posts`
+ return new Promise((resolve) => {
+ return this._post(url, { raw, title, category }).then((d) => {
+ resolve(d);
+ }).catch((e) => {
+ resolve(e.response.data);
+ })
+ });
+ }
+
+ /**
+ * Update a post with the content
+ * @param postID the identifier of the post to update
+ * @param content the new raw content for the post
+ * @param reason the reason, if provided, for modifying the post
+ * @param old if the old raw content is provided, then the update verified that you are working with the latest post content before applying the update
+ */
+ async updatePost(
+ postID: number,
+ content: string,
+ reason: string = 'api update',
+ old?: string
+ ): Promise {
+ // prepare the request
+ const data: PostUpdateRequest = {
+ post: {
+ raw: content,
+ edit_reason: reason,
+ },
+ }
+ if (old) {
+ data.post.raw_old = old
+ }
+
+ // send the update
+ const url = `${this.host}/posts/${postID}.json`
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put',
+ body: JSON.stringify(data),
+ },
+ })
+
+ // return the response
+ return response.post
+ }
+
+ /**
+ * Update post meta
+ */
+ async updateTopic(
+ postId: number,
+ category_id: number,
+ title: string,
+ tags?: string[]
+ ): Promise {
+ const data =
+ {
+ title,
+ tags: tags || [],
+ featuredLink: null,
+ category_id
+ }
+
+ const url = `${this.host}/t/${postId}.json`
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put',
+ body: JSON.stringify(data),
+ },
+ })
+ return response.basic_topic
+ }
+
+
+
+ async rebakePost(postID: number): Promise {
+
+ const url = `${this.host}/posts/${postID}/rebake`
+ logger.debug('rebaking', postID)
+
+ const response = await this.fetch({
+ url,
+ request: {
+ method: 'put'
+ }
+ })
+ logger.debug('rebaked', postID)
+ return response
+ }
+
+
+
+ /**
+ * Modify a post using a modifier
+ */
+ async modifyPost(
+ post: PostResponse,
+ modifier: PostModifier
+ ): Promise {
+ // check if we received a post item, instead of a post response
+ if (post.raw == null) {
+ post = await this.getPost(post.id)
+ }
+
+ // check
+ if (!post.raw) {
+ return Promise.resolve(null)
+ }
+
+ // replace
+ const { result, reason } = modifier(post)
+ if (result === post.raw) {
+ // if (post.cooked) {
+ // const { result, reason } = modifier(post.cooked)
+ // if (result !== post.cooked) {
+ // logger.debug(
+ // 'replace did have an effect on cooked post',
+ // postID,
+ // 'so rebaking it'
+ // )
+ // return await this.rebakePost(postID)
+ // }
+ // }
+ return Promise.resolve(null)
+ }
+
+ // dry
+ if (this.dry) {
+ return Promise.resolve({
+ ...((post as unknown) as PostUpdateItem),
+ result,
+ reason,
+ })
+ }
+
+ // update
+ try {
+ return await this.updatePost(post.id, result, reason, post.raw)
+ } catch (err) {
+ if (
+ err.message.includes(
+ 'That post was edited by another user and your changes can no longer be saved.'
+ )
+ ) {
+ return this.modifyPost(
+ await this.getPost(post.id, { useCache: false }),
+ modifier
+ )
+ }
+ logger.error(err);
+ return Promise.reject(`modifying post ${post.id} failed`)
+ }
+ }
+
+ /**
+ * Modify a post (via its post identifier) using a modifier
+ */
+ async modifyPostID(post: number, modifier: PostModifier) {
+ return this.modifyPost(await this.getPost(post), modifier)
+ }
+
+ /**
+ * Modify a post (via fetching the whole post from the partial post identifier) using a modifier
+ */
+ async modifyPostItem(post: PostItem, modifier: PostModifier) {
+ return this.modifyPost(await this.getPost(post.id), modifier)
+ }
+
+ /**
+ * Run the post modifier on all specified posts
+ */
+ async modifyPosts(
+ posts: PostResponse[],
+ modifier: PostModifier
+ ): Promise {
+ const updates = await Promise.all(
+ posts.map((post) => this.modifyPost(post, modifier))
+ )
+ const updated = updates.filter((i) => i) as PostUpdateItem[]
+ return updated
+ }
+
+ // =================================
+ // THREADS
+
+ /**
+ * Fetch the partial information, for all posts of a specific topic
+ * Alias of {@link .getPostItemsOfTopic}.
+ */
+ async getThread(topicID: number, opts: FetchOptions = {}): Promise {
+ const topic = await this.getTopic(topicID, opts)
+ const [post, ...replies] = await this.getPostItemsOfTopic(topicID, opts)
+ return {
+ topic,
+ post,
+ replies,
+ }
+ }
+
+ /**
+ * Fetch the partial information, for all posts of specific topics, grouped by topic
+ */
+ async getThreads(
+ topicIDs: number[],
+ opts: FetchOptions = {}
+ ): Promise {
+ return await Promise.all(topicIDs.map((id) => this.getThread(id, opts)))
+ }
+
+ /**
+ * Fetch the partial information, for all posts of specific categories, grouped by topic
+ */
+ async getThreadsOfCategory(
+ categoryID: number,
+ opts: FetchOptions = {}
+ ): Promise {
+ // fetch topics for the category
+ const topics = await this.getTopicItemsOfCategory(categoryID, opts)
+ const topicIDs = topics.map((i) => i.id)
+ // return threads
+ return await this.getThreads(topicIDs)
+ }
+
+ /**
+ * Fetch the partial information, for all posts of specific categories, grouped by category, then topic
+ */
+ async getThreadsOfCategories(
+ categoryIDs: number[],
+ opts: FetchOptions = {}
+ ): Promise {
+ return await Promise.all(
+ categoryIDs.map((id) => this.getThreadsOfCategory(id, opts))
+ )
+ }
+
+ async updateUserProfile(userId, prefs: UserPreferencesUpdate): Promise {
+
+ const url = `${this.host}/u/${userId}.json`
+ let data: any = new FormData()
+
+ data.append('bio_raw', prefs.bio_raw)
+
+ prefs.location && data.append('location', prefs.location)
+ prefs.website && data.append('website', prefs.website)
+
+ return await axios.put(url, data, {
+ headers: {
+ 'accept': 'application/json',
+ 'Accept-Language': 'en-US,en;q=0.8',
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ 'Api-Key': this.key,
+ 'Api-Username': this.username
+ }
+ })
+ }
+
+ /*
+ {
+ "bio_raw": "about me\n\ntest",
+ "website": "https://shop.osr-plastic.org",
+ "location": "Barcelona",
+ "custom_fields": {
+ "geo_location": {
+ "lat": "9.4170689",
+ "lon": "123.3351935",
+ "address": "Santander, Cebu, Central Visayas, 6026, Philippines",
+ "countrycode": "ph",
+ "city": "Santander",
+ "state": "Cebu",
+ "country": "Philippines",
+ "postalcode": "6026",
+ "boundingbox": [
+ "9.3630227",
+ "9.491731",
+ "123.2684005",
+ "123.3642727"
+ ],
+ "type": "administrative"
+ }
+ },
+ "timezone": "Europe/Berlin",
+ "default_calendar": "none_selected"
+ }*/
+ /*
+ fetch("https://forum.osr-plastic.org/u/katharinaelleke.json", {
+ "headers": {
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ "discourse-logged-in": "true",
+ "discourse-present": "true",
+ "sec-ch-ua": "\"Not.A/Brand\";v=\"8\", \"Chromium\";v=\"114\", \"Google Chrome\";v=\"114\"",
+ "sec-ch-ua-mobile": "?0",
+ "sec-ch-ua-platform": "\"Windows\"",
+ "x-csrf-token": "0Nau_ylBzR68D5OvfxfOHYii6GI_7gSrr_Ci_9S8ZDjqjy5mavF_O_INAPD8xfCQHgJkDH4rdgS0kPfjMAMBFw",
+ "x-requested-with": "XMLHttpRequest",
+ "Referer": "https://forum.osr-plastic.org/u/katharinaelleke/preferences/profile",
+ "Referrer-Policy": "strict-origin-when-cross-origin"
+ },
+ "body": "bio_raw=Curious%2C+serious+and+not+so+serious+%3Aslight_smile%3A+%0A&website=https%3A%2F%2Fwww.theflipflopi.com%2F&custom_fields%5Bnotify_me_when_followed%5D=false&custom_fields%5Bnotify_followed_user_when_followed%5D=false&custom_fields%5Bnotify_me_when_followed_replies%5D=false&custom_fields%5Bnotify_me_when_followed_creates_topic%5D=false&custom_fields%5Ballow_people_to_follow_me%5D=false&custom_fields%5Bgeo_location%5D%5Blat%5D=-2.294164&custom_fields%5Bgeo_location%5D%5Blon%5D=40.91501&custom_fields%5Bgeo_location%5D%5Baddress%5D=African+Corner%2C+Lamu%2C+Coast%2C+Kenya&custom_fields%5Bgeo_location%5D%5Bcountrycode%5D=ke&custom_fields%5Bgeo_location%5D%5Bcity%5D=&custom_fields%5Bgeo_location%5D%5Bstate%5D=Coast&custom_fields%5Bgeo_location%5D%5Bcountry%5D=Kenya&custom_fields%5Bgeo_location%5D%5Bpostalcode%5D=&custom_fields%5Bgeo_location%5D%5Bboundingbox%5D%5B%5D=-2.294164&custom_fields%5Bgeo_location%5D%5Bboundingbox%5D%5B%5D=-2.294164&custom_fields%5Bgeo_location%5D%5Bboundingbox%5D%5B%5D=40.91501&custom_fields%5Bgeo_location%5D%5Bboundingbox%5D%5B%5D=40.91501&custom_fields%5Bgeo_location%5D%5Btype%5D=&user_fields%5B1%5D=https%3A%2F%2Fshop.osr-plastic.org%2Fafrica%2F&user_fields%5B2%5D=https%3A%2F%2Fwww.theflipflopi.com%2F&user_fields%5B3%5D=https%3A%2F%2Fwww.instagram.com%2Fkatatungo%2F&user_fields%5B4%5D=unknown&user_fields%5B5%5D=unknown&profile_background_upload_url=https%3A%2F%2Fforum.osr-plastic.org%2Fuploads%2Fdefault%2Foriginal%2F2X%2F0%2F0875e1aea65f41172b9c4ad60b1a372cbaa72b2b.jpeg&card_background_upload_url=https%3A%2F%2Fforum.osr-plastic.org%2Fuploads%2Fdefault%2Foriginal%2F2X%2F3%2F357088c493bd0f66e651211853fb18beee2ec2e4.jpeg&timezone=Africa%2FNairobi&default_calendar=none_selected",
+ "method": "PUT"
+ });
+
+
+ fetch("https://forum.osr-plastic.org/u/admin-osr.json", {
+ "headers": {
+ "accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
+ "content-type": "application/x-www-form-urlencoded; charset=UTF-8",
+ "discourse-logged-in": "true",
+ "discourse-present": "true",
+ "sec-ch-ua": "\"Not/A)Brand\";v=\"99\", \"Google Chrome\";v=\"115\", \"Chromium\";v=\"115\"",
+ "sec-ch-ua-mobile": "?0",
+ "sec-ch-ua-platform": "\"Windows\"",
+ "sec-fetch-dest": "empty",
+ "sec-fetch-mode": "cors",
+ "sec-fetch-site": "same-origin",
+ "x-csrf-token": "gjd-DOi_nULFDhLyUh4igqFZENxL6B4rufR3dfbY9H9Soc-YDwOQS1SYSwJlj6f2f7BpDf5CO9y-zyOPBj-E1Q",
+ "x-requested-with": "XMLHttpRequest",
+ "cookie": "_ga=GA1.1.983567986.1691921410; _t=onvQ4UWFfLfjFsFkmebQdDot6JXW8%2FAWgFEtJUZ51AqXbTKnI%2BPF80usnZkhYqyYYW9Q%2B1fuMyEy5bDXc9AJpwwkcVIg%2Fu1DTE39y3nGdpXMiiVsmkMqBkyGA%2FvpvZUrM23CDS0xT%2B09VSSlNUbu8lZY27hYWXio4ETx7DRTmBk0xY52d3R6bcmtofynfxldP5KceF0APNtl9AV6iUhWloQ32CK6PmzpSFq4E3hstsS1WPTf7SwLGvESWm4tn3M4EQ2v4RHuLiHaAj%2F0--mv8Byxo5aHGcgKPO--%2F9eiy%2B24FCNmiLF3%2FpGZag%3D%3D; _ga_GVR8PEPG6C=GS1.1.1691940751.2.1.1691940775.0.0.0; _forum_session=bLbNekWpq6fkdK%2B19Nw6ZoKeEk9Ijp8LPfmQAjBiGK0TcnIYzMhZ5LJmLrxmG39e85SgUz%2F7NMI3NXZM9j%2F35eJuO3hxnUAkFvBNwjwwS9LGhDB4kB3ebAjjcBpoLPzUMWqyslQuR9RM8JcjZ%2FfX%2FWw0E61l9jhfrG0dr8Ds97IW7XedjKCmI7x7xinv10R2bRb51%2F72t2Z4dVG86wyCAtI5Spom0yjHoWPHwWBZ7VPYtOCmSBVygusuF%2FW5hpO9wgn1oqc0ZZ%2BXj%2FPiFc0FsADEcKYh3Q%3D%3D--xdEsXmADtTKkFGSc--x%2Fd9m02lRNk0uH%2BPxZTNwQ%3D%3D",
+ "Referer": "https://forum.osr-plastic.org/u/admin-osr/preferences/profile",
+ "Referrer-Policy": "strict-origin-when-cross-origin"
+ },
+ "body": "bio_raw=%23%23+Test%0A%0A%60%60%60js%0Aconst+t+%3D+0%0A%60%60%60%0A%0A%5Btest%5D(www.test.com)%0A%0A&website=www.test-site.com&location=test-loc&profile_background_upload_url=https%3A%2F%2Fforum.osr-plastic.org%2Fuploads%2Fdefault%2Foriginal%2F2X%2Fd%2Fd097423e34a6c677cdb0933d091fb84bcfbcec2e.jpeg&card_background_upload_url=https%3A%2F%2Fforum.osr-plastic.org%2Fuploads%2Fdefault%2Foriginal%2F2X%2Fb%2Fb4c30d1b981964fd6f936ebaac0f86ad4dc01209.png&timezone=Europe%2FBerlin&default_calendar=none_selected",
+ "method": "PUT"
+});
+
+
+ */
+
+
+}
+
+
+export const Instance = (config?: IDiscourseConfig, key: EDiscourseConfigKey = 'discourse_admin') => {
+
+ return new Discourser(config || (CONFIG_DEFAULT() as IOSRConfig)[key])
+
+ /*
+
+ d.getTopicItemsOfCategories([cat]).then(posts => {
+ //console.log('posts', posts)
+ let content = ""
+ posts = posts.map((p) => {
+ const url = `${config.discourse.host}/t/${p.id}`;
+ const title = `${p.fancy_title}`;
+ return `${title} `;
+ }).join('\n');
+ content += posts + " ";
+ resolve(content);
+
+ });
+ */
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/discourse/types.ts b/packages/discourse/src/lib/discourse/types.ts
new file mode 100644
index 00000000..dc7e3502
--- /dev/null
+++ b/packages/discourse/src/lib/discourse/types.ts
@@ -0,0 +1,761 @@
+// Attempt at TypeScript Types for the Discourse API
+// https://docs.discourse.org
+
+
+export interface Failure {
+ success: 'OK' // docs say lowercase, reality is uppercase
+}
+export interface Success {
+ failed: 'FAILED'
+}
+export type Response = Failure & Success
+
+export interface Action {
+ can_act: boolean
+ id: number
+ count?: number
+ hidden?: boolean
+}
+export interface Poster {
+ description: string
+ extras: string
+ user_id: number
+}
+export interface Person {
+ avatar_template: string
+ id: number
+ username: string
+}
+export interface Participant extends Person {
+ post_count: number
+}
+
+// This isn't documented, but is is there on
+// https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}.json/get
+export interface Link {
+ url: string
+ internal: boolean
+ reflection: boolean
+ title: string
+ clicks: number
+}
+
+/**
+ * Update a Topic Timestamp
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1change-timestamp/put
+ */
+export interface TopicUpdateTimestampRequest {
+ timestamp: number
+}
+export type TopicUpdateTimestampResponse = Response
+
+/**
+ * Update a Post
+ * https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/put
+ */
+export interface PostUpdateResponse {
+ post: PostUpdateItem
+}
+
+export interface TopicUpdateBasicTopic {
+ fancy_title: string
+ id: number
+ posts_count: number
+ slug: string
+ title: string
+}
+
+export interface TopicUpdateResponse{
+ basic_topic: TopicUpdateBasicTopic
+}
+
+export interface PostUpdateItem {
+ actions_summary: Array
+ admin: boolean
+ avatar_template: string
+ avg_time: object
+ can_delete: boolean
+ can_edit: boolean
+ can_recover: boolean
+ can_view_edit_history: boolean
+ can_wiki: boolean
+ cooked: string
+ created_at: string
+ deleted_at: object
+ display_username: string
+ draft_sequence: number
+ edit_reason: object
+ hidden_reason_id: object
+ hidden: boolean
+ id: number
+ incoming_link_count: number
+ moderator: boolean
+ name: string
+ post_number: number
+ post_type: number
+ primary_group_flair_bg_color: object
+ primary_group_flair_color: object
+ primary_group_flair_url: object
+ primary_group_name: object
+ quote_count: number
+ reads: number
+ reply_count: number
+ reply_to_post_number: object
+ score: number
+ staff: boolean
+ topic_id: number
+ topic_slug: string
+ trust_level: number
+ updated_at: string
+ user_deleted: boolean
+ user_id: number
+ user_title: object
+ username: string
+ version: number
+ wiki: boolean
+ yours: boolean
+}
+export interface PostUpdateRequest {
+ post: {
+ raw: string
+ raw_old?: string
+ edit_reason?: string
+ cooked?: string
+ }
+}
+
+// https://docs.discourse.org/#tag/Tags/operation/listTags
+
+export interface TagsResponse {
+ tags: Tag[]
+ extras: TagsExtras
+}
+
+export interface TagsExtras {
+ categories: any[]
+}
+
+export interface Tag {
+ count: number
+ description: null
+ id: string
+ name: string
+ pm_only: boolean
+ target_tag: null
+ text: string
+}
+
+
+/** https://docs.discourse.org/#tag/Categories/paths/~1categories.json/get */
+export interface CategoriesResponse {
+ category_list: {
+ can_create_category: boolean
+ can_create_topic: boolean
+ categories: Category[]
+ draft_key: string
+ draft_sequence: number
+ draft: boolean
+ }
+}
+export interface Category {
+ background_url: string
+ can_edit: boolean
+ color: string
+ description_excerpt: string
+ description_text: string
+ description: string
+ has_children: boolean
+ id: number
+ logo_url: string
+ name: string
+ notification_level: string
+ permission: number
+ position: number
+ post_count: number
+ read_restricted: boolean
+ slug: string
+ text_color: string
+ topic_count: number
+ topic_template: string
+ topic_url: string
+ topics_all_time: number
+ topics_day: number
+ topics_month: number
+ topics_week: number
+ topics_year: number
+}
+
+/**
+ * Get Single Topic
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}.json/get
+ */
+export interface TopicResponse {
+ actions_summary: Array
+ archetype: string
+ archived: boolean
+ bookmarked: object
+ category_id: number
+ chunk_size: number
+ closed: boolean
+ created_at: string
+ deleted_at: object
+ deleted_by: object
+ details: TopicDetails
+ draft_key: string
+ draft_sequence: object
+ draft: object
+ fancy_title: string
+ has_summary: boolean
+ highest_post_number: number
+ id: number
+ last_posted_at: object
+ like_count: number
+ participant_count: number
+ pinned_at: string
+ pinned_globally: boolean
+ pinned_until: object
+ pinned: boolean
+ posts_count: number
+ reply_count: number
+ slug: string
+ tags: string[] // not part of the api docs, but is there
+ title: string
+ unpinned: object
+ user_id: number
+ views: number
+ visible: boolean
+ word_count: object
+ post_stream: {
+ posts: Array
+ // not sure what this is
+ stream: Array
+ }
+ // not sure what this is
+ timeline_lookup: [
+ {
+ '0': Array
+ }
+ ]
+}
+export interface TopicDetails {
+ auto_close_at: object
+ auto_close_based_on_last_post: boolean
+ auto_close_hours: object
+ can_flag_topic: boolean
+ created_by: Person
+ last_poster: Person
+ notification_level: number
+ participants: Array
+ suggested_topics: Array
+}
+export interface TopicItem {
+ archetype: string
+ archived: boolean
+ bookmarked: object
+ bumped_at: string
+ bumped: boolean
+ category_id: number
+ closed: boolean
+ created_at: string
+ excerpt: string
+ fancy_title: string
+ has_summary: boolean
+ highest_post_number: number
+ id: number
+ image_url: string
+ last_posted_at: string
+ last_poster_username: string
+ like_count: number
+ liked: object
+ pinned_globally: boolean
+ pinned: boolean
+ posters: Array
+ posts_count: number
+ reply_count: number
+ slug: string
+ title: string
+ unpinned: boolean
+ unseen: boolean
+ views: number
+ visible: boolean
+}
+
+/**
+ * Get Topics for Category
+ * https://docs.discourse.org/#tag/Categories/paths/~1c~1{id}.json/get
+ */
+export interface CategoryResponse {
+ users: Person[]
+ topic_list: {
+ can_create_topic: boolean
+ draft: boolean
+ draft_key: string
+ draft_sequence: number
+ per_page: number
+ topics: Array
+ }
+}
+
+/**
+ * Whole Post Information
+ * As returned by getting a single Post
+ * https://docs.discourse.org/#tag/Posts/paths/~1posts~1{id}.json/get
+ */
+export interface PostResponse {
+ actions_summary: Array
+ admin: boolean
+ avatar_template: string
+ avg_time: object
+ can_delete: boolean
+ can_edit: boolean
+ can_recover: boolean
+ can_view_edit_history: boolean
+ can_wiki: boolean
+ cooked: string
+ created_at: string
+ deleted_at: object
+ display_username: string
+ edit_reason: object
+ hidden_reason_id: object
+ hidden: boolean
+ id: number
+ incoming_link_count: number
+ moderator: boolean
+ name: string
+ post_number: number
+ post_type: number
+ primary_group_flair_bg_color: object
+ primary_group_flair_color: object
+ primary_group_flair_url: object
+ primary_group_name: object
+ quote_count: number
+ raw: string
+ reads: number
+ reply_count: number
+ reply_to_post_number: object
+ score: number
+ staff: boolean
+ topic_id: number
+ topic_slug: string
+ trust_level: number
+ updated_at: string
+ user_deleted: boolean
+ user_id: number
+ user_title: object
+ username: string
+ version: number
+ wiki: boolean
+ yours: boolean
+}
+
+export interface ICreateUserResponse {
+ success: boolean;
+ active: boolean;
+ message: string;
+ user_id: number;
+ password: string;
+}
+
+
+
+/**
+ * Get the Posts of a Topic
+ * https://docs.discourse.org/#tag/Topics/paths/~1t~1{id}~1posts.json/get
+ */
+export interface PostsResponse {
+ post_stream: {
+ posts: Array
+ }
+ id: number
+}
+/**
+ * Partial Post Information
+ * As returned by a listing
+ */
+export interface PostItem {
+ accepted_answer: boolean
+ actions_summary: Array
+ admin: boolean
+ avatar_template: string
+ can_accept_answer: boolean
+ can_delete: boolean
+ can_edit: boolean
+ can_recover: boolean
+ can_unaccept_answer: boolean
+ can_view_edit_history: boolean
+ can_wiki: boolean
+ cooked: string
+ created_at: string
+ deleted_at: null
+ display_username: string
+ edit_reason: null
+ hidden: boolean
+ id: number
+ incoming_link_count: number
+ link_counts: Array
+ moderator: boolean
+ name: string
+ post_number: number
+ post_type: number
+ primary_group_flair_bg_color: null | object
+ primary_group_flair_color: null | object
+ primary_group_flair_url: null | object
+ primary_group_name: null | object
+ quote_count: number
+ read: boolean
+ readers_count: number
+ reads: number
+ reply_count: number
+ reply_to_post_number: null | number
+ reviewable_id: number
+ reviewable_score_count: number
+ reviewable_score_pending_count: number
+ score: number
+ staff: boolean
+ topic_id: number
+ topic_slug: string
+ trust_level: number
+ updated_at: string
+ user_deleted: boolean
+ user_id: number
+ user_title: null | object
+ username: string
+ version: number
+ wiki: boolean
+ yours: boolean
+}
+export type Thread = {
+ topic: TopicResponse
+ post: PostItem
+ replies: PostItem[]
+}
+
+// import { post } from 'request';
+
+/** When finding and replacing, determine replacements using a method that matches this */
+export type PostModifier = (
+ post: PostResponse
+) => { result: string; reason?: string }
+
+/** Configuration for Discourser */
+export interface IDiscourserConfig {
+ /** the discourse hostname to connect to, including protocol */
+ host: string
+ /** the API key to connect with */
+ key: string
+ /** the username to behave as */
+ username: string
+ /** the cache directory to use, if we are caching */
+ cache?: string
+ /** Whether or not we should read from the cache */
+ useCache?: boolean
+ /** whether or not updates should be dry (non-applying) */
+ dry?: boolean
+ /** how many concurrency requests to send to the server at once */
+ rateLimitConcurrency?: number
+}
+
+export interface FetchOptions {
+ /** Whether or not we should read from the cache */
+ useCache?: boolean
+ /** Only applicable to fetching topics of category */
+ page?: number
+ /** Any thing to init the fetch call with? */
+ request?: RequestInit
+
+ include_subcategories?: boolean
+}
+
+
+
+
+
+export interface FetchConfig extends FetchOptions {
+ url: string
+}
+
+export interface PostConfig extends FetchOptions {
+ url: string,
+ data: any
+}
+
+
+export interface ISearchPost {
+ id: number;
+ name: string;
+ username: string;
+ avatar_template: string;
+ created_at: Date;
+ like_count: number;
+ blurb: string;
+ post_number: number;
+ topic_id: number;
+}
+
+export interface ISearchTagsDescriptions {
+}
+
+export interface ISearchTopic {
+ id: number;
+ title: string;
+ fancy_title: string;
+ slug: string;
+ posts_count: number;
+ reply_count: number;
+ highest_post_number: number;
+ created_at: Date;
+ last_posted_at: Date;
+ bumped: boolean;
+ bumped_at: Date;
+ archetype: string;
+ unseen: boolean;
+ pinned: boolean;
+ unpinned?: any;
+ excerpt: string;
+ visible: boolean;
+ closed: boolean;
+ archived: boolean;
+ bookmarked?: any;
+ liked?: any;
+ tags: any[];
+ tags_descriptions: ISearchTagsDescriptions;
+ category_id: number;
+ has_accepted_answer: boolean;
+}
+
+export interface IGroupedSearchResult {
+ more_posts?: any;
+ more_users?: any;
+ more_categories?: any;
+ term: string;
+ search_log_id: number;
+ more_full_page_results?: any;
+ can_create_topic: boolean;
+ error?: any;
+ post_ids: number[];
+ user_ids: any[];
+ category_ids: any[];
+ tag_ids: any[];
+ group_ids: any[];
+}
+
+export interface ISearchResult {
+ posts: ISearchPost[];
+ topics: ISearchTopic[];
+ users: any[];
+ categories: any[];
+ tags: any[];
+ groups: any[];
+ grouped_search_result: IGroupedSearchResult;
+}
+
+
+export interface IUserDetail {
+ id: number
+ username: string
+ name: string
+ avatar_template: string
+ email: string
+ secondary_emails: any[]
+ active: boolean
+ admin: boolean
+ moderator: boolean
+ last_seen_at: string
+ last_emailed_at: string
+ created_at: string
+ last_seen_age: number
+ last_emailed_age: number
+ created_at_age: number
+ trust_level: number
+ manual_locked_trust_level: any
+ flag_level: number
+ title: string
+ time_read: number
+ staged: boolean
+ days_visited: number
+ posts_read_count: number
+ topics_entered: number
+ post_count: number
+ associated_accounts: AssociatedAccount[]
+ can_send_activation_email: boolean
+ can_activate: boolean
+ can_deactivate: boolean
+ ip_address: string
+ registration_ip_address: string
+ can_grant_admin: boolean
+ can_revoke_admin: boolean
+ can_grant_moderation: boolean
+ can_revoke_moderation: boolean
+ can_impersonate: boolean
+ like_count: number
+ like_given_count: number
+ topic_count: number
+ post_edits_count: number
+ flags_given_count: number
+ flags_received_count: number
+ private_topics_count: number
+ can_delete_all_posts: boolean
+ can_be_deleted: boolean
+ can_be_anonymized: boolean
+ can_be_merged: boolean
+ full_suspend_reason: any
+ silence_reason: any
+ penalty_counts: PenaltyCounts
+ next_penalty: string
+ primary_group_id: any
+ badge_count: number
+ warnings_received_count: number
+ user_fields: UserFields
+ bounce_score: number
+ reset_bounce_score_after: any
+ can_view_action_logs: boolean
+ can_disable_second_factor: boolean
+ can_delete_sso_record: boolean
+ api_key_count: number
+ external_ids: ExternalIds
+ single_sign_on_record: any
+ approved_by: ApprovedBy
+ suspended_by: any
+ silenced_by: any
+ tl3_requirements: Tl3Requirements
+ groups: Group[]
+}
+
+export interface AssociatedAccount {
+ name: string
+ description: string
+}
+
+export interface PenaltyCounts {
+ silenced: number
+ suspended: number
+}
+
+export interface UserFields {
+ "1": string
+ "2": string
+ "3": string
+ "4": string
+ "5": string
+}
+
+export interface ExternalIds {
+ google_oauth2: string
+}
+
+export interface ApprovedBy {
+ id: number
+ username: string
+ name: string
+ avatar_template: string
+}
+
+export interface Tl3Requirements {
+ time_period: number
+ requirements_met: boolean
+ requirements_lost: boolean
+ trust_level_locked: boolean
+ on_grace_period: boolean
+ days_visited: number
+ min_days_visited: number
+ num_topics_replied_to: number
+ min_topics_replied_to: number
+ topics_viewed: number
+ min_topics_viewed: number
+ posts_read: number
+ min_posts_read: number
+ topics_viewed_all_time: number
+ min_topics_viewed_all_time: number
+ posts_read_all_time: number
+ min_posts_read_all_time: number
+ num_flagged_posts: number
+ max_flagged_posts: number
+ num_flagged_by_users: number
+ max_flagged_by_users: number
+ num_likes_given: number
+ min_likes_given: number
+ num_likes_received: number
+ min_likes_received: number
+ num_likes_received_days: number
+ min_likes_received_days: number
+ num_likes_received_users: number
+ min_likes_received_users: number
+ penalty_counts: PenaltyCounts2
+}
+
+export interface PenaltyCounts2 {
+ silenced: number
+ suspended: number
+ total: number
+}
+
+export interface Group {
+ id: number
+ automatic: boolean
+ name: string
+ display_name?: string
+ user_count: number
+ mentionable_level: number
+ messageable_level: number
+ visibility_level: number
+ primary_group: boolean
+ title: any
+ grant_trust_level?: number
+ incoming_email: any
+ has_messages: boolean
+ flair_url: any
+ flair_bg_color?: string
+ flair_color?: string
+ bio_raw?: string
+ bio_cooked?: string
+ bio_excerpt?: string
+ public_admission: boolean
+ public_exit: boolean
+ allow_membership_requests: boolean
+ full_name?: string
+ default_notification_level: number
+ membership_request_template: any
+ members_visibility_level: number
+ can_see_members: boolean
+ can_admin_group: boolean
+ publish_read_state: boolean
+ can_edit_group?: boolean
+}
+
+export type TPostStatus = 'visible' | 'archived' | 'pinned' | 'closed'
+
+export interface TPostStatusUpdate {
+ success:string,
+ topic_status_update: any
+}
+
+export interface UserPreferencesUpdate {
+ bio_raw?: string
+ website?: string
+ location?: string
+ custom_fields?: CustomFields
+ timezone?: string
+ default_calendar?: string
+ // https://forum.osr-plastic.org/uploads/default/original/2X/4/476f01418c38779ac641bb45e985ad4097c7d175.jpeg
+ profile_background_upload_url?: string
+ card_background_upload_url?: string
+ }
+
+ export interface CustomFields {
+ geo_location: GeoLocation
+ }
+
+ export interface GeoLocation {
+ lat: string
+ lon: string
+ address: string
+ countrycode: string
+ city: string
+ state: string
+ country: string
+ postalcode: string
+ boundingbox: string[]
+ type: string
+ }
+
+
\ No newline at end of file
diff --git a/packages/discourse/src/lib/git/index.ts b/packages/discourse/src/lib/git/index.ts
new file mode 100644
index 00000000..c239350a
--- /dev/null
+++ b/packages/discourse/src/lib/git/index.ts
@@ -0,0 +1,42 @@
+
+import {logger} from '../../index'
+
+const GIT_CHANGELOG_MESSAGE_PREFIX = ''
+
+import * as path from 'path';
+
+import * as simpleGit from 'simple-git/promise';
+import { SimpleGit } from 'simple-git';
+import * as moment from 'moment';
+
+export async function git_status(cwd, dir) {
+
+ const git: SimpleGit = simpleGit(cwd);
+ let statusSummary:any = null;
+ try {
+ statusSummary = await git.log(['--stat', dir]);
+ }
+ catch (e) {
+ logger.error('Error Git', e);
+ }
+ return statusSummary;
+}
+
+export async function git_log(cwd, dir) {
+ const stats = await git_status(cwd, dir);
+ logger.info(`Reading Git log at ${cwd}/${dir}`);
+ let changelogs = stats.all.filter((e) => e.message.trim().toLowerCase().startsWith(GIT_CHANGELOG_MESSAGE_PREFIX.toLowerCase()));
+ if (!changelogs.length) {
+ return { files: [], last:stats.latest }
+ }
+ let pretty = changelogs.map((e) => {
+ return {
+ files: e.diff.files.map((f) => { return { path: f.file } }),
+ msg: e.message.toLowerCase().replace(GIT_CHANGELOG_MESSAGE_PREFIX.toLowerCase(), '').trim(),
+ hash: e.hash,
+ date: moment(e.date).format('LLLL')
+ }
+ });
+
+ return { files: pretty, last: stats.latest };
+};
\ No newline at end of file
diff --git a/packages/discourse/src/lib/index.ts b/packages/discourse/src/lib/index.ts
new file mode 100644
index 00000000..80bc51e3
--- /dev/null
+++ b/packages/discourse/src/lib/index.ts
@@ -0,0 +1,3 @@
+export * from './discourse'
+export * from './discourse/types'
+
diff --git a/packages/discourse/src/lib/markdown/Pattern.ts b/packages/discourse/src/lib/markdown/Pattern.ts
new file mode 100644
index 00000000..a1bfc465
--- /dev/null
+++ b/packages/discourse/src/lib/markdown/Pattern.ts
@@ -0,0 +1,13 @@
+import { RegExCallback } from './types'
+export class Pattern {
+ regex: RegExp;
+ replacement: RegExCallback
+ constructor(regex: RegExp, replacement: any) {
+ this.regex = regex
+ this.replacement = replacement
+ }
+
+ apply(raw: string): string {
+ return raw.replace(this.regex, this.replacement)
+ }
+}
diff --git a/packages/discourse/src/lib/markdown/Rule.ts b/packages/discourse/src/lib/markdown/Rule.ts
new file mode 100644
index 00000000..73c296cc
--- /dev/null
+++ b/packages/discourse/src/lib/markdown/Rule.ts
@@ -0,0 +1,17 @@
+import { Pattern } from './Pattern';
+
+export class Rule {
+ name: string;
+ patterns: Pattern[];
+ constructor(name: string, patterns: Pattern[]) {
+ this.name = name;
+ this.patterns = patterns;
+ }
+
+ apply(raw: string): string {
+ return this.patterns.reduce(
+ (result, pattern) => pattern.apply(result),
+ raw
+ );
+ }
+}
diff --git a/packages/discourse/src/lib/markdown/index.test.ts b/packages/discourse/src/lib/markdown/index.test.ts
new file mode 100644
index 00000000..929727f5
--- /dev/null
+++ b/packages/discourse/src/lib/markdown/index.test.ts
@@ -0,0 +1,144 @@
+import { Pattern, RMark, Rule } from './index';
+
+const sampleText = `# Header 1
+## Header 2
+### Header 3
+#### Header 4
+##### Header 5
+###### Header 6
+
+**Bold**
+*Italic*
+
+[Link](https://github.com/tlylt/rmark)
+
+
+This is **Bold** and this is *Italic*.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ornare erat facilisis odio viverra gravida. Phasellus in finibus libero. Duis eget pellentesque arcu, ut lobortis mi. Praesent vitae nulla sed leo dignissim finibus eget hendrerit arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vestibulum enim nibh, eu pellentesque tellus fermentum venenatis. Nam consectetur sem a magna mattis, sed luctus purus tincidunt. Nam faucibus tellus sed ligula molestie pulvinar. Mauris facilisis felis ex, eu tempor justo commodo et. Aenean lobortis dignissim diam eget tempor.
+
+Sed pellentesque nulla sit amet tincidunt sagittis. Phasellus eget justo nulla. Cras nisi odio, lobortis nec ante eget, commodo euismod
+turpis. Cras id orci dolor. Etiam auctor, nisl luctus volutpat lacinia, turpis orci euismod magna, pharetra eleifend massa metus aliquet
+`;
+
+const sampleHtml = `
+
Header 1
+
+
+
Header 2
+
+
+
Header 3
+
+
+
Header 4
+
+
+
Header 5
+
+
+
Header 6
+
+
+
+Bold
+
+
+Italic
+
+
+
+Link
+
+
+
+
+
+
+This is Bold and this is Italic .
+
+
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ornare erat facilisis odio viverra gravida. Phasellus in finibus libero. Duis eget pellentesque arcu, ut lobortis mi. Praesent vitae nulla sed leo dignissim finibus eget hendrerit arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vestibulum enim nibh, eu pellentesque tellus fermentum venenatis. Nam consectetur sem a magna mattis, sed luctus purus tincidunt. Nam faucibus tellus sed ligula molestie pulvinar. Mauris facilisis felis ex, eu tempor justo commodo et. Aenean lobortis dignissim diam eget tempor.
+
+
+
+Sed pellentesque nulla sit amet tincidunt sagittis. Phasellus eget justo nulla. Cras nisi odio, lobortis nec ante eget, commodo euismod
+
+
+turpis. Cras id orci dolor. Etiam auctor, nisl luctus volutpat lacinia, turpis orci euismod magna, pharetra eleifend massa metus aliquet
+
+`;
+
+describe('testing index file', () => {
+ test('empty string should render nothing', () => {
+ expect(new RMark().render('')).toBe('');
+ });
+ test('should render paragraph', () => {
+ expect(
+ new RMark().render(
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
+ )
+ ).toBe(
+ '\nLorem ipsum dolor sit amet, consectetur adipiscing elit.
\n'
+ );
+ });
+ test('should render header', () => {
+ expect(new RMark().render('# Header 1')).toBe(
+ '\n
Header 1 \n'
+ );
+ expect(new RMark().render('## Header 2')).toBe(
+ '\n
Header 2 \n'
+ );
+ expect(new RMark().render('### Header 3')).toBe(
+ '\n
Header 3 \n'
+ );
+ expect(new RMark().render('#### Header 4')).toBe(
+ '\n
Header 4 \n'
+ );
+ expect(new RMark().render('##### Header 5')).toBe(
+ '\n
Header 5 \n'
+ );
+ expect(new RMark().render('###### Header 6')).toBe(
+ '\n
Header 6 \n'
+ );
+ });
+ test('should render bold', () => {
+ expect(new RMark().render('**Bold**')).toBe('\nBold
\n');
+ expect(new RMark().render('__Bold__')).toBe('\nBold
\n');
+ expect(new RMark().render('This is **Bold**')).toBe(
+ '\nThis is Bold
\n'
+ );
+ });
+ test('should render italic', () => {
+ expect(new RMark().render('*Italic*')).toBe('\nItalic
\n');
+ expect(new RMark().render('_Italic_')).toBe('\nItalic
\n');
+ });
+ test('should render image', () => {
+ expect(
+ new RMark().render(
+ ''
+ )
+ ).toBe(
+ '\n
\n'
+ );
+ });
+ test('should render link', () => {
+ expect(new RMark().render('[Link](https://github.com)')).toBe(
+ '\nLink
\n'
+ );
+ });
+ test('should render paragraph with multiple lines', () => {
+ expect(new RMark().render(sampleText)).toBe(sampleHtml);
+ });
+ test('should work with adding rules', () => {
+ const rmark = new RMark();
+ rmark.addRule(
+ new Rule('horizontal', [
+ new Pattern(/^(-{3})/gm, ' '),
+ new Pattern(/^(_{3})/gm, ' '),
+ ])
+ );
+ expect(rmark.render('---')).toBe('\n
\n');
+ });
+});
diff --git a/packages/discourse/src/lib/markdown/index.ts b/packages/discourse/src/lib/markdown/index.ts
new file mode 100644
index 00000000..02014e13
--- /dev/null
+++ b/packages/discourse/src/lib/markdown/index.ts
@@ -0,0 +1,125 @@
+import { Rule } from './Rule'
+import { Pattern } from './Pattern'
+
+import { RMarkOptions } from './types'
+
+export const RE_IMAGES: RegExp = /\!\[([^\]]+)\]\((\S+)\)/g
+export const RE_LINKS: RegExp = /\[([^\n]+)\]\(([^\n]+)\)/g
+
+import * as markdown from 'markdown-it'
+import Token from "markdown-it/lib/token"
+import Renderer from "markdown-it/lib/renderer"
+
+const defaultRules: Rule[] = [
+ new Rule('header', [
+ new Pattern(/^#{6}\s?([^\n]+)/gm, '$1 '),
+ new Pattern(/^#{5}\s?([^\n]+)/gm, '$1 '),
+ new Pattern(/^#{4}\s?([^\n]+)/gm, '$1 '),
+ new Pattern(/^#{3}\s?([^\n]+)/gm, '$1 '),
+ new Pattern(/^#{2}\s?([^\n]+)/gm, '$1 '),
+ new Pattern(/^#{1}\s?([^\n]+)/gm, '$1 '),
+ ]),
+ new Rule('bold', [
+ new Pattern(/\*\*\s?([^\n]+)\*\*/g, '$1 '),
+ new Pattern(/\_\_\s?([^\n]+)\_\_/g, '$1 '),
+ ]),
+ new Rule('italic', [
+ new Pattern(/\*\s?([^\n]+)\*/g, '$1 '),
+ new Pattern(/\_\s?([^\n]+)\_/g, '$1 '),
+ ]),
+ new Rule('image', [
+ new Pattern(/\!\[([^\]]+)\]\((\S+)\)/g, ' '),
+ ]),
+ new Rule('link', [
+ new Pattern(
+ /\[([^\n]+)\]\(([^\n]+)\)/g,
+ '$1 '
+ ),
+ ]),
+ new Rule('paragraph', [
+ // this regex can't skip processed HTML
+ new Pattern(/([^\n]+\n?)/g, '\n$1
\n'),
+ // another possible regex that can't skip processed HTML
+ // new Pattern(/(?:^|\n)([^\n\<]+(?:\n[^\n\>]+)*)(?:\n|$)/gm, '\n$1
\n'),
+ ])
+]
+
+const defaultRulesDiscourse = (images, links) => {
+ return [
+ new Rule('image', [
+ new Pattern(RE_LINKS, images)
+ ])/*,
+ new Rule('link', [
+ new Pattern(
+ RE_LINKS,
+ links
+ )
+ ])*/
+ ]
+}
+
+export class RMark {
+
+ constructor(options: RMarkOptions) {
+ this.rules = defaultRulesDiscourse(options.images, options.links)
+ }
+
+ private rules: Rule[]
+
+ public addRuleBefore(rule: Rule, before: string): RMark {
+ const index = this.rules.findIndex((r) => r.name === before);
+ if (index !== -1) {
+ this.rules.splice(index, 0, rule);
+ }
+ return this;
+ }
+
+ public addRule(rule: Rule): RMark {
+ this.addRuleBefore(rule, 'paragraph');
+ return this;
+ }
+
+ public render(raw: string) {
+ let result = raw;
+ this.rules.forEach((rule) => {
+ result = rule.apply(result);
+ });
+ return result;
+ }
+}
+
+export { Rule } from './Rule';
+export { Pattern } from './Pattern';
+
+// export const find = (content:string, reg:RegExp) => content.match(reg)
+
+
+
+
+export const toHTML = (content) => {
+
+ const md = new markdown({
+ html: true,
+ breaks:true
+ })
+
+ return md.render(content)
+}
+
+function image_urls(input: string): string[] {
+ const regex = /https?:\/\/(?:[a-z0-9\-]+\.)+[a-z]{2,}(?:\/[^\/#\s]*)*\.(?:jpe?g|gif|png|webp)/g
+ const matches = input.match(regex)
+ return matches || []
+}
+
+function image_urls_local(input: string): string[] {
+ const regex = /\/(?:[^\/#\s]+\/)*[^\/#\s]+\.(?:jpe?g|gif|png|webp)/g
+ const matches = input.match(regex)
+ return matches || []
+}
+
+function findUploadImageUrls(input: string): string[] {
+ const regex = /upload:\/\/[^\s]+?\.(?:jpe?g|gif|png)/gi;
+ const matches = input.match(regex);
+ return matches || [];
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/markdown/page.ts b/packages/discourse/src/lib/markdown/page.ts
new file mode 100644
index 00000000..049c2ee4
--- /dev/null
+++ b/packages/discourse/src/lib/markdown/page.ts
@@ -0,0 +1,28 @@
+import { RMark } from '.';
+
+const sampleText = `# Header 1
+## Header 2
+### Header 3
+#### Header 4
+##### Header 5
+###### Header 6
+
+**Bold**
+*Italic*
+
+[Link](https://github.com/tlylt/rmark)
+
+
+This is **Bold** and this is *Italic*.
+
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ornare erat facilisis odio viverra gravida. Phasellus in finibus libero. Duis eget pellentesque arcu, ut lobortis mi. Praesent vitae nulla sed leo dignissim finibus eget hendrerit arcu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vestibulum enim nibh, eu pellentesque tellus fermentum venenatis. Nam consectetur sem a magna mattis, sed luctus purus tincidunt. Nam faucibus tellus sed ligula molestie pulvinar. Mauris facilisis felis ex, eu tempor justo commodo et. Aenean lobortis dignissim diam eget tempor.
+
+Sed pellentesque nulla sit amet tincidunt sagittis. Phasellus eget justo nulla. Cras nisi odio, lobortis nec ante eget, commodo euismod
+turpis. Cras id orci dolor. Etiam auctor, nisl luctus volutpat lacinia, turpis orci euismod magna, pharetra eleifend massa metus aliquet
+`;
+
+const page = document.getElementById('page');
+
+if (page) {
+ page.innerHTML = new RMark().render(sampleText);
+}
diff --git a/packages/discourse/src/lib/markdown/types.ts b/packages/discourse/src/lib/markdown/types.ts
new file mode 100644
index 00000000..20331a2e
--- /dev/null
+++ b/packages/discourse/src/lib/markdown/types.ts
@@ -0,0 +1,6 @@
+export type RegExCallback = (match, capture, arg1, arg2) => string
+
+export interface RMarkOptions {
+ images: RegExCallback,
+ links?: RegExCallback
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/oa/commons.ts b/packages/discourse/src/lib/oa/commons.ts
new file mode 100644
index 00000000..fe27340c
--- /dev/null
+++ b/packages/discourse/src/lib/oa/commons.ts
@@ -0,0 +1,141 @@
+
+import { Promise as BPromise } from 'bluebird'
+import { IUploadedFileMeta } from '@plastichub/osr-commons'
+import { forward_slash } from '@plastichub/osr-cli-commons'
+
+import {
+ IOptions,
+ IImportUser,
+ IOAHowto,
+ IOACategory,
+ IOATags,
+ IOAHowtoImport
+} from '../../'
+
+import {
+ logger
+} from '../../index'
+
+import {
+ HT_CATS
+} from '../discourse/constants'
+
+
+import { Discourser } from '../index'
+import { sanitize, convert } from './lib'
+
+import * as path from 'path'
+import { sync as read } from '@plastichub/fs/read'
+import { sync as exists } from '@plastichub/fs/exists'
+
+import { sync as write } from '@plastichub/fs/write'
+
+import { resolve } from '@plastichub/osr-commons'
+
+import * as cheerio from 'cheerio'
+import { getUsers, get_user_name } from './users'
+
+import { html_beautify } from 'js-beautify'
+import { Converter } from 'showdown'
+var escapeHtml = require('escape-html');
+import { sync as mkdir } from '@plastichub/fs/dir'
+import { files } from '@plastichub/osr-cli-commons'
+const pretty = require('pretty')
+
+
+const TEST = false
+
+export const DEFAULT_HT_CATEGORY = {
+ "_modified": "2022-09-18T08:51:47.196Z",
+ "label": "Guides",
+ "_id": "CrZjHORWfxEl6iDrrPIO",
+ "_created": "2022-09-18T08:51:47.196Z",
+ "_deleted": false
+}
+
+
+export const LATEST_TRACK = '${OSR_ROOT}/oa-data/howtos/latest_track.json'
+export const LATEST_TEST = './latest_test.json'
+
+export const DEFAULT_USER = 'katharinaelleke'
+
+export const getDataPath = (_path = '') => path.resolve(path.join(resolve('${OSR_ROOT}/oa-data/howtos/'), _path))
+export const getHowtosPath = () => path.resolve(resolve(TEST ? LATEST_TEST : LATEST_TRACK))
+export const getHowtos = () => (read(path.resolve(getHowtosPath()), 'json') as any) as IOAHowtoImport[] || []
+
+export const read_howtos = (src: string): IOAHowtoImport[] => {
+ const raw = read(src, 'json') as any
+ return raw.v3_howtos
+}
+
+export const read_categories = (src: string): IOACategory[] => {
+ const raw = read(src, 'json') as any
+ return raw.v3_categories
+}
+
+export const read_tags = (src: string): IOATags[] => {
+ const raw = read(src, 'json') as any
+ return raw.v3_tags
+}
+
+export const filter_valid = (users: IOAHowtoImport[]) => {
+ return users.filter((user) => {
+ if(user.title==='Build a Fishing Canoe'){
+ //debugger
+ }
+ if (user.moderation.toLowerCase() !== 'accepted') {
+ return false
+ }
+ return true;
+ })
+}
+
+export const kb_howto_folder = (howto) => path.resolve(path.join(resolve("${KB_ROOT}/src/howtos/"), howto.slug))
+export const kb_howto_file = (howto, filename) => path.resolve(path.join(resolve("${KB_ROOT}/src/howtos/"), howto.slug, sanitize(filename)))
+
+export const getHowtoUser = (howto: IOAHowto) => {
+ const users = getUsers()
+ let user = users.find((u) => u._id == howto._createdBy)
+ if (user && user.f_id) {
+ return user
+ } else {
+ user = users.find((u) => u._id == DEFAULT_USER)
+ if (user && user.f_id) {
+ console.error('using default user : ' + DEFAULT_USER + ' : for' + howto.slug)
+ return user
+ }
+ }
+}
+
+export const toMDImage = (image: IUploadedFileMeta) => ``
+
+export const md_edit_wrap = (content, f, prefix = '', context = '') =>
+ html_beautify(`${content}
`)
+
+export const removeEmojis = (string) => {
+ return string.replace(/([#0-9]\u20E3)|[\xA9\xAE\u203C\u2047-\u2049\u2122\u2139\u3030\u303D\u3297\u3299][\uFE00-\uFEFF]?|[\u2190-\u21FF][\uFE00-\uFEFF]?|[\u2300-\u23FF][\uFE00-\uFEFF]?|[\u2460-\u24FF][\uFE00-\uFEFF]?|[\u25A0-\u25FF][\uFE00-\uFEFF]?|[\u2600-\u27BF][\uFE00-\uFEFF]?|[\u2900-\u297F][\uFE00-\uFEFF]?|[\u2B00-\u2BF0][\uFE00-\uFEFF]?|(?:\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDEFF])[\uFE00-\uFEFF]?/g, '');
+}
+
+export const toHTML = (path, markdown) => {
+ const content = read(path, 'string') as string;
+ if (!markdown) {
+ let converter = new Converter({ tables: true });
+ converter.setOption('literalMidWordUnderscores', 'true');
+ return converter.makeHtml(content);
+ } else {
+ return content;
+ }
+}
+
+export const createTextLinks_ = (text) => {
+ return (text || "").replace(
+ /([^\S]|^)(((https?\:\/\/)|(www\.))(\S+))/gi,
+ function (match, space, url) {
+ var hyperlink = url
+ if (!hyperlink.match('^https?:\/\/')) {
+ hyperlink = 'http://' + hyperlink
+ }
+ return space + '' + url + ' '
+ }
+ )
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/oa/howtos.ts b/packages/discourse/src/lib/oa/howtos.ts
new file mode 100644
index 00000000..55e81b56
--- /dev/null
+++ b/packages/discourse/src/lib/oa/howtos.ts
@@ -0,0 +1,607 @@
+import { Promise as BPromise } from 'bluebird'
+import { IUploadedFileMeta } from '@plastichub/osr-commons'
+import { forward_slash } from '@plastichub/osr-cli-commons'
+import { resolveConfig } from '@plastichub/core'
+import { substitute } from '@plastichub/core/strings'
+
+import {
+ IOptions,
+ IImportUser,
+ IOAHowto,
+ IOACategory,
+ IOATags,
+ IOAHowtoImport
+} from '../../'
+
+import {
+ logger
+} from '../../index'
+
+import {
+ HT_CATS
+} from '../discourse/constants'
+
+
+import { Discourser } from '../index'
+import { sanitize, convert } from './lib'
+
+import * as path from 'path'
+import { sync as read } from '@plastichub/fs/read'
+import { sync as exists } from '@plastichub/fs/exists'
+
+import { sync as write } from '@plastichub/fs/write'
+
+import { resolve } from '@plastichub/osr-commons'
+
+import * as cheerio from 'cheerio'
+import { getUsers, get_user_name } from './users'
+
+var escapeHtml = require('escape-html');
+import { sync as mkdir } from '@plastichub/fs/dir'
+import { files } from '@plastichub/osr-cli-commons'
+
+import * as moment from 'moment'
+
+const FUCKING_TOKEN = 'j7oYrkQe5nbnikCNHcfoP2DGtXKV4iHHzDFip8gGatS145g3B65UU6mI09KeFday9mY5HNQnU2jXUTe7LLkP-w'
+
+import {
+ read_categories,
+ kb_howto_file,
+ kb_howto_folder,
+ getHowtos,
+ getHowtosPath,
+ getHowtoUser,
+ md_edit_wrap,
+ toHTML,
+ toMDImage,
+ createTextLinks_,
+ removeEmojis,
+ DEFAULT_HT_CATEGORY,
+ read_tags
+} from './commons'
+
+export const mergeLatest = (discorse, options: IOptions, oa_howtos: IOAHowtoImport[]): IOAHowtoImport[] => {
+
+ const howtos: any[] = getHowtos()
+ oa_howtos.forEach((h) => {
+ const howto = howtos.find((tu) => {
+ return tu._id === h._id
+ })
+ if (!howto) {
+ howtos.push(h)
+ }
+
+ })
+ write(getHowtosPath(), howtos)
+ return howtos
+}
+
+const updateHowtoFile = (howto) => {
+ const howtos: any[] = getHowtos()
+ const index = howtos.findIndex((u) => u._id == howto._id)
+ howtos[index] = howto
+ write(getHowtosPath(), howtos)
+}
+
+
+const uploadImage = async (discourse: Discourser, user: IImportUser, image: IUploadedFileMeta, localPath) => {
+ if (image.data) {
+ return image
+ }
+ logger.debug('uploading image:', image.name)
+ const upped: any = await discourse.uploadFile(user.f_id, localPath)
+ const data = upped.data;
+ if (data && data.id) {
+ image.data = data
+ } else {
+ logger.error('error uploading image')
+ }
+ return image
+}
+
+
+export const read_fragments = (src, config, prefix = '', context = '') => {
+ if (!exists(src)) {
+ mkdir(src);
+ }
+ let fragments = files(src, '*.html');
+ fragments.map((f) => {
+ config[path.parse(f).name] = md_edit_wrap(toHTML(f, true), f, prefix, context);
+ });
+
+ fragments = files(src, '*.md');
+ fragments.map((f) => {
+ config[path.parse(f).name] = md_edit_wrap(toHTML(f, false), f, prefix, context);
+ });
+ return config;
+}
+
+export async function howto_content(howto: IOAHowtoImport, folder: string, fragments, templates: any) {
+
+ //const tags = data.v3_tags;
+ const howtoTags = [];
+ /*
+ for (const ht in howto.tags) {
+ const gt = tags.find((t) => t._id === ht);
+ if (gt) {
+ howtoTags.push(gt.label);
+ // logger.debug('resolved ' + ht + ' to ' + gt.label);
+ } else {
+ // logger.error('Cant resolve tag : ' + ht);
+ }
+ }
+*/
+
+ howto.slug = howto.slug.trim();
+
+ let s: string = '';
+
+ let step_template = "" + templates.step;
+
+ let invalid_step_images = false
+
+ const step_image = (i: IUploadedFileMeta) => {
+ if (!i.data || !i.data.short_url) {
+ logger.error('invalid image : ' + i.downloadUrl + ' : ' + howto.slug)
+ invalid_step_images = true
+ return '\n'
+ }
+ return `\n${toMDImage(i)}`
+ }
+
+ const step_file = (i) => {
+ const image = `/howtos/${howto.slug}/${encodeURIComponent(sanitize(i.name))}`;
+ return ``
+ }
+
+ const step_files = (s) => {
+ const files = s.files.map(step_file).join('\n');
+ return `
+ ${files}
+
+ `
+ }
+
+ const step_images = (s) => {
+ const images = s.images.map(step_image).join('\n');
+ return `${images}`
+ }
+
+ const step_images_gallery = (s) => {
+ const images = s.images.map(step_image).join('');
+ return `\n${images}
`
+ }
+
+ const step = (s, i) => {
+ const t = substitute(step_template, {
+ title: s.title,
+ text: createTextLinks_(escapeHtml(s.text.trim()).replace(/(?:\r\n|\r|\n)/g, '\n\n')),
+ step_number: i + 1,
+ images: s.images.length > 1 ? step_images_gallery(s) : step_images(s)
+ });
+ return t;
+ }
+
+ const steps = howto.steps.map((s, i) => step(s, i)).join('\n\n');
+
+ const attachments = howto.files.map((f) => {
+ return `[${sanitize(f.name)}](${f.downloadUrl})`
+ })
+
+ howto.description = removeEmojis(howto.description);
+ howto.description = createTextLinks_(howto.description);
+
+ let authorName = (howto.user && howto.user.data && howto.user.data && howto.user.data.title) ? howto.user.data.title : (howto.user ? howto.user._id : 'OSR-Plastic');
+ if (authorName === 'Precious Plastic Headquarters') {
+ authorName = 'Precious Plastic Nantes';
+ }
+
+ let _3dFiles: any = [...files(path.resolve(`${folder}`), '**/**/*.step'), ...files(path.resolve(`${folder}`), '**/**/*.STEP'), ...files(path.resolve(`${folder}`), '**/**/*.stp')];
+
+ _3dFiles = _3dFiles.map((f) => {
+ return forward_slash(`${howto.slug}/${path.relative(path.resolve(folder), f)}`);
+ })
+
+ let previews = '';
+ if (_3dFiles.length) {
+ previews += '';
+ previews += '
';
+
+ _3dFiles = _3dFiles.map((f) => {
+ return `
+
+ 3D Step File: ${f.replace(howto.slug, '')} -
+
+ Preview
+
+ `
+ })
+
+ previews += _3dFiles.join('');
+ previews += ' ';
+ }
+
+ if (invalid_step_images) {
+ return false
+ }
+
+ let index = substitute(templates.howto, {
+ ...fragments,
+ image: `/howtos/${howto.slug}/${encodeURIComponent(sanitize(howto.cover_image.name))}`,
+ title: howto.title.trim(),
+ description: escapeHtml(howto.description.trim()) || "",
+ enabled: howto.moderation == "accepted" ? true : false,
+ steps: steps,
+ keywords: ['Precious plastic', 'Preciousplastic', 'plastichub', 'osr', ...howtoTags].join(','),
+ user: howto._createdBy,
+ files: `${attachments.join('\n')}`,
+ authorName: authorName,
+ authorUrl: `https://osr-plastic.org/users/${howto.user ? howto.user._id : 'https://osr-plastic.org/users/plastichub'}.html`,
+ // short: escapeHtml(howto.description.trim()).substring(0, 100) + '....',
+ slug: howto.slug,
+ previews3D: previews
+ });
+
+ const $ = cheerio.load(index as string, {
+ xmlMode: true
+ });
+
+ /*
+ $('a').each(function () {
+ const url = $(this).attr("href");
+ logger.debug('url : ' + url);
+ if(url.indexOf('dropbox')){
+
+ }
+ });*/
+
+ //write(index_md, pretty(index, { ocd: true }));
+
+ return removeEmojis(index)
+
+}
+
+export const createHowtoTopic = async (discourse, howto: IOAHowtoImport, create = true) => {
+
+ if (!howto.category || !howto.category.label) {
+ howto.category = DEFAULT_HT_CATEGORY
+ logger.error(`create howto : invalid category: ${howto.category} : ${howto.slug}`)
+ }
+
+ const user = getHowtoUser(howto)
+ if (!user) {
+ logger.error(`create howto : invalid user : ${howto._createdBy} :: ${howto.title}`)
+ }
+
+ const howto_folder = kb_howto_folder(howto)
+
+ const howto_cover_image = kb_howto_file(howto, howto.cover_image.name)
+
+ if (!exists(howto_folder)) {
+ logger.error('howto folder doesnt exists', howto.title)
+ }
+
+ if (!exists(howto_cover_image)) {
+ logger.error('howto cover image doesnt exists', howto.title)
+ }
+
+ if (!user || !user.f_id) {
+ logger.error(`create howto : invalid user : ${howto._createdBy} :: ${howto.title}`)
+ return false
+ }
+
+ howto.cover_image = await uploadImage(discourse, user, howto.cover_image, howto_cover_image)
+
+ updateHowtoFile(howto)
+
+ let invalid_images = false
+
+ for (const step of howto.steps) {
+ let i = 0
+ for await (const image of step.images) {
+ const image_name = sanitize(image.name)
+
+ const imagePath = path.resolve(path.join(howto_folder, sanitize(image_name)))
+
+ if (!exists(imagePath)) {
+ logger.error('step image doesnt exists : ' + image.name + ' in ' + howto.slug)
+ invalid_images = true
+ continue
+ }
+
+ step.images[i] = await uploadImage(discourse, user, step.images[i], imagePath)
+ updateHowtoFile(howto)
+ i++
+ }
+ }
+
+ if (invalid_images) {
+ logger.error('invalid images : ' + howto.slug)
+ return false
+ }
+
+ const cat = HT_CATS[howto.category.label]
+
+ if (!cat) {
+ logger.error('invalid kat')
+ return false
+ }
+
+ const templatesRoot = path.resolve(resolve("${OSR_ROOT}/osr-templates/discourse"))
+ const cPath = path.resolve(`${templatesRoot}/base.json`)
+
+ logger.debug(`read config at ${cPath}`)
+
+ const config = read(cPath, 'json') as any
+
+ const templates = path.resolve(`${templatesRoot}/howto`)
+
+ if (!exists(templates)) {
+ logger.error(`\t Cant find templates at ${templates}, path doesn't exists`)
+ return;
+ }
+
+ let fragments: any = { ...config.variables }
+
+ read_fragments(templates, fragments, "product_rel_path_name", "machine")
+
+ let template = read(path.resolve(`${templates}/howto.md`), 'string')
+
+ let step = read(path.resolve(`${templates}/step.md`), 'string')
+
+ resolveConfig(fragments);
+
+ const content = await howto_content(
+ howto,
+ howto_folder,
+ fragments,
+ {
+ howto: template,
+ step: '' + step
+ });
+
+ if (!content) {
+ logger.error('invalid content : ' + howto.slug)
+ return
+ }
+
+ let data
+ if (create) {
+ data = await discourse.createPost(sanitize(howto.title), content, cat);
+ if (data) {
+ logger.debug('created topic : ' + howto.title + ' : ' + data.id);
+ if (data && data.id) {
+ howto.post_id = data.id;
+ howto.topic_id = data.topic_id
+ updateHowtoFile(howto)
+ try {
+ logger.debug('change user to ', user._id)
+ await discourse.changeOwner(howto.post_id, howto.topic_id, get_user_name(user));
+ } catch (e) {
+ logger.debug('changing owner ' + howto.title + ' failed!');
+ howto.oF = true;
+ updateHowtoFile(howto)
+ }
+ } else {
+ logger.debug('creating ' + howto.title + ' failed!', data.errors);
+ howto.post_id = 'failed';
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + howto.slug)
+ howto.post_id = 'already';
+ }
+ }
+ updateHowtoFile(howto)
+ }
+ }
+ } else {
+ data = await discourse.updatePost(howto.post_id, content)
+ howto._updatedContent1 = true
+ updateHowtoFile(howto)
+ }
+}
+
+
+
+export const importHowto = async (discorse, howto: IOAHowtoImport) => {
+ //const howtos = getHowtos()
+ //const index = howtos.findIndex((u) => u._id == howto._id)
+ const ret = await createHowtoTopic(discorse, howto)
+ return ret
+}
+
+export const importHowtos = async (discorse, options: IOptions, howtos: IOAHowtoImport[]) => {
+
+ logger.debug('read howtos from ', path.resolve(getHowtosPath()))
+
+ howtos = mergeLatest(discorse, options, howtos)
+
+ howtos = howtos.filter((h) => {
+
+ if (h.title === 'Build a Fishing Canoe') {
+ //debugger
+ }
+
+ if (h.post_id || h.post_id as number < 0) {
+ return false;
+ }
+
+ if (h.post_id === 'failed') {
+ logger.debug('skip failed : ' + h.slug)
+ return false
+ }
+
+ //if (u.alreadyExists || u.invalidData) {
+ // return false;
+ //}
+ return true
+ })
+
+ return await BPromise.resolve(howtos).map((h: IOAHowtoImport) => {
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = importHowto(discorse, h)
+ if (d) {
+ d.then(resolve)
+ } else {
+ reject()
+ }
+ }, 500)
+
+ })
+
+ } catch (e) {
+ debugger;
+ logger.error('error creating howto ' + h._id, e)
+ }
+ }, { concurrency: 1 })
+}
+
+/////////////////////////////////////////////////////////////////////////
+//
+// Update Howtos
+//
+let _discorseTags
+
+const getDiscourseTags = async (discourse: Discourser) => {
+ if (!_discorseTags) {
+ _discorseTags = await discourse.getTags()
+ }
+
+ return _discorseTags
+}
+
+export const updateHowto = async (discourse: Discourser, howto: IOAHowtoImport, options: IOptions) => {
+
+ const tags = read_tags(options.src)
+ let howtoTags = []
+
+ for (const ht in howto.tags) {
+ const t = ht
+ const gt = tags.find((t: any) => {
+ return t._id === ht
+ });
+ if (gt) {
+ howtoTags.push(gt.label);
+ } else {
+ // logger.error('Cant resolve tag : ' + ht);
+ }
+ }
+
+ howtoTags.push('oa-import')
+
+ let discorseTags = await getDiscourseTags(discourse)
+
+ const cat = HT_CATS[howto.category.label]
+
+ if (howtoTags && howtoTags.length) {
+ try {
+ const ret = await discourse.updateTopic(howto.topic_id, cat as number, sanitize(howto.title), howtoTags)
+ logger.debug('Updating howto tags : ' + howto.title)
+ } catch (error) {
+ logger.error('Error updating post' + howto.title, howto.topic_id, cat, howtoTags,error)
+ howto['updateFailed1']=1
+ updateHowtoFile(howto)
+ //debugger
+ }
+
+ }
+ howto.updatedTags = true
+ updateHowtoFile(howto)
+
+ const _date = howto._modified || howto._created
+
+ if (_date) {
+ let date: Date = new Date(_date)
+ logger.debug('update ts ' + howto.slug + ' : ' + new Date(date).toLocaleDateString())
+ let offset = 0
+ const valueOf = date.valueOf() - (offset) * 60000
+ let ts = Math.floor(valueOf / 1000)
+ const tUpdate = await discourse.updateTopicTimestamp(howto.topic_id, ts, FUCKING_TOKEN)
+ if (tUpdate) {
+ howto.updatedTime8 = true
+ updateHowtoFile(howto)
+ return true
+ }
+ } else {
+ logger.error('Have no ts : ' + howto.slug)
+ }
+}
+
+export const updateHowtos = async (discorse, options: IOptions, howtos: IOAHowtoImport[]) => {
+
+ logger.debug('update howtos from ', path.resolve(getHowtosPath()))
+
+ howtos = mergeLatest(discorse, options, howtos)
+
+ const forceUpdateContent = true
+ const forceUpdateMeta = true
+
+ const updateContent = true
+ const updateMeta = true
+
+ howtos = howtos.filter((h) => {
+
+ if (!h.post_id || !h.topic_id) {
+ return false
+ }
+
+ if (h.post_id === 'failed') {
+ logger.debug('skip failed : ' + h.slug)
+ return false
+ }
+
+ if (forceUpdateContent || forceUpdateMeta) {
+ return true
+ }
+
+ if (!h._updatedContent1) {
+ return true
+ }
+
+ if (h.updatedTags && h.updatedTime8) {
+ return false
+ }
+
+ if (!h.updatedTags || !h.updatedTime8) {
+ return true
+ }
+
+ return true
+ })
+
+ return await BPromise.resolve(howtos).map((h: IOAHowtoImport) => {
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ if (updateContent) {
+ logger.debug('\t recook howto content', h.title)
+ let d = createHowtoTopic(discorse, h, false)
+ d.then(() => {
+ if (updateMeta) {
+ d = updateHowto(discorse, h, options)
+ if (d) {
+ d.then(resolve)
+ } else {
+ reject()
+ }
+ } else {
+ resolve(1)
+ }
+ })
+ }
+ }, 500)
+ })
+
+ } catch (e) {
+ debugger;
+ logger.error('error creating howto ' + h._id, e)
+ }
+ }, { concurrency: 1 })
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/oa/index.ts b/packages/discourse/src/lib/oa/index.ts
new file mode 100644
index 00000000..1e889f46
--- /dev/null
+++ b/packages/discourse/src/lib/oa/index.ts
@@ -0,0 +1,4 @@
+export * from './lib'
+export * from './users'
+export * from './types'
+
diff --git a/packages/discourse/src/lib/oa/lib.ts b/packages/discourse/src/lib/oa/lib.ts
new file mode 100644
index 00000000..de5db8dd
--- /dev/null
+++ b/packages/discourse/src/lib/oa/lib.ts
@@ -0,0 +1,194 @@
+const _sanitize = require("sanitize-filename")
+const URI = require("uri-js")
+import * as path from 'path'
+const filenamify = require('filenamify')
+var TurndownService = require('turndown');
+export const sanitize = (f) => {
+ let str: string = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "");
+ if (str.startsWith('_')) {
+ str = str.substring(1)
+ }
+ return str
+}
+
+
+export const getImageName = (url) => {
+ const parsed = URI.parse(decodeURIComponent(url));
+ const pParsed = path.parse(parsed.path);
+ const fileName = sanitize(decodeURIComponent(pParsed.base))
+ return fileName
+}
+
+export const convert = (input: string) => {
+ var turndownService = new TurndownService()
+ return turndownService.turndown(input);
+}
+
+/*
+
+
+const getFUser = (users, user_name) => {
+ return users.find((u) => {
+ return u.name == user_name
+ })
+}
+
+
+const indexUsers = async (d, forum: string, detail) => {
+
+ const forumUsers = await getForumUsers(d, detail)
+ const raw = (read(path.resolve(forum + '/index.json'), 'json') as any)
+ const users_raw = raw.users
+ let users = []
+ for (let u in users_raw) {
+ const user = users_raw[u];
+ const avatar = getOAvatar(raw, u);
+ let aFileName = '';
+ let fUser = getFUser(forumUsers, u);
+ if (avatar) {
+ const parsed = URI.parse(avatar);
+ const pParsed = path.parse(parsed.path);
+ aFileName = pParsed.base;
+ }
+ users.push({
+ name: u,
+ avatar: avatar,
+ avatarFileName: aFileName,
+ user_id: fUser ? fUser.id : -1
+ });
+ }
+ write(path.resolve(forum + '/user.json'), users);
+}
+
+const _createUser = async (discorse, forum, name, email) => {
+
+ const users = getUsers()
+ const index = users.findIndex((u) => u.detail.name == name)
+ let user = await createUser(discorse, null)
+
+
+ if (user && users[index].upload_id) {
+ await discorse.setUserAvatar(name, users[index].upload_id);
+ //return users;
+ }
+
+ if (user > 0 && index) {
+ users[index].f_id = user;
+ console.log('created ' + name + ' ' + user);
+ write(getUsersPath(), users);
+ } else {
+ console.error('cant create user - error', name, user)
+ }
+}
+
+
+const _updateGroup = async (discorse, forum, name, id, forumUsers) => {
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const index = users.findIndex((u) => u.name == name);
+ try {
+ const d = await discorse.updateGroup(name, pUserGroup);
+ console.log('updated user group for ' + name);
+ users[index].g_id = pUserGroup;
+ write(path.resolve(forum + '/user.json'), users);
+ if (users[index].upload_id) {
+ //await discorse.setUserAvatar(name, users[index].upload_id);
+ }
+ } catch (e) {
+ if (e.data && e.data.status == 422) {
+ users[index].g_id = pUserGroup;
+ write(path.resolve(forum + '/user.json'), users);
+ console.log('updated user group for ' + name);
+ }
+ }
+}
+
+const _updateAvatar = async (discorse, forum, name) => {
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const index = users.findIndex((u) => u.name == name);
+ return new Promise((resolve, reject) => {
+ try {
+ setTimeout(() => {
+ discorse.setUserAvatar(name, users[index].upload_id).then(() => {
+ console.log('updated avatar for ' + name);
+ users[index].avatarSet = true;
+ write(path.resolve(forum + '/user.json'), users);
+ resolve(1);
+ });
+ }, 200);
+ } catch (e) {
+ console.error('-error setting avatar', e);
+ debugger;
+ }
+ });
+}
+
+
+const createUsers = async (d, forum) => {
+
+ const forumUsers = await getForumUsers(d, true)
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const toBeCreated = users.filter((u) => {
+ if (u.f_id || u.f_id < 0) {
+ return false;
+ }
+ if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
+ return false
+ }
+ return true;
+ });
+
+ console.log('Create Users ' + users.length + ' Total | Left: ' + toBeCreated.length);
+
+ return await BPromise.resolve(toBeCreated).map((u: any) => {
+ const t = _createUser(d, forum, u.name, u.email);
+ return t;
+ }, { concurrency: 1 })
+
+}
+
+const updateUserGroups = async (forum) => {
+ const forumUsers = (read(path.resolve(forum + '/fusers.json'), 'json') as any);
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const toBeUpdated = users.filter((u) => {
+ if (u.g_id) {
+ return false;
+ }
+ if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
+ return false
+ }
+ return true;
+ });
+ const d = getDiscourse();
+ console.log('Update Users ' + users.length + ' Total | Left: ' + toBeUpdated.length);
+ return await BPromise.resolve(toBeUpdated).map((u: any) => {
+ const t = _updateGroup(d, forum, u.name, u.f_id, forumUsers);
+ return t;
+ }, { concurrency: 1 })
+
+}
+
+const updateUserAvatars = async (forum) => {
+ const users = (read(path.resolve(forum + '/user.json'), 'json') as any);
+ const toBeUpdated = users.filter((u) => {
+ if (!u.upload_id) {
+ return false;
+ }
+
+ if (u.avatarSet) {
+ return false;
+ }
+
+ if (u.name === 'plastichub' || u.name === 'lu' || u.name === 'timberstar' || u.name === 'nickname') {
+ return false
+ }
+ return true;
+ });
+ const d = getDiscourse();
+ console.log('Update User Avatar ' + users.length + ' Total | Left: ' + toBeUpdated.length);
+ return await BPromise.resolve(toBeUpdated).map((u: any) => {
+ const t = _updateAvatar(d, forum, u.name);
+ return t;
+ }, { concurrency: 1 })
+
+}
+*/
\ No newline at end of file
diff --git a/packages/discourse/src/lib/oa/types.ts b/packages/discourse/src/lib/oa/types.ts
new file mode 100644
index 00000000..a7c99c4a
--- /dev/null
+++ b/packages/discourse/src/lib/oa/types.ts
@@ -0,0 +1,120 @@
+import {
+ IImage,
+ IModerationStatus,
+ IOpeningHours,
+ IConvertedFileMeta,
+ IModerable,
+ IPlasticType,
+ IUploadedFileMeta,
+ I_OSR_USER
+} from '@plastichub/osr-commons'
+
+
+
+/// Taxonomy
+export interface IOACategory {
+ _created: string
+ _id: string
+ _deleted: boolean
+ label: string
+ _modified: string
+}
+
+export interface IOATag {
+ categories: string[]
+ image: string
+ _created: string
+ _deleted: boolean
+ label: string
+ _createdBy: string
+ _modified: string
+ _id: string
+}
+
+// Howtos
+
+export type IOADifficultyLevel = 'Easy' | 'Medium' | 'Hard' | 'Very Hard'
+
+export interface IDImage {
+ id: number
+ url: string
+ original_filename: string
+ filesize: number
+ width: number
+ height: number
+ thumbnail_width: number
+ thumbnail_height: number
+ extension: string
+ short_url: string
+ short_path: string
+ retain_hours: any
+ human_filesize: string
+ }
+
+
+export interface IOAHowto {
+ moderation: string
+ category: IOACategory
+ previousSlugs: string[]
+ total_downloads: number
+ _createdBy: string
+ slug: string
+ cover_image: IUploadedFileMeta
+ _modified: string
+ files: any[]
+ description: string
+ mentions: any[]
+ time: string
+ _created: string
+ fileLink: string
+ steps: IOAStep[]
+ creatorCountry: string
+ title: string
+ tags: IOATags
+ _id: string
+ _deleted: boolean
+ total_views: number
+ difficulty_level: IOADifficultyLevel
+ comments: any[]
+ user: IImportUser
+ pics?:string[]
+}
+
+export interface IOAStep {
+ _animationKey: string
+ images: IUploadedFileMeta[]
+ text: string
+ title: string
+}
+export interface IOATags {
+ [key: string]: boolean
+}
+
+
+export type IOAHowtoImport = IOAHowto &
+{
+ post_id?:number | string
+ topic_id?:number
+ oF?:boolean
+ updatedTags?:boolean
+
+ updatedTime8?:boolean
+ _updatedContent1? : boolean
+
+}
+
+
+export interface IImportUser extends I_OSR_USER {
+ f_id: number
+ upload_id: number
+ avatar: string
+ _didSetAvatar: boolean
+ _didSetGroup: boolean
+ alreadyExists: boolean
+ invalidData: boolean
+ didUpdateName: boolean
+
+ profileHeader?: IDImage
+ cardBackground?: IDImage
+ avatarImage?: IDImage
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/oa/users.ts b/packages/discourse/src/lib/oa/users.ts
new file mode 100644
index 00000000..b0887cf4
--- /dev/null
+++ b/packages/discourse/src/lib/oa/users.ts
@@ -0,0 +1,1090 @@
+
+import { Promise as BPromise } from 'bluebird'
+import { I_OSR_USER } from '@plastichub/osr-commons'
+
+import { IOptions, IImportUser, IDiscourseUser } from '../../'
+import { Discourser } from '../index'
+import { getImageName, sanitize } from './lib'
+
+import { capitalize, replace, replaceAll } from '@plastichub/core/utils'
+import * as path from 'path'
+import { sync as read } from '@plastichub/fs/read'
+import { sync as exists } from '@plastichub/fs/exists'
+import { sync as write } from '@plastichub/fs/write'
+
+import { resolve } from '@plastichub/osr-commons'
+
+import { logger } from '../../index'
+
+const slugify = require('slugify')
+
+import { resolveConfig, substitute } from '@plastichub/core'
+
+import { html_beautify } from 'js-beautify'
+import { sync as mkdir } from '@plastichub/fs/dir'
+import { files, forward_slash } from '@plastichub/osr-cli-commons'
+import { Converter } from 'showdown'
+const URI = require("uri-js")
+
+import {
+ OA_USER_IMPORT_GROUP,
+ LATEST_TEST,
+ LATEST_TRACK,
+ FETCH_DUSERS,
+ F_USERS_ALL,
+ F_USERS_NOW,
+ DEFAULT_PASSWORD,
+ DATA_PATH,
+ HT_CATS,
+ OA_DIRECTORY_OVERVIEW_TOPIC
+} from '../discourse/constants'
+
+import { IOSRConfig } from '@plastichub/osr-cli-commons'
+
+
+const filenamify = require('filenamify')
+const fg = require('fast-glob')
+
+
+const TEST = false
+
+
+
+export const read_users = (src: string): I_OSR_USER[] => {
+ const raw = read(src, 'json') as any
+ return raw.v3_mappins.filter((f) => f.data != null)
+}
+
+export const filter_valid = (users: IImportUser[]) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false
+ }
+ if (!user.geo) {
+ return false
+ }
+
+ if (!user.data.urls) {
+ return false
+ }
+
+ if (!user.data.title) {
+ return false
+ }
+
+ if (!user.detail) {
+ return false
+ }
+
+ if (!user.detail.heroImageUrl) {
+ return false
+ }
+
+ if (user.data && user.data.jsError) {
+ return false
+ }
+
+ if (user.moderation !== 'accepted') {
+ //return false
+ }
+
+ return true;
+ })
+}
+
+export const filter_email_only = (users: any[]) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+
+ if (!user.detail) {
+ return false
+ }
+
+ if (!user.detail.name) {
+ return false
+ }
+
+ if (user.data.urls.find((l) => l.name == 'Email') == undefined) {
+ return false;
+ }
+ return true;
+ })
+}
+
+export const filter_invalid = (users: any[]) => {
+
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+
+
+ if (!user.detail.name) {
+ return true
+ }
+
+ if (user.data.urls.find((l) => l.name == 'Email') == undefined) {
+ return true;
+ }
+
+ if (user.moderation !== 'accepted') {
+ return true;
+ }
+
+ return false;
+ })
+}
+
+export const filter_email_missing = (users: any[]) => {
+
+ return users.filter((user) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ if (!user.detail) {
+ return false
+ }
+
+ if (!user.detail.name) {
+ return false
+ }
+
+ if (user.moderation !== 'accepted') {
+ return false;
+ }
+ if (!user.data.urls.find((l) => l.name == 'Email')) {
+ return true;
+ }
+ return false;
+ })
+}
+
+export const filter_accepted = (users: IImportUser[]) => {
+ return users.filter((user) => {
+ if (!user.data) {
+ return false
+ }
+ if (!user.geo) {
+ return false
+ }
+ if (!user.data.urls) {
+ return false
+ }
+
+ if (!user.detail.heroImageUrl) {
+ return false
+ }
+
+ if (user.data && user.data.jsError) {
+ return false
+ }
+
+ if (user.moderation !== 'accepted') {
+ return false
+ }
+
+ return true;
+ })
+}
+
+export const oa_user_email = (user: I_OSR_USER) => {
+ if (!user.data) {
+ return false;
+ }
+ if (!user.geo) {
+ return false;
+ }
+ if (!user.data.urls) {
+ return false;
+ }
+ if (user.data && user.data.jsError) {
+ return false;
+ }
+ let u = user.data.urls.find((l) => l.name == 'Email')
+ if (u) {
+ return u.url.replace('mailto:', '')
+ }
+
+}
+
+export const get_user_name = (user: IImportUser) => {
+ let ret = replaceAll('--', '-', sanitize(filenamify(user._id)).replace(/^\-+/g, '').replace(/\-$/, ''))
+
+ ret = ret.replace(/\-$/, '')
+ ret = ret.replace(/\_$/, '')
+
+ if (!oa_user_email(user)) {
+ ret += '-uc'
+ }
+
+ return ret
+}
+
+export const get_user_display_name = (user: IImportUser) => replaceAll('--', '-', sanitize(filenamify(user.data.title)).replace(/^\-+/g, '').replace(/\-$/, ''));
+
+export const getDataPath = (_path = '') => path.resolve(path.join(resolve(DATA_PATH), _path))
+
+export const getUsersPath = () => path.resolve(resolve(TEST ? LATEST_TEST : LATEST_TRACK))
+
+export const getUsers = () => (read(path.resolve(getUsersPath()), 'json') as any) as IImportUser[] || []
+
+let uPage = 1
+let usersAll = []
+
+export const _getForumUsers = async (d: Discourser, page, detail) => {
+
+ if (uPage == 1) {
+ usersAll = []
+ }
+ let users: any = await d.getUsers(page);
+ if (users.length) {
+ usersAll = usersAll.concat(users);
+ uPage++;
+ return _getForumUsers(d, uPage, detail);
+ } else {
+ uPage = 1;
+
+ write(path.resolve(F_USERS_NOW), usersAll);
+
+ let fUsers: IDiscourseUser[] = read(path.resolve(F_USERS_ALL), 'json') || [] as any;
+
+ const add = async (u: IDiscourseUser) => {
+ return new Promise((resolve, reject) => {
+ let fUser = fUsers.find((fu) => u.id == fu.id)
+ if (!fUser) {
+ fUsers.push(u)
+ fUser = u
+ }
+
+ if (!fUser.detail) {
+ logger.debug('Retrieve User Detail ' + u.name)
+ setTimeout(() => {
+ d.getUser(fUser.id).then((detail) => {
+ if (detail) {
+ fUser.detail = detail
+ }
+ write(path.resolve('./fusers-all.json'), fUsers)
+ resolve(fUser)
+ })
+ }, 200)
+ } else {
+ resolve(fUser)
+ }
+ })
+ }
+ return await BPromise.resolve(usersAll).map((u: IDiscourseUser) => {
+ return add(u)
+ }, { concurrency: 1 })
+
+ }
+}
+export const getForumUsers = async (d, detail): Promise => {
+ if (!FETCH_DUSERS) {
+ return read(getDataPath(F_USERS_ALL), 'json') || [] as any
+ }
+ return _getForumUsers(d, uPage, detail)
+}
+
+export const createUser = async (discourse: Discourser, oa_user: IImportUser) => {
+ /*
+ Bazar
+ https://shop.osr-plastic.org
+ Website
+ website2
+ Instagram
+ https://www.instagram.com/osr_plastic/
+ Directory / Map Url
+ https://www.google.com/maps/contrib/117674167598277014013
+ OSR - Marketplace Url
+ https://shop.osr-plastic.org/plastichub/
+ */
+ if (!oa_user.data.title) {
+ return -120
+ }
+
+ let name = replaceAll('--', '-', get_user_display_name(oa_user).replace(/^\-+/g, '').replace(/\-$/, ''))
+ let user_name = get_user_name(oa_user)
+
+ name = user_name.replace(/\-$/, '')
+ name = user_name.replace(/\_$/, '')
+
+ let opts = {
+ "name": name,
+ "email": oa_user_email(oa_user) || `${user_name}_uc@osr-plastic.org`,
+ "password": DEFAULT_PASSWORD(),
+ "username": user_name,
+ "active": true,
+ "approved": true,
+ "user_fields[1]": true
+ }
+
+ let user: any = await discourse.createUser(opts)
+
+ if (name.length < 4) {
+ return -120
+ }
+
+ if (user_name.length > 50) {
+ return -120
+ }
+
+ if (user && user.errors) {
+
+
+ if (user.message === "Username must be no more than 50 characters" ||
+ user.message === 'Username must not contain a sequence of 2 or more special chars (.-_)') {
+ return -120
+ }
+
+ if (user.message === "Username must be unique" || user.message === "Primary email has already been taken") {
+ return -100
+ }
+
+ if (user.errors.email && user.errors.username) {
+ user = await discourse.getUserByUsername(user_name)
+ if (user && user.id && !oa_user._didSetGroup) {
+ try {
+ let gret = await discourse.updateGroup(user_name, OA_USER_IMPORT_GROUP);
+ } catch (e) {
+ logger.error('error adding to group', user_name)
+ }
+ return user.id
+ };
+ }
+ logger.error('Error creating user ' + user_name, user.errors)
+ }
+ if (user && user.user_id) {
+ try {
+ await discourse.updateGroup(user_name, OA_USER_IMPORT_GROUP);
+ return user.user_id;
+ } catch (e) {
+ logger.error('error adding to group', user_name)
+ return user.user_id;
+ }
+
+ } else {
+ if (user && user.message && user.message == 'Username must be unique\nPrimary email has already been taken') {
+ logger.error('already created', oa_user.detail.name)
+ return -10;
+ } else if (user && user.message && user.message == 'Your account is activated and ready to use.') {
+ if (user.user_id) {
+ return user.user_id;
+ }
+ return -10;
+ } else {
+ logger.debug('cant create user ' + oa_user.detail.name, user);
+ }
+ return null;
+ }
+ return null;
+}
+
+export const uploadAvatar = async (discourse, name, filePath) => {
+ const users = getUsers()
+ const index = users.findIndex((u) => u.detail.name == name)
+ try {
+ const upped = await discourse.upload(1, filePath)
+ const data = upped.data
+
+ if (data && data.id) {
+ users[index].upload_id = data.id
+ logger.debug('uploaded avatar ' + name + ' ' + data.id)
+ write(getUsersPath(), users)
+ } else {
+ logger.error('upload - error', name)
+ }
+ return users
+ } catch (error) {
+ users[index].upload_id = -1
+ logger.error('error uploading avatar', name)
+ write(getUsersPath(), users)
+ }
+
+}
+
+const uploadAvatars = async (discourse: Discourser, users: IImportUser[]) => {
+
+ const toBeUploaded = users.filter((u) => {
+ if (u.upload_id) {
+ return false
+ }
+
+ const hero = getImageName(u.detail.heroImageUrl)
+ const avatar = findAvatar(u, hero)
+ if (!avatar) {
+ logger.error('cant find avatar : ', u._id, hero)
+ return false
+ }
+ u.avatar = avatar
+ return true
+ })
+
+ return await BPromise.resolve(toBeUploaded).map((u: IImportUser) => {
+ if (!u.detail.name) {
+ return
+ }
+ logger.debug('upload avatar : ' + u._id)
+ const t = uploadAvatar(discourse, u.detail.name, u.avatar)
+ return t;
+ }, { concurrency: 1 })
+
+}
+
+const findAvatar = (user: IImportUser, filename) => {
+
+ const root = path.resolve(resolve(DATA_PATH))
+
+ const _path = path.resolve(`${root}/${user._id}/${filename}`)
+ if (exists(_path)) {
+ return _path
+ }
+ const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: root, absolute: true });
+ if (files.length == 0) {
+ return false;
+
+ }
+ return files[0];
+}
+
+/////////////////////////////////////////////////////
+//
+// users
+//
+export const updateUser = async (discorse: Discourser, oa_user: IImportUser) => {
+
+ const users = getUsers()
+
+ const index = users.findIndex((u) => u.detail.name == oa_user.detail.name)
+
+ const user_name = replaceAll('--', '-', get_user_name(oa_user).replace(/^\-+/g, '').replace(/\-$/, ''))
+
+ let ret: any = null;
+
+ try {
+
+ ret = await discorse.updateUser(user_name, {
+ name: oa_user.data.title
+ })
+
+
+ try {
+
+ let location
+ if (oa_user.geo) {
+ location = `${oa_user.geo.continent} / ${oa_user.geo.countryName} / ${oa_user.geo.city} `
+ }
+
+
+ let website
+ if (oa_user.data) {
+ website = oa_user.data.urls.find((l) => l.name == 'Website')
+ if (website) {
+ website = website.url
+ }
+ }
+
+
+ let description
+ if (oa_user.data) {
+ if (oa_user.data.description) {
+ description += oa_user.data.description
+ }
+
+ description += '\n'
+
+ if (oa_user.data.services) {
+ let services = `### Services \n`;
+ let hasServices = false;
+ for (let s in oa_user.data.services[0]) {
+ if (oa_user.data.services[0][s]) {
+ services += `- [x] ${capitalize(s)}\n`
+ hasServices = true;
+ }
+ }
+ if (hasServices) {
+ description += services
+ }
+ }
+ }
+
+ let links = ''
+ if (oa_user.data.urls) {
+ links = oa_user.data.urls.filter(
+
+ (r) => r.name !== 'Bazar' && r.name !== 'sponsor the work'
+
+ ).map((l) => {
+ let label = '' + l.name;
+
+ if (label === 'Social media') {
+ if (l.url.indexOf('facebook') !== -1) {
+ label = 'Facebook';
+ }
+ if (l.url.indexOf('instagram') !== -1) {
+ label = 'Instagram';
+ }
+ }
+
+ label += " - " + l.url;
+ label = label.replace("https://", "");
+ label = label.replace("http://", "");
+ label = label.replace("mailto:", "");
+
+ return `${label} `
+ }).join(" \n")
+
+ description += '\n### Links\n'
+ description += links
+ }
+
+ if (oa_user.location) {
+ description += `\n\n Get Directions \n`
+ }
+
+
+ let updatePrefs = await discorse.updateUserProfile(user_name, {
+ bio_raw: replaceAll('undefined', '', description),
+ location,
+ website
+ })
+
+
+ } catch (error) {
+ logger.error(`Error updating user prefs : ${user_name}`)
+ }
+
+ } catch (error) {
+ logger.error('error updating user', oa_user._id, error.message)
+ return
+ }
+
+
+ if (ret.status === 200) {
+ users[index].didUpdateName = true
+ logger.debug('did update user', oa_user._id, ' # ', oa_user.data.title)
+ write(getUsersPath(), users)
+ } else {
+ logger.error('did update user failed ', oa_user._id)
+ }
+}
+export const importUser = async (discorse: Discourser, oa_user: IImportUser) => {
+
+ const users = getUsers()
+
+ const index = users.findIndex((u) => u._id == oa_user._id)
+
+ let user = null
+
+ try {
+ user = await createUser(discorse, oa_user)
+ } catch (error) {
+ debugger
+ logger.error('error creating user', error)
+ return false
+ }
+
+ if (user === -100) {
+ users[index].alreadyExists = true
+ write(getUsersPath(), users)
+ return
+ }
+
+ if (user === -120) {
+ users[index].invalidData = true
+ write(getUsersPath(), users)
+ return
+ }
+
+
+ if (user && users[index].upload_id && !users[index]._didSetAvatar) {
+ try {
+ await discorse.setUserAvatar(get_user_name(oa_user), users[index].upload_id)
+ } catch (e) {
+ logger.error('error setting avatar', get_user_name(oa_user))
+ }
+ }
+
+ const _t = users[index];
+
+ if (user > 0) {
+ users[index].f_id = user
+ users[index]._didSetAvatar = true
+ users[index]._didSetGroup = true
+ logger.debug('\t created ' + oa_user.data.title)
+ write(getUsersPath(), users)
+ } else {
+ logger.error('cant create user - error', oa_user.detail.name, user)
+ }
+ return users[index]
+}
+
+export const mergeLatestUsers = (discorse, options: IOptions, oa_users: I_OSR_USER[]): IImportUser[] => {
+ const users: any[] = getUsers()
+ oa_users.forEach((u) => {
+ const tUser = users.find((tu) => {
+ return tu._id === u._id
+ })
+ if (!tUser) {
+ users.push(u)
+ }
+
+ })
+ logger.debug(`Merged users to ${getUsersPath()}`)
+ write(getUsersPath(), users)
+ return users
+}
+
+export const mergeLatestUsersTest = (discorse, options: IOptions, oa_users: I_OSR_USER[]): IImportUser[] => {
+ const users: any[] = (read(LATEST_TEST, 'json') as [] || [])
+ oa_users.forEach((u) => {
+ const tUser = users.find((u) => {
+ return u._id === u._id
+ })
+ if (!tUser) {
+ users.push(u)
+ }
+ })
+ write(options.track, users)
+ return users
+}
+
+export const importUsers = async (discorse, options: IOptions, oa_users: I_OSR_USER[]) => {
+
+ logger.debug('read users from ', path.resolve(getUsersPath()))
+
+ let users = mergeLatestUsers(discorse, options, oa_users)
+ //const users = mergeLatestUsersTest(discorse, options, oa_users)
+
+ users = users.filter((u) => {
+ if (u.f_id || u.f_id < 0) {
+ return false;
+ }
+ if (u.detail.name === 'plastichub' || u.detail.name === 'lu' || u.detail.name === 'timberstar' || u.detail.name === 'nickname') {
+ return false
+ }
+ if (u.alreadyExists || u.invalidData) {
+ return false;
+ }
+ return true
+ })
+
+ logger.debug('Create Users ' + users.length + ' Total | Left: ' + users.length)
+
+ await uploadAvatars(discorse, users)
+
+ return await BPromise.resolve(users).map((u: IImportUser) => {
+ logger.debug('import user ' + get_user_name(u))
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = importUser(discorse, u)
+ if (d) {
+ d.then(resolve)
+ } else {
+ reject()
+ }
+ }, 500)
+
+ })
+
+ } catch (e) {
+ debugger;
+ logger.error('error creating user ' + u._id, e)
+ }
+ }, { concurrency: 1 })
+
+}
+
+export const updateUsers = async (discorse, options: IOptions, oa_users: I_OSR_USER[]) => {
+ // https://forum.osr-plastic.org/u/easymoulds/preferences/profile
+ const users = mergeLatestUsers(discorse, options, oa_users)
+ //const users = mergeLatestUsersTest(discorse, options, oa_users)
+
+ let toBeCreated = users.filter((u) => {
+ if (u.f_id || u.f_id < 0) {
+ return true;
+ }
+ if (u.didUpdateName) {
+ return false
+ }
+ return true
+ })
+
+ const testUser = 'easymoulds'
+
+ const test = toBeCreated.find((u) => {
+ return u._id === testUser
+ })
+
+ // toBeCreated = [test]
+
+ return await BPromise.resolve(toBeCreated).map((u: IImportUser) => {
+ /*
+ if (u.didUpdateName) {
+ return false
+ }
+ */
+
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = updateUser(discorse, u)
+ if (d) {
+ d.then(resolve)
+ } else {
+ reject()
+ }
+ }, 200)
+
+ })
+
+ } catch (e) {
+ debugger;
+ logger.error('error creating user ' + u._id, e)
+ }
+ }, { concurrency: 1 })
+}
+
+export const md_edit_wrap = (content, f, prefix = '', context = '') => {
+ return html_beautify(`${content}
`);
+}
+export const toHTML = (path, markdown) => {
+ const content = read(path, 'string') as string;
+ if (!markdown) {
+ let converter = new Converter({ tables: true });
+ converter.setOption('literalMidWordUnderscores', 'true');
+ return converter.makeHtml(content);
+ } else {
+ return content;
+ }
+}
+export const imageName = (url) => {
+ if (!url) {
+ return ""
+ }
+ try {
+ const parsed = URI.parse(decodeURIComponent(url));
+ const pParsed = path.parse(parsed.path);
+ return sanitize(decodeURIComponent(pParsed.base));
+ } catch (error) {
+ logger.error('error image name : ', url)
+ return ""
+ }
+}
+export const read_fragments = (src, config, prefix = '', context = '') => {
+
+ if (!exists(src)) {
+ //debug.warn(`Create template folder ${src}`);
+ mkdir(src);
+ }
+ let fragments = files(src, '*.html');
+ fragments.map((f) => {
+ config[path.parse(f).name] = md_edit_wrap(toHTML(f, true), f, prefix, context);
+ });
+
+ fragments = files(src, '*.md');
+ fragments.map((f) => {
+ config[path.parse(f).name] = md_edit_wrap(toHTML(f, false), f, prefix, context);
+ });
+ return config;
+}
+
+export const indexUsers = async (discorse, options: IOptions, oa_users: I_OSR_USER[]) => {
+
+ let users = mergeLatestUsers(discorse, options, oa_users)
+
+ users = users.filter((u) => {
+ if (u.f_id && u.data && u.geo) {
+ return true;
+ }
+ return false
+ })
+
+ const continents = []
+ const countries = []
+ const navIndex: any[] = []
+
+ users.forEach((u) => {
+ if (!u.geo || !u.data || u.data.jsError || !u.detail || !u.detail.heroImageUrl) {
+ return;
+ }
+ if (!u.detail.heroImageUrl) {
+ return;
+ }
+ let code = null;
+
+ if (u.geo.continent && continents.indexOf(u.geo.continent) == -1) {
+ continents.push(u.geo.continent);
+ navIndex.push({
+ title: u.geo.continent,
+ url: `/users/${slugify(u.geo.continent)}.html`,
+ children: [],
+ code: u.geo.continentCode
+ // code:u.geo.continentCode
+ })
+ }
+
+ if (countries.indexOf(u.geo.countryName) == -1) {
+ countries.push(u.geo.countryName);
+ }
+ const c = navIndex.find((c) => c.title === u.geo.continent);
+ if (c) {
+ const cc = c.children.find((i) => i.title == u.geo.countryName);
+ if (!cc) {
+ c.children.push({
+ title: u.geo.countryName,
+ url: `/users/${slugify(c.title)}.html#${slugify((u.geo.countryName as string).toLocaleLowerCase())}`,
+ postTitle: `Directory - ${u.geo.countryName}`
+ })
+ }
+ }
+ });
+
+ navIndex.sort((a, b) => {
+ if (a.title < b.title) { return -1; }
+ if (a.title > b.title) { return 1; }
+ return 0;
+ });
+
+ navIndex.forEach((c) => {
+ c.children.sort((a, b) => {
+ if (a.title < b.title) { return -1; }
+ if (a.title > b.title) { return 1; }
+ return 0;
+ });
+ });
+
+ const directoryRoot = path.resolve(resolve('${OSR_ROOT}/osr-directory/pp'))
+
+ const createContinentPage = (continent) => {
+
+ const templates_path = path.resolve(`${directoryRoot}/templates`);
+ if (!exists(templates_path)) {
+ logger.error(`\t Cant find templates at ${templates_path}, path doesn't exists`);
+ return;
+ }
+ const cPath = path.resolve(`${directoryRoot}/templates/config.json`)
+ const config = read(cPath, 'json') as IOSRConfig
+ let fragments: any = { ...config }
+
+ read_fragments(templates_path, fragments, "product_rel_path_name", "machine");
+
+ let templateCountry = read(path.resolve(`${templates_path}/country_users.md`), 'string');
+ const ccountries = {};
+
+ let code = null;
+
+
+ users.forEach((u) => {
+
+ if (!u.geo || !u.data || u.data.jsError || !u.detail || !u.detail.heroImageUrl) {
+ return;
+ }
+ if (!u.detail.heroImageUrl) {
+ return;
+ }
+ if (u.geo.continent && u.geo.continent === continent) {
+ if (!code) {
+ code = u.geo.continentCode;
+ }
+ if (!ccountries[u.geo.countryName]) {
+ ccountries[u.geo.countryName] = [];
+ }
+
+ ccountries[u.geo.countryName].push(u);
+ }
+ });
+
+ if (continent === 'Africa') {
+ //debugger;
+ }
+
+ let weight = 100;
+ for (var country in ccountries) {
+
+ let cPage = "";
+
+ if (country === 'Kenya') {
+ //debugger;
+ }
+
+ cPage += `\n#### ${slugify(country)}\n\n`;
+ if (country === 'undefined' || country === 'unknown' || !country) {
+ return;
+ }
+ cPage += '';
+ cPage += '
';
+
+ let cusers = ccountries[country];
+ cusers = cusers.sort((a, b) => a.type === b.type ? 1 : -1);
+ const cUsersC = cusers.map((u) => {
+ const prefix = u.moderation === 'rejected' ? "
Censored " : "";
+ const image = `/users/${u._id}/${encodeURIComponent(sanitize(imageName(u.detail.heroImageUrl)))}`;
+ const title = u.data && u.data.title ? u.data.title : u._id;
+ const uUrl = `/directory/users/${u._id}`;
+ let censored = u.moderation === 'rejected' ? '
Yes ' : 'No'
+ return `
+
+
+
+
${title}
+
Type: ${u.type}
+
Censored: ${censored}
+
+
${u.geo.principalSubdivision} / ${u.geo.locality} - ${u.geo.principalSubdivisionCode} - ${u.geo.postcode}
+
+
`;
+ })
+ cPage += cUsersC.join('');
+ cPage += '
';
+
+ country = country.replace(' (the)', '');
+
+ /*
+ const cPagePath = path.resolve(`${kb}/src/directory/users_${sanitize(slugify(country))}-${code}.md`)
+
+ const title = 'Users - ' + country;
+
+ cPage = substitute(templateCountry, {
+ ...fragments,
+ title: title,
+ keywords: 'Precious Plastic, Precious Plastic Users - ' + country,
+ content: html_beautify(cPage),
+ continent: slugify(continent),
+ country: slugify(country),
+ identifier: country + "-" + continent,
+ weight: weight
+ });
+
+ weight++;
+ write(cPagePath, cPage);
+ console.log('write ' + cPagePath);
+ */
+ }
+
+
+ /*
+ content = substitute(template, {
+ ...fragments,
+ title: 'Precious Plastic - Users ' + continent,
+ keywords: 'Precious Plastic, Precious Plastic Users - ' + continent,
+ content: content,
+ continent: slugify(continent)
+ });
+ */
+
+ //const index_md = path.resolve(`${root}/_pages/users_${code}.md`);
+ //write(index_md, content);
+ }
+
+ const templates_path = path.resolve(`${directoryRoot}/templates`);
+
+ const createCountryPages = async (index: any[], indexPath: string) => {
+ let i = 0;
+ for await (const continent of index) {
+ const countries = continent.children
+ for await (const country of countries as any) {
+ const d=0
+ }
+
+ }
+ }
+
+ await createCountryPages(navIndex,'./')
+
+ const createIntroPage = async (users, index: any[], dst: string) => {
+
+ let template = read(path.resolve(`${templates_path}/intro_users.md`))
+
+ let content = ""
+
+ const usersPerCountry = (country: string) => {
+ return users.filter((u) => u.geo.countryName === country)
+ }
+
+ index.forEach((i) => {
+ const heading = `## ${i.title}`
+ let countries = ''
+ i.children.forEach((c) => {
+ let title = c.title.replace(/ *\([^)]*\) */g, "")
+ const nb = usersPerCountry(c.title).length
+ title = `${title} \(${nb}\)`
+ const cPagePath = `/directory/users_${sanitize(slugify(c.title))}-${i.code}`
+ countries += `- [${(title)}](${cPagePath.toLowerCase()})\n`
+ })
+ content += `${heading}\n ${countries}`
+ })
+
+ write(dst, substitute(template, {
+ content: content,
+ /*hidden: data.v3_mappins.filter((u) => u.moderation !== "accepted").length,
+ total: data.v3_mappins.length*/
+ }))
+
+ let data: any
+ try {
+ data = await discorse.updatePost(OA_DIRECTORY_OVERVIEW_TOPIC, content)
+ debugger
+ //logger.debug('update post : ' + options.title + ' : ' + data.id + ' | topic id ' + data.topic_id)
+ } catch (e) {
+ return false
+ }
+
+ }
+
+ // await createIntroPage(users, navIndex, './index.md')
+
+
+ /*
+
+ return await BPromise.resolve(users).map((u: IImportUser) => {
+ try {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ const d = updateUser(discorse, u)
+ if (d) {
+ d.then(resolve)
+ } else {
+ reject()
+ }
+ }, 200)
+
+ })
+
+ } catch (e) {
+ debugger;
+ logger.error('error creating user ' + u._id, e)
+ }
+ }, { concurrency: 1 })
+
+ */
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/oa/utils.ts b/packages/discourse/src/lib/oa/utils.ts
new file mode 100644
index 00000000..113ac6b0
--- /dev/null
+++ b/packages/discourse/src/lib/oa/utils.ts
@@ -0,0 +1,180 @@
+import fs from 'fs'
+import { inspect as utilInspect } from 'util'
+import { resolve, dirname } from 'path'
+const cwd = process.cwd()
+var TurndownService = require('turndown')
+import { Discourser } from '../index'
+
+
+import * as path from 'path'
+const fg = require('fast-glob')
+import slugify from "slugify"
+
+var sanitize = require("sanitize-filename")
+
+import { sync as read } from '@plastichub/fs/read'
+import { sync as write } from '@plastichub/fs/write'
+
+//import { replaceAll } from '../../lib';
+
+
+var mom = require('moment')
+
+export const uploadFile = async (discourse, forum, name, filePath) => {
+ return await discourse.upload(1, filePath);
+}
+
+export const findReplyPage = (b, pages) => {
+ return pages.find((p) => {
+ return p.replies.find((r) => {
+ return r.replyBody == b;
+ })
+ })
+}
+
+export const findReplyUpload = (u, page) => {
+ const f_pics = page.f_pics || [];
+ return f_pics.find((p) => {
+ return p.url === u;
+ })
+}
+
+export const getPages = (topics, topic) => {
+ return topics.filter((t) => {
+ return t.title == topic.title;
+ });
+};
+
+export const getReplies = (topics, topic) => {
+ if (topic.nextPages) {
+ const all = topics.filter((t) => {
+ return t.title == topic.title;
+ });
+ let replies: [] = all.map((t) => t.replies);
+ replies = [].concat.apply([], replies);
+ replies = replies.sort((a: any, b: any) => {
+ const d1 = mom(a.replyDate,'DD/MM/YYYY AT HH:mm').toDate()
+ const d2 = mom(b.replyDate,'DD/MM/YYYY AT HH:mm').toDate()
+ return new Date(d1).getTime() > new Date(d2).getTime() ? 1 : -1;
+ });
+
+ return replies;
+ /*
+ const findReply = (b, pages) => {
+ return pages.find((p) => {
+ return p.replies.find((r) => {
+ return r.replyBody == b;
+ })
+ })
+ }
+ const p = findReply('\n\n\nsounds great, let me get Old Tony´s Schaeubling 13 and a surface grinder first, after that I can do the parts for the espresso machine in the best maker porn fashion possible, no seriously, every time I thought I know something, there’s just another video around the next corner making me cry like a baby, incl. the coffee machine
\n', all);
+ debugger;
+ */
+ }
+ return [];
+}
+
+export const findFile = (folder, filename) => {
+ const files = fg.sync('**/**/*' + filename + '*', { dot: true, cwd: folder, absolute: true });
+ if (files.length == 0) {
+ return false;
+
+ }
+ return files[0];
+}
+
+export const topicFolder = (forum, folder, title) => {
+ const _title = sanitize(slugify(title));
+ const tf = path.resolve(forum + '/' + folder + '/' + _title);
+ return tf;
+}
+
+export const getFUser = (users, user_name) => {
+ return users.find((u) => {
+ return u.name == user_name
+ })
+}
+
+export const dOptions = {
+ host: 'https://forum.osr-plastic.org',
+ key: 'f624b8385fb2219cb49de63d1e22883afdf7b7367a0bebf822523f49f2678031',
+ username: 'admin',
+ rateLimitConcurrency: 1
+}
+
+export const getOAvatar = (index, user) => {
+ const topics = getTopics(index);
+ let topic: any = topics.find((t:any) => {
+ return t.authorName == user;
+ });
+ if (topic) {
+ return topic.authorImage;
+ }
+ for (let i = 0; i < topics.length; i++) {
+ const t: any = topics[i]
+ if (t.replies) {
+ const r = (t.replies as any[]).find((r) => {
+ return r.user == user;
+ })
+ if (r) {
+ return r.avatar;
+ }
+ }
+ }
+ return null;
+}
+
+export const getTopics = (index:any) => {
+ let topics = [];
+ for (let t in index) {
+ topics.push(index[t]);
+ }
+ return topics;
+}
+
+export const convert = (input: string) => {
+ var turndownService = new TurndownService()
+ return turndownService.turndown(input);
+}
+
+export const getDiscourse = () => {
+ return new Discourser(dOptions);
+}
+
+export function inspect(arg: any) {
+ return utilInspect(arg, {
+ depth: 5,
+ colors: true,
+ })
+}
+
+export function log(...args: any[]) {
+ console.log(...args.map((arg) => inspect(arg)))
+}
+
+export async function mkdirp(path: string) {
+ try {
+ await fs.promises.mkdir(path)
+ } catch (err) {
+ // don't care if it already exists
+ }
+}
+
+export async function readJSON(path: string): Promise {
+ const text = await fs.promises.readFile(path, 'utf8')
+ return JSON.parse(text)
+}
+
+export function writeJSON(path: string, data: object) {
+ return fs.promises.writeFile(path, JSON.stringify(data))
+}
+
+export function exists(path: string): Promise {
+ return new Promise(function (resolve) {
+ fs.exists(path, resolve)
+ })
+}
+
+export function escape(path: string): string {
+ return path.replace(/[^\w]/g, '-').replace(/-+/, '-')
+}
diff --git a/packages/discourse/src/lib/osr/index.ts b/packages/discourse/src/lib/osr/index.ts
new file mode 100644
index 00000000..4036bcd4
--- /dev/null
+++ b/packages/discourse/src/lib/osr/index.ts
@@ -0,0 +1 @@
+export * from './urls'
diff --git a/packages/discourse/src/lib/osr/urls.ts b/packages/discourse/src/lib/osr/urls.ts
new file mode 100644
index 00000000..5bccb065
--- /dev/null
+++ b/packages/discourse/src/lib/osr/urls.ts
@@ -0,0 +1,2 @@
+export const marketplaceUrl = (store, product_id) =>
+ `${store}/dispatch=products.view&product_id=${product_id}`
\ No newline at end of file
diff --git a/packages/discourse/src/lib/sync/commons.ts b/packages/discourse/src/lib/sync/commons.ts
new file mode 100644
index 00000000..68c541d4
--- /dev/null
+++ b/packages/discourse/src/lib/sync/commons.ts
@@ -0,0 +1,204 @@
+import * as path from 'path'
+import { IOptions } from '@plastichub/osrl/types'
+import { Engine as engine } from '@plastichub/osrl/Engine'
+import { parse } from '@plastichub/osrl/options'
+
+import { pathInfo } from '@plastichub/osr-cli-commons/glob'
+import { resolve } from '@plastichub/osr-commons'
+import { IOptionsSync, IOptionsSyncComponent, logger } from '../../'
+import { sync as exists } from '@plastichub/fs/exists'
+import { sync as read } from '@plastichub/fs/read'
+import { sync as write } from '@plastichub/fs/write'
+
+import { Promise as BPromise } from 'bluebird'
+
+import {
+ MODULE_NAME
+} from '../../constants'
+
+const chokidar = require("chokidar")
+const cheerio = require('cheerio')
+const frontMatter = require('front-matter')
+
+
+export const fileAsBuffer = (path: string) => read(path, 'buffer') as Buffer || Buffer.from("-")
+
+import { get_cached, set_cached } from '@plastichub/osr-cache/lib'
+import { OSR_CACHE } from '@plastichub/osr-cli-commons'
+
+import * as md5 from 'md5'
+
+import { RMark, toHTML } from '../markdown'
+export const images_urls = (content: string) => {
+
+ const html = toHTML(content)
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+
+ const images = []
+ const links = []
+ $('img').each(function () {
+ images.push($(this).attr('src'))
+ })
+
+ return images
+}
+
+export const adjustUrls = (content: string, options: IOptionsSync) => {
+ let ret = new RMark(
+ {
+ images: (match, capture, arg1, arg2) => ``,
+ //links: (match, capture, arg1, arg2) => `[${capture}](${arg1})`
+ }
+ ).render(content)
+ return ret
+}
+export const fromJSON = (content: string, file:string, options: IOptionsSyncComponent) => {
+
+}
+export const fromYAML = (content: string, options: IOptionsSync) => {
+ if (frontMatter.test(content)) {
+ const fm = frontMatter(content)
+ return {
+ attributes: fm.attributes,
+ body: fm.body
+ }
+ } else {
+ return {
+ attributes: {},
+ body: content
+ }
+ }
+}
+
+// to be changed to osr-defaults
+export const option = (option: string, taskOptions: any, col, _default?: any) => {
+
+ // support grunt or yargs
+ const val = col.option ? col.option : (option) => col[option]
+
+ let ret = taskOptions[option] !== undefined ? taskOptions[option] : _default;
+ if (val(option) !== undefined) {
+ ret = val(option)
+ }
+ return ret
+}
+
+export const createContent = async (file, _options) => {
+ const parts = path.parse(file);
+ const rel = path.relative(_options.root, file);
+
+ let output = _options.output;
+ let outputInfo = pathInfo(_options.output)
+ const variables = {
+ root: '.',
+ cwd: _options.cwd || path.resolve('.'),
+ ..._options.variables
+ }
+
+ if (!outputInfo.FILE_EXT) {
+ output = path.resolve(`${_options.output}/${path.parse(rel).dir}/${parts.name}.md`)
+ } else {
+ output = path.resolve(resolve(output, false, variables));
+ }
+
+ const defaults: any = {
+ language: _options.lang,
+ debug: _options.debug,
+ profile: _options.profile,
+ output: output,
+ plugins: _options.plugins,
+ env: _options.env || 'library',
+ cwd: _options.cwd || path.resolve('.'),
+ source: file,
+ variables
+ }
+
+
+ const options = parse(defaults, defaults);
+ const eOptions = {
+ ...options,
+ root: [
+ ...options.profile.includes,
+ path.parse(file).dir
+ ],
+ toHTML: false,
+ cache: false,
+ keepOutputType: true,
+ trimTagRight: false,
+ trimTagLeft: false,
+ trimOutputRight: false,
+ trimOutputLeft: false,
+ greedy: false
+ } as IOptions
+
+ const Engine = new engine(eOptions)
+
+ options.source = path.resolve(options.source)
+
+ const osr_cache = OSR_CACHE()
+ const cached = await get_cached(options.source, eOptions, _options.module || MODULE_NAME)
+
+ if (osr_cache && cached && _options.cache !== false) {
+ options.debug && logger.info('Compile file serving from cache: ' + options.source)
+
+ let md5Src = md5(Buffer.from(cached));
+ let md5Dst = md5(fileAsBuffer(options.output));
+ if (!exists(options.output) || md5Src !== md5Dst) {
+ write(options.output, cached);
+ }
+ return cached
+ }
+
+ options.debug && logger.info('Compile file ' + file, eOptions)
+
+ let content = await Engine.render(options.source, options.variables)
+
+ if (_options.onCompiled) {
+ content = await _options.onCompiled(options.source, output, content)
+ }
+
+ if (osr_cache && _options.cache !== false) {
+ options.debug && logger.info('Write output to cache', output)
+ await set_cached(options.source, eOptions, _options.module || MODULE_NAME, content)
+ }
+
+ let dst = path.resolve(resolve(output, false, options.variables))
+ _options.debug && logger.info('Write output to: ', dst)
+ write(dst, content)
+
+ if (_options.onCompileDone) {
+ await _options.onCompileDone(options.source, dst, options, content)
+ }
+
+ return content
+}
+
+const watch = async (src, options) => {
+ src = path.resolve(src);
+ const watcher = chokidar.watch(`${src}`, {
+ ignored: /(^|[\/\\])\../,
+ persistent: true
+ });
+ watcher.on('change', async path => {
+ await createContent(path, options)
+ });
+ return watcher
+}
+
+const compileAll = async (files, options) => {
+ return await BPromise.resolve(files).map((f) => {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ createContent(f, options).then(() => resolve(true))
+ }, 50)
+ });
+ }, { concurrency: 1 });
+}
+
+const compileAllEx = async (files, options) => {
+ return await BPromise.resolve(files).map((f) => {
+ return createContent(f, options)
+ }, { concurrency: 1 });
+}
diff --git a/packages/discourse/src/lib/sync/component.ts b/packages/discourse/src/lib/sync/component.ts
new file mode 100644
index 00000000..07236dd5
--- /dev/null
+++ b/packages/discourse/src/lib/sync/component.ts
@@ -0,0 +1,454 @@
+import * as path from 'path'
+import { sync as exists } from "@plastichub/fs/exists"
+import { async as move } from "@plastichub/fs/move"
+import { sync as dir } from "@plastichub/fs/dir"
+import { sync as write } from "@plastichub/fs/write"
+import { sync as read } from "@plastichub/fs/read"
+
+import { resolve } from "@plastichub/osr-commons"
+
+import { Promise as BPromise } from 'bluebird'
+import { IOptionsSync, IDiscoursePostBaseOptions } from '../../types'
+
+import { createContent } from './osrl'
+
+const YAML = require('json-to-pretty-yaml')
+const cheerio = require('cheerio')
+const findUp = require('find-up')
+const frontMatter = require('front-matter')
+const md5 = require('md5')
+
+import { imageName, downloadFile } from './download'
+
+import { toHTML } from '../markdown'
+import { isNumber } from '@plastichub/core/primitives'
+
+import { defaultConfig, fromJSON, tracking, trackingPath } from './'
+
+import {
+ SYNC_TRACK_FILENAME,
+ EDiscourseConfigKey
+} from '../discourse/constants'
+
+import {
+ cacheCategories,
+ cacheTags,
+ cacheTopics,
+ cacheUsers
+} from '../discourse/cache'
+
+
+import {
+ Discourser,
+ Instance
+} from '../discourse'
+
+import {
+ images_urls
+} from './commons'
+
+
+import { ISearchPost, ISearchTopic } from "../.."
+
+import * as md5 from 'md5'
+
+import { IComponentConfig } from '@plastichub/osr-commons'
+import { marketplaceUrl } from '../osr'
+
+import { isValidLibraryComponent, readOSRConfig } from '@plastichub/osr-fs-utils'
+
+import { logger } from '../../index'
+import { forward_slash } from '@plastichub/osr-cli-commons'
+
+const CONTENT_TEST = false
+const SKIP_EXISTING = false
+
+export const createPost = async (discourse: Discourser, options: IOptionsSync, content) => {
+
+ if (!isNumber(options.cat)) {
+ logger.error(`category not a number! ${options.title} `)
+ }
+
+ let data: any
+ try {
+ data = await discourse.createPost(options.title, content, options.cat as number)
+ } catch (e) {
+ debugger
+ }
+
+ if (data) {
+ if (data && data.id) {
+ try {
+ options.post_id = data.id;
+ options.topic_id = data.topic_id
+ await discourse.changeOwner(options.post_id, options.topic_id, options.user_name)
+ logger.debug('created topic : ' + options.title + ' : ' + data.id + ' | topic id :' + data.topic_id)
+ return true
+ } catch (e) {
+ logger.error('changing owner ' + options.title + ' failed!', e)
+ }
+ } else {
+ logger.debug('creating ' + options.title + ' failed!', data.errors, data);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + options.title)
+ }
+ }
+ }
+ } else {
+ return false
+ }
+}
+
+export const updatePost = async (discourse: Discourser, options: IOptionsSync, topic_id, content) => {
+
+ let data: any
+ try {
+ data = await discourse.updatePost(topic_id, content)
+ logger.debug('update post : ' + options.title + ' : ' + data.id + ' | topic id ' + data.topic_id)
+ } catch (e) {
+ return false
+ }
+
+ if (data) {
+ if (data && data.id) {
+ try {
+ // logger.debug('change user to ', options.owner);
+ options.post_id = data.id;
+ options.topic_id = data.topic_id
+ await new Promise(f => setTimeout(f, 1000));
+ await discourse.changeOwner(topic_id, topic_id, options.user_name)
+ return true
+ } catch (e) {
+ logger.debug('changing owner ' + options.title + ' failed!')
+ return false
+ }
+ } else {
+ logger.debug('creating ' + options.title + ' failed!', data.errors)
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + options.title)
+ }
+ return false
+ }
+ }
+ }
+}
+
+
+
+const uploadImages = async (content: string, discourse: Discourser, options: IOptionsSync) => {
+
+ const root = path.resolve(resolve(options.root))
+ if (!exists(root)) {
+ return false
+ }
+
+ const track_path = trackingPath(root)
+ const track = tracking(root)
+
+ const html = toHTML(content)
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+
+ const images = images_urls(content)
+
+ $('img').each(function () {
+ if ($(this).attr('src') && $(this).attr('src').length > 5) {
+ images.push($(this).attr('src'))
+ }
+ })
+
+ for await (const image of Object.entries(images)) {
+ const url: string = image[1]
+
+ if (url.length < 10) {
+ continue
+ }
+
+ if (url.startsWith('upload:')) {
+ continue
+ }
+ if (options.uploadRemote && url.startsWith('http')) {
+
+ const contentHash = md5(content).substring(0, 5)
+ const cache_path = path.resolve(resolve('${OSR_CACHE}/discourse-downloads/' + contentHash))
+ if (!exists(cache_path)) {
+ dir(cache_path)
+ }
+ const image_name = imageName(url)
+ const image_local = path.join(cache_path, image_name)
+ if (!exists(image_local)) {
+ try {
+ await downloadFile(url, cache_path)
+ } catch (e) {
+ continue
+ }
+ }
+ if (!exists(image_local)) {
+ continue
+ }
+
+ if (!track[url]) {
+ const upped: any = await discourse.uploadFile(options.owner, image_local)
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data
+ write(track_path, track)
+ } else {
+ console.error('error uploading image')
+ }
+ }
+
+ continue
+ }
+
+ if (options.uploadLocal) {
+ const image_path = path.join(root, url)
+ if (exists(image_path) && (!track[url] || options.cache === false)) {
+ const upped: any = await discourse.uploadFile(options.owner, image_path)
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data
+ write(track_path, track)
+ } else {
+ console.error('error uploading image')
+ }
+ }
+ }
+ }
+
+ return track
+}
+
+const syncFile = async (file: string, options: IOptionsSync) => {
+
+ const discourse = Instance(null, options.config as EDiscourseConfigKey)
+
+ let config = fromJSON(file, options) || {} as IComponentConfig
+
+ const componentDir = path.parse(file).dir
+
+ // ph3 back sync
+ const rel = forward_slash(path.relative(options.root, componentDir))
+ const productConfigPath = path.join(options.product_root, rel, 'config.json')
+
+ let body = await createContent(componentDir, options)
+
+ let images_track
+
+ if (options.uploadLocal || options.uploadRemote) {
+ images_track = await uploadImages(body, discourse, options)
+ const image_urls = images_urls(body)
+ image_urls.forEach((i) => {
+ if (images_track[i]) {
+ body = body.replace(i, images_track[i].short_url)
+ } else {
+ logger.warn(`Cant resolve image url : ${i} - ${componentDir} ! Image Upload track invalid`)
+ }
+ })
+ }
+
+
+
+ logger.debug(`Processing ${componentDir}`);
+
+ const output = path.join(componentDir, '.osr/discourse_raw.md')
+ let dst = path.resolve(resolve(output))
+ options.debug && logger.info('Write output to: ', dst)
+ write(dst, body)
+
+ let post_id, topic_id
+
+ let dOpts: IDiscoursePostBaseOptions = {
+ ...options,
+ cat: config.forumCategory,
+ id: options.id,
+ owner: config.forumUserId || 1,
+ tags: config.forumTags as string,
+ title: config.name,
+ topic_id: config.forumTopicId,
+ post_id: config.forumPostId
+ }
+
+ options = {
+ ...options,
+ ...dOpts
+ }
+
+ const hash = md5(JSON.stringify({
+ cat: dOpts.cat,
+ tags: dOpts.tags,
+ owner: dOpts.owner,
+ body,
+ title: dOpts.title
+ }, null))
+
+
+
+
+ // const cats = await cacheCategories(options, discourse)
+ // const tags = await cacheTags(options, discourse)
+
+ const users = await cacheUsers(options, discourse)
+ await new Promise(f => setTimeout(f, 1000));
+ let search = await discourse.search(dOpts.title)
+ await new Promise(f => setTimeout(f, 2000));
+
+ let dTopic: ISearchTopic
+ let dPost: ISearchPost
+
+ if (search && search.posts && search.topics) {
+ search.topics.forEach((t, i) => {
+ if (t.title === dOpts.title) {
+ dTopic = t
+ dPost = search.posts[i]
+ topic_id = dTopic.id
+ post_id = dPost.id
+ }
+ })
+ }
+
+ if (!dTopic || !dPost) {
+ console.error('!dTopic || !dPost : cant find ' + dOpts.title)
+ // return
+ }
+
+ const user = users.find((u) => {
+ return u.id === dOpts.owner
+ })
+
+ if (!user) {
+ logger.error('Invalid user : ', dOpts.owner)
+ return false
+ }
+
+ options.user_name = user.username
+
+ if (SKIP_EXISTING && hash === config.forumPostHash &&
+ config.forumTopicId && config.forumPostId) {
+ return
+ }
+
+ if (CONTENT_TEST) {
+ return
+ }
+
+ if (post_id) {
+ if (await updatePost(discourse, options, post_id, body)) {
+ if (topic_id) {
+ await new Promise(f => setTimeout(f, 2000));
+ await discourse.updateTopic(topic_id, dOpts.cat as number, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : [])
+ }
+ } else {
+ logger.error(`Error updating post ${dOpts.title}`)
+ }
+ } else {
+ if (await createPost(discourse, options, body)) {
+ await new Promise(f => setTimeout(f, 1000));
+ await discourse.updateTopic(options.topic_id, dOpts.cat as number, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : [])
+ } else {
+ logger.error('Creating post failed !', dOpts.title)
+ }
+ }
+
+ // const visStatus = await discourse.updateTopicVisibility(topic_id, true)
+
+ // re-read without defaults
+ config = readOSRConfig(file)
+
+ config.forumPostHash = hash
+
+ if (dTopic) {
+ config.forumTopicId = dTopic.id
+ }else if(topic_id){
+ config.forumTopicId = topic_id
+ }
+
+ if (dPost) {
+ config.forumPostId = dPost.id
+ }else if(post_id){
+ config.forumPostId = post_id
+ }
+
+ write(file, config)
+
+ //ph3 products
+ if (exists(productConfigPath)) {
+ let pConfig = readOSRConfig(productConfigPath)
+ logger.debug(`Updating product config ${productConfigPath}`)
+ pConfig = {
+ ...config
+ //...pConfig,
+ //...
+ /*
+ forumTopicId:config.forumTopicId,
+ forumPostId:config.forumPostId,
+ forumPostHash: config.forumPostHash
+ */
+ }
+ write(productConfigPath, pConfig)
+ }
+ return body
+}
+
+export const syncComponent = async (options: IOptionsSync) => {
+
+ let components = options.srcInfo.FILES.filter(isValidLibraryComponent)
+ //let components = options.srcInfo.FILES.filter((c) => {
+ //components = components.filter((c) => {
+ /*
+try {
+ const config = readOSRConfig(c) as IComponentConfig
+ if (config) {
+ if (config.forum === false) {
+ return false
+ }
+ // return !config.code && !config.cscartId && !config.steps
+ return !!config.name
+ }
+ return false
+} catch (error) {
+ logger.error(`Invalid config : ${c}`)
+}
+})*/
+
+ const skipExisting = options.skip
+ /*
+ [
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/asterix-pp/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/asterix-sm-morren/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/bicycle-shredder/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/idefix/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/obelix/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/pp-v3.3/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/components/shredder_v21-light-ex/config.json",
+ "C:/Users/mc007/Desktop/osr/osr-machines/shredder/components/shredder_v31-light/config.json",
+ ]
+ */
+ if (skipExisting) {
+ components = components.filter((f) => {
+ const config = readOSRConfig(f) as IComponentConfig
+ if (config.forumPostId && config.forumTopicId) {
+ return false
+ }
+ return true
+ })
+ }
+
+ //components = [components[0]]
+ logger.info(`Syncing ${components.length} components`, components)
+ await BPromise.resolve(components).map((f) => {
+ try {
+ return syncFile(f, options)
+ } catch (error) {
+ debugger
+ }
+ }, { concurrency: 1 })
+
+}
+
+export const sync = async (options: IOptionsSync) => {
+ return syncComponent(options)
+}
diff --git a/packages/discourse/src/lib/sync/directory.ts b/packages/discourse/src/lib/sync/directory.ts
new file mode 100644
index 00000000..e33194de
--- /dev/null
+++ b/packages/discourse/src/lib/sync/directory.ts
@@ -0,0 +1,400 @@
+import * as path from 'path'
+import { sync as exists } from "@plastichub/fs/exists"
+import { async as move } from "@plastichub/fs/move"
+import { sync as dir } from "@plastichub/fs/dir"
+import { sync as write } from "@plastichub/fs/write"
+import { sync as read } from "@plastichub/fs/read"
+
+import { resolve } from "@plastichub/osr-commons"
+
+import { Promise as BPromise } from 'bluebird'
+import { IOptionsSync, IDiscoursePostBaseOptions } from '../../types'
+
+import { createContent } from './osrl'
+
+const YAML = require('json-to-pretty-yaml')
+const cheerio = require('cheerio')
+const findUp = require('find-up')
+const frontMatter = require('front-matter')
+
+import { imageName, downloadFile } from './download'
+
+import { toHTML } from '../markdown'
+
+import { defaultConfig, fromJSON, tracking, trackingPath } from './'
+
+import {
+
+ SYNC_TRACK_FILENAME,
+ EDiscourseConfigKey
+} from '../discourse/constants'
+
+import {
+ cacheCategories,
+ cacheTags,
+ cacheTopics,
+ cacheUsers
+} from '../discourse/cache'
+
+
+import {
+ Discourser,
+ Instance
+} from '../discourse'
+
+import {
+ images_urls
+} from './commons'
+
+
+import { ISearchPost, ISearchTopic } from "../.."
+
+import * as md5 from 'md5'
+
+import { IComponentConfig } from '@plastichub/osr-commons'
+
+import { isValidLibraryComponent, readOSRConfig } from '@plastichub/osr-fs-utils'
+
+import { logger } from '../../index'
+
+
+const fromYAML = (content: string, options: IOptionsSync) => {
+ if (frontMatter.test(content)) {
+ const fm = frontMatter(content)
+ return {
+ attributes: fm.attributes,
+ body: fm.body
+ }
+ } else {
+ return {
+ attributes: {},
+ body: content
+ }
+ }
+}
+
+
+
+export const createTopic = async (discourse: Discourser, options: IOptionsSync, content) => {
+
+ let data: any
+ try {
+ data = await discourse.createPost(options.title, content, options.cat as number)
+ } catch (e) {
+ debugger
+ }
+
+ if (data) {
+ logger.debug('created topic : ' + options.title + ' : ' + data.id)
+ if (data && data.id) {
+
+ try {
+ options.post_id = data.id;
+ options.topic_id = data.topic_id
+ await discourse.changeOwner(options.post_id, options.topic_id, options.user_name)
+ } catch (e) {
+ logger.error('changing owner ' + options.title + ' failed!', e)
+ }
+ } else {
+ logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + options.title)
+ }
+ }
+ }
+ }
+}
+
+export const updateTopic = async (discourse: Discourser, options: IOptionsSync, topic_id, content) => {
+
+ let data: any
+ try {
+ data = await discourse.updatePost(topic_id, content)
+ } catch (e) {
+ return false
+ }
+
+ if (data) {
+ logger.debug('created topic : ' + options.title + ' : ' + data.id)
+ if (data && data.id) {
+ try {
+ logger.debug('change user to ', options.owner);
+ options.post_id = data.id;
+ options.topic_id = data.topic_id
+ await discourse.changeOwner(topic_id, topic_id, options.user_name)
+ return true
+ } catch (e) {
+ logger.debug('changing owner ' + options.title + ' failed!')
+ return false
+ }
+ } else {
+ logger.debug('creating ' + options.title + ' failed!', data.errors)
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + options.title)
+ }
+ return false
+ }
+ }
+ }
+}
+
+
+
+const uploadImages = async (content: string, discourse: Discourser, options: IOptionsSync) => {
+
+ const root = path.resolve(resolve(options.root))
+ if (!exists(root)) {
+ return false
+ }
+
+ const track_path = trackingPath(root)
+ const track = tracking(root)
+
+ const html = toHTML(content)
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+
+ const images = images_urls(content)
+
+ $('img').each(function () {
+ if ($(this).attr('src') && $(this).attr('src').length > 5) {
+ images.push($(this).attr('src'))
+ }
+ })
+
+ for await (const image of Object.entries(images)) {
+ const url: string = image[1]
+
+ if (url.length < 10) {
+ continue
+ }
+
+ if (url.startsWith('upload:')) {
+ continue
+ }
+ if (options.uploadRemote && url.startsWith('http')) {
+
+ const contentHash = md5(content).substring(0, 5)
+ const cache_path = path.resolve(resolve('${OSR_CACHE}/discourse-downloads/' + contentHash))
+ if (!exists(cache_path)) {
+ dir(cache_path)
+ }
+ const image_name = imageName(url)
+ const image_local = path.join(cache_path, image_name)
+ if (!exists(image_local)) {
+ try {
+ await downloadFile(url, cache_path)
+ } catch (e) {
+ continue
+ }
+ }
+ if (!exists(image_local)) {
+ continue
+ }
+
+ if (!track[url]) {
+ const upped: any = await discourse.uploadFile(options.owner, image_local)
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data
+ write(track_path, track)
+ } else {
+ console.error('error uploading image')
+ }
+ }
+
+ continue
+ }
+
+ if (options.uploadLocal) {
+ const image_path = path.join(root, url)
+ if (exists(image_path) && !track[url]) {
+ const upped: any = await discourse.uploadFile(options.owner, image_path)
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data
+ write(track_path, track)
+ } else {
+ console.error('error uploading image')
+ }
+ }
+ }
+ }
+
+ return track
+}
+
+const syncFile = async (file: string, options: IOptionsSync) => {
+
+ const discourse = Instance(null, options.config as EDiscourseConfigKey)
+
+ let config = fromJSON(file, options) || {} as IComponentConfig
+
+ const componentDir = path.parse(file).dir
+
+ let body = await createContent(componentDir, options)
+
+ let images_track
+
+ if (options.uploadLocal || options.uploadRemote) {
+ images_track = await uploadImages(body, discourse, options)
+ const image_urls = images_urls(body)
+ image_urls.forEach((i) => {
+ if (images_track[i]) {
+ body = body.replace(i, images_track[i].short_url)
+ } else {
+ logger.warn(`Cant resolve image url : ${i}`)
+ }
+ })
+ }
+
+
+
+ const output = path.join(componentDir, '.osr/discourse_raw.md')
+ let dst = path.resolve(resolve(output))
+ options.debug && logger.info('Write output to: ', dst)
+ write(dst, body)
+
+ let dOpts: IDiscoursePostBaseOptions = {
+ ...options,
+ cat: config.forumCategory,
+ id: options.id,
+ owner: config.forumUserId || 1,
+ tags: config.forumTags as string,
+ title: config.name
+ }
+
+ options = {
+ ...options,
+ ...dOpts
+ }
+
+ // const cats = await cacheCategories(options, discourse)
+ // const tags = await cacheTags(options, discourse)
+
+ const users = await cacheUsers(options, discourse)
+ let search = await discourse.search(dOpts.title)
+
+ let post_id, topic_id
+
+ if (options.yaml) {
+ post_id = dOpts.post_id
+ topic_id = dOpts.topic_id
+ }
+
+ let dTopic: ISearchTopic
+ let dPost: ISearchPost
+
+ if (search && search.posts && search.topics
+ && search.posts[0] && search.topics[0]
+ && search.topics[0].title === dOpts.title) {
+ dPost = search.posts[0]
+ dTopic = search.topics[0]
+ topic_id = dTopic.id
+ post_id = dPost.id
+ } else if (post_id && topic_id) {
+
+ }
+
+ if (!dTopic || !dPost) {
+ console.error('cant find ' + dOpts.title)
+ // return
+ }
+
+ const user = users.find((u) => {
+ return u.id === dOpts.owner
+ })
+
+ if (!user) {
+ logger.error('Invalid user : ', dOpts.owner)
+ return false
+ }
+
+ options.user_name = user.username
+
+ let topic = null
+ if (post_id) {
+ await updateTopic(discourse, options, post_id, body)
+ if (topic_id) {
+ topic = await discourse.updateTopic(topic_id, dOpts.cat as number, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : [])
+ }
+ } else {
+ const d = await createTopic(discourse, options, body)
+ if (options.topic_id) {
+ topic_id = options.topic_id
+ post_id = options.post_id
+ await discourse.updateTopic(topic_id, dOpts.cat as number, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : [])
+ }else{
+ logger.error('Creating topic failed !')
+ }
+ }
+
+ // const visStatus = await discourse.updateTopicVisibility(topic_id, true)
+
+ // re-read without defaults
+ config = readOSRConfig(file)
+
+ if (dTopic) {
+ options.topic_id = dTopic.id
+ config.forumTopicId = dTopic.id
+ }
+ if (dPost) {
+ options.post_id = dPost.id
+ config.forumPostId = dPost.id
+ }
+
+ write(file, config)
+
+ return body
+}
+
+export const syncComponent = async (options: IOptionsSync) => {
+
+ // let components = options.srcInfo.FILES.filter(isValidLibraryComponent)
+
+ let components = options.srcInfo.FILES.filter(isValidLibraryComponent)
+ //components = options.srcInfo.FILES.filter((c) => {
+ components = components.filter((c) => {
+ try {
+ const config = readOSRConfig(c) as any
+ if (config) {
+ // return !config.code && !config.cscartId && !config.steps
+ return !!config.name
+ }
+ return false
+ } catch (error) {
+ logger.error(`Invalid config : ${c}`)
+ }
+ })
+
+ const skipExisting = false
+
+ if (skipExisting) {
+ components = components.filter((f) => {
+ const config = readOSRConfig(f) as IComponentConfig
+ if (config.forumPostId && config.forumTopicId) {
+ return false
+ }
+ return true
+ })
+ }
+
+ //components = [components[0]]
+
+ await BPromise.resolve(components).map((f) => {
+ try {
+ return syncFile(f, options)
+ } catch (error) {
+ debugger
+ }
+
+ }, { concurrency: 1 })
+
+}
+
+export const sync = async (options: IOptionsSync) => {
+ return syncComponent(options)
+}
diff --git a/packages/discourse/src/lib/sync/download.ts b/packages/discourse/src/lib/sync/download.ts
new file mode 100644
index 00000000..7b6fe966
--- /dev/null
+++ b/packages/discourse/src/lib/sync/download.ts
@@ -0,0 +1,46 @@
+import * as path from 'path'
+
+const _sanitize = require("sanitize-filename")
+
+const filenamify = require('filenamify')
+import * as download from 'download'
+const URI = require("uri-js")
+
+import * as url from 'url'
+
+export const sanitize = (f) => {
+ let str: string = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "");
+ if (str.startsWith('_')) {
+ str = str.substring(1);
+ }
+ return str;
+}
+
+export const sanitize_ex = (f) => {
+ let str: string = filenamify(_sanitize(f)).replace(/[^\x00-\x7F]/g, "").replace('_', '');
+ return str;
+}
+
+export const filename = (_url) => {
+ return path.basename(url.parse(_url).path);
+}
+
+
+export const imageName = (url) => {
+ if(!url){
+ return ""
+ }
+ try {
+ const parsed = URI.parse(decodeURIComponent(url));
+ const pParsed = path.parse(parsed.path);
+ return sanitize(decodeURIComponent(pParsed.base));
+ } catch (error) {
+ console.error('error image name : ',url)
+ return ""
+ }
+}
+export const downloadFile = async (_url:string, dir:string) =>{
+ return download(_url, dir, {
+ filename: imageName(_url)
+ })
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/sync/file.ts b/packages/discourse/src/lib/sync/file.ts
new file mode 100644
index 00000000..52565697
--- /dev/null
+++ b/packages/discourse/src/lib/sync/file.ts
@@ -0,0 +1,314 @@
+import * as path from 'path'
+import { sync as exists } from "@plastichub/fs/exists"
+import { async as move } from "@plastichub/fs/move"
+import { sync as dir } from "@plastichub/fs/dir"
+import { sync as write } from "@plastichub/fs/write"
+import { sync as read } from "@plastichub/fs/read"
+
+import { resolve } from "@plastichub/osr-commons"
+
+import { Promise as BPromise } from 'bluebird'
+import { IOptionsSync, IDiscoursePostBaseOptions } from '../../types'
+import { imageName, downloadFile } from './download'
+
+
+const YAML = require('json-to-pretty-yaml')
+const cheerio = require('cheerio');
+
+import { toHTML } from '../markdown'
+
+import {
+ SYNC_TRACK_FILENAME
+} from '../discourse/constants'
+
+import {
+ cacheCategories,
+ cacheTags,
+ cacheTopics,
+ cacheUsers
+} from '../discourse/cache'
+
+import {
+ Discourser,
+ Instance
+} from '../discourse'
+
+import {
+ fromYAML
+} from './commons'
+
+import { EDiscourseConfigKey } from "lib/discourse/constants"
+import { ISearchPost, ISearchTopic, logger } from "../../index"
+
+import * as md5 from 'md5'
+
+export const createTopic = async (discourse: Discourser, options: IOptionsSync, content) => {
+
+ let data: any
+ try {
+ data = await discourse.createPost(options.title, content, options.cat as number)
+ } catch (e) {
+ debugger
+ }
+
+ if (data) {
+ logger.debug('created topic : ' + options.title + ' : ' + data.id)
+ if (data && data.id) {
+
+ try {
+ options.post_id = data.id;
+ options.topic_id = data.topic_id
+ await discourse.changeOwner(options.post_id, options.topic_id, options.user_name)
+ } catch (e) {
+ logger.error('changing owner ' + options.title + ' failed!', e)
+ }
+ } else {
+ logger.debug('creating ' + options.title + ' failed!', data.errors);
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + options.title)
+ }
+ }
+ }
+ }
+}
+
+export const updateTopic = async (discourse: Discourser, options: IOptionsSync, topic_id, content) => {
+
+ let data: any
+ try {
+ data = await discourse.updatePost(topic_id, content)
+ } catch (e) {
+
+ }
+
+ if (data) {
+ logger.debug('created topic : ' + options.title + ' : ' + data.id)
+ if (data && data.id) {
+ try {
+ logger.debug('change user to ', options.owner);
+ options.post_id = data.id;
+ options.topic_id = data.topic_id
+ await discourse.changeOwner(topic_id, topic_id, options.user_name)
+ } catch (e) {
+ logger.debug('changing owner ' + options.title + ' failed!')
+
+ }
+ } else {
+ logger.debug('creating ' + options.title + ' failed!', data.errors)
+ if (data.errors) {
+ if (data.errors[0] && data.errors[0] === 'Title has already been used') {
+ logger.error('title already used : ' + options.title)
+ }
+ }
+ }
+ }
+}
+
+const images_urls = (content: string) => {
+ const html = toHTML(content)
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+
+ const images = []
+ const links = []
+ $('img').each(function () {
+ images.push($(this).attr('src'))
+ })
+
+ return images
+}
+
+const uploadImages = async (content: string, discourse: Discourser, options: IOptionsSync) => {
+
+ const root = path.resolve(resolve(options.root))
+ if (!exists(root)) {
+ return false
+ }
+
+ const track_path = path.join(root, SYNC_TRACK_FILENAME)
+ const track = read(track_path, 'json') || {}
+
+ const html = toHTML(content)
+ const $ = cheerio.load(html, {
+ xmlMode: true
+ });
+
+ const images = images_urls(content)
+
+ $('img').each(function () {
+ images.push($(this).attr('src'))
+ })
+
+ for await (const image of Object.entries(images)) {
+
+ const url: string = image[1]
+
+ if (url.startsWith('upload:')) {
+ continue
+ }
+ if (options.uploadRemote && url.startsWith('http')) {
+
+ const contentHash = md5(content).substring(0, 5)
+ const cache_path = path.resolve(resolve('${OSR_CACHE}/discourse-downloads/' + contentHash))
+ if (!exists(cache_path)) {
+ dir(cache_path)
+ }
+ const image_name = imageName(url)
+ const image_local = path.join(cache_path, image_name)
+ if (!exists(image_local)) {
+ await downloadFile(url, cache_path)
+ }
+
+ if (exists(image_local)) {
+ const upped: any = await discourse.uploadFile(options.owner, image_local)
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data
+ write(track_path, track)
+ } else {
+ console.error('error uploading image')
+ }
+ }
+
+ continue
+ }
+
+ if (options.uploadLocal) {
+ const image_path = path.join(root, url)
+ if (exists(image_path) && !track[url]) {
+ const upped: any = await discourse.uploadFile(options.owner, image_path)
+ const data = upped.data;
+ if (data && data.id) {
+ track[url] = data
+ write(track_path, track)
+ } else {
+ console.error('error uploading image')
+ }
+ }
+ }
+ }
+
+ return track
+}
+
+const syncFile = async (file: string, options: IOptionsSync) => {
+
+ const discourse = Instance(null, options.config as EDiscourseConfigKey)
+
+ let content = read(file) as string
+
+ const fm: any = fromYAML(content, options) || {}
+
+ let body = "" + fm.body
+
+ let images_track
+
+ if (options.uploadLocal || options.uploadRemote) {
+ images_track = await uploadImages(body, discourse, options)
+ const image_urls = images_urls(body)
+ image_urls.forEach((i) => {
+ if (images_track[i])
+ body = body.replace(i, images_track[i].short_url)
+ })
+ }
+ write('./out/md.md', body)
+
+ let dOpts: IDiscoursePostBaseOptions = options.yaml ? fm.attributes : {
+ cat: options.cat,
+ id: options.id,
+ owner: options.owner,
+ tags: options.tags,
+ title: options.title
+ }
+
+ options = {
+ ...options,
+ ...dOpts
+ }
+
+ const cats = await cacheCategories(options, discourse)
+ const tags = await cacheTags(options, discourse)
+ const users = await cacheUsers(options, discourse)
+ const search = await discourse.search(dOpts.title)
+
+ let post_id, topic_id
+ if (options.yaml) {
+ post_id = dOpts.post_id
+ topic_id = dOpts.topic_id
+ }
+
+
+ let dTopic: ISearchTopic
+ let dPost: ISearchPost
+
+ if (search.posts && search.topics
+ && search.posts[0] && search.topics[0]
+ && search.topics[0].title === dOpts.title) {
+ dPost = search.posts[0]
+ dTopic = search.topics[0]
+ topic_id = dTopic.id
+ post_id = dPost.id
+ } else if (post_id && topic_id) {
+
+ }
+
+ const user = users.find((u) => {
+ return u.id === dOpts.owner
+ })
+
+ if (!user) {
+ logger.error('Invalid user : ', dOpts.owner)
+ return false
+ }
+
+ options.user_name = user.username
+
+ let topic = null
+ if (post_id) {
+ topic = await updateTopic(discourse, options, post_id, body)
+ if (topic_id) {
+ topic = await discourse.updateTopic(topic_id, dOpts.cat as number, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : [])
+ }
+ } else {
+ await createTopic(discourse, options, body)
+ topic_id = options.topic_id
+ post_id = options.post_id
+
+ await discourse.updateTopic(topic_id, dOpts.cat as number, dOpts.title, dOpts.tags ? dOpts.tags.split(',') : [])
+ }
+
+ if (dTopic) {
+ options.topic_id = dTopic.id
+ }
+ if (dPost) {
+ options.post_id = dPost.id
+ }
+
+
+ if (options.yaml) {
+ let contentOut = `---\n`
+ contentOut += YAML.stringify({
+ ...fm.attributes,
+ topic_id: topic_id,
+ post_id: post_id
+ })
+ contentOut += `---\n`
+ contentOut += fm.body
+ write(file, contentOut)
+ }
+ return content
+
+}
+
+export const syncYAML = async (options: IOptionsSync) => {
+ await BPromise.resolve(options.srcInfo.FILES).map((f) => {
+ return syncFile(f, options)
+ }, { concurrency: 1 })
+
+}
+
+export const sync = async (options: IOptionsSync) => {
+ return syncYAML(options)
+}
diff --git a/packages/discourse/src/lib/sync/index.ts b/packages/discourse/src/lib/sync/index.ts
new file mode 100644
index 00000000..54f1fc40
--- /dev/null
+++ b/packages/discourse/src/lib/sync/index.ts
@@ -0,0 +1,55 @@
+import * as path from 'path'
+import { sync as read } from "@plastichub/fs/read"
+import {
+ SYNC_TRACK_FILENAME
+} from '../discourse/constants'
+
+import { sync as exists } from "@plastichub/fs/exists"
+import { async as move } from "@plastichub/fs/move"
+import { sync as dir } from "@plastichub/fs/dir"
+import { sync as write } from "@plastichub/fs/write"
+
+import { resolve } from "@plastichub/osr-commons"
+
+import { Promise as BPromise } from 'bluebird'
+import { IOptionsSync, IDiscoursePostBaseOptions } from '../../types'
+
+import { createContent } from './osrl'
+
+const YAML = require('json-to-pretty-yaml')
+const cheerio = require('cheerio')
+const findUp = require('find-up')
+const frontMatter = require('front-matter')
+
+import { imageName, downloadFile } from './download'
+import { IComponentConfig } from '@plastichub/osr-commons'
+import { isValidLibraryComponent, readOSRConfig } from '@plastichub/osr-fs-utils'
+
+export const trackingPath = (root) =>
+ path.join(root, SYNC_TRACK_FILENAME)
+
+
+export const tracking = (root) =>
+ read(trackingPath(root), 'json') || {}
+
+export const defaultConfig = (configFile: string, options: IOptionsSync): IComponentConfig => {
+ let defaultsJSON = findUp.sync('defaults.json', {
+ cwd: path.parse(configFile).dir,
+ stopAt: options.root
+ })
+ if (defaultsJSON) {
+ return readOSRConfig(defaultsJSON)
+ }
+ return {
+
+ } as IComponentConfig
+}
+
+export const fromJSON = (configFile: string, options: IOptionsSync): IComponentConfig => {
+ const defaults = defaultConfig(configFile, options)
+ const config = readOSRConfig(configFile)
+ return {
+ ...defaults,
+ ...config
+ }
+}
\ No newline at end of file
diff --git a/packages/discourse/src/lib/sync/osrl.ts b/packages/discourse/src/lib/sync/osrl.ts
new file mode 100644
index 00000000..5156341e
--- /dev/null
+++ b/packages/discourse/src/lib/sync/osrl.ts
@@ -0,0 +1,80 @@
+import * as path from 'path'
+import { IOptions } from '@plastichub/osrl/types'
+import { Engine as engine } from '@plastichub/osrl/Engine'
+import { parse } from '@plastichub/osrl/options'
+
+import { forward_slash } from '@plastichub/osr-cli-commons/glob'
+
+import { resolve } from '@plastichub/osr-commons'
+
+import { IOptionsSyncComponent } from '../../'
+import { logger } from '../../index'
+import { git_status } from '../git'
+import * as moment from 'moment'
+import { sync as read } from '@plastichub/fs/read'
+
+export const fileAsBuffer = (path: string) => read(path, 'buffer') as Buffer || Buffer.from("-")
+const variable_extras = async (component, rel, options: IOptionsSyncComponent) => {
+ const root = path.resolve(resolve('${OSR_LIBRARY_MACHINES}'))
+ const gitStats = await git_status(root, rel)
+ const latest = gitStats.latest
+ return {
+ "GIT_LAST": moment(latest.date ).format('LLLL'),
+ "GIT_AUTHOR" : latest.author_name,
+ "GIT_MESSAGE": latest.message,
+ "GIT_COMMIT" : latest.hash
+ }
+}
+
+export const createContent = async (component, _options: IOptionsSyncComponent) => {
+
+ const parts = path.parse(component)
+ const rel = forward_slash(path.relative(_options.root, component))
+ const extras = await variable_extras(component,rel, _options)
+ const variables = {
+ root: _options.root,
+ cwd: _options.cwd,
+ ..._options.variables,
+ product: rel,
+ product_rel: rel,
+ product_rel_min: rel,
+ ...extras
+ }
+ const defaults: any = {
+ language: _options.language,
+ debug: false,
+ profile: _options.profile,
+ // output: output,
+ plugins: [],
+ env: _options.env || 'forum',
+ cwd: _options.cwd,
+ source: _options.src,
+ variables
+ }
+ const options = parse(defaults, defaults);
+ const eOptions = {
+ ...options,
+ root: [
+ ...options.profile.includes,
+ component
+ ],
+ toHTML: false,
+ cache: false,
+ keepOutputType: true,
+ trimTagRight: false,
+ trimTagLeft: false,
+ trimOutputRight: false,
+ trimOutputLeft: false,
+ greedy: false
+ } as IOptions
+
+ const Engine = new engine(eOptions);
+
+ options.debug && logger.info('Compile file ' + component, eOptions)
+
+ let content = await Engine.render(options.source, {
+ ...options.variables,
+ ...extras
+ })
+ return content
+}
diff --git a/packages/discourse/src/main.ts b/packages/discourse/src/main.ts
new file mode 100644
index 00000000..1d3d991a
--- /dev/null
+++ b/packages/discourse/src/main.ts
@@ -0,0 +1,22 @@
+#!/usr/bin/env node
+process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
+
+import { defaults } from './_cli'; defaults();
+import * as cli from 'yargs';
+import { register as registerInfo } from './commands/info'; registerInfo(cli)
+import { register as registerQuery } from './commands/query'; registerQuery(cli)
+
+import { register as registerOAImport } from './commands/import-oa-users'; registerOAImport(cli)
+import { register as registerOAImportHowtos } from './commands/import-oa-howtos'; registerOAImportHowtos(cli)
+
+import { register as registerSync } from './commands/sync-file'; registerSync(cli)
+import { register as registerSyncComponent } from './commands/sync-component'; registerSyncComponent(cli)
+
+const argv: any = cli.argv;
+
+if (argv.help) {
+ cli.showHelp();
+ process.exit();
+} else if (argv.v || argv.version) {
+ process.exit();
+}
diff --git a/packages/discourse/src/options.ts b/packages/discourse/src/options.ts
new file mode 100644
index 00000000..e526b3df
--- /dev/null
+++ b/packages/discourse/src/options.ts
@@ -0,0 +1,33 @@
+import * as path from 'path'
+
+import { resolveConfig } from '@plastichub/core'
+
+// import * as deepmerge from '@plastichub/core/deepmerge'
+
+import { clone, deepClone } from '@plastichub/core/objects'
+
+export * from './lib'
+
+import { IOptions } from './types'
+
+
+export const parse = (options: IOptions, argv: any): IOptions => {
+
+ for (const k in argv) {
+ if (!(k in options.variables) && k !== '_'
+ && k !== '$0'
+ && k !== 'variables'
+ && k !== 'src'
+ && k !== 'format'
+ && k !== 'profile'
+ && k !== 'output') {
+ options.variables[k] = argv[k];
+ }
+ }
+
+ options.variables['cwd'] = options.variables['cwd'] ? options.variables['cwd'] : options.cwd
+ resolveConfig(options.variables)
+ let variables = {}
+ options.pathVariables = variables
+ return options
+}
\ No newline at end of file
diff --git a/packages/discourse/src/types.ts b/packages/discourse/src/types.ts
new file mode 100644
index 00000000..0cdd8642
--- /dev/null
+++ b/packages/discourse/src/types.ts
@@ -0,0 +1,214 @@
+import { IObjectLiteral } from '@plastichub/core';
+
+import { I_OSR_USER } from '@plastichub/osr-commons'
+
+import { PATH_INFO, PATH_VARIABLES, SRC_VARIABLES } from '@plastichub/osr-cli-commons'
+
+import { IDiscourseConfig } from '@plastichub/osr-cli-commons/types'
+
+import {
+ IBaseOptions as IOSRLBaseOptions,
+ IProfile as IOSRLProfile
+
+} from '@plastichub/osrl'
+
+import { EDiscourseConfigKey } from 'lib/discourse/constants'
+import { IProcessingNode } from '@plastichub/fs/interfaces'
+import { TFindFilter } from '@plastichub/osr-fs-utils'
+
+export interface Hash {
+ [id: string]: T
+}
+
+export type IOptions = {
+ src: string
+ id: string
+ cat: string
+ track: string
+ variables: Hash
+ cwd: string
+ env: string
+ verb: string
+ debug: boolean
+ disabled: boolean
+ dry?: boolean
+ all?: boolean
+ stdout: boolean
+ pathVariables: Hash
+}
+
+///////////////////////////////////////////////////////
+//
+// Sync Types
+//
+
+/**
+ * An enumeration to narrow a conflict resolve to a single item or for all following conflicts.
+ *
+ * @export
+ * @enum {number}
+ */
+export enum EResolve {
+ /**
+ * Always will use the chose conflict settings for all following conflicts.
+ */
+ ALWAYS,
+ /**
+ * 'This' will use the conflict settings for a single conflict so the conflict callback will be triggered again for the next conflict.
+ */
+ THIS
+}
+
+/**
+ * The possible modes to resolve a conflict during a sync
+ *
+ * @export
+ * @enum {number}
+ */
+export enum EResolveMode {
+ SKIP = 0,
+ OVERWRITE,
+ IF_NEWER,
+ IF_SIZE_DIFFERS,
+ THROW,
+ RETRY,
+ ABORT
+}
+export interface IConflictSettings {
+ /**
+ * How to resolve this conflict/error.
+ *
+ * @type {EResolveMode}
+ * @memberOf IConflictSettings
+ */
+ overwrite: EResolveMode
+ /**
+ * The scope of this conflict resolver: always or this.
+ *
+ * @type {EResolve}
+ * @memberOf IConflictSettings
+ */
+ mode: EResolve
+ /**
+ * Track the origin error type for this settings.
+ *
+ * @type {string}
+ * @memberOf IConflictSettings
+ */
+ error?: string
+}
+
+export type EMergeConflictMode = 'theirs' | 'mine'
+
+export type EPostType = 'post' | 'reply'
+
+export type ISyncNodeReport = IProcessingNode & {
+
+}
+
+export interface IDiscoursePostBaseOptions {
+ title?: string
+ id?: string
+ cat?: string | number
+ tags?: string
+ owner?: string | number
+ timestamp?: string | number | Date
+ uploadLocal?: boolean
+ uploadRemote?: boolean
+ yaml?: boolean
+ post_id?: number
+ topic_id?: number
+ type?: EPostType
+ user_name?: string
+}
+
+export type IOptionsSync = IDiscoursePostBaseOptions & IOSRLBaseOptions & {
+
+ // common options
+ debug?: boolean
+ verbose?: boolean
+ logLevel?: string
+ skip?: boolean
+ alt?: boolean
+ src?: string
+ verb: string
+
+ // cache options
+ cache?: boolean
+
+ filter?: TFindFilter | string
+
+ // OSR - Config Discorse Key
+ config?: string | EDiscourseConfigKey
+
+ // internals
+ pathVariables?: Hash
+ variables?: SRC_VARIABLES
+
+ repo?: string
+ root?: string
+
+ product_root?: string
+
+ // parsed options
+ srcInfo?: PATH_INFO
+
+ //tracking
+ post_id?: number
+ topic_id?: number
+
+}
+
+export type IOptionsSyncComponent = IOptionsSync &
+{
+ format?:string
+ module?:string
+ plugins?:string
+ onCompiled?: () => void
+ onCompileDone?: () => void
+ cache?: boolean
+ skip?: boolean
+
+}
+
+
+//////////////////////////////////////////////////////////////////
+//
+// Basic types
+//
+
+export interface IDBConfig {
+ user: string
+ password: string
+ database: string
+ host: string
+ prefix: string
+}
+
+
+export interface IDiscourseUser {
+ id: number
+ username: string
+ name: string
+ avatar_template: string
+ active: boolean
+ admin: boolean
+ moderator: boolean
+ last_seen_at: any
+ last_emailed_at: string
+ created_at: string
+ last_seen_age: any
+ last_emailed_age: number
+ created_at_age: number
+ trust_level: number
+ manual_locked_trust_level: any
+ flag_level: number
+ title: any
+ time_read: number
+ staged: boolean
+ days_visited: number
+ posts_read_count: number
+ topics_entered: number
+ post_count: number
+ detail: any
+}
diff --git a/packages/discourse/temp/h.json b/packages/discourse/temp/h.json
new file mode 100644
index 00000000..3c3190ec
--- /dev/null
+++ b/packages/discourse/temp/h.json
@@ -0,0 +1 @@
+"{\"env\":\"forum\",\"forumTags\":\"extrusion\",\"forumCategory\":51,\"Preview3d\":true,\"howtoSection\":\"https://forum.osr-plastic.org/tags/c/kb/54/injection\",\"download\":\"${OSR_FILES_WEB}/${product_rel_min}\",\"product_dimensions\":\"${OSR_MACHINES_ASSETS_URL}/${product_rel}/drawings/dimensions.jpg\",\"preview\":\"${OSR_MACHINES_ASSETS_URL}/${product_rel}/media/latest.jpg\",\"product_parts\":\"${OSR_MACHINES_ASSETS_URL}/${product_rel_min}/drawings/parts.jpg\",\"edrawings\":\"${OSR_MACHINES_ASSETS_URL}/${product_rel_min}/resources/edrawings.html\",\"forumUserId\":1,\"hasSpecs\":true,\"slug\":\"lydia-mini\",\"version\":\"1.0\",\"category\":\"extrusion\",\"code\":\"LMI\",\"name\":\"Lydia-Mini\",\"parts\":\"parts.csv\",\"opensource\":true,\"bestseller\":true,\"showDimensions\":false,\"showParts\":false,\"cscartId\":13,\"authors\":[{\"name\":\"PlasticHub S.L.\",\"url\":\"${author_link}\"},{\"name\":\"Jason Knight\",\"url\":\"https://www.mandin.earth/\"}],\"forumTopicId\":10117,\"forumPostId\":27525,\"forumPostHash\":\"7473a5ff4f3b11604d0b4f1dee24c4dc\",\"image\":\"${product_rel}/renderings/perspective.jpg\",\"config\":{\"includes\":[\"${root}/osr\",\"${root}/osr/widgets\",\"${OSR_ROOT}/osr-templates/commons\",\"${OSR_ROOT}/osr-templates/discourse\",\"${OSR_ROOT}/osr-templates/discourse/commons\",\"${OSR_ROOT}/osr-templates/discourse/widgets\",\"${PRODUCT_ROOT}\",\"${PRODUCT_ROOT}/templates/site/\",\"${PRODUCT_ROOT}/templates/shared/\"],\"variables\":{\"PRODUCT_ROOT\":\"${root}/${product}/\",\"abs_url\":\"https://assets.osr-plastic.org\",\"CACHE\":\"${root}/cache/\",\"GIT_REPO\":\"https://git.osr-plastic.org/osr-plastic/osr-machines\",\"OSR_MACHINES_ASSETS_URL\":\"https://assets.osr-plastic.org/machines/\",\"PRODUCTS_ASSETS_URL\":\"https://assets.osr-plastic.org/machines/${product}\",\"OSR_FILES_WEB\":\"http://files.osr-plastic.org/files/osr-machines\",\"PRODUCTS_FILES_URL\":\"${OSR_FILES_WEB}/${product_rel}\",\"vendor_name\":\"Plastic Hub\",\"vendor_website\":\"https://osr-plastic.org/\",\"vendor_products_external\":\"https://plastic-hub.com/products/\",\"vendor_instagram\":\"https://www.instagram.com/osr_plastic/\",\"_vendor_youtube\":\"https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber\",\"vendor_github\":\"https://git.osr-plastic.org/osr-plastic\",\"vendor_contact_email\":\"mailto:sales2@plastic-hub.com\",\"vendor_whatsapp\":\"tel:0034691952287\",\"vendor_facebook\":\"https://www.facebook.com/plastichubcat/\",\"vendor_discord\":\"https://discord.gg/vR5d6ShTez\",\"author_link_pp\":\"https://preciousplastic.com/\",\"author_link\":\"https://osr-plastic.org\",\"vendor_forum\":\"https://forum.osr-plastic.org\",\"OSR_HOWTOS_ROOT_URL\":\"${vendor_forum}/c/wiki/howtos/72\",\"OSR_HOWTOS_PATH\":\"../../ph3/pp-next2/howtos\",\"show\":{\"badges\":false,\"authors\":true,\"head\":true,\"debug\":false,\"wiki\":false,\"forum\":false,\"others\":false,\"howtos\":false,\"instagram\":false,\"shipping\":false,\"payment_terms\":false,\"components\":true,\"marketplaceLinks\":true,\"productDump\":true,\"configDump\":false,\"issues\":false,\"alternatives\":true,\"replacedBy\":true,\"meta\":true}},\"env\":{\"bazar\":{\"includes\":[],\"variables\":{\"abs_url\":\"https://dev.osr-plastic.org/\"}},\"bazar-release\":{\"includes\":[],\"variables\":{\"abs_url\":\"https://shop.osr-plastic.org/\"}},\"test-import\":{},\"forum\":{\"includes\":[],\"variables\":{\"forum_url\":\"https://forum.osr-plastic.org/\",\"show\":{\"badges\":true,\"authors\":true,\"head\":true,\"debug\":false,\"wiki\":false,\"forum\":false,\"others\":false,\"howtos\":true,\"instagram\":false,\"shipping\":false,\"payment_terms\":false,\"components\":true,\"marketplaceLinks\":true,\"meta\":true,\"productDump\":true,\"configDump\":false}}}}},\"OSR_ROOT\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\",\"OSR_TEMP\":\"C:\\\\Users\\\\mc007\\\\AppData\\\\Local\\\\Temp\\\\osr\",\"PRODUCT_ROOT\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-machines/extrusion/lydia-mini/\",\"OA_ROOT\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\ph3\\\\pp-next2\",\"KB_ROOT\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-kb-next\",\"OSR_CACHE\":\"C:\\\\Users\\\\mc007\\\\.osr\\\\cache\",\"OSR_LIBRARY_MACHINES\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-machines\",\"OSR_USER_ASSETS\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-user-assets\",\"OSR_PRIVATE\":\"C:\\\\Users\\\\mc007\\\\.osr\\\\\",\"OSR_TEMPLATES\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-templates\",\"OSR_CONTENT\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-content\",\"OSR_PROFILES\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-profiles\",\"root\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-machines\",\"cwd\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr\\\\osr-discourse\",\"SRC_PATH\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr/osr-templates/discourse/root.html\",\"SRC_DIR\":\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr/osr-templates/discourse\",\"SRC_NAME\":\"root\",\"SRC_FILE_NAME\":\"root.html\",\"SRC_FILE_EXT\":\"html\",\"SRC_IS_FILE\":true,\"SRC_IS_FOLDER\":false,\"SRC_IS_EXPRESSION\":false,\"SRC_IS_GLOB\":false,\"SRC_GLOB\":\"**/config.+(json)\",\"SRC_GLOB_EXTENSIONS\":[\"json\"],\"SRC_FILES\":[\"C:\\\\Users\\\\mc007\\\\Desktop\\\\osr/osr-templates/discourse/root.html\"],\"product\":\"extrusion/lydia-mini\",\"product_rel\":\"extrusion/lydia-mini\",\"product_rel_min\":\"extrusion/lydia-mini\",\"GIT_LAST\":\"Thursday, July 27, 2023 6:34 AM\",\"GIT_AUTHOR\":\"lovebird\",\"GIT_MESSAGE\":\"extrusion : meta | Filament :)\",\"GIT_COMMIT\":\"4f02ac6173b6aac8022600d4cfcf424d1121c61d\",\"debug\":false}"
\ No newline at end of file
diff --git a/packages/discourse/temp/l.md b/packages/discourse/temp/l.md
new file mode 100644
index 00000000..7d45fb64
--- /dev/null
+++ b/packages/discourse/temp/l.md
@@ -0,0 +1 @@
+"In this How-to we’re going to guide you through all the steps to set up an Extrusion Workspace. Learn about plastic, how to find a space, get the Extrusion machine, find customers and connect to the Precious Plastic Universe. Step 1-3: Intro Step 4-9: Learn Step 10-19: Set up Step 20-25: Run Step 26-29: Share\n\n\n\n---\n\n\n\n#### Attachments\n\n\n\n#### Resources\n\n- [Browse Files](http://files.osr-plastic.org/files/howtos/set-up-an-extrusion-workspace/)\n\n#### 3D Files\n\n\n\n---\n\nStep 1 - Role \n\n\n First of all, make sure you had a look at the showcase page of this Starterkit! \n\n preciousplastic.com/starterkits/showcase/extrusion \n\n \n\nNow about your Role: \n\n \n\nExtrusion workspaces buy recycled shredded plastic (from Shredder Workspaces or from the Bazar) and transform it into recycled beams and bricks, or whatever other useful material and products you can come up with. \n\n \n\nThe recycled plastic material can then be sold as raw material for others to create, or maybe you even turn them into valuable objects yourself. \n\n \n\nExtrusion workspaces should also reach out to Community Point to connect with the local Precious Plastic community and, maybe, get help selling their materials.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 2 - Outcomes \n\n\n The outcome of an Extrusion Workspace can be recycled plastic beams, bricks or other material (there are a lot of possibilites). \n\n \n\nThe beams can be of various sizes and shapes, and as long as needed. Make sure you don't miss playing around with different gradients and colours to make create a playful variety of outcomes.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 3 - Is this for you? \n\n\n For the Extrusion Workspace you will have to be quite technical as you have to understand how the Extrusion machine works, ideally know how to maintain it and, as a plus, know how to fix it when it needs a bit of extra love. \n\n \n\nAttention to details is also a nice, and some creativity to come up with new patterns and techniques.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 4 - Learn about Precious Plastic \n\n\n As a start, it’s super important to really know and understand Precious Plastic. What drives the project, how it works, its philosophy and solutions. \n\n \n\nIf you haven’t already, dig our website, community platform and Bazar to have a deep understanding of the project. \n\n preciousplastic.com \n\n community.preciousplastic.com \n\n bazar.preciousplastic.com \n\n \n\nAlso, make sure to check the Universe chapter to fully understand how the Precious Plastic Universe works. \n\n community.preciousplastic.com/academy/universe\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 5 - Check out your area \n\n\n Get an overview of who and what is already existing in your area. \n\n \n\nHave a look on the Precious Plastic Map to see the activity around you. You can also search for more people on the Precious Plastic Bazar or search for #preciousplastic on social media. \n\n \n\nMake sure not to jam the local network, if there are already many Extrusion Workspaces around, have a chat about collaboration with them first, or maybe consider starting another type of space. \n\n \n\n community.preciousplastic.com/map\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 6 - Find a Community Point near you \n\n\n Community Points are the glue of the Precious Plastic Universe. They know the ins and outs of your local network. They can help you in multiple ways but they generally have a very in-depth overview of local Precious Plastic spaces, people, useful shops, resources and can help you with planning out your project. You can find them on the map here. \n\n \n\n community.preciousplastic.com/map\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 7 - Find your plastic supply \n\n\n You can use the Precious Plastic Map and the Bazar to find Shredder workspaces around you that can provide you with the raw material: shredded plastic waste. \n\n \n\nIf you have a local Community Point, they might be able to give you a hand with this as well. \n\n \n\n community.preciousplastic.com/map \n\n bazar.preciousplastic.com\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 8 - Get on Discord \n\n\n Day to day discussions in the Precious Plastic Universe happen on Discord. \n\n \n\nIntroduce yourself, say hi in your country channel and start to discover the different channels where people go deep into specific topics (building, collection, design etc..) \n\n \n\nJoin the Discord: \n\n discordapp.com/invite/rnx7m4t\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 9 - Learn the basics of plastic \n\n\n Before you start it is crucial to get a solid understanding of plastic. How it works, the different types, melting temperatures and so on. Head over to our Academy and dive into the plastic chapters to learn about the different types and properties etc. \n\n \n\n community.preciousplastic.com/academy/plastic/basics\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 10 - Fill in the Action Plan \n\n\n Before jumping into making machines or finding a space it is smart to sit down and properly plan your project and shape your vision. \n\n \n\nTo help you plan we’ve made a graphic tool called the Action Plan that helps you to craft your mission, understand your customers, revenue streams, costs and much more. With this tool, you should get a step closer to create a successful project. \n\n \n\nYou can find the Action Plan in the Download Kit or learn more in the Academy \n\n community.preciousplastic.com/academy/business/actionplan\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 11 - Workspace Calculator \n\n\n Now you have your project nicely planned out and it’s starting to take shape in your mind. \n\n \n\nIt is important at this stage to make a serious estimation of how much it will cost you to set up and run your workspace. Otherwise, you might run out of money halfway. The Workspace Calculator is a spreadsheet that helps you do just that. \n\n \n\nYou can find the Workspace Calculator in the Download Kit or learn more in the Academy: \n\n community.preciousplastic.com/academy/business/workspacecalculator\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 12 - Business Plan Template \n\n\n To help you pitch your idea to potential partners, financial institutions or investors we made a Business Plan Template (and a specific example for the Extrusion Workspace) for you to use. \n\n \n\nThis template helps you to talk the business language and should help you access the necessary money to begin. \n\n \n\nFor more explanation check out the video in the Academy: \n\n community.preciousplastic.com/academy/business/businessplan\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 13 - Tool list \n\n\n Alongside your Extrusion machine, you will need a number of other tools and machines to help you with the operations of the Extrusion Workspace. \n\n \n\nIn the Download Kit, you will find a tool list with all the necessary tools to run your workspace.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 14 - Find the space \n\n\n To help you find the perfect place for your workspace you can use the floor plan in the Download Kit, with all the minimum requirements and a little cardboard tool to place your machines and tools in the workspace.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 15 - Get your extrusion \n\n\n Cool, now you have a space it’s time to get hold of your Extrusion machine. There are three ways to do that: \n\n \n\n1 Build it yourself following our tutorials \n\n community.preciousplastic.com/academy/build/extrusionprobuild \n\n \n\n2 Buy it on the Bazar. \n\n bazar.preciousplastic.com \n\n \n\n3 Find a Machine Shop near you on the map that can build it for you. \n\n community.preciousplastic.com/map\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 16 - Build your space \n\n\n Super, you’ve got your Extrusion! But an Extrusion alone is not enough. \n\n \n\nYou can watch our video on how to fully set up your Extrusion workspace with all the additional tools, furniture and posters needed to make your space ready. \n\n \n\n community.preciousplastic.com/academy/spaces/extrusion\n
\n\n \n\n\n\n \n\n \n\n\nStep 17 - Safety \n\n\n Always stay safe! \n\n \n\nOf course, Extrusion machines get hot. And can cause a hazard in different ways. \n\n \n\nSo before starting to melt, please check out our safety video to learn about dangers and how to stay safe when working with plastic. \n\n \n\n community.preciousplastic.com/academy/plastic/safety\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 18 - Buy shredded plastic \n\n\n Buy shredded plastic \n\n- from a local Shredder Workspace \n\ncommunity.preciousplastic.com/map \n\n- or from the Bazar \n\nbazar.preciousplastic.com \n\n \n\nMake sure to specify your preferred shreds size (small, medium or large) and to have a variety of colours and types.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 19 - Time to produce! \n\n\n Now that you have all the things in place it’s time to start making your recycled plastic material. Watch this video to learn how to make beams and adopt the best practices. \n\n \n\nYou can also find tutorials and ideas for other products in the How-to's under the tag "extrusion".\n
\n\n \n\n\n\n \n\n \n\n\nStep 20 - Make a variety \n\n\n Once you get a grasp on the process make sure to make a nice variety of colours, sizes and thicknesses to attract different customers.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 21 - Maintenance \n\n\n As you run your Extrusion Workspace it is crucial that you maintain the Extrusion machines in order to prevent failures. Find out here how to best maintain the Extrusion.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 22 - Sell your beams \n\n\n You can now make beautiful beams. Many every day. Now is crucial to find people and organisations that want to buy your recycled beams. \n\n \n\nFirst, you should put them on the Precious Plastic Bazar to access an audience that is already interested in recycled products. Then you have to get creative on how to sell your beams locally. Shops, design studios, online stores and more.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 23 - Create your profile \n\n\n If you haven’t already, it’s time to create your profile on the Precious Plastic Community Platform to connect with people. Follow this link and sign up with your email, pick your role, put your pin on the map and upload nice pics to show the world what you’re doing.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 24 - Create How-tos! \n\n\n Share to the world how you run your Extrusion Workspace so other people can learn from you and start using your solution to tackle the plastic problem. \n\n \n\nMake sure to only create How-tos for your best processes and techniques, not tryouts or one-offs. This can also help you create a name for yourself in the Precious Plastic community. \n\n \n\n community.preciousplastic.com/how-to\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 25 - Stay active on Discord \n\n\n Precious Plastic is people. People working together and helping each other. Go to Discord and connect with people.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 26 - Good things take time \n\n\n Starting off will take some time in the beginning. It’s normal. Be patience, work smart and reach out to your Precious Plastic community if you need help. Everything will take off. \n\nYou’re changing the world.\n
\n\n \n\n\n\n\n\n \n\n \n\n\nStep 27 - Download and start! \n\n\n Ready and excited to start? \n\nYou're a hero! \n\n \n\nIf you haven't done it yet, click on the yellow download button (in the top section of this page) to get the package with all the files you need to set up your Extrusion Workspace. \n\n \n\nDownload and start your recycling journey! :)\n
\n\n \n\n\n\n\n\n \n\n\n---\n\n\n\n---\n\n\n---\n"
\ No newline at end of file
diff --git a/packages/discourse/temp/post.html b/packages/discourse/temp/post.html
new file mode 100644
index 00000000..4402dbe1
--- /dev/null
+++ b/packages/discourse/temp/post.html
@@ -0,0 +1,969 @@
+
+
+
+
+
+ User & Service Directory Germany - Europe - OSR - Forum
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jerom
+ (Jerome)
+
+
+
+
+
+
+
+ 23 July 2023 09:44
+
+
+ 1
+
+
+
+
User & Service Directory Germany
+
Machine Builders
+
+
Services
+
Producers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jerom
+ (Jerome)
+ Unlisted
+
+
+
+
+
+
+
+ 23 July 2023 14:23
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ jerom
+ (Jerome)
+ Tags updated
+
+
+
+
+
+
+
+ 13 August 2023 15:07
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/discourse/temp/t.json b/packages/discourse/temp/t.json
new file mode 100644
index 00000000..773dd4bf
--- /dev/null
+++ b/packages/discourse/temp/t.json
@@ -0,0 +1,7 @@
+{
+ "id": 10045,
+ "title": "OSR - Discourse Test sync:fs",
+ "fancy_title": "OSR - Discourse Test sync:fs",
+ "slug": "osr-discourse-test-sync-fs",
+ "posts_count": 3
+}
\ No newline at end of file
diff --git a/packages/discourse/temp/user.json b/packages/discourse/temp/user.json
new file mode 100644
index 00000000..1ccd8d76
--- /dev/null
+++ b/packages/discourse/temp/user.json
@@ -0,0 +1,447 @@
+{
+ id: 1000,
+ username: "grydis",
+ name: "grydis",
+ avatar_template: "/letter_avatar_proxy/v4/letter/g/7c8e57/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-20T11:40:17.110Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41038738.66242003,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 8,
+ can_send_activation_email: true,
+ can_activate: false,
+ can_deactivate: true,
+ ip_address: "79.155.255.123",
+ registration_ip_address: "79.155.255.123",
+ can_grant_admin: true,
+ can_revoke_admin: false,
+ can_grant_moderation: true,
+ can_revoke_moderation: false,
+ can_impersonate: true,
+ like_count: 0,
+ like_given_count: 0,
+ topic_count: 0,
+ post_edits_count: null,
+ flags_given_count: 0,
+ flags_received_count: 0,
+ private_topics_count: 1,
+ can_delete_all_posts: true,
+ can_be_deleted: true,
+ can_be_anonymized: true,
+ can_be_merged: true,
+ full_suspend_reason: null,
+ silence_reason: null,
+ penalty_counts: {
+ silenced: 0,
+ suspended: 0
+ },
+ next_penalty: "2023-06-11T11:19:15.821Z",
+ primary_group_id: null,
+ badge_count: 2,
+ warnings_received_count: 0,
+ user_fields: {
+ 1: null,
+ 2: null,
+ 3: null,
+ 4: null,
+ 5: null
+ },
+ bounce_score: 0,
+ reset_bounce_score_after: null,
+ can_view_action_logs: true,
+ can_disable_second_factor: true,
+ can_delete_sso_record: false,
+ api_key_count: 0,
+ external_ids: { },
+ similar_users: [
+ {
+ id: 57,
+ username: "soumyaadhikary",
+ name: "soumyaadhikary",
+ avatar_template: "/letter_avatar_proxy/v4/letter/s/4491bb/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-19T19:46:37.993Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41095957.85595296,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 1,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 2851,
+ username: "katharinaelleke",
+ name: "katharinaelleke",
+ avatar_template: "/user_avatar/forum.osr-plastic.org/katharinaelleke/{size}/743_2.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: "2023-03-05T09:53:16.582Z",
+ created_at: "2022-02-20T12:12:40.403Z",
+ last_seen_age: null,
+ last_emailed_age: 8385959.269099995,
+ created_at_age: 41036795.44807909,
+ trust_level: 2,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 53,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 929,
+ username: "johnbusch",
+ name: "johnbusch",
+ avatar_template: "/user_avatar/forum.osr-plastic.org/johnbusch/{size}/323_2.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-20T11:39:46.879Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41038768.97448851,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 3,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 663,
+ username: "waxfoot",
+ name: "waxfoot",
+ avatar_template: "/user_avatar/forum.osr-plastic.org/waxfoot/{size}/179_2.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: "2022-02-27T17:23:20.455Z",
+ created_at: "2022-02-19T20:53:26.355Z",
+ last_seen_age: null,
+ last_emailed_age: 40413355.39907482,
+ created_at_age: 41091949.49975334,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 0,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 494,
+ username: "ebrad",
+ name: "ebrad",
+ avatar_template: "/letter_avatar_proxy/v4/letter/e/13edae/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-19T20:51:18.529Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41092077.32719634,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 1,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 535,
+ username: "shadabz",
+ name: "shadabz",
+ avatar_template: "/letter_avatar_proxy/v4/letter/s/c0e974/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-19T20:51:36.412Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41092059.44598454,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 1,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 567,
+ username: "jmwombacher",
+ name: "jmwombacher",
+ avatar_template: "/letter_avatar_proxy/v4/letter/j/ba9def/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-19T20:51:50.381Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41092045.47811591,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 1,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 1552,
+ username: "ettejah",
+ name: "ettejah",
+ avatar_template: "/letter_avatar_proxy/v4/letter/e/dc4da7/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-20T12:01:01.251Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41037494.60984397,
+ trust_level: 0,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 1,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 761,
+ username: "raffiki",
+ name: "raffiki",
+ avatar_template: "/letter_avatar_proxy/v4/letter/r/7ab992/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-20T11:38:38.473Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41038837.38932683,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 0,
+ can_be_suspended: true,
+ can_be_silenced: true
+ },
+ {
+ id: 1811,
+ username: "lael",
+ name: "lael",
+ avatar_template: "/letter_avatar_proxy/v4/letter/l/5f8ce5/{size}.png",
+ active: true,
+ admin: false,
+ moderator: false,
+ last_seen_at: null,
+ last_emailed_at: null,
+ created_at: "2022-02-20T12:02:57.464Z",
+ last_seen_age: null,
+ last_emailed_age: null,
+ created_at_age: 41037378.40062601,
+ trust_level: 1,
+ manual_locked_trust_level: null,
+ flag_level: 0,
+ title: null,
+ time_read: 0,
+ staged: false,
+ days_visited: 0,
+ posts_read_count: 0,
+ topics_entered: 0,
+ post_count: 1,
+ can_be_suspended: true,
+ can_be_silenced: true
+ }
+ ],
+ similar_users_count: 2888,
+ single_sign_on_record: null,
+ approved_by: {
+ id: 1,
+ username: "jerom",
+ name: "Jerome",
+ avatar_template: "/user_avatar/forum.osr-plastic.org/jerom/{size}/5655_2.png"
+ },
+ suspended_by: null,
+ silenced_by: null,
+ groups: [
+ {
+ id: 10,
+ automatic: true,
+ name: "trust_level_0",
+ display_name: "trust_level_0",
+ user_count: 2945,
+ mentionable_level: 0,
+ messageable_level: 0,
+ visibility_level: 1,
+ primary_group: false,
+ title: null,
+ grant_trust_level: null,
+ incoming_email: null,
+ has_messages: false,
+ flair_url: null,
+ flair_bg_color: null,
+ flair_color: null,
+ bio_raw: null,
+ bio_cooked: null,
+ bio_excerpt: null,
+ public_admission: false,
+ public_exit: false,
+ allow_membership_requests: false,
+ full_name: null,
+ default_notification_level: 3,
+ membership_request_template: null,
+ members_visibility_level: 0,
+ can_see_members: true,
+ can_admin_group: true,
+ publish_read_state: false
+ },
+ {
+ id: 11,
+ automatic: true,
+ name: "trust_level_1",
+ display_name: "trust_level_1",
+ user_count: 2655,
+ mentionable_level: 0,
+ messageable_level: 0,
+ visibility_level: 1,
+ primary_group: false,
+ title: null,
+ grant_trust_level: null,
+ incoming_email: null,
+ has_messages: false,
+ flair_url: null,
+ flair_bg_color: null,
+ flair_color: null,
+ bio_raw: null,
+ bio_cooked: null,
+ bio_excerpt: null,
+ public_admission: false,
+ public_exit: false,
+ allow_membership_requests: false,
+ full_name: null,
+ default_notification_level: 3,
+ membership_request_template: null,
+ members_visibility_level: 0,
+ can_see_members: true,
+ can_admin_group: true,
+ publish_read_state: false
+ },
+ {
+ id: 41,
+ automatic: false,
+ name: "OldForum",
+ user_count: 2605,
+ mentionable_level: 0,
+ messageable_level: 0,
+ visibility_level: 0,
+ primary_group: false,
+ title: "",
+ grant_trust_level: 1,
+ incoming_email: null,
+ has_messages: false,
+ flair_url: null,
+ flair_bg_color: "",
+ flair_color: "",
+ bio_raw: "",
+ bio_cooked: null,
+ bio_excerpt: null,
+ public_admission: true,
+ public_exit: true,
+ allow_membership_requests: false,
+ full_name: "OldForum",
+ default_notification_level: 3,
+ membership_request_template: "",
+ members_visibility_level: 0,
+ can_see_members: true,
+ can_admin_group: true,
+ can_edit_group: true,
+ publish_read_state: false
+ }
+ ]
+ }
\ No newline at end of file
diff --git a/packages/discourse/templates/discourse/machines/debug.osr b/packages/discourse/templates/discourse/machines/debug.osr
new file mode 100644
index 00000000..f1db6cc9
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/debug.osr
@@ -0,0 +1,6 @@
+## Product
+[% js %]
+ if(debug){
+ return "" + prettyJSON(store.product) + " ";
+ }
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/global.json b/packages/discourse/templates/discourse/machines/global.json
new file mode 100644
index 00000000..32cf6363
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/global.json
@@ -0,0 +1,33 @@
+{
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://plastic-hub.com/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales2@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_blog": "https://precious-plastic.org/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "site": "https://precious-plastic.org/",
+ "OSR_HOWTOS_ROOT_URL": "https://osr-plastic.org/howtos/",
+ "OSR_HOWTOS_PATH": "../../ph3/pp-next2/howtos",
+ "OSR_FILES_WEB":"http://files.osr-plastic.org/files/osr-machines/",
+ "OSR_MACHINES_ASSETS_URL":"https://assets.osr-plastic.org/machines/",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos":false,
+ "instagram":false,
+ "shipping":true,
+ "payment_terms":true
+ }
+}
\ No newline at end of file
diff --git a/packages/discourse/templates/discourse/machines/header_jekyll.osr b/packages/discourse/templates/discourse/machines/header_jekyll.osr
new file mode 100644
index 00000000..d3632bfe
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/header_jekyll.osr
@@ -0,0 +1,95 @@
+[% capture config %][% js %]
+const globalVariables = readJSON('${root}/osr/global.json');
+addGlobal({config:globalVariables});
+return globalVariables;
+[%endjs%][% endcapture %]
+[% capture product %][% js %]
+
+ let globalVariables = readJSON('${root}/osr/global.json');
+ let localVariables = readJSON('${PRODUCT_ROOT}/config.json');
+ let localYAML = readFile('${PRODUCT_ROOT}/config.yaml');
+
+ let defaultsYAML = fs.findUp.sync('defaults.yaml', {
+ cwd:PRODUCT_ROOT,
+ stopAt:root
+ });
+
+ if(defaultsYAML){
+ defaultsYAML = readFile(defaultsYAML).trim();
+ localYAML = `${defaultsYAML}\n${localYAML}`;
+ }
+
+ let defaultsJSON = fs.findUp.sync('defaults.json', {
+ cwd:PRODUCT_ROOT,
+ stopAt:root
+ });
+
+ if(defaultsJSON){
+ defaultsJSON = readJSON(defaultsJSON);
+ localVariables = {
+ ...defaultsJSON,
+ ...localVariables
+ }
+ }
+
+
+ let allVariables = {
+ ...localVariables,
+ ...globalVariables,
+ ...scope
+ }
+ let all = substitute(JSON.stringify(allVariables,null,2),allVariables);
+ allVariables = JSON.parse(all);
+ resolveConfig(allVariables);
+ return allVariables;
+
+[%endjs%][% endcapture %]
+---
+[% js %]
+let globalVariables = readJSON('${root}/osr/global.json');
+resolveConfig(globalVariables);
+addGlobal(globalVariables);
+let localVariables = readJSON('${PRODUCT_ROOT}/config.json');
+let localYAML = readFile('${PRODUCT_ROOT}/config.yaml');
+
+let defaultsYAML = fs.findUp.sync('defaults.yaml', {
+ cwd:PRODUCT_ROOT,
+ stopAt:root
+});
+
+if(defaultsYAML){
+ defaultsYAML = readFile(defaultsYAML).trim();
+ localYAML = `${defaultsYAML}\n${localYAML}`;
+}
+
+let defaultsJSON = fs.findUp.sync('defaults.json', {
+ cwd:PRODUCT_ROOT,
+ stopAt:root
+});
+
+if(defaultsJSON){
+ defaultsJSON = readJSON(defaultsJSON);
+ localVariables = {
+ ...defaultsJSON,
+ ...localVariables
+ }
+}
+localVariables['rel']=product.replace('products/','');
+localVariables['image']='${abs_url}/${product_rel}/renderings/perspective.jpg';
+let allVariables = {
+ ...localVariables,
+ ...globalVariables,
+ ...scope
+
+}
+
+let all = substitute(JSON.stringify(allVariables, null, 2), allVariables);
+allVariables = JSON.parse(all);
+resolveConfig(allVariables);
+store.product = allVariables;
+addGlobal(allVariables);
+register('product', allVariables);
+const yaml = substitute(localYAML, allVariables);
+return (YAML.stringify(allVariables) + yaml).trim();
+[%endjs%]
+---
diff --git a/packages/discourse/templates/discourse/machines/plugins/html.js b/packages/discourse/templates/discourse/machines/plugins/html.js
new file mode 100644
index 00000000..9ba73ea7
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/plugins/html.js
@@ -0,0 +1,50 @@
+const path = require('path');
+
+const link = (name, link, _class) => `${name} `;
+const wrap = (content) => `
+
+`;
+
+const image = (src, link, style) => ` `;
+
+const item = (content, style = 'border-color: #c5c5c5;width: 300px;display: inline-block', title) =>
+ `
+ ${content}
+
${title||''}
+`;
+
+const styles = {
+ thumb: 'border:none; width:200px;max-height:200px'
+};
+
+const center_caption = (el = 'h5', text) => `<${el} style="text-align:center">${text}${el}>`;
+
+const thumbs = (url, folder) => {
+ const context = require('@plastichub/osrl/library').getContext();
+ folder = path.resolve(folder);
+ let images = context.fs.images(folder, {
+ absolute: false
+ });
+ images = images.map((i) => item(image(`${url}/${i}`), 'border:none; width:200px;max-height:200px'));
+ images = wrap(images.join('\n'));
+ return images;
+}
+module.exports = {
+ html: {
+ link: link,
+ caption: {
+ center: center_caption
+ },
+ container: {
+ wrap: wrap,
+ item: item
+ },
+ image: image,
+ styles: styles,
+ thumbs: thumbs
+ }
+};
\ No newline at end of file
diff --git a/packages/discourse/templates/discourse/machines/root.html b/packages/discourse/templates/discourse/machines/root.html
new file mode 100644
index 00000000..ef5b6fc9
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/root.html
@@ -0,0 +1,54 @@
+[% include "product_variables.osr" %]
+[% include "body.md" %]
+[% include "header_notice.osr" %]
+[%- include "product_overview_drawings.osr" -%]
+
+[%- if product.showSpecs !=false || config.show.authors -%]
+
+
+ [%- if product.showSpecs !=false -%]
+
+
Specification
+ [% include "product_specs.osr" html:false %]
+
+ [%endif%]
+
+ [% if config.show.authors %]
+ [%- if product.showAuthors !=false -%]
+ [% include "authors_html.osr" authors:product.authors showHeader:true %]
+ [%endif%]
+ [%endif%]
+
+
+
+[%endif%]
+
+[%- if product.showResources !=false %]
+ [% include "product_resources.osr" %]
+[%endif%]
+
+
+
+[% if config.show.shipping %]
+ [% include "product_shipping.osr" %]
+[% endif -%]
+
+[% if config.show.payment_terms %]
+ [% include "payment_terms.osr" %]
+[% endif -%]
+
+
+
+[% if config.show.others %]
+ [% include "other_products.osr" %]
+[%endif%]
+[% if config.show.howtos %]
+ [% include "product_howtos.osr" %]
+[%endif%]
+[% include "social_links.osr" %]
+[% if config.show.instagram %]
+[% include "vendor_instagram.osr" %]
+[%endif%]
+[% if config.show.debug %]
+ [% include "product_debug.osr" %]
+[%endif%]
diff --git a/packages/discourse/templates/discourse/machines/variables.osr b/packages/discourse/templates/discourse/machines/variables.osr
new file mode 100644
index 00000000..c0ec07cf
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/variables.osr
@@ -0,0 +1,56 @@
+[% capture config %][% js %]
+const globalVariables = readJSON('${root}/osr/global.json');
+addGlobal({config:globalVariables});
+return globalVariables;
+[%endjs%][% endcapture %]
+
+[% capture product %][% js %]
+
+ let globalVariables = readJSON('${root}/osr/global.json');
+ let localVariables = readJSON('${PRODUCT_ROOT}/config.json');
+ localVariables['image']='${product_rel}/renderings/perspective.jpg';
+ localVariables['rel']=product.replace('products/','');
+ localVariables['sidebar'] = {
+ nav: "machines"
+ };
+
+ let localYAML = readFile('${PRODUCT_ROOT}/config.yaml');
+
+ let defaultsYAML = fs.findUp.sync('defaults.yaml', {
+ cwd:PRODUCT_ROOT,
+ stopAt:root
+ });
+
+ if(defaultsYAML){
+ defaultsYAML = readFile(defaultsYAML).trim();
+ localYAML = `${defaultsYAML}\n${localYAML}`;
+ }
+
+ let defaultsJSON = fs.findUp.sync('defaults.json', {
+ cwd:PRODUCT_ROOT,
+ stopAt:root
+ });
+
+ if(defaultsJSON){
+ defaultsJSON = readJSON(defaultsJSON);
+ localVariables = {
+ ...defaultsJSON,
+ ...localVariables
+ }
+ }
+
+
+ let allVariables = {
+ ...localVariables,
+ ...globalVariables,
+ ...scope
+ }
+ allVariables.product_rel = product;
+ allVariables.product_rel_min = product.replace('products/','')
+ let all = substitute(JSON.stringify(allVariables,null,2),allVariables);
+ allVariables = JSON.parse(all);
+ resolveConfig(allVariables);
+ addGlobal({product:allVariables});
+ return allVariables;
+
+[%endjs%][% endcapture %]
diff --git a/packages/discourse/templates/discourse/machines/widgets/authors.osr b/packages/discourse/templates/discourse/machines/widgets/authors.osr
new file mode 100644
index 00000000..b1877bb8
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/authors.osr
@@ -0,0 +1,10 @@
+[%if showHeader %]
+## Authors
+[%endif%]
+
+[% for author in authors %]
+- [ [[author.name]] ]( [[author.url]] )
+[% endfor %]
+
+[% js %]
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/authors_html.osr b/packages/discourse/templates/discourse/machines/widgets/authors_html.osr
new file mode 100644
index 00000000..9e64af50
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/authors_html.osr
@@ -0,0 +1,8 @@
+[%if showHeader %]
+ Authors
+[%endif%]
+
diff --git a/packages/discourse/templates/discourse/machines/widgets/extra_resources.md b/packages/discourse/templates/discourse/machines/widgets/extra_resources.md
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/discourse/templates/discourse/machines/widgets/forum.osr b/packages/discourse/templates/discourse/machines/widgets/forum.osr
new file mode 100644
index 00000000..d1990202
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/forum.osr
@@ -0,0 +1,25 @@
+[%js%]
+try{
+ return new Promise((resolve, reject) => {
+ const d = new Discourse.Discourser({
+ host: config.discourse.host,
+ key: config.discourse.key,
+ username: config.discourse.username,
+ rateLimitConcurrency: 1
+ });
+ d.getTopicItemsOfCategories([category]).then((posts) => {
+ if(!posts.length){
+ return '';
+ }
+ posts = posts.map((p)=>{
+ const url = `${config.discourse.host}/t/${p.id}`;
+ const title = `${p.fancy_title}`;
+ return `${title} `;
+ }).join('\n');
+ resolve(posts);
+ });
+ });
+}catch(e){
+ debugger;
+}
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/gallery.osr b/packages/discourse/templates/discourse/machines/widgets/gallery.osr
new file mode 100644
index 00000000..b4fda644
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/gallery.osr
@@ -0,0 +1,10 @@
+[%js%]
+const _path = substitute(`${cwd}/${product_rel}/${path}`)
+if(fs.images(_path).length)
+{
+ const t = html.thumbs(`${abs_url}/${product_rel}/${path}`,_path);
+ return `${name} ${t}`;
+}else{
+ console.log(_path + 'doesnt exists');
+}
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/howtos.osr b/packages/discourse/templates/discourse/machines/widgets/howtos.osr
new file mode 100644
index 00000000..79207c4b
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/howtos.osr
@@ -0,0 +1,12 @@
+[%js%]
+if(store.product.howtos && store.product.howtos.length){
+ return store.product.howtos.map((i)=>{
+ return i
+ }).join('\n ');
+ /*
+ const t = html.thumbs(`${abs_url}/${product}/media/products`,`${PRODUCT_ROOT}/media/products`);
+ return `Products done with ${store.product.name}
+ ${t}`;
+ */
+}
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/other_products.osr b/packages/discourse/templates/discourse/machines/widgets/other_products.osr
new file mode 100644
index 00000000..0b87ed16
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/other_products.osr
@@ -0,0 +1,25 @@
+
+
See our other products
+
+[%js%]
+const template = readFile('${root}/osr/bazar/other_item.html');
+let product = store.product;
+let all = config.all.filter((p)=>{
+ return p.slug !== product.slug;
+})
+const ret = all.map((p)=>{
+ const vars = {
+ ...p,
+ image: p.image || substitute('${abs_url}/' + p.rel + '/renderings/perspective.jpg',global)
+ }
+ return substitute(template,vars);
+})
+return ret;
+[%endjs%]
+
+
+
diff --git a/packages/discourse/templates/discourse/machines/widgets/overview_drawings.osr b/packages/discourse/templates/discourse/machines/widgets/overview_drawings.osr
new file mode 100644
index 00000000..9ed438a8
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/overview_drawings.osr
@@ -0,0 +1,27 @@
+[%- if product.showDimensions !=false -%]
+ Dimensions
+
+
+
+
+
+
+[%- endif -%]
+[%- if product.showParts !=false -%]
+
+
+
+
+
[% include 'product_parts.osr' %]
+
+
+
+
+[%- endif -%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/parts.osr b/packages/discourse/templates/discourse/machines/widgets/parts.osr
new file mode 100644
index 00000000..46f60401
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/parts.osr
@@ -0,0 +1,7 @@
+[%js%]
+let p = PRODUCT_ROOT;
+const _path = path.resolve(PRODUCT_ROOT + './parts.xlsx');
+const data = xlsx.parse(_path);
+data[0].data = data[0].data.filter((d) => !!d.length);
+return md2html(markdownTable(data[0].data));
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/resources.osr b/packages/discourse/templates/discourse/machines/widgets/resources.osr
new file mode 100644
index 00000000..4ee51d6e
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/resources.osr
@@ -0,0 +1,45 @@
+
+### Resources
+
+[% if product.forum -%]
+- [Forum]([[product.forum]])
+[% endif %]
+[%- if product.download -%]
+- [Download]([[product.download]])
+[% endif %]
+[%- if product.firmware -%]
+- [Firmware]([[product.firmware]])
+[%- endif %]
+[%- if product.Preview3d -%]
+[%- if product.edrawings -%]
+- [3D-Preview]([[product.edrawings]])
+[% else %]
+- [3D-Preview]([[OSR_MACHINES_ASSETS_URL]]/[[product.product_rel_min]]/resources/edrawings.html)
+[% endif -%]
+- [Source Code Repository]([[GIT_REPO]]/src/branch/master/[[product.rel]])
+[%-endif-%]
+[%- if product.hasSpec -%]
+- [Specification PDF]([[OSR_MACHINES_ASSETS_URL]]/[[product.product_rel_min]]/resources/spec.pdf)
+[%- endif -%]
+[% if product.howtoSection %]
+- [How-tos]([[product.howtoSection]])
+[%- endif -%]
+[% if product.library %]
+- [Library]([[product.library]])
+[% endif %]
+
+[%- if config.show.wiki -%]
+ [%- if product.wiki_articles -%]
+Wiki Articles
+[%- include "product_wiki.osr" category:product.wiki_articles -%]
+ [%- else -%]
+ [%- endif -%]
+[%- else -%]
+[%- endif -%]
+[%- if config.show.forum -%]
+ [%- if product.forumCategory -%]
+Forum Posts
+[%- include "product_forum.osr" category:product.forumCategory -%]
+ [%- endif -%]
+[%- endif -%]
+[%- include "extra_resources.md" -%]
\ No newline at end of file
diff --git a/packages/discourse/templates/discourse/machines/widgets/showreel.osr b/packages/discourse/templates/discourse/machines/widgets/showreel.osr
new file mode 100644
index 00000000..7bd0337a
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/showreel.osr
@@ -0,0 +1,7 @@
+[%js%]
+if(fs.images(`${PRODUCT_ROOT}/media/products`).length){
+ const t = html.thumbs(`${abs_url}/${product}/media/products`,`${PRODUCT_ROOT}/media/products`);
+ return `Products done with ${store.product.name}
+ ${t}`;
+}
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/social_links.osr b/packages/discourse/templates/discourse/machines/widgets/social_links.osr
new file mode 100644
index 00000000..50856ea2
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/social_links.osr
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+ [%- if config.vendor_youtube -%]
+
+
+
+
+
+ [% endif %]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/discourse/templates/discourse/machines/widgets/specs.osr b/packages/discourse/templates/discourse/machines/widgets/specs.osr
new file mode 100644
index 00000000..562482cb
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/specs.osr
@@ -0,0 +1,18 @@
+[%js%]
+let p = PRODUCT_ROOT;
+const _path = path.resolve(PRODUCT_ROOT + './specs.xlsx');
+if(!fs.exists(_path)){
+ console.warn('cant find specs', _path)
+ return
+}
+let data = xlsx.parse(_path);
+data[0].data = data[0].data.filter((d)=>d.length >0);
+data = markdownTable(data[0].data);
+if(html){
+ return md2html(data);
+}else{
+
+ data;
+
+}
+[%endjs%]
diff --git a/packages/discourse/templates/discourse/machines/widgets/table.osr b/packages/discourse/templates/discourse/machines/widgets/table.osr
new file mode 100644
index 00000000..47f97278
--- /dev/null
+++ b/packages/discourse/templates/discourse/machines/widgets/table.osr
@@ -0,0 +1,16 @@
+[%js%]
+const _path = path.resolve(`${PRODUCT_ROOT}/${table}`)
+if(!fs.exists(_path)){
+ console.warn('cant find table', _path)
+ return
+}
+console.log(' table path ' + _path)
+let data = xlsx.parse(_path)
+data[0].data = data[0].data.filter((d)=>d.length >0)
+data = markdownTable(data[0].data)
+if(html){
+ return md2html(data)
+}else{
+ data
+}
+[%endjs%]
diff --git a/packages/discourse/tests/image.jpg b/packages/discourse/tests/image.jpg
new file mode 100644
index 00000000..d779835c
Binary files /dev/null and b/packages/discourse/tests/image.jpg differ
diff --git a/packages/discourse/tests/sync/md.md b/packages/discourse/tests/sync/md.md
new file mode 100644
index 00000000..8730dfba
--- /dev/null
+++ b/packages/discourse/tests/sync/md.md
@@ -0,0 +1,52 @@
+---
+cat: 65
+title: "OSR - Discourse Test Another Test"
+owner: 1
+tags: "plastic,meta"
+topic_id: 10047
+post_id: 27411
+---
+### Something on my heart ;-)
+
+```ts
+export const CAT_TEST = 65
+export const HT_CAT_GUIDES = 86
+export const HT_CAT_MACHINES = 87
+export const HT_CAT_PRODUCTS = 88
+export const HT_CAT_MOULDS = 89
+
+export const HT_CATS = {
+ 'Guides' : HT_CAT_GUIDES,
+ 'Machines': HT_CAT_MACHINES,
+ 'Products' : HT_CAT_PRODUCTS,
+ 'Moulds' : HT_CAT_MOULDS
+}
+```
+
+### Images
+
+#### Remote Image
+
+
+
+#### Local Image
+
+
+
+### Discourse Image
+
+
+
+### Paths / Urls
+
+#### Remote Url
+
+[Valve](https://osr-plastic.org/machines/304_Valve-40mm.html)
+
+#### Local Path
+
+[Test MD](./tests/md.md)
+
+### Discourse Url
+
+- [PID Firmware for Injection](https://forum.osr-plastic.org/t/pid-firmware-for-injection/6603)
diff --git a/packages/discourse/tmp-a.json b/packages/discourse/tmp-a.json
new file mode 100644
index 00000000..990c2a1e
--- /dev/null
+++ b/packages/discourse/tmp-a.json
@@ -0,0 +1,268 @@
+{
+ "PRODUCT_ROOT": "C://Users//mc007//Desktop//osr//osr-machines/sheetpress/100cm/",
+ "abs_url": "https://assets.osr-plastic.org",
+ "CACHE": "C://Users//mc007//Desktop//osr//osr-machines/cache/",
+ "GIT_REPO": "https://git.osr-plastic.org/osr-plastic/osr-machines",
+ "OSR_MACHINES_ASSETS_URL": "https://assets.osr-plastic.org/machines/",
+ "OSR_FILES_WEB": "https://files.osr-plastic.org/files/osr-machines",
+ "OSR_DIRECTORY_ASSETS_URL": "https://assets.osr-plastic.org/directory/",
+ "OSR_DIRECTORY_FILES_WEB": "http://files.osr-plastic.org/files/directory",
+ "PRODUCTS_FILES_URL": "https://files.osr-plastic.org/files/osr-machines/sheetpress/100cm",
+ "PRODUCTS_ASSETS_URL": "https://assets.osr-plastic.org/machines/sheetpress/100cm",
+ "OSR_HOWTOS_ROOT_URL": "https://forum.osr-plastic.org/c/wiki/howtos/72",
+ "OSR_FORUM_URL": "https://forum.osr-plastic.org",
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://osr-plastic.org/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "vendor_forum": "https://forum.osr-plastic.org",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": false,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "productDump": false,
+ "configDump": false,
+ "issues": false,
+ "alternatives": true,
+ "replacedBy": true,
+ "meta": true
+ },
+ "forumCategory": 63,
+ "forum": "https://forum.osr-plastic.org/c/machines/sheetpress/63",
+ "howtoSection": "https://osr-plastic.org/howto/#sheetpress",
+ "edrawings:": "https://assets.osr-plastic.org/machines//sheetpress/100cmresources/edrawings.html",
+ "showParts": false,
+ "showDimensions": false,
+ "Preview3d": true,
+ "forumTags": "sheetpress",
+ "forumUserId": 1,
+ "howto_categories": "86",
+ "download": "https://files.osr-plastic.org/files/osr-machines/sheetpress/100cm",
+ "library": "https://osr-plastic.org/machines/sheetpress.html",
+ "preview": "https://assets.osr-plastic.org/machines//sheetpress/100cm/media/latest.jpg",
+ "product_parts": "https://assets.osr-plastic.org/machines//sheetpress/100cm/drawings/parts.jpg",
+ "product_dimensions": "https://assets.osr-plastic.org/machines//sheetpress/100cm/drawings/dimensions.jpg",
+ "slug": "sheetpress",
+ "category": "sheetpress",
+ "feature": "1m Sheets",
+ "code": "SPM",
+ "name": "Sheetpress",
+ "keywords": "sheetpress",
+ "authors": [
+ {
+ "name": "Jason Knight",
+ "url": "https://www.mandin.earth/"
+ }
+ ],
+ "forumPostHash": "da522fc5546d4d7c3c86bada779d1aa4",
+ "forumTopicId": 10152,
+ "forumPostId": 27597,
+ "image": "sheetpress/100cm/renderings/perspective.jpg",
+ "config": {
+ "includes": [
+ "C:/Users/mc007/Desktop/osr/osr-machines/osr",
+ "C:/Users/mc007/Desktop/osr/osr-machines/osr/widgets",
+ "C:/Users/mc007/Desktop/osr/osr-templates/commons",
+ "C:/Users/mc007/Desktop/osr/osr-templates/discourse",
+ "C:/Users/mc007/Desktop/osr/osr-templates/discourse/commons",
+ "C:/Users/mc007/Desktop/osr/osr-templates/discourse/widgets",
+ "C:/Users/mc007/Desktop/osr/osr-machines/sheetpress/100cm/",
+ "C:/Users/mc007/Desktop/osr/osr-machines/sheetpress/100cm//templates/site/",
+ "C:/Users/mc007/Desktop/osr/osr-machines/sheetpress/100cm//templates/shared/"
+ ],
+ "variables": {
+ "PRODUCT_ROOT": "C:/Users/mc007/Desktop/osr/osr-machines/sheetpress/100cm/",
+ "abs_url": "https://assets.osr-plastic.org",
+ "CACHE": "C:/Users/mc007/Desktop/osr/osr-machines/cache/",
+ "GIT_REPO": "https://git.osr-plastic.org/osr-plastic/osr-machines",
+ "OSR_MACHINES_ASSETS_URL": "https://assets.osr-plastic.org/machines/",
+ "OSR_FILES_WEB": "https://files.osr-plastic.org/files/osr-machines",
+ "OSR_DIRECTORY_ASSETS_URL": "https://assets.osr-plastic.org/directory/",
+ "OSR_DIRECTORY_FILES_WEB": "http://files.osr-plastic.org/files/directory",
+ "PRODUCTS_FILES_URL": "https://files.osr-plastic.org/files/osr-machines/sheetpress/100cm",
+ "PRODUCTS_ASSETS_URL": "https://assets.osr-plastic.org/machines/sheetpress/100cm",
+ "OSR_HOWTOS_ROOT_URL": "https://forum.osr-plastic.org/c/wiki/howtos/72",
+ "OSR_FORUM_URL": "https://forum.osr-plastic.org",
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://osr-plastic.org/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "vendor_forum": "https://forum.osr-plastic.org",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": false,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "productDump": false,
+ "configDump": false,
+ "issues": false,
+ "alternatives": true,
+ "replacedBy": true,
+ "meta": true
+ }
+ },
+ "env": {
+ "bazar": {
+ "includes": [],
+ "variables": {
+ "abs_url": "https://dev.osr-plastic.org/"
+ }
+ },
+ "bazar-release": {
+ "includes": [],
+ "variables": {
+ "abs_url": "https://shop.osr-plastic.org/"
+ }
+ },
+ "test-import": {},
+ "forum": {
+ "includes": [],
+ "variables": {
+ "forum_url": "https://forum.osr-plastic.org/",
+ "show": {
+ "badges": true,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": true,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "meta": true,
+ "productDump": true,
+ "configDump": false
+ }
+ }
+ }
+ }
+ },
+ "variables": {
+ "PRODUCT_ROOT": "C:/Users/mc007/Desktop/osr/osr-machines/sheetpress/100cm/",
+ "abs_url": "https://assets.osr-plastic.org",
+ "CACHE": "C:/Users/mc007/Desktop/osr/osr-machines/cache/",
+ "GIT_REPO": "https://git.osr-plastic.org/osr-plastic/osr-machines",
+ "OSR_MACHINES_ASSETS_URL": "https://assets.osr-plastic.org/machines/",
+ "OSR_FILES_WEB": "https://files.osr-plastic.org/files/osr-machines",
+ "OSR_DIRECTORY_ASSETS_URL": "https://assets.osr-plastic.org/directory/",
+ "OSR_DIRECTORY_FILES_WEB": "http://files.osr-plastic.org/files/directory",
+ "PRODUCTS_FILES_URL": "https://files.osr-plastic.org/files/osr-machines/sheetpress/100cm",
+ "PRODUCTS_ASSETS_URL": "https://assets.osr-plastic.org/machines/sheetpress/100cm",
+ "OSR_HOWTOS_ROOT_URL": "https://forum.osr-plastic.org/c/wiki/howtos/72",
+ "OSR_FORUM_URL": "https://forum.osr-plastic.org",
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://osr-plastic.org/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "vendor_forum": "https://forum.osr-plastic.org",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": false,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "productDump": false,
+ "configDump": false,
+ "issues": false,
+ "alternatives": true,
+ "replacedBy": true,
+ "meta": true
+ }
+ },
+ "i18n": "C:/Users/mc007/Desktop/osr/i18n-store/store-en.json",
+ "OSR_ROOT": "C://Users//mc007//Desktop//osr",
+ "OSR_TEMP": "C://Users//mc007//AppData//Local//Temp//osr",
+ "OA_ROOT": "C://Users//mc007//Desktop//ph3//pp-next2",
+ "KB_ROOT": "C://Users//mc007//Desktop//osr//osr-kb-next",
+ "OSR_CACHE": "C://Users//mc007//.osr//cache",
+ "OSR_LIBRARY": "C://Users//mc007//Desktop//osr//osr-machines",
+ "OSR_LIBRARY_MACHINES": "C://Users//mc007//Desktop//osr//osr-machines",
+ "OSR_USER_ASSETS": "C://Users//mc007//Desktop//osr//osr-user-assets",
+ "OSR_PRIVATE": "C://Users//mc007//.osr//",
+ "OSR_TEMPLATES": "C://Users//mc007//Desktop//osr//osr-templates",
+ "OSR_CONTENT": "C://Users//mc007//Desktop//osr//osr-content",
+ "OSR_PROFILES": "C://Users//mc007//Desktop//osr//osr-profiles",
+ "root": "C://Users//mc007//Desktop//osr//osr-machines",
+ "cwd": "C://Users//mc007//Desktop//osr//osr-discourse",
+ "SRC_PATH": "C://Users//mc007//Desktop//osr/osr-templates/discourse/root.html",
+ "SRC_DIR": "C://Users//mc007//Desktop//osr/osr-templates/discourse",
+ "SRC_NAME": "root",
+ "SRC_FILE_NAME": "root.html",
+ "SRC_FILE_EXT": "html",
+ "SRC_IS_FILE": true,
+ "SRC_IS_FOLDER": false,
+ "SRC_IS_EXPRESSION": false,
+ "SRC_IS_GLOB": false,
+ "SRC_GLOB": "**/config.+(json)",
+ "SRC_GLOB_EXTENSIONS": [
+ "json"
+ ],
+ "SRC_FILES": [
+ "C://Users//mc007//Desktop//osr/osr-templates/discourse/root.html"
+ ],
+ "product": "sheetpress/100cm",
+ "product_rel": "sheetpress/100cm",
+ "product_rel_min": "sheetpress/100cm",
+ "GIT_LAST": "Thursday, February 15, 2024 12:52 PM",
+ "GIT_AUTHOR": "lovebird",
+ "GIT_MESSAGE": "todos | latest :)",
+ "GIT_COMMIT": "2bdacc5427b7d47e4d5aaf73bf0fe48fd703f2e0",
+ "debug": false,
+ "env": "forum",
+ "forum_url": "https://forum.osr-plastic.org/"
+}
\ No newline at end of file
diff --git a/packages/discourse/tmp.json b/packages/discourse/tmp.json
new file mode 100644
index 00000000..8f290618
--- /dev/null
+++ b/packages/discourse/tmp.json
@@ -0,0 +1,268 @@
+{
+ "PRODUCT_ROOT": "C:\\Users\\mc007\\Desktop\\osr\\osr-machines/sheetpress/100cm/",
+ "abs_url": "https://assets.osr-plastic.org",
+ "CACHE": "C:\\Users\\mc007\\Desktop\\osr\\osr-machines/cache/",
+ "GIT_REPO": "https://git.osr-plastic.org/osr-plastic/osr-machines",
+ "OSR_MACHINES_ASSETS_URL": "https://assets.osr-plastic.org/machines/",
+ "OSR_FILES_WEB": "https://files.osr-plastic.org/files/osr-machines",
+ "OSR_DIRECTORY_ASSETS_URL": "https://assets.osr-plastic.org/directory/",
+ "OSR_DIRECTORY_FILES_WEB": "http://files.osr-plastic.org/files/directory",
+ "PRODUCTS_FILES_URL": "https://files.osr-plastic.org/files/osr-machines/sheetpress/100cm",
+ "PRODUCTS_ASSETS_URL": "https://assets.osr-plastic.org/machines/sheetpress/100cm",
+ "OSR_HOWTOS_ROOT_URL": "https://forum.osr-plastic.org/c/wiki/howtos/72",
+ "OSR_FORUM_URL": "https://forum.osr-plastic.org",
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://osr-plastic.org/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "vendor_forum": "https://forum.osr-plastic.org",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": false,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "productDump": false,
+ "configDump": false,
+ "issues": false,
+ "alternatives": true,
+ "replacedBy": true,
+ "meta": true
+ },
+ "forumCategory": 63,
+ "forum": "https://forum.osr-plastic.org/c/machines/sheetpress/63",
+ "howtoSection": "https://osr-plastic.org/howto/#sheetpress",
+ "edrawings:": "${OSR_MACHINES_ASSETS_URL}/${product_rel}resources/edrawings.html",
+ "showParts": false,
+ "showDimensions": false,
+ "Preview3d": true,
+ "forumTags": "sheetpress",
+ "forumUserId": 1,
+ "howto_categories": "86",
+ "download": "${OSR_FILES_WEB}/${product_rel_min}",
+ "library": "https://osr-plastic.org/machines/${slug}.html",
+ "preview": "${OSR_MACHINES_ASSETS_URL}/${product_rel}/media/latest.jpg",
+ "product_parts": "${OSR_MACHINES_ASSETS_URL}/${product_rel_min}/drawings/parts.jpg",
+ "product_dimensions": "${OSR_MACHINES_ASSETS_URL}/${product_rel_min}/drawings/dimensions.jpg",
+ "slug": "sheetpress",
+ "category": "sheetpress",
+ "feature": "1m Sheets",
+ "code": "SPM",
+ "name": "Sheetpress",
+ "keywords": "sheetpress",
+ "authors": [
+ {
+ "name": "Jason Knight",
+ "url": "https://www.mandin.earth/"
+ }
+ ],
+ "forumPostHash": "da522fc5546d4d7c3c86bada779d1aa4",
+ "forumTopicId": 10152,
+ "forumPostId": 27597,
+ "image": "${product_rel}/renderings/perspective.jpg",
+ "config": {
+ "includes": [
+ "${root}/osr",
+ "${root}/osr/widgets",
+ "${OSR_ROOT}/osr-templates/commons",
+ "${OSR_ROOT}/osr-templates/discourse",
+ "${OSR_ROOT}/osr-templates/discourse/commons",
+ "${OSR_ROOT}/osr-templates/discourse/widgets",
+ "${PRODUCT_ROOT}",
+ "${PRODUCT_ROOT}/templates/site/",
+ "${PRODUCT_ROOT}/templates/shared/"
+ ],
+ "variables": {
+ "PRODUCT_ROOT": "${root}/${product}/",
+ "abs_url": "https://assets.osr-plastic.org",
+ "CACHE": "${root}/cache/",
+ "GIT_REPO": "https://git.osr-plastic.org/osr-plastic/osr-machines",
+ "OSR_MACHINES_ASSETS_URL": "https://assets.osr-plastic.org/machines/",
+ "OSR_FILES_WEB": "https://files.osr-plastic.org/files/osr-machines",
+ "OSR_DIRECTORY_ASSETS_URL": "https://assets.osr-plastic.org/directory/",
+ "OSR_DIRECTORY_FILES_WEB": "http://files.osr-plastic.org/files/directory",
+ "PRODUCTS_FILES_URL": "${OSR_FILES_WEB}/${product_rel}",
+ "PRODUCTS_ASSETS_URL": "https://assets.osr-plastic.org/machines/${product}",
+ "OSR_HOWTOS_ROOT_URL": "${vendor_forum}/c/wiki/howtos/72",
+ "OSR_FORUM_URL": "https://forum.osr-plastic.org",
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://osr-plastic.org/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "vendor_forum": "https://forum.osr-plastic.org",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": false,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "productDump": false,
+ "configDump": false,
+ "issues": false,
+ "alternatives": true,
+ "replacedBy": true,
+ "meta": true
+ }
+ },
+ "env": {
+ "bazar": {
+ "includes": [],
+ "variables": {
+ "abs_url": "https://dev.osr-plastic.org/"
+ }
+ },
+ "bazar-release": {
+ "includes": [],
+ "variables": {
+ "abs_url": "https://shop.osr-plastic.org/"
+ }
+ },
+ "test-import": {},
+ "forum": {
+ "includes": [],
+ "variables": {
+ "forum_url": "https://forum.osr-plastic.org/",
+ "show": {
+ "badges": true,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": true,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "meta": true,
+ "productDump": true,
+ "configDump": false
+ }
+ }
+ }
+ }
+ },
+ "variables": {
+ "PRODUCT_ROOT": "${root}/${product}/",
+ "abs_url": "https://assets.osr-plastic.org",
+ "CACHE": "${root}/cache/",
+ "GIT_REPO": "https://git.osr-plastic.org/osr-plastic/osr-machines",
+ "OSR_MACHINES_ASSETS_URL": "https://assets.osr-plastic.org/machines/",
+ "OSR_FILES_WEB": "https://files.osr-plastic.org/files/osr-machines",
+ "OSR_DIRECTORY_ASSETS_URL": "https://assets.osr-plastic.org/directory/",
+ "OSR_DIRECTORY_FILES_WEB": "http://files.osr-plastic.org/files/directory",
+ "PRODUCTS_FILES_URL": "${OSR_FILES_WEB}/${product_rel}",
+ "PRODUCTS_ASSETS_URL": "https://assets.osr-plastic.org/machines/${product}",
+ "OSR_HOWTOS_ROOT_URL": "${vendor_forum}/c/wiki/howtos/72",
+ "OSR_FORUM_URL": "https://forum.osr-plastic.org",
+ "vendor_name": "Plastic Hub",
+ "vendor_website": "https://osr-plastic.org/",
+ "vendor_products_external": "https://plastic-hub.com/products/",
+ "vendor_instagram": "https://www.instagram.com/osr_plastic/",
+ "_vendor_youtube": "https://www.youtube.com/channel/UCuWDxJtV2pf5BefHEy09Cew/featured?view_as=subscriber",
+ "vendor_github": "https://git.osr-plastic.org/osr-plastic",
+ "vendor_contact_email": "mailto:sales@plastic-hub.com",
+ "vendor_whatsapp": "tel:0034691952287",
+ "vendor_facebook": "https://www.facebook.com/plastichubcat/",
+ "vendor_discord": "https://discord.gg/vR5d6ShTez",
+ "author_link_pp": "https://preciousplastic.com/",
+ "author_link": "https://osr-plastic.org",
+ "vendor_forum": "https://forum.osr-plastic.org",
+ "show": {
+ "badges": false,
+ "authors": true,
+ "head": true,
+ "debug": false,
+ "wiki": false,
+ "forum": false,
+ "others": false,
+ "howtos": false,
+ "instagram": false,
+ "shipping": false,
+ "payment_terms": false,
+ "components": true,
+ "marketplaceLinks": true,
+ "productDump": false,
+ "configDump": false,
+ "issues": false,
+ "alternatives": true,
+ "replacedBy": true,
+ "meta": true
+ }
+ },
+ "i18n": "${OSR_ROOT}/i18n-store/store-en.json",
+ "OSR_ROOT": "C:\\Users\\mc007\\Desktop\\osr",
+ "OSR_TEMP": "C:\\Users\\mc007\\AppData\\Local\\Temp\\osr",
+ "OA_ROOT": "C:\\Users\\mc007\\Desktop\\ph3\\pp-next2",
+ "KB_ROOT": "C:\\Users\\mc007\\Desktop\\osr\\osr-kb-next",
+ "OSR_CACHE": "C:\\Users\\mc007\\.osr\\cache",
+ "OSR_LIBRARY": "C:\\Users\\mc007\\Desktop\\osr\\osr-machines",
+ "OSR_LIBRARY_MACHINES": "C:\\Users\\mc007\\Desktop\\osr\\osr-machines",
+ "OSR_USER_ASSETS": "C:\\Users\\mc007\\Desktop\\osr\\osr-user-assets",
+ "OSR_PRIVATE": "C:\\Users\\mc007\\.osr\\",
+ "OSR_TEMPLATES": "C:\\Users\\mc007\\Desktop\\osr\\osr-templates",
+ "OSR_CONTENT": "C:\\Users\\mc007\\Desktop\\osr\\osr-content",
+ "OSR_PROFILES": "C:\\Users\\mc007\\Desktop\\osr\\osr-profiles",
+ "root": "C:\\Users\\mc007\\Desktop\\osr\\osr-machines",
+ "cwd": "C:\\Users\\mc007\\Desktop\\osr\\osr-discourse",
+ "SRC_PATH": "C:\\Users\\mc007\\Desktop\\osr/osr-templates/discourse/root.html",
+ "SRC_DIR": "C:\\Users\\mc007\\Desktop\\osr/osr-templates/discourse",
+ "SRC_NAME": "root",
+ "SRC_FILE_NAME": "root.html",
+ "SRC_FILE_EXT": "html",
+ "SRC_IS_FILE": true,
+ "SRC_IS_FOLDER": false,
+ "SRC_IS_EXPRESSION": false,
+ "SRC_IS_GLOB": false,
+ "SRC_GLOB": "**/config.+(json)",
+ "SRC_GLOB_EXTENSIONS": [
+ "json"
+ ],
+ "SRC_FILES": [
+ "C:\\Users\\mc007\\Desktop\\osr/osr-templates/discourse/root.html"
+ ],
+ "product": "sheetpress/100cm",
+ "product_rel": "sheetpress/100cm",
+ "product_rel_min": "sheetpress/100cm",
+ "GIT_LAST": "Thursday, February 15, 2024 12:52 PM",
+ "GIT_AUTHOR": "lovebird",
+ "GIT_MESSAGE": "todos | latest :)",
+ "GIT_COMMIT": "2bdacc5427b7d47e4d5aaf73bf0fe48fd703f2e0",
+ "debug": false,
+ "env": "forum",
+ "forum_url": "https://forum.osr-plastic.org/"
+}
\ No newline at end of file
diff --git a/packages/discourse/tsconfig.json b/packages/discourse/tsconfig.json
new file mode 100644
index 00000000..57e47309
--- /dev/null
+++ b/packages/discourse/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "ES2019",
+ "allowJs": true,
+ "noImplicitAny": false,
+ "noImplicitThis": false,
+ "alwaysStrict": true,
+ "inlineSourceMap": true,
+ "outDir": "./",
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
+ "pretty": false,
+ "baseUrl": "./src",
+ "rootDir": "./src",
+ "watch": false,
+ "allowSyntheticDefaultImports": true
+ },
+ "filesGlob": [
+ "./src/**/*.ts"
+ ],
+ "files": [
+ "./src/index.ts",
+ "./src/main.ts"
+ ]
+}
\ No newline at end of file
diff --git a/packages/discourse/types.d.ts b/packages/discourse/types.d.ts
new file mode 100644
index 00000000..fdf88bdb
--- /dev/null
+++ b/packages/discourse/types.d.ts
@@ -0,0 +1,158 @@
+import { PATH_INFO, SRC_VARIABLES } from '@plastichub/osr-cli-commons';
+import { IBaseOptions as IOSRLBaseOptions } from '@plastichub/osrl';
+import { EDiscourseConfigKey } from 'lib/discourse/constants';
+import { IProcessingNode } from '@plastichub/fs/interfaces';
+import { TFindFilter } from '@plastichub/osr-fs-utils';
+export interface Hash {
+ [id: string]: T;
+}
+export type IOptions = {
+ src: string;
+ id: string;
+ cat: string;
+ track: string;
+ variables: Hash;
+ cwd: string;
+ env: string;
+ verb: string;
+ debug: boolean;
+ disabled: boolean;
+ dry?: boolean;
+ all?: boolean;
+ stdout: boolean;
+ pathVariables: Hash;
+};
+/**
+ * An enumeration to narrow a conflict resolve to a single item or for all following conflicts.
+ *
+ * @export
+ * @enum {number}
+ */
+export declare enum EResolve {
+ /**
+ * Always will use the chose conflict settings for all following conflicts.
+ */
+ ALWAYS = 0,
+ /**
+ * 'This' will use the conflict settings for a single conflict so the conflict callback will be triggered again for the next conflict.
+ */
+ THIS = 1
+}
+/**
+ * The possible modes to resolve a conflict during a sync
+ *
+ * @export
+ * @enum {number}
+ */
+export declare enum EResolveMode {
+ SKIP = 0,
+ OVERWRITE = 1,
+ IF_NEWER = 2,
+ IF_SIZE_DIFFERS = 3,
+ THROW = 4,
+ RETRY = 5,
+ ABORT = 6
+}
+export interface IConflictSettings {
+ /**
+ * How to resolve this conflict/error.
+ *
+ * @type {EResolveMode}
+ * @memberOf IConflictSettings
+ */
+ overwrite: EResolveMode;
+ /**
+ * The scope of this conflict resolver: always or this.
+ *
+ * @type {EResolve}
+ * @memberOf IConflictSettings
+ */
+ mode: EResolve;
+ /**
+ * Track the origin error type for this settings.
+ *
+ * @type {string}
+ * @memberOf IConflictSettings
+ */
+ error?: string;
+}
+export type EMergeConflictMode = 'theirs' | 'mine';
+export type EPostType = 'post' | 'reply';
+export type ISyncNodeReport = IProcessingNode & {};
+export interface IDiscoursePostBaseOptions {
+ title?: string;
+ id?: string;
+ cat?: string | number;
+ tags?: string;
+ owner?: string | number;
+ timestamp?: string | number | Date;
+ uploadLocal?: boolean;
+ uploadRemote?: boolean;
+ yaml?: boolean;
+ post_id?: number;
+ topic_id?: number;
+ type?: EPostType;
+ user_name?: string;
+}
+export type IOptionsSync = IDiscoursePostBaseOptions & IOSRLBaseOptions & {
+ debug?: boolean;
+ verbose?: boolean;
+ logLevel?: string;
+ skip?: boolean;
+ alt?: boolean;
+ src?: string;
+ verb: string;
+ cache?: boolean;
+ filter?: TFindFilter | string;
+ config?: string | EDiscourseConfigKey;
+ pathVariables?: Hash;
+ variables?: SRC_VARIABLES;
+ repo?: string;
+ root?: string;
+ product_root?: string;
+ srcInfo?: PATH_INFO;
+ post_id?: number;
+ topic_id?: number;
+};
+export type IOptionsSyncComponent = IOptionsSync & {
+ format?: string;
+ module?: string;
+ plugins?: string;
+ onCompiled?: () => void;
+ onCompileDone?: () => void;
+ cache?: boolean;
+ skip?: boolean;
+};
+export interface IDBConfig {
+ user: string;
+ password: string;
+ database: string;
+ host: string;
+ prefix: string;
+}
+export interface IDiscourseUser {
+ id: number;
+ username: string;
+ name: string;
+ avatar_template: string;
+ active: boolean;
+ admin: boolean;
+ moderator: boolean;
+ last_seen_at: any;
+ last_emailed_at: string;
+ created_at: string;
+ last_seen_age: any;
+ last_emailed_age: number;
+ created_at_age: number;
+ trust_level: number;
+ manual_locked_trust_level: any;
+ flag_level: number;
+ title: any;
+ time_read: number;
+ staged: boolean;
+ days_visited: number;
+ posts_read_count: number;
+ topics_entered: number;
+ post_count: number;
+ detail: any;
+}
diff --git a/packages/discourse/types.js b/packages/discourse/types.js
new file mode 100644
index 00000000..d0463cde
--- /dev/null
+++ b/packages/discourse/types.js
@@ -0,0 +1,41 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.EResolveMode = exports.EResolve = void 0;
+///////////////////////////////////////////////////////
+//
+// Sync Types
+//
+/**
+ * An enumeration to narrow a conflict resolve to a single item or for all following conflicts.
+ *
+ * @export
+ * @enum {number}
+ */
+var EResolve;
+(function (EResolve) {
+ /**
+ * Always will use the chose conflict settings for all following conflicts.
+ */
+ EResolve[EResolve["ALWAYS"] = 0] = "ALWAYS";
+ /**
+ * 'This' will use the conflict settings for a single conflict so the conflict callback will be triggered again for the next conflict.
+ */
+ EResolve[EResolve["THIS"] = 1] = "THIS";
+})(EResolve = exports.EResolve || (exports.EResolve = {}));
+/**
+ * The possible modes to resolve a conflict during a sync
+ *
+ * @export
+ * @enum {number}
+ */
+var EResolveMode;
+(function (EResolveMode) {
+ EResolveMode[EResolveMode["SKIP"] = 0] = "SKIP";
+ EResolveMode[EResolveMode["OVERWRITE"] = 1] = "OVERWRITE";
+ EResolveMode[EResolveMode["IF_NEWER"] = 2] = "IF_NEWER";
+ EResolveMode[EResolveMode["IF_SIZE_DIFFERS"] = 3] = "IF_SIZE_DIFFERS";
+ EResolveMode[EResolveMode["THROW"] = 4] = "THROW";
+ EResolveMode[EResolveMode["RETRY"] = 5] = "RETRY";
+ EResolveMode[EResolveMode["ABORT"] = 6] = "ABORT";
+})(EResolveMode = exports.EResolveMode || (exports.EResolveMode = {}));
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBdUNBLHVEQUF1RDtBQUN2RCxFQUFFO0FBQ0YsYUFBYTtBQUNiLEVBQUU7QUFFRjs7Ozs7R0FLRztBQUNILElBQVksUUFTWDtBQVRELFdBQVksUUFBUTtJQUNuQjs7T0FFRztJQUNILDJDQUFNLENBQUE7SUFDTjs7T0FFRztJQUNILHVDQUFJLENBQUE7QUFDTCxDQUFDLEVBVFcsUUFBUSxHQUFSLGdCQUFRLEtBQVIsZ0JBQVEsUUFTbkI7QUFFRDs7Ozs7R0FLRztBQUNILElBQVksWUFRWDtBQVJELFdBQVksWUFBWTtJQUN2QiwrQ0FBUSxDQUFBO0lBQ1IseURBQVMsQ0FBQTtJQUNULHVEQUFRLENBQUE7SUFDUixxRUFBZSxDQUFBO0lBQ2YsaURBQUssQ0FBQTtJQUNMLGlEQUFLLENBQUE7SUFDTCxpREFBSyxDQUFBO0FBQ04sQ0FBQyxFQVJXLFlBQVksR0FBWixvQkFBWSxLQUFaLG9CQUFZLFFBUXZCIn0=
\ No newline at end of file
diff --git a/packages/discourse/types.js.map b/packages/discourse/types.js.map
new file mode 100644
index 00000000..14058397
--- /dev/null
+++ b/packages/discourse/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["src/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/registry/.gitignore b/packages/registry/.gitignore
new file mode 100644
index 00000000..cab85ca2
--- /dev/null
+++ b/packages/registry/.gitignore
@@ -0,0 +1,4 @@
+/node_modules
+/coverage
+*.log
+.DS_Store
diff --git a/packages/registry/.npmignore b/packages/registry/.npmignore
new file mode 100644
index 00000000..4c9addac
--- /dev/null
+++ b/packages/registry/.npmignore
@@ -0,0 +1,4 @@
+./docs
+./scripts
+./tests
+./incoming
\ No newline at end of file
diff --git a/packages/registry/LICENSE b/packages/registry/LICENSE
new file mode 100644
index 00000000..b0e20f53
--- /dev/null
+++ b/packages/registry/LICENSE
@@ -0,0 +1,9 @@
+Copyright (c) All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/registry/README.md b/packages/registry/README.md
new file mode 100644
index 00000000..fd6bc18e
--- /dev/null
+++ b/packages/registry/README.md
@@ -0,0 +1,21 @@
+# osr-package-template
+
+## References
+
+https://github.com/MrMaxie/ts-types-parser
+https://github.com/typestack/class-transformer#readme
+
+## Multistore
+
+- https://github.com/jaredwray/keyv
+- https://github.com/zaaack/keyv-file
+
+https://github.com/Level/abstract-level (?)
+
+## Utils
+
+https://www.npmjs.com/package/filter-obj
+
+## Graph store
+
+https://www.npmjs.com/package/gun
\ No newline at end of file
diff --git a/packages/registry/_cli.d.ts b/packages/registry/_cli.d.ts
new file mode 100644
index 00000000..9c57c0f2
--- /dev/null
+++ b/packages/registry/_cli.d.ts
@@ -0,0 +1,3 @@
+import { IOptions } from './types';
+export declare const defaults: () => void;
+export declare const sanitize: (argv: any) => IOptions | boolean;
diff --git a/packages/registry/_cli.js b/packages/registry/_cli.js
new file mode 100644
index 00000000..9c40d463
--- /dev/null
+++ b/packages/registry/_cli.js
@@ -0,0 +1,21 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sanitize = exports.defaults = void 0;
+// tweaks and handlers
+const defaults = () => {
+ // default command
+ const DefaultCommand = 'info';
+ if (process.argv.length === 2) {
+ process.argv.push(DefaultCommand);
+ }
+ // currently no default handler, display only :
+ process.on('unhandledRejection', (reason) => {
+ console.error('Unhandled rejection, reason: ', reason);
+ });
+};
+exports.defaults = defaults;
+const sanitize = (argv) => {
+ return argv;
+};
+exports.sanitize = sanitize;
+//# sourceMappingURL=_cli.js.map
\ No newline at end of file
diff --git a/packages/registry/_cli.js.map b/packages/registry/_cli.js.map
new file mode 100644
index 00000000..ebbb9a75
--- /dev/null
+++ b/packages/registry/_cli.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"_cli.js","sourceRoot":"","sources":["src/_cli.ts"],"names":[],"mappings":";;;AAKA,sBAAsB;AACf,MAAM,QAAQ,GAAG,GAAG,EAAE;IACzB,kBAAkB;IAClB,MAAM,cAAc,GAAG,MAAM,CAAC;IAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KACrC;IAED,+CAA+C;IAC/C,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAc,EAAE,EAAE;QAChD,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAXW,QAAA,QAAQ,YAWnB;AAEK,MAAM,QAAQ,GAAG,CAAC,IAAS,EAAsB,EAAE;IAEtD,OAAO,IAAI,CAAA;AACf,CAAC,CAAA;AAHY,QAAA,QAAQ,YAGpB"}
\ No newline at end of file
diff --git a/packages/registry/commands/info.d.ts b/packages/registry/commands/info.d.ts
new file mode 100644
index 00000000..443f33e5
--- /dev/null
+++ b/packages/registry/commands/info.d.ts
@@ -0,0 +1,2 @@
+import * as CLI from 'yargs';
+export declare const register: (cli: CLI.Argv) => CLI.Argv<{}>;
diff --git a/packages/registry/commands/info.js b/packages/registry/commands/info.js
new file mode 100644
index 00000000..f7b995af
--- /dev/null
+++ b/packages/registry/commands/info.js
@@ -0,0 +1,51 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+const __1 = require("../");
+const _cli_1 = require("../_cli");
+const path = require("path");
+const osr_commons_1 = require("@plastichub/osr-commons");
+const defaultOptions = (yargs) => {
+ return yargs.option('debug', {
+ default: 'false',
+ describe: 'debug messages'
+ }).option('verb', {
+ description: 'search api: scaleserp',
+ default: 'scaleserp'
+ }).option('location', {
+ description: 'location to be searched from',
+ default: 'Berlin, Germany'
+ }).option('query', {
+ description: 'the query',
+ default: 'Precious Plastic Munich'
+ }).option('dst', {
+ description: 'dst output path, supports XLS|CSV|HTML',
+ default: './tests/data/serpwow.json'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path'
+ });
+};
+let options = (yargs) => defaultOptions(yargs);
+const register = (cli) => {
+ return cli.command('info ', 'Search', options, async (argv) => {
+ (0, _cli_1.defaults)();
+ if (argv.help) {
+ return;
+ }
+ const args = argv;
+ const config = (0, osr_commons_1.CONFIG_DEFAULT)(args.env_key);
+ const opts = {
+ verb: argv.verb,
+ query: argv.query,
+ dst: path.resolve(args.dst)
+ };
+ if (!opts.verb) {
+ __1.logger.error('No verb specified');
+ return;
+ }
+ __1.logger.debug(`Reading OSR Config with key "${argv.env_key}"`, opts);
+ });
+};
+exports.register = register;
+//# sourceMappingURL=info.js.map
\ No newline at end of file
diff --git a/packages/registry/commands/info.js.map b/packages/registry/commands/info.js.map
new file mode 100644
index 00000000..395c765f
--- /dev/null
+++ b/packages/registry/commands/info.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"info.js","sourceRoot":"","sources":["../src/commands/info.ts"],"names":[],"mappings":";;;AAAA,2BAA4B;AAC5B,kCAAkC;AAGlC,6BAA4B;AAC5B,yDAAwD;AAExD,MAAM,cAAc,GAAG,CAAC,KAAe,EAAE,EAAE;IACvC,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE;QACzB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,gBAAgB;KAC7B,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE;QACd,WAAW,EAAE,uBAAuB;QACpC,OAAO,EAAE,WAAW;KACvB,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE;QAClB,WAAW,EAAE,8BAA8B;QAC3C,OAAO,EAAE,iBAAiB;KAC7B,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE;QACf,WAAW,EAAE,WAAW;QACxB,OAAO,EAAE,yBAAyB;KACrC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE;QACb,WAAW,EAAE,wCAAwC;QACrD,OAAO,EAAE,2BAA2B;KACvC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE;QACjB,OAAO,EAAE,YAAY;QACrB,QAAQ,EAAE,oCAAoC;KACjD,CAAC,CAAC;AACP,CAAC,CAAC;AAEF,IAAI,OAAO,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;AAGlD,MAAM,QAAQ,GAAG,CAAC,GAAa,EAAE,EAAE;IACtC,OAAO,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAmB,EAAE,EAAE;QAC/E,IAAA,eAAQ,GAAE,CAAA;QACV,IAAI,IAAI,CAAC,IAAI,EAAE;YAAE,OAAM;SAAE;QACzB,MAAM,IAAI,GAAQ,IAAI,CAAA;QAEtB,MAAM,MAAM,GAAG,IAAA,4BAAc,EAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAE3C,MAAM,IAAI,GAAG;YACT,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;SAC9B,CAAA;QAED,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YACZ,UAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YAClC,OAAM;SACT;QACD,UAAM,CAAC,KAAK,CAAC,gCAAgC,IAAI,CAAC,OAAO,GAAG,EAAE,IAAI,CAAC,CAAA;IACvE,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AApBY,QAAA,QAAQ,YAoBpB"}
\ No newline at end of file
diff --git a/packages/registry/constants.d.ts b/packages/registry/constants.d.ts
new file mode 100644
index 00000000..37e90ab0
--- /dev/null
+++ b/packages/registry/constants.d.ts
@@ -0,0 +1 @@
+export declare const MODULE_NAME = "OSR-REGISTRY";
diff --git a/packages/registry/constants.js b/packages/registry/constants.js
new file mode 100644
index 00000000..0fc2ad28
--- /dev/null
+++ b/packages/registry/constants.js
@@ -0,0 +1,5 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MODULE_NAME = void 0;
+exports.MODULE_NAME = `OSR-REGISTRY`;
+//# sourceMappingURL=constants.js.map
\ No newline at end of file
diff --git a/packages/registry/constants.js.map b/packages/registry/constants.js.map
new file mode 100644
index 00000000..6ff6cec1
--- /dev/null
+++ b/packages/registry/constants.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"constants.js","sourceRoot":"","sources":["src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,cAAc,CAAA"}
\ No newline at end of file
diff --git a/packages/registry/index.d.ts b/packages/registry/index.d.ts
new file mode 100644
index 00000000..fe6af40a
--- /dev/null
+++ b/packages/registry/index.d.ts
@@ -0,0 +1,4 @@
+export * from './lib/index';
+export declare const logger: import("@plastichub/core/debug").Logger;
+export { sanitize } from './_cli';
+export { MODULE_NAME } from './constants';
diff --git a/packages/registry/index.js b/packages/registry/index.js
new file mode 100644
index 00000000..e8f68973
--- /dev/null
+++ b/packages/registry/index.js
@@ -0,0 +1,26 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.MODULE_NAME = exports.sanitize = exports.logger = void 0;
+const debug_1 = require("@plastichub/core/debug");
+const constants_1 = require("./constants");
+__exportStar(require("./lib/index"), exports);
+exports.logger = (0, debug_1.logger)(constants_1.MODULE_NAME);
+var _cli_1 = require("./_cli");
+Object.defineProperty(exports, "sanitize", { enumerable: true, get: function () { return _cli_1.sanitize; } });
+var constants_2 = require("./constants");
+Object.defineProperty(exports, "MODULE_NAME", { enumerable: true, get: function () { return constants_2.MODULE_NAME; } });
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/registry/index.js.map b/packages/registry/index.js.map
new file mode 100644
index 00000000..69c25493
--- /dev/null
+++ b/packages/registry/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AACA,kDAA0D;AAE1D,2CAAyC;AACzC,8CAA2B;AAEd,QAAA,MAAM,GAAG,IAAA,cAAO,EAAC,uBAAW,CAAC,CAAA;AAC1C,+BAAiC;AAAxB,gGAAA,QAAQ,OAAA;AACjB,yCAAyC;AAAhC,wGAAA,WAAW,OAAA"}
\ No newline at end of file
diff --git a/packages/registry/lib/index.d.ts b/packages/registry/lib/index.d.ts
new file mode 100644
index 00000000..5f157516
--- /dev/null
+++ b/packages/registry/lib/index.d.ts
@@ -0,0 +1,2 @@
+export * from './types';
+export * from './keyv';
diff --git a/packages/registry/lib/index.js b/packages/registry/lib/index.js
new file mode 100644
index 00000000..fb8a92dc
--- /dev/null
+++ b/packages/registry/lib/index.js
@@ -0,0 +1,19 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ var desc = Object.getOwnPropertyDescriptor(m, k);
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
+ desc = { enumerable: true, get: function() { return m[k]; } };
+ }
+ Object.defineProperty(o, k2, desc);
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+__exportStar(require("./types"), exports);
+__exportStar(require("./keyv"), exports);
+//# sourceMappingURL=index.js.map
\ No newline at end of file
diff --git a/packages/registry/lib/index.js.map b/packages/registry/lib/index.js.map
new file mode 100644
index 00000000..a1f2a330
--- /dev/null
+++ b/packages/registry/lib/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAKA,0CAAuB;AACvB,yCAAsB"}
\ No newline at end of file
diff --git a/packages/registry/lib/keyv.d.ts b/packages/registry/lib/keyv.d.ts
new file mode 100644
index 00000000..141cfa14
--- /dev/null
+++ b/packages/registry/lib/keyv.d.ts
@@ -0,0 +1,5 @@
+import Keyv from 'keyv';
+export declare const store: (storePath: string, ns?: string, opts?: any) => Keyv;
+export declare const get: (key: string, storePath: string, ns?: string, opts?: any) => Promise;
+export declare const set: (key: string, value: any, storePath: string, ns?: string, opts?: any) => Promise;
+export declare const list: (key: string, value: any, storePath: string, ns?: string, opts?: any) => Promise;
diff --git a/packages/registry/lib/keyv.js b/packages/registry/lib/keyv.js
new file mode 100644
index 00000000..9bc8636a
--- /dev/null
+++ b/packages/registry/lib/keyv.js
@@ -0,0 +1,28 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.list = exports.set = exports.get = exports.store = void 0;
+const path = require("path");
+const keyv_1 = require("keyv");
+const sqlite_1 = require("@keyv/sqlite");
+const osr_commons_1 = require("@plastichub/osr-commons");
+const store = (storePath, ns = 'ns-unknown', opts = {}) => {
+ const keyvSqlite = new sqlite_1.default(path.resolve((0, osr_commons_1.resolve)(storePath)));
+ return new keyv_1.default({ store: keyvSqlite, ttl: 5000, namespace: ns, ...opts });
+};
+exports.store = store;
+const get = async (key, storePath, ns = 'ns-unknown', opts = {}) => {
+ const keyv = (0, exports.store)(storePath, ns, opts);
+ return await keyv.get(key);
+};
+exports.get = get;
+const set = async (key, value, storePath, ns = 'ns-unknown', opts = {}) => {
+ const keyv = (0, exports.store)(storePath, ns, opts);
+ return await keyv.set(key, value);
+};
+exports.set = set;
+const list = async (key, value, storePath, ns = 'ns-unknown', opts = {}) => {
+ const keyv = (0, exports.store)(storePath, ns, opts);
+ return await keyv.set(key, value);
+};
+exports.list = list;
+//# sourceMappingURL=keyv.js.map
\ No newline at end of file
diff --git a/packages/registry/lib/keyv.js.map b/packages/registry/lib/keyv.js.map
new file mode 100644
index 00000000..743123dc
--- /dev/null
+++ b/packages/registry/lib/keyv.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"keyv.js","sourceRoot":"","sources":["../src/lib/keyv.ts"],"names":[],"mappings":";;;AAAA,6BAA4B;AAC5B,+BAAuB;AACvB,yCAAqC;AAErC,yDAAiD;AAE1C,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAE,KAAa,YAAY,EAAE,OAAY,EAAE,EAAE,EAAE;IAClF,MAAM,UAAU,GAAG,IAAI,gBAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAA,qBAAO,EAAC,SAAS,CAAC,CAAC,CAAC,CAAA;IACnE,OAAO,IAAI,cAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;AAC7E,CAAC,CAAA;AAHY,QAAA,KAAK,SAGjB;AACM,MAAM,GAAG,GAAG,KAAK,EAAE,GAAW,EAAE,SAAiB,EAAE,KAAa,YAAY,EAAE,OAAY,EAAE,EAAE,EAAE;IACnG,MAAM,IAAI,GAAG,IAAA,aAAK,EAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;IACvC,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;AAC9B,CAAC,CAAA;AAHY,QAAA,GAAG,OAGf;AACM,MAAM,GAAG,GAAG,KAAK,EAAE,GAAW,EAAE,KAAU,EAAE,SAAiB,EAAE,KAAa,YAAY,EAAE,OAAY,EAAE,EAAE,EAAE;IAC/G,MAAM,IAAI,GAAG,IAAA,aAAK,EAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;IACvC,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AACrC,CAAC,CAAA;AAHY,QAAA,GAAG,OAGf;AACM,MAAM,IAAI,GAAG,KAAK,EAAE,GAAW,EAAE,KAAU,EAAE,SAAiB,EAAE,KAAa,YAAY,EAAE,OAAY,EAAE,EAAE,EAAE;IAChH,MAAM,IAAI,GAAG,IAAA,aAAK,EAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;IACvC,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;AACrC,CAAC,CAAA;AAHY,QAAA,IAAI,QAGhB"}
\ No newline at end of file
diff --git a/packages/registry/lib/types.d.ts b/packages/registry/lib/types.d.ts
new file mode 100644
index 00000000..feaff3ab
--- /dev/null
+++ b/packages/registry/lib/types.d.ts
@@ -0,0 +1,2 @@
+export interface Noop {
+}
diff --git a/packages/registry/lib/types.js b/packages/registry/lib/types.js
new file mode 100644
index 00000000..3da8b318
--- /dev/null
+++ b/packages/registry/lib/types.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=types.js.map
\ No newline at end of file
diff --git a/packages/registry/lib/types.js.map b/packages/registry/lib/types.js.map
new file mode 100644
index 00000000..247b4c7e
--- /dev/null
+++ b/packages/registry/lib/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/lib/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/registry/main.d.ts b/packages/registry/main.d.ts
new file mode 100644
index 00000000..d1ebc9c7
--- /dev/null
+++ b/packages/registry/main.d.ts
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+export {};
diff --git a/packages/registry/main.js b/packages/registry/main.js
new file mode 100644
index 00000000..a5a53b3c
--- /dev/null
+++ b/packages/registry/main.js
@@ -0,0 +1,17 @@
+#!/usr/bin/env node
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+const _cli_1 = require("./_cli");
+(0, _cli_1.defaults)();
+const cli = require("yargs");
+const info_1 = require("./commands/info");
+(0, info_1.register)(cli);
+const argv = cli.argv;
+if (argv.help) {
+ cli.showHelp();
+ process.exit();
+}
+else if (argv.v || argv.version) {
+ process.exit();
+}
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/packages/registry/main.js.map b/packages/registry/main.js.map
new file mode 100644
index 00000000..aab21cdc
--- /dev/null
+++ b/packages/registry/main.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"main.js","sourceRoot":"","sources":["src/main.ts"],"names":[],"mappings":";;;AACA,iCAAkC;AAAC,IAAA,eAAQ,GAAE,CAAA;AAC7C,6BAA4B;AAE5B,0CAA2D;AAAC,IAAA,eAAY,EAAC,GAAG,CAAC,CAAA;AAE7E,MAAM,IAAI,GAAQ,GAAG,CAAC,IAAI,CAAC;AAE3B,IAAI,IAAI,CAAC,IAAI,EAAE;IACX,GAAG,CAAC,QAAQ,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,EAAE,CAAC;CAClB;KAAM,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE;IAC/B,OAAO,CAAC,IAAI,EAAE,CAAC;CAClB"}
\ No newline at end of file
diff --git a/packages/registry/package-lock.json b/packages/registry/package-lock.json
new file mode 100644
index 00000000..eb98f624
--- /dev/null
+++ b/packages/registry/package-lock.json
@@ -0,0 +1,4848 @@
+{
+ "name": "@plastichub/osr-registry",
+ "version": "0.1.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@plastichub/osr-registry",
+ "version": "0.1.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@keyv/sqlite": "^4.0.1",
+ "@plastichub/core": "^0.1.9",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-cli-commons": "^0.5.1",
+ "@plastichub/osr-commons": "^0.3.4",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.2",
+ "env-var": "^7.0.1",
+ "keyv": "^5.1.0",
+ "keyv-file": "^0.2.0",
+ "p-map": "^4.0.0",
+ "typescript": "^4.3.5",
+ "yargs": "^14.2.3"
+ },
+ "bin": {
+ "osr-registry": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@keyv/serialize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.0.1.tgz",
+ "integrity": "sha512-kKXeynfORDGPUEEl2PvTExM2zs+IldC6ZD8jPcfvI351MDNtfMlw9V9s4XZXuJNDK2qR5gbEKxRyoYx3quHUVQ==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^6.0.3"
+ }
+ },
+ "node_modules/@keyv/sqlite": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@keyv/sqlite/-/sqlite-4.0.1.tgz",
+ "integrity": "sha512-Ngs9jhElXN7efS9WvvCC/p6rXMbihna8eNLVBc421Zf+VcFd+pR4DOcS6yA9V22EKtAy4DEj7LtvEEIm0bb80A==",
+ "license": "MIT",
+ "dependencies": {
+ "sqlite3": "^5.1.7"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
+ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "@gar/promisify": "^1.0.1",
+ "semver": "^7.3.5"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
+ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
+ "deprecated": "This functionality has been moved to @npmcli/fs",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@plastichub/core": {
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/@plastichub/core/-/core-0.1.9.tgz",
+ "integrity": "sha512-yFRnXBzzq65w95r/Y7RvFxHi8dvrrNv9alH5g+ZihOxaKEsZH2TI05Vf4KaQ9oYSNJXEiB7PWJSE0/ormWPvQw==",
+ "dependencies": {
+ "base-64": "^0.1.0",
+ "chalk": "^2.4.1",
+ "cli-spinners": "^1.3.1",
+ "defaults": "^1.0.3",
+ "jsonpath": "^1.1.1",
+ "qs": "^6.4.0",
+ "tslog": "^3.3.3",
+ "typescript": "^4.3.5"
+ }
+ },
+ "node_modules/@plastichub/fs": {
+ "version": "0.13.32",
+ "resolved": "https://registry.npmjs.org/@plastichub/fs/-/fs-0.13.32.tgz",
+ "integrity": "sha512-O6IR+mG7ZWQNlsPtVrY280BLZG6QgQDJbaAWHEiz/v2NXbPXl5+0rfki4poPnJUvZDYI09vum+kP1n2BPUxaMw==",
+ "dependencies": {
+ "@plastichub/core": "^0.2.0",
+ "@types/minimatch": "^3.0.3",
+ "@types/node": "^14.11.10",
+ "denodeify": "^1.2.1",
+ "errno": "^0.1.4",
+ "mime": "^2.0.3",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "progress-stream": "^1.2.0",
+ "q": "^1.4.1",
+ "rimraf": "^2.6.2",
+ "throttle": "^1.0.3",
+ "trash": "^4.0.1",
+ "typescript": "^4.0.3",
+ "write-file-atomic": "^1.3.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/@plastichub/core": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@plastichub/core/-/core-0.2.0.tgz",
+ "integrity": "sha512-mTfe8aaWb5BmdT22VoPTIbK39cWxdI32yRI+jMTH7W5BoZN3AnQ8xv6CK31ju57hSyhlmVjdnVsDvRooFug92w==",
+ "dependencies": {
+ "tslog": "^3.3.3"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-cli-commons/-/osr-cli-commons-0.5.1.tgz",
+ "integrity": "sha512-qEhCgnLsQ5xHivRL1/lfWGb7sBZSKYnjhvN9bdh8bA/qvIHbUa4azoFbC+wKMX6DxMZNlnzRUqH3fQvTQ8kkoQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-commons": "^0.3.3",
+ "@types/cacache": "^15.0.1",
+ "@types/node": "^20.14.9",
+ "@types/which": "^3.0.4",
+ "@types/yargs": "^17.0.2",
+ "bluebird": "^3.7.2",
+ "cacache": "^16.1.2",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "fast-glob": "^3.2.11",
+ "glob": "^10.4.1",
+ "glob-base": "github:justin-caribou/glob-base",
+ "is-glob": "^4.0.3",
+ "parse-glob": "^3.0.4",
+ "rage-edit": "^1.2.0",
+ "typescript": "^4.3.5",
+ "which": "^4.0.0",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-cli": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "license": "ISC",
+ "dependencies": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "deprecated": "This functionality has been moved to @npmcli/fs",
+ "license": "MIT",
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@plastichub/core": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@plastichub/core/-/core-0.2.6.tgz",
+ "integrity": "sha512-DF2IUZu6cw8+iVnFv2BFvd+s/7DYfrfXh7o3Uhg0IjbZ/QOIXY21URarnMQoTl9NEwUKN8ZZIHJmOIulT8helg==",
+ "license": "BSD",
+ "dependencies": {
+ "deepmerge": "^4.3.1",
+ "tslog": "^3.3.3"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@types/node": {
+ "version": "20.16.12",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.12.tgz",
+ "integrity": "sha512-LfPFB0zOeCeCNQV3i+67rcoVvoN5n0NVuR2vLG0O5ySQMgchuZlC4lgz546ZOJyDtj5KIgOxy+lacOimfqZAIA==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "license": "ISC",
+ "dependencies": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/cacache/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/cacache/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/glob/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/isexe": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
+ "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "license": "ISC",
+ "dependencies": {
+ "unique-slug": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/which": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^3.1.1"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-commons": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-commons/-/osr-commons-0.3.4.tgz",
+ "integrity": "sha512-u1//H4T0Z88wEJtMcvSm8FETsZpO6RFS+C/Qvi6HQUR21cyieg3zs3TxFc9JAwkP+kvPImw8f3y5gisuuJOUDA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.1",
+ "@plastichub/fs": "^0.13.32",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "filenamify": "^4.3.0",
+ "querystring": "^0.2.1",
+ "sanitize-filename": "^1.6.3",
+ "shell-escape": "^0.2.0",
+ "tslog": "^3.3.3",
+ "typescript": "^4.3.5",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-commons": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/@plastichub/core": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@plastichub/core/-/core-0.2.6.tgz",
+ "integrity": "sha512-DF2IUZu6cw8+iVnFv2BFvd+s/7DYfrfXh7o3Uhg0IjbZ/QOIXY21URarnMQoTl9NEwUKN8ZZIHJmOIulT8helg==",
+ "license": "BSD",
+ "dependencies": {
+ "deepmerge": "^4.3.1",
+ "tslog": "^3.3.3"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-commons/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sindresorhus/df": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-2.1.0.tgz",
+ "integrity": "sha512-yozEsK3X8sEjh9fiolh3JntMUuGKe2n2t8gtE3yZ1PqAFFeaSxTrSiEVORy/YkPzUsxQ85RzLcGqmqSOgiFhtg==",
+ "dependencies": {
+ "execa": "^0.2.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/execa": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz",
+ "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==",
+ "dependencies": {
+ "cross-spawn-async": "^2.1.1",
+ "npm-run-path": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "path-key": "^1.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/npm-run-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz",
+ "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==",
+ "dependencies": {
+ "path-key": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/path-key": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz",
+ "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@types/cacache": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@types/cacache/-/cacache-15.0.1.tgz",
+ "integrity": "sha512-JhL2GFJuHMx4RMg4z0XfXB4ZkKdyiOaOLpjoYMXcyKfrkF3IBXNZBj6/Peo9zX/7PPHyfI63NWVD589cI2YTzg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
+ },
+ "node_modules/@types/node": {
+ "version": "14.18.42",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz",
+ "integrity": "sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg=="
+ },
+ "node_modules/@types/which": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/which/-/which-3.0.4.tgz",
+ "integrity": "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w==",
+ "license": "MIT"
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.24",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
+ "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
+ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agent-base/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/agent-base/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
+ "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "license": "MIT",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/are-we-there-yet/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/are-we-there-yet/node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+ "dependencies": {
+ "array-uniq": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base-64": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
+ "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bl/node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bl/node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ },
+ "node_modules/cacache": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
+ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "@npmcli/fs": "^1.0.0",
+ "@npmcli/move-file": "^1.0.1",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "glob": "^7.1.4",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.1",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.2",
+ "mkdirp": "^1.0.3",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.0.2",
+ "unique-filename": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cacache/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cacache/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
+ "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dependencies": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/convert-units": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/convert-units/-/convert-units-2.3.4.tgz",
+ "integrity": "sha512-ERHfdA0UhHJp1IpwE6PnFJx8LqG7B1ZjJ20UvVCmopEnVCfER68Tbe3kvN63dLbYXDA2xFWRE6zd4Wsf0w7POg==",
+ "dependencies": {
+ "lodash.foreach": "2.3.x",
+ "lodash.keys": "2.3.x"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/cross-spawn-async": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
+ "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==",
+ "deprecated": "cross-spawn no longer requires a build toolchain, use it instead",
+ "dependencies": {
+ "lru-cache": "^4.0.0",
+ "which": "^1.2.8"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
+ },
+ "node_modules/cross-spawn/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/cryptr": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/cryptr/-/cryptr-6.3.0.tgz",
+ "integrity": "sha512-TA4byAuorT8qooU9H8YJhBwnqD151i1rcauHfJ3Divg6HmukHB2AYMp0hmjv2873J2alr4t15QqC7zAnWFrtfQ==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/denodeify": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
+ "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg=="
+ },
+ "node_modules/detect-libc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dependencies": {
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+ },
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/env-var": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/env-var/-/env-var-7.3.0.tgz",
+ "integrity": "sha512-qwtwYJ9d3XFxXRDudPEAMszaggpDgcfb1ZGYb9/cNyMugN2/a8EtviopnRL6c+petj2vp6/gxwYd9ExL1/iPcw==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/errno": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
+ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+ "dependencies": {
+ "prr": "~1.0.1"
+ },
+ "bin": {
+ "errno": "cli.js"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-applescript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-applescript/-/escape-string-applescript-2.0.0.tgz",
+ "integrity": "sha512-Z7OsRJUi5+OHT89RRJlkS8cKxIh9AyPmgtEevsSQFCx5WLIiS3hy/HRiiQZzYQMsn6MWyCDZ5elBFa/9dxT0BA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "1.14.3",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
+ "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^4.2.0",
+ "esutils": "^2.0.2",
+ "optionator": "^0.8.1"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=4.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/escodegen/node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz",
+ "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/execa": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+ "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "dependencies": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "license": "(MIT OR WTFPL)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "license": "MIT"
+ },
+ "node_modules/filename-reserved-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
+ "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/filenamify": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
+ "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
+ "license": "MIT",
+ "dependencies": {
+ "filename-reserved-regex": "^2.0.0",
+ "strip-outer": "^1.0.1",
+ "trim-repeated": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "license": "ISC",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
+ "node_modules/fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0",
+ "path-is-absolute": "^1.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "node_modules/gauge": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/gauge/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/gauge/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gauge/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
+ "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "license": "MIT"
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-base": {
+ "version": "0.3.0",
+ "resolved": "git+ssh://git@github.com/justin-caribou/glob-base.git#d4fe4313e55988a902a3940127cb946a7defbb50",
+ "license": "MIT",
+ "dependencies": {
+ "glob-parent": "^6.0.2",
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/glob-parent/node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/is-glob/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
+ "dependencies": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+ "license": "BSD-2-Clause",
+ "optional": true
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+ "license": "ISC"
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonpath": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz",
+ "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==",
+ "dependencies": {
+ "esprima": "1.2.2",
+ "static-eval": "2.0.2",
+ "underscore": "1.12.1"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.1.0.tgz",
+ "integrity": "sha512-FUr1fbKVsj9IZkPkY9reJ80Lp2B3ldtFXH+xK0wvZYzOpwgHV1er3xP4JUhu2cgkV2X3BJQw+hzAbIGqa+hNIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@keyv/serialize": "*"
+ }
+ },
+ "node_modules/keyv-file": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/keyv-file/-/keyv-file-0.2.0.tgz",
+ "integrity": "sha512-zUQ11eZRmilEUpV1gJSj8mBAHjyXpleQo1iCS0khb+GFRhiPfwavWgn4eDUKNlOyMZzmExnISl8HE1hNbim0gw==",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "fs-extra": "^4.0.1",
+ "tslib": "^1.9.3"
+ }
+ },
+ "node_modules/keyv-file/node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/keyv-file/node_modules/fs-extra": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz",
+ "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "node_modules/keyv-file/node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/keyv-file/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/lodash._basebind": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.3.0.tgz",
+ "integrity": "sha512-SHqM7YCuJ+BeGTs7lqpWnmdHEeF4MWxS3dksJctHFNxR81FXPOzA4bS5Vs5CpcGTkBpM8FCl+YEbQEblRw8ABg==",
+ "dependencies": {
+ "lodash._basecreate": "~2.3.0",
+ "lodash._setbinddata": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreate": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.3.0.tgz",
+ "integrity": "sha512-vwZaWldZwS2y9b99D8i9+WtgiZXbHKsBsMrpxJEqTsNW20NhJo5W8PBQkeQO9CmxuqEYn8UkMnfEM2MMT4cVrw==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash.isobject": "~2.3.0",
+ "lodash.noop": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreatecallback": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.3.0.tgz",
+ "integrity": "sha512-Ev+pDzzfVfgbiucpXijconLGRBar7/+KNCf05kSnk4CmdDVhAy1RdbU9efCJ/o9GXI08JdUGwZ+5QJ3QX3kj0g==",
+ "dependencies": {
+ "lodash._setbinddata": "~2.3.0",
+ "lodash.bind": "~2.3.0",
+ "lodash.identity": "~2.3.0",
+ "lodash.support": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreatewrapper": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.3.0.tgz",
+ "integrity": "sha512-YLycQ7k8AB9Wc1EOvLNxuRWcqipDkMXq2GCgnLWQR6qtgTb3gY3LELzEpnFshrEO4LOLs+R2EpcY+uCOZaLQ8Q==",
+ "dependencies": {
+ "lodash._basecreate": "~2.3.0",
+ "lodash._setbinddata": "~2.3.0",
+ "lodash._slice": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._createwrapper": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.3.0.tgz",
+ "integrity": "sha512-XjaI/rzg9W+WO4WJDQ+PRlHD5sAMJ1RhJLuT65cBxLCb1kIYs4U20jqvTDGAWyVT3c34GYiLd9AreHYuB/8yJA==",
+ "dependencies": {
+ "lodash._basebind": "~2.3.0",
+ "lodash._basecreatewrapper": "~2.3.0",
+ "lodash.isfunction": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._objecttypes": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.3.0.tgz",
+ "integrity": "sha512-jbA6QyHt9cw3BzvbWzIcnU3Z12jSneT6xBgz3Y782CJsN1tV5aTBKrFo2B4AkeHBNaxSrbPYZZpi1Lwj3xjdtg=="
+ },
+ "node_modules/lodash._renative": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._renative/-/lodash._renative-2.3.0.tgz",
+ "integrity": "sha512-v44MRirqYqZGK/h5UKoVqXWF2L+LUiLTU+Ogu5rHRVWJUA1uWIlHaMpG8f/OA8j++BzPMQij9+erXHtgFcbuwg=="
+ },
+ "node_modules/lodash._setbinddata": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.3.0.tgz",
+ "integrity": "sha512-xMFfbF7dL+sFtrdE49uHFmfpBAEwlFtfgMp86nQRlAF6aizYL+3MTbnYMKJSkP1W501PhsgiBED5kBbZd8kR2g==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash.noop": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._shimkeys": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.3.0.tgz",
+ "integrity": "sha512-9Iuyi7TiWMGa/9+2rqEE+Zwye4b/U2w7Saw6UX1h6Xs88mEER+uz9FZcEBPKMVKsad9Pw5GNAcIBRnW2jNpneQ==",
+ "dependencies": {
+ "lodash._objecttypes": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._slice": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.3.0.tgz",
+ "integrity": "sha512-7C61GhzRUv36gTafr+RIb+AomCAYsSATEoK4OP0VkNBcwvsM022Z22AVgqjjzikeNO1U29LzsJZDvLbiNPUYvA=="
+ },
+ "node_modules/lodash.bind": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.3.0.tgz",
+ "integrity": "sha512-goakyOo+FMN8lttMPnZ0UNlr5RlzX4IrUXyTJPT2A0tGCMXySupond9wzvDqTvVmYTcQjIKGrj8naJDS2xWAlQ==",
+ "dependencies": {
+ "lodash._createwrapper": "~2.3.0",
+ "lodash._renative": "~2.3.0",
+ "lodash._slice": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.foreach": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-2.3.0.tgz",
+ "integrity": "sha512-yLnyptVRJd0//AbGp480grgQG9iaDIV5uOgSbpurRy1dYybPbjNTLQ3FyLEQ84buVLPG7jyaiyvpzgfOutRB3Q==",
+ "dependencies": {
+ "lodash._basecreatecallback": "~2.3.0",
+ "lodash.forown": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.forown": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-2.3.0.tgz",
+ "integrity": "sha512-dUnCsuQTtq3Y7bxPNoEEqjJjPL2ftLtcz2PTeRKvhbpdM514AvnqCjewHGsm/W+dwspIwa14KoWEZeizJ7smxA==",
+ "dependencies": {
+ "lodash._basecreatecallback": "~2.3.0",
+ "lodash._objecttypes": "~2.3.0",
+ "lodash.keys": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.identity": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.3.0.tgz",
+ "integrity": "sha512-NYJ2r2cwy3tkx/saqbIZEX6oQUzjWTnGRu7d/zmBjMCZos3eHBxCpbvWFWSetv8jFVrptsp6EbWjzNgBKhUoOA=="
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.3.0.tgz",
+ "integrity": "sha512-X5lteBYlCrVO7Qc00fxP8W90fzRp6Ax9XcHANmU3OsZHdSyIVZ9ZlX5QTTpRq8aGY+9I5Rmd0UTzTIIyWPugEQ=="
+ },
+ "node_modules/lodash.isobject": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.3.0.tgz",
+ "integrity": "sha512-jo1pfV61C4TE8BfEzqaHj6EIKiSkFANJrB6yscwuCJMSRw5tbqjk4Gv7nJzk4Z6nFKobZjGZ8Qd41vmnwgeQqQ==",
+ "dependencies": {
+ "lodash._objecttypes": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.keys": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.3.0.tgz",
+ "integrity": "sha512-c0UW0ffqMxSCtoVbmVt2lERJLkEqgoOn2ejPsWXzr0ZrqRbl3uruGgwHzhtqXxi6K/ei3Ey7zimOqSwXgzazPg==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash._shimkeys": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.noop": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.3.0.tgz",
+ "integrity": "sha512-NpSm8HRm1WkBBWHUveDukLF4Kfb5P5E3fjHc9Qre9A11nNubozLWD2wH3UBTZbu+KSuX8aSUvy9b+PUyEceJ8g=="
+ },
+ "node_modules/lodash.support": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.3.0.tgz",
+ "integrity": "sha512-etc7VWbB0U3Iya8ixj2xy4sDBN3jvPX7ODi8iXtn4KkkjNpdngrdc7Vlt5jub/Vgqx6/dWtp7Ml9awhCQPYKGQ==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/make-fetch-happen": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
+ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "agentkeepalive": "^4.1.3",
+ "cacache": "^15.2.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^1.3.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.2",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^6.0.0",
+ "ssri": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-fetch": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
+ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.1.0",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.12"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "license": "MIT"
+ },
+ "node_modules/mount-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mount-point/-/mount-point-3.0.0.tgz",
+ "integrity": "sha512-jAhfD7ZCG+dbESZjcY1SdFVFqSJkh/yGbdsifHcPkvuLRO5ugK0Ssmd9jdATu29BTd4JiN+vkpMzVvsUgP3SZA==",
+ "dependencies": {
+ "@sindresorhus/df": "^1.0.1",
+ "pify": "^2.3.0",
+ "pinkie-promise": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mount-point/node_modules/@sindresorhus/df": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-1.0.1.tgz",
+ "integrity": "sha512-1Hyp7NQnD/u4DSxR2DGW78TF9k7R0wZ8ev0BpMAIzA6yTQSHqNb5wTuvtcPYf4FWbVse2rW7RgDsyL8ua2vXHw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mount-point/node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
+ "node_modules/node-abi": {
+ "version": "3.71.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz",
+ "integrity": "sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "license": "MIT"
+ },
+ "node_modules/node-gyp": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
+ "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^9.1.0",
+ "nopt": "^5.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": ">= 10.12.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/node-gyp/node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
+ "dependencies": {
+ "path-key": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npmlog": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
+ "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw=="
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-limit/node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "license": "MIT",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==",
+ "license": "MIT",
+ "dependencies": {
+ "glob-base": "^0.3.0",
+ "is-dotfile": "^1.0.0",
+ "is-extglob": "^1.0.0",
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/path-scurry/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+ "dependencies": {
+ "pinkie": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
+ "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/progress-stream": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz",
+ "integrity": "sha512-MIBPjZz6oGNSw5rn2mSp+nP9FGoaVo6QsPyPVEaD4puilz5hZNa3kfnrlqRNYFsugslbU3An4mnkLLtZOaWvrA==",
+ "dependencies": {
+ "speedometer": "~0.1.2",
+ "through2": "~0.2.3"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+ "license": "ISC"
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
+ },
+ "node_modules/pump": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
+ "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
+ "engines": {
+ "node": ">=0.6.0",
+ "teleport": ">=0.2.0"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.11.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
+ "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystring": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
+ "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/rage-edit": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/rage-edit/-/rage-edit-1.2.0.tgz",
+ "integrity": "sha512-0RspBRc2s6We4g7hRCvT5mu7YPEnfjvQK8Tt354a2uUNJCMC7MKLvo/1mLvHUCQ/zbP6siQyp5VRZN7UCpMFZg==",
+ "license": "MIT"
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.3.0.tgz",
+ "integrity": "sha512-MuEnA0lbSi7JS8XM+WNJlWZkHAAdm7gETHdFK//Q/mChGyj2akEFtdLZh32jSdkWGbRwCW9pn6g3LWDdDeZnBQ==",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-3.2.0.tgz",
+ "integrity": "sha512-Ep0RsvAjnRcBX1p5vogbaBdAGu/8j/ewpvGqnQYunnLd9SM0vWcPJewPKNnWFggf0hF0pwIgwV5XK7qQ7UZ8Qg==",
+ "dependencies": {
+ "execa": "^0.10.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/sanitize-filename": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
+ "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
+ "license": "WTFPL OR ISC",
+ "dependencies": {
+ "truncate-utf8-bytes": "^1.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+ },
+ "node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shell-escape": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz",
+ "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==",
+ "license": "MIT"
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/slide": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+ "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
+ "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/speedometer": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz",
+ "integrity": "sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q=="
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
+ "license": "BSD-3-Clause",
+ "optional": true
+ },
+ "node_modules/sqlite3": {
+ "version": "5.1.7",
+ "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
+ "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "node-addon-api": "^7.0.0",
+ "prebuild-install": "^7.1.1",
+ "tar": "^6.1.11"
+ },
+ "optionalDependencies": {
+ "node-gyp": "8.x"
+ },
+ "peerDependencies": {
+ "node-gyp": "8.x"
+ },
+ "peerDependenciesMeta": {
+ "node-gyp": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ssri": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/static-eval": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
+ "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==",
+ "dependencies": {
+ "escodegen": "^1.8.1"
+ }
+ },
+ "node_modules/stream-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
+ "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
+ "dependencies": {
+ "debug": "2"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ },
+ "node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-outer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
+ "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "license": "ISC",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-fs/node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "license": "ISC"
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar-stream/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/tar-stream/node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/throttle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/throttle/-/throttle-1.0.3.tgz",
+ "integrity": "sha512-VYINSQFQeFdmhCds0tTqvQmLmdAjzGX1D6GnRQa4zlq8OpTtWSMddNyRq8Z4Snw/d6QZrWt9cM/cH8xTiGUkYA==",
+ "dependencies": {
+ "readable-stream": ">= 0.3.0",
+ "stream-parser": ">= 0.0.2"
+ },
+ "engines": {
+ "node": ">= v0.8.0"
+ }
+ },
+ "node_modules/through2": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
+ "integrity": "sha512-mLa8Bn2mZurjyomGKWRu3Bo2mvoQojFks9NvOK8H+k4kDJNkdEqG522KFZsEFBEl6rKkxTgFbE5+OPcgfvPEHA==",
+ "dependencies": {
+ "readable-stream": "~1.1.9",
+ "xtend": "~2.1.1"
+ }
+ },
+ "node_modules/through2/node_modules/readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/trash": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/trash/-/trash-4.3.0.tgz",
+ "integrity": "sha512-f36TKwIaBiXm63xSrn8OTNghg5CYHBsFVJvcObMo76LRpgariuRi2CqXQHw1VzfeximD0igdGaonOG6N760BtQ==",
+ "dependencies": {
+ "escape-string-applescript": "^2.0.0",
+ "fs-extra": "^0.30.0",
+ "globby": "^7.1.1",
+ "p-map": "^1.2.0",
+ "p-try": "^1.0.0",
+ "pify": "^3.0.0",
+ "run-applescript": "^3.0.0",
+ "uuid": "^3.1.0",
+ "xdg-trashdir": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trim-repeated": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
+ "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
+ "license": "MIT",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/truncate-utf8-bytes": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
+ "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==",
+ "license": "WTFPL",
+ "dependencies": {
+ "utf8-byte-length": "^1.0.1"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/tslog": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.3.4.tgz",
+ "integrity": "sha512-N0HHuHE0e/o75ALfkioFObknHR5dVchUad4F0XyFf3gXJYB++DewEzwGI/uIOM216E5a43ovnRNEeQIq9qgm4Q==",
+ "dependencies": {
+ "source-map-support": "^0.5.21"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "dependencies": {
+ "prelude-ls": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/underscore": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
+ "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw=="
+ },
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
+ },
+ "node_modules/unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/user-home": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
+ "integrity": "sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==",
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/utf8-byte-length": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz",
+ "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==",
+ "license": "(WTFPL OR MIT)"
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q=="
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/write-file-atomic": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz",
+ "integrity": "sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "slide": "^1.1.5"
+ }
+ },
+ "node_modules/xdg-basedir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz",
+ "integrity": "sha512-NF1pPn594TaRSUO/HARoB4jK8I+rWgcpVlpQCK6/6o5PHyLUt2CSiDrpUZbQ6rROck+W2EwF8mBJcTs+W98J9w==",
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/xdg-trashdir": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/xdg-trashdir/-/xdg-trashdir-2.1.1.tgz",
+ "integrity": "sha512-KcVhPaOu2ZurYNHSRTf1+ZHORkTZGCQ+u0JHN17QixRISJq4pXOnjt/lQcehvtHL5QAKhSzKgyjrcNnPdkPBHA==",
+ "dependencies": {
+ "@sindresorhus/df": "^2.1.0",
+ "mount-point": "^3.0.0",
+ "pify": "^2.2.0",
+ "user-home": "^2.0.0",
+ "xdg-basedir": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/xdg-trashdir/node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
+ "integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==",
+ "dependencies": {
+ "object-keys": "~0.4.0"
+ },
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+ "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
+ "dependencies": {
+ "cliui": "^5.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.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": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^15.0.1"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "15.0.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz",
+ "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+}
diff --git a/packages/registry/package.json b/packages/registry/package.json
new file mode 100644
index 00000000..a6d0a121
--- /dev/null
+++ b/packages/registry/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "@plastichub/osr-registry",
+ "description": "",
+ "version": "0.1.0",
+ "typings": "index.d.ts",
+ "publishConfig": {
+ "access": "public"
+ },
+ "bin": {
+ "osr-registry": "main.js"
+ },
+ "dependencies": {
+ "@keyv/sqlite": "^4.0.1",
+ "@plastichub/core": "^0.1.9",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-commons": "link:..\\osr-commons",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.2",
+ "env-var": "^7.0.1",
+ "keyv": "^5.1.0",
+ "keyv-file": "^0.2.0",
+ "p-map": "^4.0.0",
+ "typescript": "^4.3.5",
+ "yargs": "^14.2.3"
+ },
+ "scripts": {
+ "test": "tsc; mocha --full-trace mocha \"spec/**/*.spec.js\"",
+ "test-with-coverage": "istanbul cover node_modules/.bin/_mocha -- 'spec/**/*.spec.js'",
+ "lint": "tslint --project=./tsconfig.json",
+ "build": "tsc -p .",
+ "dev": "tsc -p . --declaration -w",
+ "typings": "tsc --declaration",
+ "docs": "npx typedoc src/index.ts",
+ "dev-test-watch": "mocha-typescript-watch"
+ },
+ "homepage": "https://git.osr-plastic.org/plastichub/lib-content",
+ "repository": {
+ "type": "git",
+ "url": "https://git.osr-plastic.org/plastichub/lib-content.git"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "license": "BSD-3-Clause",
+ "keywords": [
+ "typescript"
+ ]
+}
diff --git a/packages/registry/ref/CKBaseManager.h b/packages/registry/ref/CKBaseManager.h
new file mode 100644
index 00000000..0befc831
--- /dev/null
+++ b/packages/registry/ref/CKBaseManager.h
@@ -0,0 +1,743 @@
+/**************************************************************************/
+/* File : CKBaseManager.h */
+/* Author : Romain Sididris */
+/* */
+/* Base Class for Virtools Managers */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKBASEMANAGER_H
+
+#define CKBASEMANAGER_H "$Id:$"
+
+#include "CKDefines.h"
+
+class CKFile;
+class CKStateChunk;
+
+
+#define MAX_MANAGERFUNC_PRIORITY 30000
+
+#define DEFAULT_MANAGERFUNC_PRIORITY 0
+
+/*************************************************
+Summary: Mask for Base Manager overridable functions.
+
+Remarks:
+ + When implementing a manager the CKBaseManager::GetValidFunctionsMask
+ must be overriden to return a combination of these flag to indicate
+ which methods are implemented.
+See also: CKBaseManager,CKBaseManager::GetValidFunctionsMask
+*************************************************/
+typedef enum CKMANAGER_FUNCTIONS {
+ CKMANAGER_FUNC_OnSequenceToBeDeleted = 0x00000001, // CKBaseManager::OnSequenceToBeDeleted
+ CKMANAGER_FUNC_OnSequenceDeleted = 0x00000002, // CKBaseManager::OnSequenceDeleted
+ CKMANAGER_FUNC_PreProcess = 0x00000004, // CKBaseManager::PreProcess
+ CKMANAGER_FUNC_PostProcess = 0x00000008, // CKBaseManager::PostProcess
+ CKMANAGER_FUNC_PreClearAll = 0x00000010, // CKBaseManager::PreClearAll
+ CKMANAGER_FUNC_PostClearAll = 0x00000020, // CKBaseManager::PostClearAll
+ CKMANAGER_FUNC_OnCKInit = 0x00000040, // CKBaseManager::OnCKInit
+ CKMANAGER_FUNC_OnCKEnd = 0x00000080, // CKBaseManager::OnCKEnd
+ CKMANAGER_FUNC_OnCKPlay = 0x00000100, // CKBaseManager::OnCKPlay
+ CKMANAGER_FUNC_OnCKPause = 0x00000200, // CKBaseManager::OnCKPause
+ CKMANAGER_FUNC_PreLoad = 0x00000400, // CKBaseManager::PreLoad
+ CKMANAGER_FUNC_PreSave = 0x00000800, // CKBaseManager::PreSave
+ CKMANAGER_FUNC_PreLaunchScene = 0x00001000, // CKBaseManager::PreLaunchScene
+ CKMANAGER_FUNC_PostLaunchScene = 0x00002000, // CKBaseManager::PostLaunchScene
+ CKMANAGER_FUNC_OnCKReset = 0x00004000, // CKBaseManager::OnCKReset
+ CKMANAGER_FUNC_PostLoad = 0x00008000, // CKBaseManager::PostLoad
+ CKMANAGER_FUNC_PostSave = 0x00010000, // CKBaseManager::PostSave
+ CKMANAGER_FUNC_OnCKPostReset = 0x00020000, // CKBaseManager::OnCKPostReset
+ CKMANAGER_FUNC_OnSequenceAddedToScene = 0x00040000, // CKBaseManager::OnSequenceAddedToScene
+ CKMANAGER_FUNC_OnSequenceRemovedFromScene = 0x00080000, // CKBaseManager::OnSequenceRemovedFromScene
+ CKMANAGER_FUNC_OnPreCopy = 0x00100000, // CKBaseManager::OnPreCopy
+ CKMANAGER_FUNC_OnPostCopy = 0x00200000, // CKBaseManager::OnPostCopy
+ CKMANAGER_FUNC_OnPreRender = 0x00400000, // CKBaseManager::OnPreRender
+ CKMANAGER_FUNC_OnPostRender = 0x00800000, // CKBaseManager::OnPostRender
+ CKMANAGER_FUNC_OnPostSpriteRender = 0x01000000, // CKBaseManager::OnPostSpriteRender
+ CKMANAGER_FUNC_OnPreBackToFront = 0x02000000, // CKBaseManager::OnPreBackToFront
+ CKMANAGER_FUNC_OnPostBackToFront = 0x04000000, // CKBaseManager::OnPostBackToFront
+ CKMANAGER_FUNC_OnPreFullScreen = 0x08000000, // CKBaseManager::OnPreFullScreen
+ CKMANAGER_FUNC_OnPostFullScreen = 0x10000000, // CKBaseManager::OnPostFullScreen
+ CKMANAGER_FUNC_OnRasterizerEvent = 0x20000000, // CKBaseManager::OnRasterizerEvent
+ CKMANAGER_FUNC_OnPreSpriteRender = 0x40000000 // CKBaseManager::OnPreSpriteRender
+} CKMANAGER_FUNCTIONS;
+
+
+typedef enum CKMANAGER_FUNCTIONS_INDEX {
+ CKMANAGER_INDEX_OnSequenceToBeDeleted = 0,
+ CKMANAGER_INDEX_OnSequenceDeleted = 1,
+ CKMANAGER_INDEX_PreProcess = 2,
+ CKMANAGER_INDEX_PostProcess = 3,
+ CKMANAGER_INDEX_PreClearAll = 4,
+ CKMANAGER_INDEX_PostClearAll = 5,
+ CKMANAGER_INDEX_OnCKInit = 6,
+ CKMANAGER_INDEX_OnCKEnd = 7,
+ CKMANAGER_INDEX_OnCKPlay = 8,
+ CKMANAGER_INDEX_OnCKPause = 9,
+ CKMANAGER_INDEX_PreLoad = 10,
+ CKMANAGER_INDEX_PreSave = 11,
+ CKMANAGER_INDEX_PreLaunchScene = 12,
+ CKMANAGER_INDEX_PostLaunchScene = 13,
+ CKMANAGER_INDEX_OnCKReset = 14,
+ CKMANAGER_INDEX_PostLoad = 15,
+ CKMANAGER_INDEX_PostSave = 16,
+ CKMANAGER_INDEX_OnCKPostReset = 17,
+ CKMANAGER_INDEX_OnSequenceAddedToScene = 18,
+ CKMANAGER_INDEX_OnSequenceRemovedFromScene = 19,
+ CKMANAGER_INDEX_OnPreCopy = 20,
+ CKMANAGER_INDEX_OnPostCopy = 21,
+ CKMANAGER_INDEX_OnPreRender = 22,
+ CKMANAGER_INDEX_OnPostRender = 23,
+ CKMANAGER_INDEX_OnPostSpriteRender = 24,
+ CKMANAGER_INDEX_OnPreBackToFront = 25,
+ CKMANAGER_INDEX_OnPostBackToFront = 26,
+ CKMANAGER_INDEX_OnPreFullScreen = 27,
+ CKMANAGER_INDEX_OnPostFullScreen = 28,
+ CKMANAGER_INDEX_OnRasterizerEvent = 29,
+ CKMANAGER_INDEX_OnPreSpriteRender = 30,
+} CKMANAGER_FUNCTIONS_INDEX;
+
+
+/*************************************************************************
+Summary: Base Class for managers.
+
+Remarks:
++ This class provides virtual methods that can be override by any managers. Any manager that inherits from CKBaseManager can override function to do some processing.
+
++ The instances of managers may be retrieved through the global function CKContext::GetManagerByGuid()
+
++ Some default managers implemented in Virtools can be accessed directly : See Managers Access
+
+
+
+See also: CKContext::RegisterNewManager,Implementing a external Manager
+*************************************************************************/
+class CKBaseManager {
+public:
+
+ CKBaseManager(CKContext *Context,CKGUID guid,CKSTRING Name);
+
+ virtual ~CKBaseManager();
+
+/*************************************************
+Summary: Acces to Manager GUID
+
+Return Value:
+ CKGUID of this manager.
+Remarks:
+ + Each Manager is given an unique GUID. When creating a new manager it should
+ assign itself a GUID and name before registering itsef.
+
+{html:}
+
+ CKAttributeManager::CKAttributeManager(CKContext *Context):CKBaseManager(Context,ATTRIBUTE_MANAGER_GUID,"Attribute Manager")
+ {
+ ....
+ ....
+ Context->RegisterNewManager(this);
+ }
+
+{html:
}
+
+See Also: CKContext::RegisterNewManager,GetName
+*************************************************/
+ CKGUID GetGuid() { return m_ManagerGuid; }
+/*************************************************
+Summary: Acces to Manager name
+
+Return Value:
+ Name of this manager.
+Remarks:
+ + Each Manager can be given a name. When creating a new manager it should
+ assign itself a GUID and name before registering itsef.
+
+{html:}
+
+ CKAttributeManager::CKAttributeManager(CKContext *Context):CKBaseManager(Context,ATTRIBUTE_MANAGER_GUID,"Attribute Manager")
+ {
+ ....
+ ....
+ Context->RegisterNewManager(this);
+ }
+
+{html:
}
+
+See Also: CKContext::RegisterNewManager,GetGuid
+*************************************************/
+ CKSTRING GetName() { return m_ManagerName; }
+
+/*************************************************
+Summary: Called to save manager data.
+
+Arguments:
+ SavedFile: A pointer to the CKFile being saved.
+Return Value:
+ This function should return a valid CKStateChunk that contain data to save or NULL if there is nothing to save.
+Remarks:
++ During a save operation, each manager is given the opportunity to save its data in the file.
++ The file being saved is given for information only and must not be modified. It can be used to decide whether it is worth saving
+data for your manager.
+See Also: CKStateChunk,LoadData
+*************************************************/
+ virtual CKStateChunk* SaveData(CKFile* SavedFile) { return NULL; }
+
+/*************************************************
+Summary: Called to load manager data.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ chunk: A pointer to a CKStateChunk that was saved in the file.
+ LoadedFile: A pointer to the CKFile being loaded.
+Remarks:
+ + During a load operation, each manager is automatically called if there was a chunk saved in the file with SaveData.
+See Also: CKStateChunk,SaveData
+*************************************************/
+ virtual CKERROR LoadData(CKStateChunk *chunk,CKFile* LoadedFile) { return CK_OK; }
+
+/*************************************************
+Summary: Called at the beginning of a CKContext::ClearAll operation.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the beginning of a CKContext::ClearAll operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PreClearAll for this function to get called.
+
+See Also:Main Virtools Events,PostClearAll,CKContext::ClearAll
+*************************************************/
+ virtual CKERROR PreClearAll() { return CK_OK; }
+/*************************************************
+Summary: Called at the end of a CKContext::ClearAll operation.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the end of a CKContext::ClearAll operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PostClearAll for this function to get called.
+
+See Also:Main Virtools Events,PreClearAll,CKContext::ClearAll,
+*************************************************/
+ virtual CKERROR PostClearAll() { return CK_OK; }
+
+/*************************************************
+Summary: Called at the beginning of each process loop.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the beginning of a CKContext::Process operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PreProcess for this function to get called.
+See Also:Main Virtools Events,PostProcess,CKContext::Process,
+*************************************************/
+ virtual CKERROR PreProcess() { return CK_OK; }
+/*************************************************
+Summary: Called at the end of each process loop.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the end of a CKContext::Process operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PostProcess for this function to get called.
+
+See Also:Main Virtools Events,PreProcess,CKContext::Process,
+*************************************************/
+ virtual CKERROR PostProcess() { return CK_OK; }
+
+
+/*************************************************
+Summary: Called when objects are added to a scene
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ scn: A pointer to the CKScene to which objects where added.
+ objids: A pointer to a list of CK_ID of the objects being added to the scene.
+ count: number of objects in objids list.
+Remarks:
++ You can override these functions to add specific processing when adding or removing objects from scene
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnSequenceAddedToScene for this function to get called.
+
+See Also:Main Virtools Events,SequenceRemovedFromScene
+*************************************************/
+ virtual CKERROR SequenceAddedToScene(CKScene *scn,CK_ID *objids,int count) { return CK_OK; }
+
+/*************************************************
+Summary: Called when objects are removed from a scene
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ scn: A pointer to the CKScene to which objects where added.
+ objids: A pointer to a list of CK_ID of the objects being added to the scene.
+ count: number of objects in objids list.
+Remarks:
++ You can override these functions to add specific processing when adding or removing objects from scene
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnSequenceRemovedFromScene for this function to get called.
+
+See Also:Main Virtools Events,SequenceAddedToScene,
+*************************************************/
+ virtual CKERROR SequenceRemovedFromScene(CKScene *scn,CK_ID *objids,int count){ return CK_OK; }
+
+/*************************************************
+Summary: Called before a scene becomes active.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ OldScene: Previous active scene.
+ NewScene: Scene to become active.
+Remarks:
++ You can override these functions to add specific processing at the beginning and at the end of a LaunchScene operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PreLaunchScene for this function to get called.
+
+See Also:Main Virtools Events,PostLaunchScene,
+*************************************************/
+ virtual CKERROR PreLaunchScene(CKScene* OldScene,CKScene* NewScene) { return CK_OK; }
+
+/*************************************************
+Summary: Called after a scene became active.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ OldScene: Previous active scene.
+ NewScene: Scene that have been activated.
+Remarks:
++ You can override these functions to add specific processing at the beginning and at the end of a LaunchScene operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PostLaunchScene for this function to get called.
+
+See Also:Main Virtools Events,PreLaunchScene
+*************************************************/
+ virtual CKERROR PostLaunchScene(CKScene* OldScene,CKScene* NewScene) { return CK_OK; }
+
+/*************************************************
+Summary: Called at the end of the creation of a CKContext.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function if you need to add specific processing at initialization.
++ If your manager is registered after the context has been created and if it implements the OnCKInit()
+function then, this function will be called upon registration.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnCKInit for this function to get called.
+
+See Also:Main Virtools Events,OnCKEnd,CKCreateContext
+*************************************************/
+ virtual CKERROR OnCKInit() { return CK_OK; }
+
+/*************************************************
+Summary: Called at deletion of a CKContext
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function if you need to clean up things at the end of the session.
++ This method is called at the beginning of the deletion of the CKContext, the manager
+is also deleted a short time after.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnCKEnd for this function to get called.
+
+See Also:Main Virtools Events,OnCKInit,CKCloseContext
+*************************************************/
+ virtual CKERROR OnCKEnd() { return CK_OK; }
+
+/*************************************************
+Summary: Called before the composition is reset.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
+You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnCKReset for this function to get called.
+
+See Also:Main Virtools Events,CKContext::Reset,OnCKPostReset,OnCKPause,OnCKPlay.
+*************************************************/
+ virtual CKERROR OnCKReset() { return CK_OK; }
+/*************************************************
+Summary: Called after the composition has been restarted.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
+You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnCKPostReset for this function to get called.
+See Also:Main Virtools Events ,CKContext::Reset,OnCKReset,OnCKPause,OnCKPlay.
+*************************************************/
+ virtual CKERROR OnCKPostReset() { return CK_OK; }
+/*************************************************
+Summary: Called when the process loop is paused.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
+You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnCKPause for this function to get called.
+See Also:Main Virtools Events,CKContext::Reset,OnCKReset,OnCKPostReset,OnCKPlay.
+*************************************************/
+ virtual CKERROR OnCKPause() { return CK_OK; }
+/*************************************************
+Summary: Called when the process loop is started .
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
+You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnCKPlay for this function to get called.
+See Also:Main Virtools Events,CKContext::Reset,OnCKReset,OnCKPostReset,OnCKPause.
+*************************************************/
+ virtual CKERROR OnCKPlay() { return CK_OK; }
+
+/*************************************************
+Summary: Called just before objects are deleted.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ objids: A pointer to a list of CK_ID of the objects being deleted.
+ count: number of objects in objids list.
+Remarks:
++ You can override this function if you need to add specific processing before objects are deleted.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnSequenceToBeDeleted for this function to get called.
+
+See Also:Main Virtools Events,CKContext::DestroyObjects,SequenceDeleted
+*************************************************/
+ virtual CKERROR SequenceToBeDeleted(CK_ID *objids,int count) { return CK_OK; }
+
+/*************************************************
+Summary: Called after objects have been deleted.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ objids: A pointer to a list of CK_ID of the objects being deleted.
+ count: number of objects in objids list.
+Remarks:
++ You can override this function if you need to add specific processing after objects have been deleted.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnSequenceDeleted for this function to get called.
+
+See Also:Main Virtools Events,CKContext::DestroyObjects,SequenceToBeDeleted
+*************************************************/
+ virtual CKERROR SequenceDeleted(CK_ID *objids,int count) { return CK_OK; }
+
+/*************************************************
+Summary: Called at the beginning of a load operation.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the beginning of a load operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PreLoad for this function to get called.
+
+See Also:Main Virtools Events,PreSave,PostSave,PostLoad,CKContext::Load
+*************************************************/
+ virtual CKERROR PreLoad() { return CK_OK; }
+
+/*************************************************
+Summary: Called at the end of a load operation.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the end of a load operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PostLoad for this function to get called.
+
+See Also:Main Virtools Events,PreSave,PostSave,PreLoad,CKContext::Load
+*************************************************/
+ virtual CKERROR PostLoad() { return CK_OK; }
+
+/*************************************************
+Summary: Called at the beginning of a save operation.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the beginning of a save operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PreSave for this function to get called.
+
+See Also:Main Virtools Events,PreSave,PostSave,PreLoad,CKContext::Load
+*************************************************/
+ virtual CKERROR PreSave() { return CK_OK; }
+
+/*************************************************
+Summary: Called at the end of a save operation.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing at the end of a save operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_PostSave for this function to get called.
+
+See Also:Main Virtools Events,PreSave,PostSave,PreLoad,CKContext::Load
+*************************************************/
+ virtual CKERROR PostSave() { return CK_OK; }
+
+/*************************************************
+Summary: Called at the beginning of a copy.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ context: A CKDependenciesContext containing the objects being copied.
+Remarks:
++ You can override this function to add specific processing at the beginning of a copy operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPreCopy for this function to get called.
+
+See Also:Main Virtools Events,OnPostCopy,CKContext::CopyObjects
+*************************************************/
+ virtual CKERROR OnPreCopy(CKDependenciesContext& context) { return CK_OK; }
+
+/*************************************************
+Summary: Called at the end of a copy.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Arguments:
+ context: A CKDependenciesContext containing the objects being copied.
+Remarks:
++ You can override this function to add specific processing at the beginning of a copy operation.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPostCopy for this function to get called.
+
+See Also:Main Virtools Events,OnPreCopy,CKContext::CopyObjects
+*************************************************/
+ virtual CKERROR OnPostCopy(CKDependenciesContext& context) { return CK_OK; }
+
+/*************************************************
+Summary: Called before the rendering of the 3D objects.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing before the rendering of the scene occured.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPreRender for this function to get called.
+See Also:OnPostRender,OnPostSpriteRender,CKRenderContext::Render,Understanding the Render Loop
+*************************************************/
+ virtual CKERROR OnPreRender(CKRenderContext* dev) { return CK_OK; }
+
+/*************************************************
+Summary: Called after the rendering of the 3D objects .
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing after the rendering of the 3D scene occured.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPostRender for this function to get called.
+See Also:OnPreRender,OnPostSpriteRender,CKRenderContext::Render,Understanding the Render Loop
+*************************************************/
+ virtual CKERROR OnPostRender(CKRenderContext* dev) { return CK_OK; }
+
+/*************************************************
+Summary: Called Before the rendering of background 2D entities.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing before the rendering of the background 2D entities occured.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPostSpriteRender for this function to get called.
+See Also:OnPostRender,OnPreRender,CKRenderContext::Render,Understanding the Render Loop
+*************************************************/
+ virtual CKERROR OnPreSpriteRender(CKRenderContext* dev) { return CK_OK; }
+
+/*************************************************
+Summary: Called after the rendering of foreground 2D entities.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing after the rendering of the foreground 2D entities occured.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPostSpriteRender for this function to get called.
+See Also:OnPostRender,OnPreRender,CKRenderContext::Render,Understanding the Render Loop
+*************************************************/
+ virtual CKERROR OnPostSpriteRender(CKRenderContext* dev) { return CK_OK; }
+
+/*************************************************
+Summary: Returns the priority of the specified manager function.
+
+Arguments:
+ Function: A CKMANAGER_FUNCTIONS to get the priority of.
+Return Value: A integer giving priority for the specified function.
+Remarks:
+ + Override this function if you want to specify a priority for one or several functions of your manager.
+ + The default implementation returns a priority of 0 for all functions.
+
+Example:
+ // To ensure that your PostProcess() function will be one of the first to be called amongst all managers:
+
+ int MyManager::GetFunctionPriority(CKMANAGER_FUNCTIONS Function)
+ {
+ if (Function==CKMANAGER_FUNC_PostProcess) return 10000; // High Priority
+ return 0;
+ }
+See Also: CKMANAGER_FUNCTIONS
+*************************************************/
+ virtual int GetFunctionPriority(CKMANAGER_FUNCTIONS Function) { return 0; }
+
+/*************************************************
+Summary: Returns list of functions implemented by the manager.
+
+Return Value: A combination of CKMANAGER_FUNCTIONS.
+Remarks.
++ You must override this function to indicate which functions your manager implements.
+Example:
+ // The attribute manager implements four CKBaseManager functions :PreClearAll,PostLoad,OnSequenceAddedToscene
+ // and OnSequenceRemovedFromScene so its GetValidFunctionsMask looks like this:
+
+ virtual CKDWORD GetValidFunctionsMask() { return CKMANAGER_FUNC_PreClearAll |
+ CKMANAGER_FUNC_PostLoad |
+ CKMANAGER_FUNC_OnSequenceAddedToScene |
+ CKMANAGER_FUNC_OnSequenceRemovedFromScene; }
+
+See Also: CKMANAGER_FUNCTIONS
+*************************************************/
+ virtual CKDWORD GetValidFunctionsMask() { return 0; }
+
+
+/*************************************************
+Summary: Called before the backbuffer is presented.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing before the backbuffer is presented.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPreBackToFront for this function to get called.
+See Also:OnPostBackToFront,CKRenderContext::Render,Understanding the Render Loop,GetValidFunctionsMask
+*************************************************/
+ virtual CKERROR OnPreBackToFront(CKRenderContext* dev) { return CK_OK; }
+/*************************************************
+Summary: Called after the backbuffer is presented.
+
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing after the backbuffer is presented.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPostBackToFront for this function to get called.
+See Also:OnPreBackToFront,CKRenderContext::Render,Understanding the Render Loop,GetValidFunctionsMask
+*************************************************/
+ virtual CKERROR OnPostBackToFront(CKRenderContext* dev) { return CK_OK; }
+/*************************************************
+Summary: Called before switching to/from fullscreen.
+
+Arguments:
+ Going2Fullscreen: TRUE if we are going to fullscreen , FALSE if returning to windowed mode.
+ dev: A Pointer to the CKRenderContext that is currently changing mode.
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing before a context switch to/from fullscreen.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPreFullScreen for this function to get called.
+
+See Also:OnPreBackToFront,CKRenderContext::Render,Understanding the Render Loop,GetValidFunctionsMask
+*************************************************/
+ virtual CKERROR OnPreFullScreen(BOOL Going2Fullscreen, CKRenderContext* dev) { return CK_OK; }
+
+/*************************************************
+Summary: Called after switching to/from fullscreen.
+
+Arguments:
+ Going2Fullscreen: TRUE if we are going to fullscreen , FALSE if returning to windowed mode.
+ dev: A Pointer to the CKRenderContext that has just changed of video mode.
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing after a context switch to/from fullscreen.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnPostFullScreen for this function to get called.
+
+See Also:OnPreBackToFront,CKRenderContext::Render,Understanding the Render Loop,GetValidFunctionsMask
+*************************************************/
+ virtual CKERROR OnPostFullScreen(BOOL Going2Fullscreen,CKRenderContext* dev) { return CK_OK; }
+
+/*************************************************
+Summary: Called for specific rasterizer events.
+
+Arguments:
+ Event: Event that was sent by the rasterizer.
+ dev: A Pointer to the CKRenderContext that has just changed of video mode.
+Return Value:
+ CK_OK if successful or an error code otherwise.
+Remarks:
++ You can override this function to add specific processing when a render context
+is created/destroyed or resized.
++ According to implementation (DirectX , OpenGL,etc.) some events can occur
+such as LostDevice with DirectX that you might need to handle when directly using
+DirectX objects in a manager.
++ You must override GetValidFunctionsMask and return a value including
+CKMANAGER_FUNC_OnRasterizerEvent for this function to get called.
+
+See Also:CKRenderContext::Render,Understanding the Render Loop,GetValidFunctionsMask
+*************************************************/
+ virtual CKERROR OnRasterizerEvent(CKRST_EVENTS Event,CKRenderContext* dev) { return CK_OK; }
+
+
+
+ CKERROR CKDestroyObject(CKObject *obj,DWORD Flags=0,CKDependencies* depoptions=NULL);
+ CKERROR CKDestroyObject(CK_ID id,DWORD Flags=0,CKDependencies* depoptions=NULL);
+ CKERROR CKDestroyObjects(CK_ID* obj_ids,int Count,DWORD Flags=0,CKDependencies* depoptions=NULL);
+ CKObject *CKGetObject(CK_ID id);
+
+/*******************************************
+Summary: Starts profiling.
+Remarks:
+
++ The time taken by the manager between the
+StartProfile / StopProfile sequence will be added
+to m_ProcessingTime member of CKBaseManager and
+will appear in the Profiler in the Virtools Interface.
+
++ The time taken by a manager on the PreProcess,PostProcess,PreRender,PostRender and PostSpriteRender
+method is automatically computed so you should use these methods if there are other parts
+of your manager you would like to be profiled.
+
+See Also:StopProfile
+**********************************************/
+ void StartProfile();
+
+/*******************************************
+Summary: Stops profiling.
+Remarks:
++ The time taken by the manager between the
+StartProfile / StopProfile sequence will be added
+to m_ProcessingTime member of CKBaseManager and
+will appear in the Profiler in the Virtools Interface.
++ The time taken by a manager on the PreProcess,PostProcess,PreRender,PostRender and PostSpriteRender
+method is automatically computed so you should use these methods if there are other parts
+of your manager you would like to be profiled.
+See Also:StopProfile
+**********************************************/
+ void StopProfile();
+
+public:
+ CKGUID m_ManagerGuid; // Manager GUID
+ CKSTRING m_ManagerName; // Manager Name
+ CKContext* m_Context; // A pointer to the CKContext on which this manager is valid.
+ float m_ProcessingTime; // Time elapsed during profiling. (Reset each frame before behavioral processing starts)
+ VxRDTSCProfiler m_Timer;
+
+};
+
+#endif
\ No newline at end of file
diff --git a/packages/registry/ref/CKBaseManager.ts b/packages/registry/ref/CKBaseManager.ts
new file mode 100644
index 00000000..67062f49
--- /dev/null
+++ b/packages/registry/ref/CKBaseManager.ts
@@ -0,0 +1,273 @@
+const MAX_MANAGERFUNC_PRIORITY = 30000;
+const DEFAULT_MANAGERFUNC_PRIORITY = 0;
+
+type CKGUID = string;
+type CKSTRING = string;
+type CKDWORD = number;
+type CK_ID = number;
+type BOOL = boolean;
+
+class CKFile {}
+class CKStateChunk {}
+class CKDependenciesContext {}
+class CKRenderContext {}
+class CKScene {}
+class CKObject {}
+type CKRST_EVENTS = any; // Placeholder
+type CKContext = any; // Placeholder
+type CKERROR = any; // Placeholder
+type CKDependencies = any; // Placeholder
+
+enum CKMANAGER_FUNCTIONS {
+ CKMANAGER_FUNC_OnSequenceToBeDeleted = 0x00000001,
+ CKMANAGER_FUNC_OnSequenceDeleted = 0x00000002,
+ CKMANAGER_FUNC_PreProcess = 0x00000004,
+ CKMANAGER_FUNC_PostProcess = 0x00000008,
+ CKMANAGER_FUNC_PreClearAll = 0x00000010,
+ CKMANAGER_FUNC_PostClearAll = 0x00000020,
+ CKMANAGER_FUNC_OnCKInit = 0x00000040,
+ CKMANAGER_FUNC_OnCKEnd = 0x00000080,
+ CKMANAGER_FUNC_OnCKPlay = 0x00000100,
+ CKMANAGER_FUNC_OnCKPause = 0x00000200,
+ CKMANAGER_FUNC_PreLoad = 0x00000400,
+ CKMANAGER_FUNC_PreSave = 0x00000800,
+ CKMANAGER_FUNC_PreLaunchScene = 0x00001000,
+ CKMANAGER_FUNC_PostLaunchScene = 0x00002000,
+ CKMANAGER_FUNC_OnCKReset = 0x00004000,
+ CKMANAGER_FUNC_PostLoad = 0x00008000,
+ CKMANAGER_FUNC_PostSave = 0x00010000,
+ CKMANAGER_FUNC_OnCKPostReset = 0x00020000,
+ CKMANAGER_FUNC_OnSequenceAddedToScene = 0x00040000,
+ CKMANAGER_FUNC_OnSequenceRemovedFromScene = 0x00080000,
+ CKMANAGER_FUNC_OnPreCopy = 0x00100000,
+ CKMANAGER_FUNC_OnPostCopy = 0x00200000,
+ CKMANAGER_FUNC_OnPreRender = 0x00400000,
+ CKMANAGER_FUNC_OnPostRender = 0x00800000,
+ CKMANAGER_FUNC_OnPostSpriteRender = 0x01000000,
+ CKMANAGER_FUNC_OnPreBackToFront = 0x02000000,
+ CKMANAGER_FUNC_OnPostBackToFront = 0x04000000,
+ CKMANAGER_FUNC_OnPreFullScreen = 0x08000000,
+ CKMANAGER_FUNC_OnPostFullScreen = 0x10000000,
+ CKMANAGER_FUNC_OnRasterizerEvent = 0x20000000,
+ CKMANAGER_FUNC_OnPreSpriteRender = 0x40000000,
+}
+
+enum CKMANAGER_FUNCTIONS_INDEX {
+ CKMANAGER_INDEX_OnSequenceToBeDeleted = 0,
+ CKMANAGER_INDEX_OnSequenceDeleted = 1,
+ CKMANAGER_INDEX_PreProcess = 2,
+ CKMANAGER_INDEX_PostProcess = 3,
+ CKMANAGER_INDEX_PreClearAll = 4,
+ CKMANAGER_INDEX_PostClearAll = 5,
+ CKMANAGER_INDEX_OnCKInit = 6,
+ CKMANAGER_INDEX_OnCKEnd = 7,
+ CKMANAGER_INDEX_OnCKPlay = 8,
+ CKMANAGER_INDEX_OnCKPause = 9,
+ CKMANAGER_INDEX_PreLoad = 10,
+ CKMANAGER_INDEX_PreSave = 11,
+ CKMANAGER_INDEX_PreLaunchScene = 12,
+ CKMANAGER_INDEX_PostLaunchScene = 13,
+ CKMANAGER_INDEX_OnCKReset = 14,
+ CKMANAGER_INDEX_PostLoad = 15,
+ CKMANAGER_INDEX_PostSave = 16,
+ CKMANAGER_INDEX_OnCKPostReset = 17,
+ CKMANAGER_INDEX_OnSequenceAddedToScene = 18,
+ CKMANAGER_INDEX_OnSequenceRemovedFromScene = 19,
+ CKMANAGER_INDEX_OnPreCopy = 20,
+ CKMANAGER_INDEX_OnPostCopy = 21,
+ CKMANAGER_INDEX_OnPreRender = 22,
+ CKMANAGER_INDEX_OnPostRender = 23,
+ CKMANAGER_INDEX_OnPostSpriteRender = 24,
+ CKMANAGER_INDEX_OnPreBackToFront = 25,
+ CKMANAGER_INDEX_OnPostBackToFront = 26,
+ CKMANAGER_INDEX_OnPreFullScreen = 27,
+ CKMANAGER_INDEX_OnPostFullScreen = 28,
+ CKMANAGER_INDEX_OnRasterizerEvent = 29,
+ CKMANAGER_INDEX_OnPreSpriteRender = 30,
+}
+
+type VxRDTSCProfiler = any; // Placeholder
+
+class CKBaseManager {
+ m_ManagerGuid: CKGUID;
+ m_ManagerName: CKSTRING;
+ m_Context: CKContext;
+ m_ProcessingTime: number;
+ m_Timer: VxRDTSCProfiler;
+
+ constructor(Context: CKContext, guid: CKGUID, Name: CKSTRING) {
+ this.m_ManagerGuid = guid;
+ this.m_ManagerName = Name;
+ this.m_Context = Context;
+ this.m_ProcessingTime = 0;
+ // this.m_Timer = new VxRDTSCProfiler(); // Initialize if needed
+ }
+
+ GetGuid(): CKGUID {
+ return this.m_ManagerGuid;
+ }
+
+ GetName(): CKSTRING {
+ return this.m_ManagerName;
+ }
+
+ SaveData(SavedFile: CKFile): CKStateChunk | null {
+ return null;
+ }
+
+ LoadData(chunk: CKStateChunk, LoadedFile: CKFile): CKERROR {
+ return CK_OK;
+ }
+
+ PreClearAll(): CKERROR {
+ return CK_OK;
+ }
+
+ PostClearAll(): CKERROR {
+ return CK_OK;
+ }
+
+ PreProcess(): CKERROR {
+ return CK_OK;
+ }
+
+ PostProcess(): CKERROR {
+ return CK_OK;
+ }
+
+ SequenceAddedToScene(scn: CKScene, objids: CK_ID[], count: number): CKERROR {
+ return CK_OK;
+ }
+
+ SequenceRemovedFromScene(scn: CKScene, objids: CK_ID[], count: number): CKERROR {
+ return CK_OK;
+ }
+
+ PreLaunchScene(OldScene: CKScene, NewScene: CKScene): CKERROR {
+ return CK_OK;
+ }
+
+ PostLaunchScene(OldScene: CKScene, NewScene: CKScene): CKERROR {
+ return CK_OK;
+ }
+
+ OnCKInit(): CKERROR {
+ return CK_OK;
+ }
+
+ OnCKEnd(): CKERROR {
+ return CK_OK;
+ }
+
+ OnCKReset(): CKERROR {
+ return CK_OK;
+ }
+
+ OnCKPostReset(): CKERROR {
+ return CK_OK;
+ }
+
+ OnCKPause(): CKERROR {
+ return CK_OK;
+ }
+
+ OnCKPlay(): CKERROR {
+ return CK_OK;
+ }
+
+ SequenceToBeDeleted(objids: CK_ID[], count: number): CKERROR {
+ return CK_OK;
+ }
+
+ SequenceDeleted(objids: CK_ID[], count: number): CKERROR {
+ return CK_OK;
+ }
+
+ PreLoad(): CKERROR {
+ return CK_OK;
+ }
+
+ PostLoad(): CKERROR {
+ return CK_OK;
+ }
+
+ PreSave(): CKERROR {
+ return CK_OK;
+ }
+
+ PostSave(): CKERROR {
+ return CK_OK;
+ }
+
+ OnPreCopy(context: CKDependenciesContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPostCopy(context: CKDependenciesContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPreRender(dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPostRender(dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPreSpriteRender(dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPostSpriteRender(dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ GetFunctionPriority(Function: CKMANAGER_FUNCTIONS): number {
+ return 0;
+ }
+
+ GetValidFunctionsMask(): CKDWORD {
+ return 0;
+ }
+
+ OnPreBackToFront(dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPostBackToFront(dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPreFullScreen(Going2Fullscreen: BOOL, dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnPostFullScreen(Going2Fullscreen: BOOL, dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ OnRasterizerEvent(Event: CKRST_EVENTS, dev: CKRenderContext): CKERROR {
+ return CK_OK;
+ }
+
+ CKDestroyObject(obj: CKObject, Flags = 0, depoptions: CKDependencies | null = null): CKERROR {
+ return CK_OK;
+ }
+
+ CKDestroyObjectById(id: CK_ID, Flags = 0, depoptions: CKDependencies | null = null): CKERROR {
+ return CK_OK;
+ }
+
+ CKDestroyObjects(obj_ids: CK_ID[], Count: number, Flags = 0, depoptions: CKDependencies | null = null): CKERROR {
+ return CK_OK;
+ }
+
+ CKGetObject(id: CK_ID): CKObject | null {
+ return null;
+ }
+
+ StartProfile() {}
+
+ StopProfile() {}
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKEnums.h b/packages/registry/ref/CKEnums.h
new file mode 100644
index 00000000..ce2f8558
--- /dev/null
+++ b/packages/registry/ref/CKEnums.h
@@ -0,0 +1,518 @@
+/*************************************************************************/
+/* File : CKEnums.h */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 1999, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKENUMS_H
+
+#define CKENUMS_H "$Id:$"
+
+
+/***************************************************
+{filename:CK_OBJECT_FLAGS}
+Summary: CKObject Flags
+
+Remarks:
++ Flags specifying special settings for basic objects.
++ Some of this flags are shared with sub-classes such as CKParameterIn,CKParameterOut and CKBehaviorIO.
++ You rarely need to modify directly this flags through CKObject::SetFlags or CKObject::ModifyObjectFlags instead
+you should always use the specific acces function (given between ()) which may need to perform additionnal operations.
+See also: CKObject,CKObject::GetObjectFlags,CKObject::ModifyObjectFlags
+*************************************************/
+typedef enum CK_OBJECT_FLAGS {
+ CK_OBJECT_INTERFACEOBJ = 0x00000001, // Reserved for Inteface Use
+ CK_OBJECT_PRIVATE = 0x00000002, // The object must not be displayed in interface (Lists,Level view,etc...),nor should it be saved. (CKObject::IsPrivate()
+ CK_OBJECT_INTERFACEMARK = 0x00000004,
+ CK_OBJECT_FREEID = 0x00000008, // ID of this object can be released safely and is free to be reused by future CKobjects.
+ CK_OBJECT_TOBEDELETED = 0x00000010, // This object is being deleted
+ CK_OBJECT_NOTTOBESAVED = 0x00000020, // This object must not be saved
+ CK_OBJECT_VISIBLE = 0x00000040, // This object is visible (CKObject::Show)
+ CK_OBJECT_NAMESHARED = 0x00000080, // This object has its name from another entity
+ CK_OBJECT_DYNAMIC = 0x00000108, // This object may be created or deleted at run-time, it also contails CK_OBJECT_FREEID. (CKObject::IsDynamic,CKContext::CreateObject)
+ CK_OBJECT_HIERACHICALHIDE = 0x00000200, // This object hides all its hierarchy (CKObject::Show)
+ CK_OBJECT_UPTODATE = 0x00000400, // (Camera,etc..)
+ CK_OBJECT_TEMPMARKER = 0x00000800,
+ CK_OBJECT_ONLYFORFILEREFERENCE = 0x00001000,
+ CK_OBJECT_NOTTOBEDELETED = 0x00002000, // This object must not be deleted in a clear all
+ CK_OBJECT_APPDATA = 0x00004000, // This object has app data
+ CK_OBJECT_SINGLEACTIVITY = 0x00008000, // this object has an information of single activity (active at scene start,etc..)
+ CK_OBJECT_LOADSKIPBEOBJECT = 0x00010000, // When loading this object the CKBeObject part should be skipped
+ CK_OBJECT_KEEPSINGLEACTIVITY = 0x00020000, // this object must keep its information of single activity (active at scene start,etc..)
+ CK_OBJECT_LOADREPLACINGOBJECT = 0x00040000, // Indicates the object being loaded is being replaced
+
+ CK_OBJECT_NOTTOBELISTEDANDSAVED = 0x00000023, // Combination of Private and Not To Be Saved
+ CK_OBJECT_SELECTIONSET = 0x00080000, // if group, then it is a selection set, otherwise, temporary flag used for objects belonging to a selection set. Used by Virtools's Interface
+ CK_OBJECT_VR_DISTRIBUTED = 0x00100000, // distributed object for VR (ie mainly used for distributed parameters for VR)
+
+
+// The following flags are specific to parameters (they are stored here for object's size purposes )
+ CK_PARAMETEROUT_SETTINGS = 0x00400000,
+ CK_PARAMETEROUT_PARAMOP = 0x00800000, // This parameter is the output of a CKParameterOperation (Automatically set by Engine)
+ CK_PARAMETERIN_DISABLED = 0x01000000, // Parameter In or Out is disabled (CKBehavior::EnableInputParameter,CKBehavior::DisableInputParameter)
+ CK_PARAMETERIN_THIS = 0x02000000, // Special parameter type : its value and type are always equal to its owner (CKParameter::SetAsMyselfParameter)
+ CK_PARAMETERIN_SHARED = 0x04000000,
+ CK_PARAMETEROUT_DELETEAFTERUSE = 0x08000000, // When adding parameters to CKMessage, they can be automatically deleted when message is released (CKMessage::AddParameter)
+ CK_OBJECT_PARAMMASK = 0x0FC00000, // Mask for options specific to parameters
+
+// The Following flags are specific for Behavior ios (CKBehaviorIO)
+ CK_BEHAVIORIO_IN = 0x10000000, // This BehaviorIO is a behavior input (CKBehaviorIO::SetType}
+ CK_BEHAVIORIO_OUT = 0x20000000, // This BehaviorIO is a behavior output (CKBehaviorIO::SetType)
+ CK_BEHAVIORIO_ACTIVE = 0x40000000, // This BehaviorIO is a currently active (CKBehaviorIO::Activate}
+ CK_OBJECT_IOTYPEMASK = 0x30000000,
+ CK_OBJECT_IOMASK = 0xF0000000,
+
+ // The Following flags are specific for Behavior ios (CKBehaviorIO)
+ CKBEHAVIORLINK_RESERVED = 0x10000000, // This BehaviorIO is a behavior input (CKBehaviorIO::SetType}
+ CKBEHAVIORLINK_ACTIVATEDLASTFRAME = 0x20000000, // This link had been activated last frame
+ CK_OBJECT_BEHAVIORLINKMASK = 0x30000000,
+} CK_OBJECT_FLAGS;
+
+
+
+/************************************************************
+{filename:CK_BEHAVIOR_FLAGS}
+Summary: Flags settings for behaviors.
+Remarks:
+ + When creating a prototype, you can precise various flags
+ about how your behavior will act: whether it will send or receive message,
+ does the user may add inputs,outputs or parameters, is it active, etc.
+
+See also: CKBehaviorPrototype::SetBehaviorFlags,Behavior Prototype Creation
+**********************************************************/
+typedef enum CK_BEHAVIOR_FLAGS {
+ CKBEHAVIOR_NONE =0x00000000, // Reserved for future use
+ CKBEHAVIOR_ACTIVE =0x00000001, // This behavior is active
+ CKBEHAVIOR_SCRIPT =0x00000002, // This behavior is a script
+ CKBEHAVIOR_RESERVED1 =0x00000004, // Reserved for internal use.
+ CKBEHAVIOR_USEFUNCTION =0x00000008, // Behavior uses a function and not a graph
+ CKBEHAVIOR_RESERVED2 =0x00000010, // Reserved for internal use.
+ CKBEHAVIOR_CUSTOMSETTINGSEDITDIALOG =0x00000020, // Behavior has a custom Dialog Box for settings edition .
+ CKBEHAVIOR_WAITSFORMESSAGE =0x00000040, // Behavior is waiting for a message to activate one of its outputs
+ CKBEHAVIOR_VARIABLEINPUTS =0x00000080, // Behavior may have its inputs changed by editing them
+ CKBEHAVIOR_VARIABLEOUTPUTS =0x00000100, // Behavior may have its outputs changed by editing them
+ CKBEHAVIOR_VARIABLEPARAMETERINPUTS =0x00000200, // Behavior may have its number of input parameters changed by editing them
+ CKBEHAVIOR_VARIABLEPARAMETEROUTPUTS =0x00000400, // Behavior may have its number of output parameters changed by editing them
+ CKBEHAVIOR_TOPMOST =0x00004000, // No other Behavior includes this one
+ CKBEHAVIOR_BUILDINGBLOCK =0x00008000, // This Behavior is a building block. Automatically set by the engine when coming from a DLL.
+ CKBEHAVIOR_MESSAGESENDER =0x00010000, // Behavior may send messages during its execution.
+ CKBEHAVIOR_MESSAGERECEIVER =0x00020000, // Behavior may check messages during its execution.
+ CKBEHAVIOR_TARGETABLE =0x00040000, // Behavior may be owned by a different object that the one to which its execution will apply.
+ CKBEHAVIOR_CUSTOMEDITDIALOG =0x00080000, // This Behavior have a custom Dialog Box for parameters edition .
+ CKBEHAVIOR_RESERVED0 =0x00100000, // Reserved for internal use.
+ CKBEHAVIOR_EXECUTEDLASTFRAME =0x00200000, // This behavior has been executed during last process. (Available only in profile mode )
+ CKBEHAVIOR_DEACTIVATENEXTFRAME =0x00400000, // Behavior will be deactivated next frame
+ CKBEHAVIOR_RESETNEXTFRAME =0x00800000, // Behavior will be reseted next frame
+ CKBEHAVIOR_INTERNALLYCREATEDINPUTS =0x01000000, // Behavior execution may create/delete inputs
+ CKBEHAVIOR_INTERNALLYCREATEDOUTPUTS =0x02000000, // Behavior execution may create/delete outputs
+ CKBEHAVIOR_INTERNALLYCREATEDINPUTPARAMS =0x04000000, // Behavior execution may create/delete input parameters or change their type
+ CKBEHAVIOR_INTERNALLYCREATEDOUTPUTPARAMS=0x08000000, // Behavior execution may create/delete output parameters or change their type
+ CKBEHAVIOR_INTERNALLYCREATEDLOCALPARAMS =0x40000000, // Behavior execution may create/delete local parameters or change their type
+ CKBEHAVIOR_ACTIVATENEXTFRAME =0x10000000, // Behavior will be activated next frame
+ CKBEHAVIOR_LOCKED =0x20000000, // Behavior is locked for utilisation in Virtools
+ CKBEHAVIOR_LAUNCHEDONCE =0x80000000, // Behavior has not yet been launched...
+} CK_BEHAVIOR_FLAGS;
+
+
+/*************************************************
+{filename:CK_BEHAVIOR_CALLBACKMASK}
+Summary: Mask for the messages the callback function of a behavior should be aware of.
+
+Remarks:
++The callback function of a behavior may ignore some messages using this mask.
++Don't forget to set the mask for the behavior callback function if you use one since it
+can improve performance not to receive useless messages.
+See also: CKBehaviorPrototype::SetBehaviorCallbackFct,Behavior Prototype Creation
+*************************************************/
+typedef enum CK_BEHAVIOR_CALLBACKMASK {
+ CKCB_BEHAVIORPRESAVE =0x00000001, // Callback will be called for CKM_BEHAVIORPRESAVE messages
+ CKCB_BEHAVIORDELETE =0x00000002, // Callback will be called for CKM_BEHAVIORDELETE messages
+ CKCB_BEHAVIORATTACH =0x00000004, // Callback will be called for CKM_BEHAVIORATTACH messages
+ CKCB_BEHAVIORDETACH =0x00000008, // Callback will be called for CKM_BEHAVIORDETACH messages
+ CKCB_BEHAVIORPAUSE =0x00000010, // Callback will be called for CKM_BEHAVIORPAUSE messages
+ CKCB_BEHAVIORRESUME =0x00000020, // Callback will be called for CKM_BEHAVIORRESUME messages
+ CKCB_BEHAVIORCREATE =0x00000040, // Callback will be called for CKM_BEHAVIORCREATE messages
+ CKCB_BEHAVIORRESET =0x00001000, // Callback will be called for CKM_BEHAVIORRESET messages
+ CKCB_BEHAVIORPOSTSAVE =0x00000100, // Callback will be called for CKM_BEHAVIORPOSTSAVE messages
+ CKCB_BEHAVIORLOAD =0x00000200, // Callback will be called for CKM_BEHAVIORLOAD messages
+ CKCB_BEHAVIOREDITED =0x00000400, // Callback will be called for CKM_BEHAVIOREDITED messages
+ CKCB_BEHAVIORSETTINGSEDITED =0x00000800, // Callback will be called for CKM_BEHAVIORSETTINGSEDITED messages
+ CKCB_BEHAVIORREADSTATE =0x00001000, // Callback will be called for CKM_BEHAVIORREADSTATE messages
+ CKCB_BEHAVIORNEWSCENE =0x00002000, // Callback will be called for CKM_BEHAVIORNEWSCENE messages
+ CKCB_BEHAVIORACTIVATESCRIPT =0x00004000, // Callback will be called for CKM_BEHAVIORACTIVATESCRIPT messages
+ CKCB_BEHAVIORDEACTIVATESCRIPT=0x00008000, // Callback will be called for CKM_BEHAVIORDEACTIVATESCRIPT messages
+ CKCB_BEHAVIORRESETINBREAKPOINT=0x00010000, // Callback will be called for CKM_BEHAVIORRESETINBREAKPOINT messages
+
+ CKCB_BEHAVIORBASE =0x0000000E, // Base flags :attach /detach /delete
+ CKCB_BEHAVIORSAVELOAD =0x00000301, // Base flags for load and save
+ CKCB_BEHAVIORPPR =0x00000130, // Base flags for play/pause/reset
+ CKCB_BEHAVIOREDITIONS =0x00000C00, // Base flags for editions of settings or parameters
+ CKCB_BEHAVIORALL =0xFFFFFFFF, // All flags
+} CK_BEHAVIOR_CALLBACKMASK;
+
+
+
+/*************************************************
+{filename:CK_BEHAVIOR_RETURN}
+Summary: Return value for the behavior execution function.
+Remarks:
+ + Return value of a behavior execution function is used to activate it
+ the next frame and handle errors.
+
+ + A return value with _RETRY (CKBR_ACTIVATENEXTFRAME bit set) forces the behavior to be reactivated next frame.
+
+See also: CKBehaviorPrototype::SetFunction
+*************************************************/
+typedef enum CK_BEHAVIOR_RETURN
+{
+ CKBR_OK = 0, // Everything's ok. Behavior is deactivated unless one of its inputs is active.
+ CKBR_ACTIVATENEXTFRAME = 1, // The behavior will be reactivated next frame
+ CKBR_ATTACHFAILED = 2, // The attach failed
+ CKBR_DETACHFAILED = 4, // The attach failed
+ CKBR_LOCKED = 6, // obsolete..
+ CKBR_INFINITELOOP = 8, // The behavior has reached the infinite loop limit...
+ CKBR_BREAK = 10, // Break the processing here => Keep on processing windows messages but keep on calling the behavior until
+ // it returns a different value (Used by script debugger )
+ CKBR_GENERICERROR = 0xA000, // Something went wrong
+ CKBR_BEHAVIORERROR = 0xA002, // The behavior gave to the code was wrong
+ CKBR_OWNERERROR = 0xA004, // The owner isn't what it should be
+ CKBR_PARAMETERERROR = 0xA008, // Some of the parameters are wrong
+ CKBR_GENERICERROR_RETRY = 0xA001,
+ CKBR_BEHAVIORERROR_RETRY = 0xA003,
+ CKBR_OWNERERROR_RETRY = 0xA005,
+ CKBR_PARAMETERERROR_RETRY = 0xA009,
+
+
+} CK_BEHAVIOR_RETURN;
+
+
+/*************************************************
+{filename:CK_BEHAVIOR_TYPE}
+Summary: Behavior Type.
+Remarks:
+ + Behaviors may be scripts, simpliest behaviors (a function) or elaborated graphs of sub-behaviors.
+
+See also: CKBehavior::GetType
+*************************************************/
+typedef enum CK_BEHAVIOR_TYPE {
+ CKBEHAVIORTYPE_BASE =0x00000000, // This Behavior is a most simple type of behavior ( a function )
+ CKBEHAVIORTYPE_SCRIPT =0x00000001, // This Behavior is a script
+ CKBEHAVIORTYPE_BEHAVIOR =0x00000004, // This Behavior is a simple one ( a graph )
+} CK_BEHAVIOR_TYPE;
+
+/*************************************************
+{filename:CK_PARAMETERTYPE_FLAGS}
+Summary: Flags settings for new parameter types
+
+Remarks:
++These flags specify special settings for a parameter type.
++Parameter may have a fixed or variable buffer size, some may be hidden
+so that they are not displayed in the interface.
+See also: CKParameterTypeDesc
+*************************************************/
+typedef enum CK_PARAMETERTYPE_FLAGS {
+ CKPARAMETERTYPE_VARIABLESIZE = 0x00000001, // Size of the buffer stored by the parameter may change
+ CKPARAMETERTYPE_RESERVED = 0x00000002, // Reserved
+ CKPARAMETERTYPE_HIDDEN = 0x00000004, // This parameter type should not be shown in the interface
+ CKPARAMETERTYPE_FLAGS = 0x00000008, // This parameter type is a flag (See CKParameterManager::RegisterNewFlags)
+ CKPARAMETERTYPE_STRUCT = 0x00000010, // This parameter type is a structure of parameters (See CKParameterManager::RegisterNewStructure)
+ CKPARAMETERTYPE_ENUMS = 0x00000020, // This parameter type is an enumeration (See CKParameterManager::RegisterNewEnum)
+ CKPARAMETERTYPE_USER = 0x00000040, // This parameter type is a user-defined one created in the interface
+ CKPARAMETERTYPE_NOENDIANCONV = 0x00000080, // Do not try to convert this parameter buffer On Big-Endian processors (strings, void buffer have this flags)
+ CKPARAMETERTYPE_TOSAVE = 0x00000100, // Temporary flag set in CKFile::EndSave(). This parameter type is to be saved in the SaveData callback of managers. Used in Parameter Manager (used user's flags & enums)
+} CK_PARAMETERTYPE_FLAGS;
+
+
+/*************************************************
+{filename:CK_ATTRIBUT_FLAGS}
+Summary: Attribute Flags
+
+Remarks:
+ + When created a new attribute type with CKAttributeManager::RegisterNewAttributeType , it can
+ be given special properties that will control its behavior in the Dev interface and other
+ special features such as the ability for an attribute to be copied or saved along with the object
+ it belongs to.
+See also: CKAttributeManager::RegisterNewAttributeType,CKAttributeManager::GetAttributeFlags
+*************************************************/
+typedef enum CK_ATTRIBUT_FLAGS {
+ CK_ATTRIBUT_CAN_MODIFY = 0x00000001, // This Attribute type may be renamed
+ CK_ATTRIBUT_CAN_DELETE = 0x00000002, // This Attribute type may be deleted
+ CK_ATTRIBUT_HIDDEN = 0x00000004, // This Attribute type will not appear in the Virtools Interface
+ CK_ATTRIBUT_DONOTSAVE = 0x00000008, // This Attribute type will not be saved
+ CK_ATTRIBUT_USER = 0x00000010, // This Attribute type was created by a user (in the Dev interface for example)
+ CK_ATTRIBUT_SYSTEM = 0x00000020, // This Attribute type was created by the system (Behavior Dll,Manager,etc...)
+ CK_ATTRIBUT_DONOTCOPY = 0x00000040, // This Attribute type will not be copied when the object that holds it is copied
+ CK_ATTRIBUT_TOSAVE = 0x00000080, // Temporary flag set in CKFile::EndSave(). This parameter type is to be saved in the SaveData callback of managers. Used in Attribute Manager (used attributes)
+} CK_ATTRIBUT_FLAGS;
+
+
+//----------------------------------------------------------////
+// Behavior Prototype Flags ////
+//----------------------------------------------------------////
+
+
+typedef enum CK_BEHAVIORPROTOTYPE_FLAGS {
+ CK_BEHAVIORPROTOTYPE_NORMAL =0x00000001,
+ CK_BEHAVIORPROTOTYPE_HIDDEN =0x00000002,
+ CK_BEHAVIORPROTOTYPE_OBSOLETE =0x00000004,
+} CK_BEHAVIORPROTOTYPE_FLAGS;
+
+
+/*************************************************
+{filename:CK_LOADMODE}
+Summary: Specify the way an object just loaded should be handled when it already exists in the level.
+{secret}
+
+See also:
+*************************************************/
+typedef enum CK_LOADMODE
+{
+ CKLOAD_INVALID=-1,// Use the existing object instead of loading
+ CKLOAD_OK=0, // Ignore ( Name unicity is broken )
+ CKLOAD_REPLACE=1, // Replace the existing object (Not yet implemented)
+ CKLOAD_RENAME=2, // Rename the loaded object
+ CKLOAD_USECURRENT=3,// Use the existing object instead of loading
+} CK_LOADMODE,CK_CREATIONMODE;
+
+/*************************************************
+{filename:CK_OBJECTCREATION_OPTIONS}
+Summary: Specify the way an object is created through CKCreateObject.
+
+Remarks:
+ + These flag controls the way an object is created, the most important of these flags
+ being CK_OBJECTCREATION_DYNAMIC which, if set in CKCreateObject, make the newly created object
+ dynamic.
+See also: CKContext::CreateObject,Dynamic Objects
+*************************************************/
+enum CK_OBJECTCREATION_OPTIONS
+{
+ CK_OBJECTCREATION_NONAMECHECK = 0, // Do not test for name unicity (may be overriden in special case)
+ CK_OBJECTCREATION_REPLACE = 1, // Replace the current object by the object being loaded
+ CK_OBJECTCREATION_RENAME = 2, // Rename the created object to ensure its uniqueness
+ CK_OBJECTCREATION_USECURRENT = 3, // Do not create a new object, use the one with the same name instead
+ CK_OBJECTCREATION_ASK = 4, // If a duplicate name if found, opens a dialog box to ask the useror use automatic load mode if any.
+ CK_OBJECTCREATION_FLAGSMASK = 0x0000000F, // Mask for previous values
+ CK_OBJECTCREATION_DYNAMIC = 0x00000010, // The object must be created dynamic
+ CK_OBJECTCREATION_ACTIVATE = 0x00000020, // The object will be copied/created active
+ CK_OBJECTCREATION_NONAMECOPY = 0x00000040 // The object will take control of the string given to it directly, without copying it
+};
+
+
+#define CK_OBJECTCREATION_SameDynamic (IsDynamic() ? CK_OBJECTCREATION_DYNAMIC : CK_OBJECTCREATION_NONAMECHECK)
+
+#define CK_OBJECTCREATION_Dynamic(x) (x ? CK_OBJECTCREATION_DYNAMIC : CK_OBJECTCREATION_NONAMECHECK)
+
+/*************************************************
+{filename:CK_DEPENDENCIES_OPMODE}
+Summary: Specify the mode of operation of a CKDependenciesContext.
+
+Remarks:
+ A CKDependenciesContext class is always used when it come to work
+ with object dependencies (A mesh if a dependencies of a CK3dEntity for example)
+See also: CKCreateObject
+*************************************************/
+typedef enum CK_DEPENDENCIES_OPMODE {
+ CK_DEPENDENCIES_COPY = 1, // Copying objects
+ CK_DEPENDENCIES_DELETE = 2, // Deleting objects
+ CK_DEPENDENCIES_REPLACE = 3,
+ CK_DEPENDENCIES_SAVE = 4, // Saving objects
+ CK_DEPENDENCIES_BUILD = 5, // Building a list of dependencies
+ CK_DEPENDENCIES_OPERATIONMODE = 0xF
+} CK_DEPENDENCIES_OPMODE;
+
+/*************************************************
+{filename:CK_FILE_WRITEMODE}
+Summary: Specify the way files are saved to disk (compression)
+
+Remarks :
+ + File write mode controls the format of a Virtools file when saved. More specifically it
+ controls whether compression is enabled and also if the Virtools Interface specific data
+ should be stored in the file (if CKFILE_FORVIEWER flag is set , no interface data is saved)
+
+See also: CKContext::SetFileWriteMode,CKContext::GetFileWriteMode,CKContext::SetCompressionLevel,CKContext::SetGlobalImagesSaveOptions,CKContext::SetGlobalSoundsSaveOptions
+*************************************************/
+typedef enum CK_FILE_WRITEMODE
+{
+ CKFILE_UNCOMPRESSED =0, // Save data uncompressed
+ CKFILE_CHUNKCOMPRESSED_OLD =1, // Obsolete
+ CKFILE_EXTERNALTEXTURES_OLD=2, // Obsolete : use CKContext::SetGlobalImagesSaveOptions instead.
+ CKFILE_FORVIEWER =4, // Don't save Interface Data within the file, the level won't be editable anymore in the interface
+ CKFILE_WHOLECOMPRESSED =8, // Compress the whole file
+} CK_FILE_WRITEMODE;
+
+
+
+/*************************************************
+{filename:CK_CONFIG_FLAGS}
+Summary: Flags specifying start options for Virtools
+
+Remarks:
+ Flags specifying start options for Virtools
+
+
+
+See also: CKCreateContext
+*************************************************/
+typedef enum CK_CONFIG_FLAGS {
+ CK_CONFIG_DISABLEDSOUND= 1, // Prevent CK from initializing Sound Engines
+ CK_CONFIG_DISABLEDINPUT= 2, // Prevent CK from initializing Input Engines
+ CK_CONFIG_DOWARN= 4 // Set this flag for message box warning (sound init failed, etc.)
+} CK_CONFIG_FLAGS;
+
+
+/*************************************************
+{filename:CK_DESTROY_FLAGS}
+Summary: Objects destruction Flags
+
+Remarks: Flags specifying how objects should be deleted.
+
+
+See also: CKContext::DestroyObjects,CKContext::DestroyObject
+*************************************************/
+typedef enum CK_DESTROY_FLAGS {
+ CK_DESTROY_FREEID = 0x00000001, // Release the CK_ID of the object so that it can be re-used bu new objects.
+ CK_DESTROY_NONOTIFY = 0x00000002, // Managers and other objects won't be notified of this deletion
+ CK_DESTROY_TEMPOBJECT = 0x00000003, // Combination for temporary objects : Do not notify and release CK_ID
+} CK_DESTROY_FLAGS;
+
+
+//----------------------------------------------------------////
+// Data Array Flags and Enums ////
+//----------------------------------------------------------////
+
+/************************************************
+{filename:CK_BINARYOPERATOR}
+Summary: Available operations between colums of a DataArray
+
+See Also: CKDataArray::ColumnTransform, CKDataArray::ColumnsOperate
+************************************************/
+typedef enum CK_BINARYOPERATOR{
+ CKADD = 1, // Addition
+ CKSUB = 2, // Substraction
+ CKMUL = 3, // Multiplication
+ CKDIV = 4 // Division
+} CK_BINARYOPERATOR;
+
+/************************************************
+{filename:CK_COMPOPERATOR}
+Summary: Available comparisons between colums of a DataArray
+Remarks:
+
+See Also: CKDataArray::CreateGroup, CKDataArray::FindLine
+************************************************/
+typedef enum CK_COMPOPERATOR{
+ CKEQUAL = 1,
+ CKNOTEQUAL = 2,
+ CKLESSER = 3,
+ CKLESSEREQUAL = 4,
+ CKGREATER = 5,
+ CKGREATEREQUAL = 6
+} CK_COMPOPERATOR;
+
+
+
+typedef enum CK_SETOPERATOR{
+ CKUNION = 1, // Addition
+ CKINTERSECTION = 2, // Intersection
+ CKSUBTRACTION = 3, // Subtraction
+} CK_SETOPERATOR;
+
+/************************************************
+{filename:CK_ARRAYTYPE}
+Summary: Enum defining the format of a Data Array element.
+Remarks:
+ + In a data array each column can contain data
+ of the given type.
+
+See Also: CKDataArray::InsertColumn, CKDataArray::GetColumnType
+************************************************/
+typedef enum CK_ARRAYTYPE{
+ CKARRAYTYPE_INT = 1, // an integer
+ CKARRAYTYPE_FLOAT = 2, // a float
+ CKARRAYTYPE_STRING = 3, // a pointer to a string
+ CKARRAYTYPE_OBJECT = 4, // a CKObject ID (CK_ID)
+ CKARRAYTYPE_PARAMETER = 5 // a CKParameter ID
+} CK_ARRAYTYPE;
+
+
+
+/*************************************************
+{filename:CK_LOAD_FLAGS}
+Summary: Load Options.
+
+Remarks:
++ This options apply when loading a Virtools file
+or a importing a 3D Model file.
++ They defines whether object geometry,only animations
+or only behaviors should be loaded.
++ One can specify (using the CK_LOAD_AS_DYNAMIC_OBJECT) if
+created CKObjects should be created as dynamic (See also Dynamic Objects)
+See also : CKContext::Load,CKContext::CKSave
+*************************************************/
+typedef enum CK_LOAD_FLAGS {
+ CK_LOAD_ANIMATION =1<<0, // Load animations
+ CK_LOAD_GEOMETRY =1<<1, // Load geometry.
+ CK_LOAD_DEFAULT =CK_LOAD_GEOMETRY|CK_LOAD_ANIMATION, // Load animations & geometry
+ CK_LOAD_ASCHARACTER =1<<2, // Load all the objects and create a character that contains them all .
+ CK_LOAD_DODIALOG =1<<3, // Check object name unicity and warns the user with a dialog box when duplicate names are found.
+ CK_LOAD_AS_DYNAMIC_OBJECT =1<<4, // Objects loaded from this file may be deleted at run-time or are temporary
+ CK_LOAD_AUTOMATICMODE =1<<5, // Check object name unicity and automatically rename or replace according to the options specified in CKContext::SetAutomaticLoadMode
+ CK_LOAD_CHECKDUPLICATES =1<<6, // Check object name unicity (The list of duplicates is stored in the CKFile class after a OpenFile call
+ CK_LOAD_CHECKDEPENDENCIES =1<<7, // Check if every plugins needed are availables
+ CK_LOAD_ONLYBEHAVIORS =1<<8, //
+ CK_LOAD_REPLACEALL_WITHSCRIPT =1<<9, // Replace all duplicates names, scripts included (old scripts are deleted)
+} CK_LOAD_FLAGS;
+
+
+/*************************************************
+{filename:CK_PLUGIN_TYPE}
+Summary: Type identifier for a Virtools plugin.
+
+Remarks:
++Each plugin must be given a type.
++This enumeration is used to identify a specific catagory
+of plugin when using the CKPluginManager.
+See also: CKPluginManager,Creating New Plugins
+*************************************************/
+typedef enum CK_PLUGIN_TYPE {
+ CKPLUGIN_BITMAP_READER = 0, // The plugin is bitmap (textures,sprites) loader
+ CKPLUGIN_SOUND_READER = 1, // Sound Reader Plugin
+ CKPLUGIN_MODEL_READER = 2, // 3D Model Reader
+ CKPLUGIN_MANAGER_DLL = 3, // The plugin implements a Manager
+ CKPLUGIN_BEHAVIOR_DLL = 4, // The plugin implements one or more behaviors
+ CKPLUGIN_RENDERENGINE_DLL = 5, // Render Engine plugin
+ CKPLUGIN_MOVIE_READER = 6, // Movie (AVI,Mpeg) reader
+ CKPLUGIN_EXTENSION_DLL = 7, // Generic extension (definition of new parameter types or operations for ex.)
+} CK_PLUGIN_TYPE;
+
+
+typedef enum CK_PARAMETER_FLAGS {
+ CKPARAMETER_LOCAL =0, // The parameter is local to a CKBehavior
+ CKPARAMETER_IN =1, // The parameter is an input of a CKBehavior
+ CKPARAMETER_OUT =2, // The parameter is an output of a CKBehavior or a parameter of a CKBeObject
+ CKPARAMETER_SETTING =3, // The parameter is used as a setting parameter by a CKBehavior.
+} CK_PARAMETER_FLAGS;
+
+
+
+typedef enum CK_PROFILE_CATEGORY {
+ CK_PROFILE_RENDERTIME = 3,
+ CK_PROFILE_IKTIME = 7,
+ CK_PROFILE_ANIMATIONTIME = 6,
+} CK_PROFILE_CATEGORY;
+
+/**********************************************************
+{filename:CK_BONES_REFERENTIAL}
+Summary : Type of bone matrices send to the skinning shader
+
+***************************************************************/
+typedef enum CK_BONES_REFERENTIAL {
+
+ CK_BONE_LOCAL = 0x00000000, // Matrices transformed from bones referential to skin holder referential
+ CK_BONE_WORLD , // Matrices transformed from bones referential to world referential
+ CK_BONE_WORLDVIEW , // Matrices transformed from bones referential to camera referential
+
+}CK_BONES_REFERENTIAL;
+
+
+#endif
diff --git a/packages/registry/ref/CKEnums.ts b/packages/registry/ref/CKEnums.ts
new file mode 100644
index 00000000..ad1c828d
--- /dev/null
+++ b/packages/registry/ref/CKEnums.ts
@@ -0,0 +1,273 @@
+enum CK_OBJECT_FLAGS {
+ CK_OBJECT_INTERFACEOBJ = 0x00000001,
+ CK_OBJECT_PRIVATE = 0x00000002,
+ CK_OBJECT_INTERFACEMARK = 0x00000004,
+ CK_OBJECT_FREEID = 0x00000008,
+ CK_OBJECT_TOBEDELETED = 0x00000010,
+ CK_OBJECT_NOTTOBESAVED = 0x00000020,
+ CK_OBJECT_VISIBLE = 0x00000040,
+ CK_OBJECT_NAMESHARED = 0x00000080,
+ CK_OBJECT_DYNAMIC = 0x00000108,
+ CK_OBJECT_HIERACHICALHIDE = 0x00000200,
+ CK_OBJECT_UPTODATE = 0x00000400,
+ CK_OBJECT_TEMPMARKER = 0x00000800,
+ CK_OBJECT_ONLYFORFILEREFERENCE = 0x00001000,
+ CK_OBJECT_NOTTOBEDELETED = 0x00002000,
+ CK_OBJECT_APPDATA = 0x00004000,
+ CK_OBJECT_SINGLEACTIVITY = 0x00008000,
+ CK_OBJECT_LOADSKIPBEOBJECT = 0x00010000,
+ CK_OBJECT_KEEPSINGLEACTIVITY = 0x00020000,
+ CK_OBJECT_LOADREPLACINGOBJECT = 0x00040000,
+ CK_OBJECT_NOTTOBELISTEDANDSAVED = 0x00000023,
+ CK_OBJECT_SELECTIONSET = 0x00080000,
+ CK_OBJECT_VR_DISTRIBUTED = 0x00100000,
+ CK_PARAMETEROUT_SETTINGS = 0x00400000,
+ CK_PARAMETEROUT_PARAMOP = 0x00800000,
+ CK_PARAMETERIN_DISABLED = 0x01000000,
+ CK_PARAMETERIN_THIS = 0x02000000,
+ CK_PARAMETERIN_SHARED = 0x04000000,
+ CK_PARAMETEROUT_DELETEAFTERUSE = 0x08000000,
+ CK_OBJECT_PARAMMASK = 0x0FC00000,
+ CK_BEHAVIORIO_IN = 0x10000000,
+ CK_BEHAVIORIO_OUT = 0x20000000,
+ CK_BEHAVIORIO_ACTIVE = 0x40000000,
+ CK_OBJECT_IOTYPEMASK = 0x30000000,
+ CK_OBJECT_IOMASK = 0xF0000000,
+ CKBEHAVIORLINK_RESERVED = 0x10000000,
+ CKBEHAVIORLINK_ACTIVATEDLASTFRAME = 0x20000000,
+ CK_OBJECT_BEHAVIORLINKMASK = 0x30000000,
+}
+
+enum CK_BEHAVIOR_FLAGS {
+ CKBEHAVIOR_NONE = 0x00000000,
+ CKBEHAVIOR_ACTIVE = 0x00000001,
+ CKBEHAVIOR_SCRIPT = 0x00000002,
+ CKBEHAVIOR_RESERVED1 = 0x00000004,
+ CKBEHAVIOR_USEFUNCTION = 0x00000008,
+ CKBEHAVIOR_RESERVED2 = 0x00000010,
+ CKBEHAVIOR_CUSTOMSETTINGSEDITDIALOG = 0x00000020,
+ CKBEHAVIOR_WAITSFORMESSAGE = 0x00000040,
+ CKBEHAVIOR_VARIABLEINPUTS = 0x00000080,
+ CKBEHAVIOR_VARIABLEOUTPUTS = 0x00000100,
+ CKBEHAVIOR_VARIABLEPARAMETERINPUTS = 0x00000200,
+ CKBEHAVIOR_VARIABLEPARAMETEROUTPUTS = 0x00000400,
+ CKBEHAVIOR_TOPMOST = 0x00004000,
+ CKBEHAVIOR_BUILDINGBLOCK = 0x00008000,
+ CKBEHAVIOR_MESSAGESENDER = 0x00010000,
+ CKBEHAVIOR_MESSAGERECEIVER = 0x00020000,
+ CKBEHAVIOR_TARGETABLE = 0x00040000,
+ CKBEHAVIOR_CUSTOMEDITDIALOG = 0x00080000,
+ CKBEHAVIOR_RESERVED0 = 0x00100000,
+ CKBEHAVIOR_EXECUTEDLASTFRAME = 0x00200000,
+ CKBEHAVIOR_DEACTIVATENEXTFRAME = 0x00400000,
+ CKBEHAVIOR_RESETNEXTFRAME = 0x00800000,
+ CKBEHAVIOR_INTERNALLYCREATEDINPUTS = 0x01000000,
+ CKBEHAVIOR_INTERNALLYCREATEDOUTPUTS = 0x02000000,
+ CKBEHAVIOR_INTERNALLYCREATEDINPUTPARAMS = 0x04000000,
+ CKBEHAVIOR_INTERNALLYCREATEDOUTPUTPARAMS = 0x08000000,
+ CKBEHAVIOR_INTERNALLYCREATEDLOCALPARAMS = 0x40000000,
+ CKBEHAVIOR_ACTIVATENEXTFRAME = 0x10000000,
+ CKBEHAVIOR_LOCKED = 0x20000000,
+ CKBEHAVIOR_LAUNCHEDONCE = 0x80000000,
+}
+
+enum CK_BEHAVIOR_CALLBACKMASK {
+ CKCB_BEHAVIORPRESAVE = 0x00000001,
+ CKCB_BEHAVIORDELETE = 0x00000002,
+ CKCB_BEHAVIORATTACH = 0x00000004,
+ CKCB_BEHAVIORDETACH = 0x00000008,
+ CKCB_BEHAVIORPAUSE = 0x00000010,
+ CKCB_BEHAVIORRESUME = 0x00000020,
+ CKCB_BEHAVIORCREATE = 0x00000040,
+ CKCB_BEHAVIORRESET = 0x00001000,
+ CKCB_BEHAVIORPOSTSAVE = 0x00000100,
+ CKCB_BEHAVIORLOAD = 0x00000200,
+ CKCB_BEHAVIOREDITED = 0x00000400,
+ CKCB_BEHAVIORSETTINGSEDITED = 0x00000800,
+ CKCB_BEHAVIORREADSTATE = 0x00001000,
+ CKCB_BEHAVIORNEWSCENE = 0x00002000,
+ CKCB_BEHAVIORACTIVATESCRIPT = 0x00004000,
+ CKCB_BEHAVIORDEACTIVATESCRIPT = 0x00008000,
+ CKCB_BEHAVIORRESETINBREAKPOINT = 0x00010000,
+ CKCB_BEHAVIORBASE = 0x0000000E,
+ CKCB_BEHAVIORSAVELOAD = 0x00000301,
+ CKCB_BEHAVIORPPR = 0x00000130,
+ CKCB_BEHAVIOREDITIONS = 0x00000C00,
+ CKCB_BEHAVIORALL = 0xFFFFFFFF,
+}
+
+enum CK_BEHAVIOR_RETURN {
+ CKBR_OK = 0,
+ CKBR_ACTIVATENEXTFRAME = 1,
+ CKBR_ATTACHFAILED = 2,
+ CKBR_DETACHFAILED = 4,
+ CKBR_LOCKED = 6,
+ CKBR_INFINITELOOP = 8,
+ CKBR_BREAK = 10,
+ CKBR_GENERICERROR = 0xA000,
+ CKBR_BEHAVIORERROR = 0xA002,
+ CKBR_OWNERERROR = 0xA004,
+ CKBR_PARAMETERERROR = 0xA008,
+ CKBR_GENERICERROR_RETRY = 0xA001,
+ CKBR_BEHAVIORERROR_RETRY = 0xA003,
+ CKBR_OWNERERROR_RETRY = 0xA005,
+ CKBR_PARAMETERERROR_RETRY = 0xA009,
+}
+
+enum CK_BEHAVIOR_TYPE {
+ CKBEHAVIORTYPE_BASE = 0x00000000,
+ CKBEHAVIORTYPE_SCRIPT = 0x00000001,
+ CKBEHAVIORTYPE_BEHAVIOR = 0x00000004,
+}
+
+enum CK_PARAMETERTYPE_FLAGS {
+ CKPARAMETERTYPE_VARIABLESIZE = 0x00000001,
+ CKPARAMETERTYPE_RESERVED = 0x00000002,
+ CKPARAMETERTYPE_HIDDEN = 0x00000004,
+ CKPARAMETERTYPE_FLAGS = 0x00000008,
+ CKPARAMETERTYPE_STRUCT = 0x00000010,
+ CKPARAMETERTYPE_ENUMS = 0x00000020,
+ CKPARAMETERTYPE_USER = 0x00000040,
+ CKPARAMETERTYPE_NOENDIANCONV = 0x00000080,
+ CKPARAMETERTYPE_TOSAVE = 0x00000100,
+}
+
+enum CK_ATTRIBUT_FLAGS {
+ CK_ATTRIBUT_CAN_MODIFY = 0x00000001,
+ CK_ATTRIBUT_CAN_DELETE = 0x00000002,
+ CK_ATTRIBUT_HIDDEN = 0x00000004,
+ CK_ATTRIBUT_DONOTSAVE = 0x00000008,
+ CK_ATTRIBUT_USER = 0x00000010,
+ CK_ATTRIBUT_SYSTEM = 0x00000020,
+ CK_ATTRIBUT_DONOTCOPY = 0x00000040,
+ CK_ATTRIBUT_TOSAVE = 0x00000080,
+}
+
+enum CK_BEHAVIORPROTOTYPE_FLAGS {
+ CK_BEHAVIORPROTOTYPE_NORMAL = 0x00000001,
+ CK_BEHAVIORPROTOTYPE_HIDDEN = 0x00000002,
+ CK_BEHAVIORPROTOTYPE_OBSOLETE = 0x00000004,
+}
+
+enum CK_LOADMODE {
+ CKLOAD_INVALID = -1,
+ CKLOAD_OK = 0,
+ CKLOAD_REPLACE = 1,
+ CKLOAD_RENAME = 2,
+ CKLOAD_USECURRENT = 3,
+}
+
+enum CK_OBJECTCREATION_OPTIONS {
+ CK_OBJECTCREATION_NONAMECHECK = 0,
+ CK_OBJECTCREATION_REPLACE = 1,
+ CK_OBJECTCREATION_RENAME = 2,
+ CK_OBJECTCREATION_USECURRENT = 3,
+ CK_OBJECTCREATION_ASK = 4,
+ CK_OBJECTCREATION_FLAGSMASK = 0x0000000F,
+ CK_OBJECTCREATION_DYNAMIC = 0x00000010,
+ CK_OBJECTCREATION_ACTIVATE = 0x00000020,
+ CK_OBJECTCREATION_NONAMECOPY = 0x00000040,
+}
+
+enum CK_DEPENDENCIES_OPMODE {
+ CK_DEPENDENCIES_COPY = 1,
+ CK_DEPENDENCIES_DELETE = 2,
+ CK_DEPENDENCIES_REPLACE = 3,
+ CK_DEPENDENCIES_SAVE = 4,
+ CK_DEPENDENCIES_BUILD = 5,
+ CK_DEPENDENCIES_OPERATIONMODE = 0xF,
+}
+
+enum CK_FILE_WRITEMODE {
+ CKFILE_UNCOMPRESSED = 0,
+ CKFILE_CHUNKCOMPRESSED_OLD = 1,
+ CKFILE_EXTERNALTEXTURES_OLD = 2,
+ CKFILE_FORVIEWER = 4,
+ CKFILE_WHOLECOMPRESSED = 8,
+}
+
+enum CK_CONFIG_FLAGS {
+ CK_CONFIG_DISABLEDSOUND = 1,
+ CK_CONFIG_DISABLEDINPUT = 2,
+ CK_CONFIG_DOWARN = 4,
+}
+
+enum CK_DESTROY_FLAGS {
+ CK_DESTROY_FREEID = 0x00000001,
+ CK_DESTROY_NONOTIFY = 0x00000002,
+ CK_DESTROY_TEMPOBJECT = 0x00000003,
+}
+
+enum CK_BINARYOPERATOR {
+ CKADD = 1,
+ CKSUB = 2,
+ CKMUL = 3,
+ CKDIV = 4,
+}
+
+enum CK_COMPOPERATOR {
+ CKEQUAL = 1,
+ CKNOTEQUAL = 2,
+ CKLESSER = 3,
+ CKLESSEREQUAL = 4,
+ CKGREATER = 5,
+ CKGREATEREQUAL = 6,
+}
+
+enum CK_SETOPERATOR {
+ CKUNION = 1,
+ CKINTERSECTION = 2,
+ CKSUBTRACTION = 3,
+}
+
+enum CK_ARRAYTYPE {
+ CKARRAYTYPE_INT = 1,
+ CKARRAYTYPE_FLOAT = 2,
+ CKARRAYTYPE_STRING = 3,
+ CKARRAYTYPE_OBJECT = 4,
+ CKARRAYTYPE_PARAMETER = 5,
+}
+
+enum CK_LOAD_FLAGS {
+ CK_LOAD_ANIMATION = 1 << 0,
+ CK_LOAD_GEOMETRY = 1 << 1,
+ CK_LOAD_DEFAULT = CK_LOAD_GEOMETRY | CK_LOAD_ANIMATION,
+ CK_LOAD_ASCHARACTER = 1 << 2,
+ CK_LOAD_DODIALOG = 1 << 3,
+ CK_LOAD_AS_DYNAMIC_OBJECT = 1 << 4,
+ CK_LOAD_AUTOMATICMODE = 1 << 5,
+ CK_LOAD_CHECKDUPLICATES = 1 << 6,
+ CK_LOAD_CHECKDEPENDENCIES = 1 << 7,
+ CK_LOAD_ONLYBEHAVIORS = 1 << 8,
+ CK_LOAD_REPLACEALL_WITHSCRIPT = 1 << 9,
+}
+
+enum CK_PLUGIN_TYPE {
+ CKPLUGIN_BITMAP_READER = 0,
+ CKPLUGIN_SOUND_READER = 1,
+ CKPLUGIN_MODEL_READER = 2,
+ CKPLUGIN_MANAGER_DLL = 3,
+ CKPLUGIN_BEHAVIOR_DLL = 4,
+ CKPLUGIN_RENDERENGINE_DLL = 5,
+ CKPLUGIN_MOVIE_READER = 6,
+ CKPLUGIN_EXTENSION_DLL = 7,
+}
+
+enum CK_PARAMETER_FLAGS {
+ CKPARAMETER_LOCAL = 0,
+ CKPARAMETER_IN = 1,
+ CKPARAMETER_OUT = 2,
+ CKPARAMETER_SETTING = 3,
+}
+
+enum CK_PROFILE_CATEGORY {
+ CK_PROFILE_RENDERTIME = 3,
+ CK_PROFILE_IKTIME = 7,
+ CK_PROFILE_ANIMATIONTIME = 6,
+}
+
+enum CK_BONES_REFERENTIAL {
+ CK_BONE_LOCAL = 0x00000000,
+ CK_BONE_WORLD,
+ CK_BONE_WORLDVIEW,
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKParameter.h b/packages/registry/ref/CKParameter.h
new file mode 100644
index 00000000..d06266ea
--- /dev/null
+++ b/packages/registry/ref/CKParameter.h
@@ -0,0 +1,160 @@
+/*************************************************************************/
+/* File : CKParameter.h */
+/* Author : Nicolas Galinotti */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKParameter_H
+
+#define CKParameter_H
+
+#include "CKObject.h"
+
+/**************************************************************************
+{filename:CKParameter}
+Name: CKParameter
+
+Summary: Base class for output and local parameter
+
+Remarks:
+
++ The type of the parameter defines the type of the data provided. These types are maintained by
+the parameter manager. It defines the size of the buffer to use, and also decides what can be plugged
+onto the output parameter. To have the list and definition of predefined parameter types see CKParameterManager.
+
++ The class id of CKParameter is CKCID_PARAMETER.
+
+See also: CKBehavior, CKParameterIn, CKParameterOperation
+**********************************************************************************/
+class CKParameter : public CKObject {
+friend class CKParameterIn;
+friend class CKParameterManager;
+public :
+//--------------------------------------------
+// Value
+
+CKObject* GetValueObject(CKBOOL update = TRUE);
+
+virtual CKERROR GetValue(void *buf, CKBOOL update = TRUE);
+virtual CKERROR SetValue(const void *buf,int size = 0);
+virtual CKERROR CopyValue(CKParameter *param,CKBOOL UpdateParam=TRUE);
+
+CKBOOL IsCompatibleWith(CKParameter *param);
+
+//--------------------------------------------
+// Data pointer
+int GetDataSize();
+virtual void * GetReadDataPtr(CKBOOL update = TRUE);
+virtual void * GetWriteDataPtr();
+
+//--------------------------------------------
+// Convertion from / to string
+virtual CKERROR SetStringValue(CKSTRING Value);
+virtual int GetStringValue(CKSTRING Value,CKBOOL update = TRUE);
+
+//--------------------------------------------
+// Type
+CKParameterType GetType();
+void SetType(CKParameterType type);
+CKGUID GetGUID();
+void SetGUID(CKGUID guid);
+CK_CLASSID GetParameterClassID();
+
+//--------------------------------------------
+// Owner
+virtual void SetOwner(CKObject *o);
+CKObject * GetOwner();
+
+// Virtual added for Fixed Size parameter support
+virtual void CheckClass(CKParameterTypeDesc* iType);
+
+//--------------------------------------------
+// Disabled parameters in behaviors
+
+//-------------------------------------------------------------------
+#ifdef DOCJETDUMMY // Docjet secret macro
+#else
+
+void Enable(CKBOOL act=TRUE);
+CKBOOL IsEnabled();
+
+
+//--------------------------------------------
+// Virtual functions
+ CKParameter(CKContext *Context,CKSTRING name = NULL);
+ virtual ~CKParameter();
+ virtual CK_CLASSID GetClassID();
+
+ virtual void PreSave(CKFile *file,CKDWORD flags);
+ virtual CKStateChunk *Save(CKFile *file,CKDWORD flags);
+ virtual CKERROR Load(CKStateChunk *chunk,CKFile* file);
+
+ virtual void CheckPostDeletion();
+
+ virtual int GetMemoryOccupation();
+ virtual int IsObjectUsed(CKObject* o,CK_CLASSID cid);
+
+//--------------------------------------------
+// Dependencies Functions
+ virtual CKERROR PrepareDependencies(CKDependenciesContext& context, CKBOOL iCaller = TRUE);
+ virtual CKERROR RemapDependencies(CKDependenciesContext& context);
+ virtual CKERROR Copy(CKObject& o,CKDependenciesContext& context);
+
+//--------------------------------------------
+// Class Registering
+ static CKSTRING GetClassName();
+ static int GetDependenciesCount(int mode);
+ static CKSTRING GetDependencies(int i,int mode);
+ static void Register();
+ static CKParameter* CreateInstance(CKContext *Context);
+ static void ReleaseInstance(CKContext* iContext,CKParameter*);
+ static CK_CLASSID m_ClassID;
+
+ // Dynamic Cast method (returns NULL if the object can't be casted)
+ static CKParameter* Cast(CKObject* iO)
+ {
+ return CKIsChildClassOf(iO,CKCID_PARAMETER)?(CKParameter*)iO:NULL;
+ }
+
+ CKERROR CreateDefaultValue();
+ void MessageDeleteAfterUse(CKBOOL act);
+ CKParameterTypeDesc* GetParameterType() { return m_ParamType; }
+
+ CKBOOL IsCandidateForFixedSize(CKParameterTypeDesc* iType);
+
+protected:
+
+ CKObject* m_Owner;
+ CKParameterTypeDesc* m_ParamType;
+
+#ifdef PSP
+ unsigned short m_DataSize;
+ unsigned short m_AllocatedSize;
+#else
+ union{
+ int m_DataSize;
+ int m_AllocatedSize;
+ };
+#endif
+
+ union {
+ CKBYTE* m_Buffer;
+ CKDWORD m_Value;
+ };
+
+friend void CK_ParameterCopier_Memcpy(CKParameter* Dst,CKParameter* Src);
+friend void CK_ParameterCopier_SaveLoad(CKParameter* Dst,CKParameter* Src);
+friend void CK_ParameterCopier_SetValue(CKParameter* Dst,CKParameter* Src);
+friend void CK_ParameterCopier_Dword(CKParameter* Dst,CKParameter* Src);
+friend void CK_ParameterCopier_BufferCompatibleWithDWORD(CKParameter* Dst,CKParameter* Src);
+
+friend void CKObjectArrayRemapfunc (CKParameter *param,CKDependenciesContext&);
+friend void CKObjectRemapFunc (CKParameter *param,CKDependenciesContext&);
+friend void CKStructRemapFunc (CKParameter *param,CKDependenciesContext&);
+
+#endif // docjet secret macro
+
+};
+
+#endif
diff --git a/packages/registry/ref/CKParameter.ts b/packages/registry/ref/CKParameter.ts
new file mode 100644
index 00000000..fe83a498
--- /dev/null
+++ b/packages/registry/ref/CKParameter.ts
@@ -0,0 +1,202 @@
+class CKParameter extends CKObject {
+ private m_Owner: CKObject | null;
+ private m_ParamType: CKParameterTypeDesc | null;
+ private m_DataSize: number;
+ private m_AllocatedSize: number;
+ private m_Buffer: Uint8Array | null;
+
+ constructor(context: CKContext, name: string | null = null) {
+ super(context, name);
+ this.m_Owner = null;
+ this.m_ParamType = null;
+ this.m_DataSize = 0;
+ this.m_AllocatedSize = 0;
+ this.m_Buffer = null;
+ }
+
+ GetValueObject(update: boolean = true): CKObject | null {
+ // Implementation goes here
+ return null;
+ }
+
+ GetValue(buf: any, update: boolean = true): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ SetValue(buf: any, size: number = 0): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ CopyValue(param: CKParameter, UpdateParam: boolean = true): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ IsCompatibleWith(param: CKParameter): boolean {
+ // Implementation goes here
+ return false;
+ }
+
+ GetDataSize(): number {
+ // Implementation goes here
+ return 0;
+ }
+
+ GetReadDataPtr(update: boolean = true): any {
+ // Implementation goes here
+ return null;
+ }
+
+ GetWriteDataPtr(): any {
+ // Implementation goes here
+ return null;
+ }
+
+ SetStringValue(Value: CKSTRING): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ GetStringValue(Value: CKSTRING, update: boolean = true): number {
+ // Implementation goes here
+ return 0;
+ }
+
+ GetType(): CKParameterType {
+ // Implementation goes here
+ return CKParameterType.INVALID;
+ }
+
+ SetType(type: CKParameterType) {
+ // Implementation goes here
+ }
+
+ GetGUID(): CKGUID {
+ // Implementation goes here
+ return { d1: 0, d2: 0, d3: 0, d4: [0] };
+ }
+
+ SetGUID(guid: CKGUID) {
+ // Implementation goes here
+ }
+
+ GetParameterClassID(): CK_CLASSID {
+ // Implementation goes here
+ return 0;
+ }
+
+ SetOwner(o: CKObject | null) {
+ // Implementation goes here
+ }
+
+ GetOwner(): CKObject | null {
+ // Implementation goes here
+ return this.m_Owner;
+ }
+
+ CheckClass(iType: CKParameterTypeDesc) {
+ // Implementation goes here
+ }
+
+ Enable(act: boolean = true) {
+ // Implementation goes here
+ }
+
+ IsEnabled(): boolean {
+ // Implementation goes here
+ return false;
+ }
+
+ PreSave(file: CKFile, flags: CKDWORD) {
+ // Implementation goes here
+ }
+
+ Save(file: CKFile, flags: CKDWORD): CKStateChunk | null {
+ // Implementation goes here
+ return null;
+ }
+
+ Load(chunk: CKStateChunk, file: CKFile): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ CheckPostDeletion() {
+ // Implementation goes here
+ }
+
+ GetMemoryOccupation(): number {
+ // Implementation goes here
+ return 0;
+ }
+
+ IsObjectUsed(o: CKObject, cid: CK_CLASSID): boolean {
+ // Implementation goes here
+ return false;
+ }
+
+ PrepareDependencies(context: CKDependenciesContext, iCaller: boolean = true): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ RemapDependencies(context: CKDependenciesContext): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ Copy(o: CKObject, context: CKDependenciesContext): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ static GetClassName(): string {
+ return "CKParameter";
+ }
+
+ static GetDependenciesCount(mode: number): number {
+ return 0;
+ }
+
+ static GetDependencies(i: number, mode: number): string {
+ return "";
+ }
+
+ static Register() {
+ // Implementation goes here
+ }
+
+ static CreateInstance(context: CKContext): CKParameter {
+ return new CKParameter(context);
+ }
+
+ static ReleaseInstance(context: CKContext, param: CKParameter) {
+ // Implementation goes here
+ }
+
+ static m_ClassID: CK_CLASSID = 0;
+
+ static Cast(iO: CKObject): CKParameter | null {
+ return CKIsChildClassOf(iO, CKCID.PARAMETER) ? (iO as CKParameter) : null;
+ }
+
+ CreateDefaultValue(): CKERROR {
+ // Implementation goes here
+ return CKERROR.SUCCESS;
+ }
+
+ MessageDeleteAfterUse(act: boolean) {
+ // Implementation goes here
+ }
+
+ GetParameterType(): CKParameterTypeDesc | null {
+ return this.m_ParamType;
+ }
+
+ IsCandidateForFixedSize(iType: CKParameterTypeDesc): boolean {
+ // Implementation goes here
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKParameterIn.h b/packages/registry/ref/CKParameterIn.h
new file mode 100644
index 00000000..d6fe87c9
--- /dev/null
+++ b/packages/registry/ref/CKParameterIn.h
@@ -0,0 +1,270 @@
+/*************************************************************************/
+/* File : CKParameterIn.h */
+/* Author : Nicolas Galinotti */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKPARAMETERIN_H
+
+#define CKPARAMETERIN_H
+
+#include "CKObject.h"
+#include "CKParameterOut.h"
+
+/**********************************************************************
+Name: CKParameterIn
+
+Summary: Input parameters
+
+Remarks:
+{Image:ParameterIn}
+
++ Input parameters allow behaviors to receive values from other behaviors or operations. They have a type defining the type a data they expect.
+
++ Data is retrieved from an input parameter using the GetReadDataPtr or GetValue methods.
+
++ An input parameter never owns its data, it always gets it from another parameter,
+whether in, out or local (which is a subset of out parameters). So data really is retrieved
+from the first output parameter found in the chain of input parameters, named thus the Real Source.
+This real source of data may be accessed through the GetRealSource method.
+
++ The input paramter may be plugged directly into an output parameter from which it will get its data.
+This parameter is thus called a DirectSource. This souce can be set using the SetDirectSource method and
+accessed using GetDirectSource method.
+
++ It may also be plugged into another input parameter coming from the enclosing behavior. This input
+parameter from the enclosing behavior may be shared by many parameters from inside the behavior.
+The method to use to plug the input parameter to such a shared input is ShareSourceWith.
+
++ The input parameter can only be plugged into a parameter of a compatible type.
+
++ A CKParameterIn is created with CKBehavior::CreateInputParameter or CKBehavior::InsertInputParameter.You can also use CKContext::CreateParameterIn though this is probably rare.
+
++ The class id of CKParameterIn is CKCID_PARAMETERIN.
+
+See also: CKBehavior, CKParameterOut, CKParameterOperation
+*************************************************/
+class CKParameterIn : public CKObject {
+friend class CKParameterManager;
+friend class CKParameterOut;
+public :
+
+/*******************************************
+Summary: Copies the input parameter's value into the given buffer
+
+Remarks:
++Retrieves the value of the input parameter and copies it into the given buffer.
++The buffer must have been allocated to the correct size
++The value is retrieved using the usual system: if data has been modified since
+the last time it was fetched, the chain of inputs is walked up until an output parameter is found
+
+Returns: CK_OK if success
+
+See Also: GetReadDataPtr, GetLastUpdate
+********************************************/
+ CKERROR GetValue(void *buf)
+ {
+ CKParameter* p = GetRealSource();
+ if (!p) return CKERR_NOTINITIALIZED;
+ return p->GetValue(buf);
+ }
+
+/*************************************************
+Summary: Retrieves a pointer to the buffer that contain the value.
+Returns: A pointer to the data.
+Remarks:
++The real pointer to the value is returned.
++This pointer must not be destroyed.
++Using this method can faster than GetValue especially for big parameters
+where a memcpy could be avoided.
+See also: GetValue, GetLastUpdate
+*************************************************/
+ void *GetReadDataPtr()
+ {
+ CKParameter* p = GetRealSource();
+ if (!p) return NULL;
+ return p->GetReadDataPtr();
+ }
+
+
+ /*******************************************
+ Summary: returns the shared source of the input parameter.
+
+ Return Value:
+ A pointer of the shared CKParameterIn if any, NULL otherwise.
+
+ See Also: ShareSourceWith, GetRealSource
+ ********************************************/
+ CKParameterIn* GetSharedSource()
+ {
+ return (!(m_ObjectFlags & CK_PARAMETERIN_SHARED))?NULL:m_InShared;
+ }
+
+
+/*******************************************
+Summary: Returns the real source of data of the input parameter
+Remarks:
+
++If the input parameter gets its value from a shared source,
+the shared source being an input parameter, it itself gets its value from another source. By walking up
+the source chain, the real source is the first parameter that is not an input parameter. This is what
+GetRealSource does. It returns the real source from which the input gets its value. This real source
+is of course an output parameter.
+
++If the input parameter has a direct source, the real source is the direct source.
+Return Value:
+ A pointer to the CKParameter that stores the data for this input parameter.
+See Also: ShareSourceWith
+********************************************/
+ CKParameter* GetRealSource()
+ {
+ if (m_ObjectFlags & CK_PARAMETERIN_SHARED) {
+ if (m_InShared) return m_InShared->GetRealSource();
+ } else
+ return m_OutSource;
+
+ return NULL;
+ }
+
+/*******************************************
+Summary: Returns the direct source of the input parameter.
+
+Remarks:
++ If the input parameter is plugged into an output parameter, from which it will get its data, this output
+parameter is called the direct source.
++ An input parameter must have either a direct source or a shared source, it cannot have both.
+
+Return Value:
+ A pointer to the CKParameter that stores the data for this input parameter or NULL
+ if has no direct source.
+
+See Also: GetRealSource,SetDirectSource,ShareSourceWith
+********************************************/
+ CKParameter* GetDirectSource()
+ {
+ if (m_ObjectFlags & CK_PARAMETERIN_SHARED) return NULL;
+ return m_OutSource;
+ }
+
+ CKERROR SetDirectSource(CKParameter* param);
+ CKERROR ShareSourceWith(CKParameterIn *param);
+
+ //-------------------------------------------------
+ // Type of the data
+ void SetType(CKParameterType type,CKBOOL UpdateSource=FALSE,CKSTRING NewName=NULL);
+ void SetGUID(CKGUID guid,CKBOOL UpdateSource=FALSE,CKSTRING NewName=NULL);
+
+ /*******************************************
+ Summary: Returns the type of the input parameter
+
+ Return Value:
+ Returns the index of the type of the input parameter. These
+ types are maintained by the parameter manager.
+
+ See Also: CKParameterIn::GetGUID,CKParameterManager
+ ********************************************/
+ CKParameterType GetType()
+ {
+ if (m_ParamType) return m_ParamType->Index;
+ else return -1;
+ }
+
+/*******************************************
+Summary: Returns the GUID of the input parameter type.
+
+Return Value:
+ Returns the GUID of the type of the input parameter.
+
+See Also: CKParameterIn::GetType,CKParameterManager
+********************************************/
+ CKGUID GetGUID()
+ {
+ if (m_ParamType) return m_ParamType->Guid;
+ else return CKGUID(0);
+ }
+
+/*******************************************
+Summary: Sets the owner of the CKParameterIn.
+
+Remarks:
+ + You normally shouldn't change the owner of
+a CKParameterIn this function being automatically by the framework.
+
+See Also: CKParameterIn::GetOwner
+********************************************/
+ void SetOwner(CKObject *o) {m_Owner = o;}
+
+/*******************************************
+Summary: Gets the owner of the CKParameterIn.
+
+Remarks:
+ + The owner of the parameter is the object with
+ wich the parameter will be saved. Typically, the owner
+ is a parameter operation of a behavior to which it is an input ( or the internal
+ behavior if the parameter is exported).
+Return Value:
+ A pointer to the CKObject that owns this input parameter usually a CKBehavior or a CKParameterOperation
+
+See Also: CKParameterIn::SetOwner
+********************************************/
+ CKObject *GetOwner() {return m_Owner;}
+
+//-------------------------------------------------------------------
+#ifdef DOCJETDUMMY // Docjet secret macro
+#else
+
+ CKParameterIn(CKContext *Context,CKSTRING name = NULL,int type = NULL);
+ virtual ~CKParameterIn();
+ virtual CK_CLASSID GetClassID();
+
+ virtual void PreSave(CKFile *file,CKDWORD flags);
+ virtual CKStateChunk *Save(CKFile *file,CKDWORD flags);
+ virtual CKERROR Load(CKStateChunk *chunk,CKFile* file);
+
+ virtual void PreDelete();
+ virtual void CheckPreDeletion();
+
+ virtual int GetMemoryOccupation();
+ virtual int IsObjectUsed(CKObject* o,CK_CLASSID cid);
+
+ //--------------------------------------------
+ // Dependencies Functions
+ virtual CKERROR RemapDependencies(CKDependenciesContext& context);
+ virtual CKERROR Copy(CKObject& o,CKDependenciesContext& context);
+
+ //--------------------------------------------
+ // Class Registering
+ static CKSTRING GetClassName();
+ static int GetDependenciesCount(int mode);
+ static CKSTRING GetDependencies(int i,int mode);
+ static void Register();
+ static CKParameterIn* CreateInstance(CKContext *Context);
+ static void ReleaseInstance(CKContext* iContext,CKParameterIn*);
+ static CK_CLASSID m_ClassID;
+
+ // Dynamic Cast method (returns NULL if the object can't be casted)
+ static CKParameterIn* Cast(CKObject* iO)
+ {
+ return CKIsChildClassOf(iO,CKCID_PARAMETERIN)?(CKParameterIn*)iO:NULL;
+ }
+
+ void Enable(CKBOOL act=TRUE) {
+ if (!act) m_ObjectFlags |= CK_PARAMETERIN_DISABLED;
+ else m_ObjectFlags&=~CK_PARAMETERIN_DISABLED;
+ }
+ CKBOOL IsEnabled() {return ((m_ObjectFlags & CK_PARAMETERIN_DISABLED)!=CK_PARAMETERIN_DISABLED);}
+
+
+protected:
+ CKObject* m_Owner;
+ union {
+ CKParameter* m_OutSource;
+ CKParameterIn* m_InShared;
+ };
+ CKParameterTypeDesc* m_ParamType;
+
+#endif // docjet secret macro
+};
+
+#endif
diff --git a/packages/registry/ref/CKParameterIn.ts b/packages/registry/ref/CKParameterIn.ts
new file mode 100644
index 00000000..bbe6b92c
--- /dev/null
+++ b/packages/registry/ref/CKParameterIn.ts
@@ -0,0 +1,110 @@
+class CKParameterIn extends CKObject {
+ constructor(Context: CKContext, name: string = null, type: number = null) {
+ super();
+ // initialization logic here
+ }
+
+ GetValue(buf: any): CKERROR {
+ let p = this.GetRealSource();
+ if (!p) return CKERR_NOTINITIALIZED;
+ return p.GetValue(buf);
+ }
+
+ GetReadDataPtr(): any {
+ let p = this.GetRealSource();
+ if (!p) return null;
+ return p.GetReadDataPtr();
+ }
+
+ GetSharedSource(): CKParameterIn {
+ return (!(this.m_ObjectFlags & CK_PARAMETERIN_SHARED)) ? null : this.m_InShared;
+ }
+
+ GetRealSource(): CKParameter {
+ if (this.m_ObjectFlags & CK_PARAMETERIN_SHARED) {
+ if (this.m_InShared) return this.m_InShared.GetRealSource();
+ } else {
+ return this.m_OutSource;
+ }
+ return null;
+ }
+
+ GetDirectSource(): CKParameter {
+ if (this.m_ObjectFlags & CK_PARAMETERIN_SHARED) return null;
+ return this.m_OutSource;
+ }
+
+ SetDirectSource(param: CKParameter): CKERROR {
+ // Method logic here
+ }
+
+ ShareSourceWith(param: CKParameterIn): CKERROR {
+ // Method logic here
+ }
+
+ SetType(type: CKParameterType, UpdateSource: CKBOOL = false, NewName: CKSTRING = null) {
+ // Method logic here
+ }
+
+ SetGUID(guid: CKGUID, UpdateSource: CKBOOL = false, NewName: CKSTRING = null) {
+ // Method logic here
+ }
+
+ GetType(): CKParameterType {
+ return this.m_ParamType ? this.m_ParamType.Index : -1;
+ }
+
+ GetGUID(): CKGUID {
+ return this.m_ParamType ? this.m_ParamType.Guid : new CKGUID(0);
+ }
+
+ SetOwner(o: CKObject) {
+ this.m_Owner = o;
+ }
+
+ GetOwner(): CKObject {
+ return this.m_Owner;
+ }
+
+ Enable(act: CKBOOL = true) {
+ if (!act) {
+ this.m_ObjectFlags |= CK_PARAMETERIN_DISABLED;
+ } else {
+ this.m_ObjectFlags &= ~CK_PARAMETERIN_DISABLED;
+ }
+ }
+
+ IsEnabled(): CKBOOL {
+ return (this.m_ObjectFlags & CK_PARAMETERIN_DISABLED) !== CK_PARAMETERIN_DISABLED;
+ }
+
+ // Omitted functions for save/load and other internal processing would go here
+
+ static GetClassName(): string {
+ // Method logic here
+ }
+
+ static GetDependenciesCount(mode: number): number {
+ // Method logic here
+ }
+
+ static GetDependencies(i: number, mode: number): string {
+ // Method logic here
+ }
+
+ static Register() {
+ // Method logic here
+ }
+
+ static CreateInstance(Context: CKContext): CKParameterIn {
+ // Method logic here
+ }
+
+ static ReleaseInstance(iContext: CKContext, instance: CKParameterIn) {
+ // Method logic here
+ }
+
+ static Cast(iO: CKObject): CKParameterIn {
+ return CKIsChildClassOf(iO, CKCID_PARAMETERIN) ? iO as CKParameterIn : null;
+ }
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKParameterLocal.h b/packages/registry/ref/CKParameterLocal.h
new file mode 100644
index 00000000..dda68563
--- /dev/null
+++ b/packages/registry/ref/CKParameterLocal.h
@@ -0,0 +1,91 @@
+/*************************************************************************/
+/* File : CKParameterLocal.h */
+/* Author : Nicolas Galinotti */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKPARAMETERLOCAL_H
+
+#define CKPARAMETERLOCAL_H
+
+#include "CKParameter.h"
+
+/*************************************************************************
+Name: CKParameterLocal
+
+Summary: Local parameter providing a value
+
+Remarks:
+{Image:ParameterLocal}
+
++ A CKParameterLocal derives directly from CKParameterOut and differs only by its class ID, it provides no additional methods.
+
++ A CKParameterLocal is created with CKBehavior::CreateLocalParameter or CKContext::CreateParameterLocal.
+
++ The class id of CKParameterLocal is CKCID_PARAMETERLOCAL.
+
+See also: CKParameterOut
+*****************************************************************************/
+class CKParameterLocal : public CKParameter {
+public :
+
+//--------------------------------------------
+// Special Parameter :: This (MySelf)
+
+
+void SetAsMyselfParameter(CKBOOL act);
+
+ CKBOOL IsMyselfParameter() {return (m_ObjectFlags & CK_PARAMETERIN_THIS);}
+
+ virtual void SetOwner(CKObject *o);
+ virtual CKERROR SetValue(const void *buf,int size = 0);
+ virtual CKERROR CopyValue(CKParameter *param,CKBOOL UpdateParam=TRUE);
+
+ virtual void * GetWriteDataPtr();
+ virtual CKERROR SetStringValue(CKSTRING Value);
+
+ void CheckClass(CKParameterTypeDesc* iType);
+
+//-------------------------------------------------------------------
+#ifdef DOCJETDUMMY // Docjet secret macro
+#else
+
+ //---------------------------------------
+ // Virtual functions
+ CKParameterLocal(CKContext *Context,CKSTRING name = NULL);
+ virtual ~CKParameterLocal();
+ virtual CK_CLASSID GetClassID();
+
+ virtual void PreDelete();
+
+ virtual CKStateChunk *Save(CKFile *file,CKDWORD flags);
+ virtual CKERROR Load(CKStateChunk *chunk,CKFile* file);
+
+ virtual int GetMemoryOccupation();
+
+ //--------------------------------------------
+ // Dependencies Functions
+ virtual CKERROR RemapDependencies(CKDependenciesContext& context);
+ virtual CKERROR Copy(CKObject& o,CKDependenciesContext& context);
+
+ //--------------------------------------------
+ // Class Registering
+ static CKSTRING GetClassName();
+ static int GetDependenciesCount(int mode);
+ static CKSTRING GetDependencies(int i,int mode);
+ static void Register();
+ static CKParameterLocal* CreateInstance(CKContext *Context);
+ static void ReleaseInstance(CKContext* iContext,CKParameterLocal*);
+ static CK_CLASSID m_ClassID;
+
+ // Dynamic Cast method (returns NULL if the object can't be casted)
+ static CKParameterLocal* Cast(CKObject* iO)
+ {
+ return CKIsChildClassOf(iO,CKCID_PARAMETERLOCAL)?(CKParameterLocal*)iO:NULL;
+ }
+
+#endif // docjet secret macro
+};
+
+#endif
diff --git a/packages/registry/ref/CKParameterLocal.ts b/packages/registry/ref/CKParameterLocal.ts
new file mode 100644
index 00000000..4319d08b
--- /dev/null
+++ b/packages/registry/ref/CKParameterLocal.ts
@@ -0,0 +1,43 @@
+class CKParameterLocal extends CKParameter {
+ SetAsMyselfParameter(act: boolean): void;
+
+ IsMyselfParameter(): boolean {
+ return (this.m_ObjectFlags & CK_PARAMETERIN_THIS) !== 0;
+ }
+
+ SetOwner(o: CKObject): void;
+ SetValue(buf: any, size?: number): CKERROR;
+ CopyValue(param: CKParameter, UpdateParam?: boolean): CKERROR;
+
+ GetWriteDataPtr(): any;
+ SetStringValue(Value: string): CKERROR;
+
+ CheckClass(iType: CKParameterTypeDesc): void;
+
+ constructor(Context: CKContext, name?: string);
+ destructor();
+
+ GetClassID(): CK_CLASSID;
+
+ PreDelete(): void;
+
+ Save(file: CKFile, flags: number): CKStateChunk;
+ Load(chunk: CKStateChunk, file: CKFile): CKERROR;
+
+ GetMemoryOccupation(): number;
+
+ RemapDependencies(context: CKDependenciesContext): CKERROR;
+ Copy(o: CKObject, context: CKDependenciesContext): CKERROR;
+
+ static GetClassName(): string;
+ static GetDependenciesCount(mode: number): number;
+ static GetDependencies(i: number, mode: number): string;
+ static Register(): void;
+ static CreateInstance(Context: CKContext): CKParameterLocal;
+ static ReleaseInstance(iContext: CKContext, instance: CKParameterLocal): void;
+ static m_ClassID: CK_CLASSID;
+
+ static Cast(iO: CKObject): CKParameterLocal | null {
+ return CKIsChildClassOf(iO, CKCID_PARAMETERLOCAL) ? (iO as CKParameterLocal) : null;
+ }
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKParameterManager.h b/packages/registry/ref/CKParameterManager.h
new file mode 100644
index 00000000..51099cb2
--- /dev/null
+++ b/packages/registry/ref/CKParameterManager.h
@@ -0,0 +1,335 @@
+/*************************************************************************/
+/* File : CKParameterManager.h */
+/* Author : Romain Sididris */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKPARAMETERMANAGER_H
+
+#define CKPARAMETERMANAGER_H "$Id:$"
+
+#include "CKParameterIn.h"
+#include "CKParameterOut.h"
+#include "CKParameterLocal.h"
+#include "CKContext.h"
+
+/********************************************************
+ Kept for compatibility issues : On macintosh the
+ const CKGUID& must be used to conform to Codewarrior, On PC
+ we do not need to to this (and must not to keep CK2 compatible
+ with previously created DLLs) {secret}
+*********************************************************/
+#ifdef macintosh
+ #define CKGUIDCONSTREF const CKGUID&
+ #define CKGUIDREF const CKGUID&
+#else
+ #define CKGUIDCONSTREF CKGUID
+ #define CKGUIDREF CKGUID&
+#endif
+
+
+typedef XHashTable XHashGuidToType;
+
+
+/***********************************************************
+Summary: Helper class to access a parameter of type structure.
+Remarks:
+
+
++ New parameter types can be created like structures with the
+CKParameterManager::RegisterNewStructure method, this class provides
+method to easily access a structure members.
+
++ A structure defined in C like this:
+
+{html:}
+
+ typedef struct MyStructure
+ {
+ float Priority;
+ VxVector Position;
+ CK_ID ObstacleId;
+ } MyStructure;
+
+{html:
}
+
+is equivalent to declare
+
+{html:}
+
+ #define CKPGUID_MYSTRUCT CKGUID(0x4a893652,0x76e72d5c)
+ ParameterManager->RegisterNewStructure(CKPGUID_MYSTRUCT,"MyStructure","Priority,Position,Obstacle",CKPGUID_FLOAT,CKPGUID_VECTOR,CKPGUID_3DENTITY);
+
+{html:
}
+
+then the CKStructHelper can help to have a description of this structure later :
+
+{html:}
+
+ CKStructHelper StructDesc(Context,CKPGUID_MYSTRUCT);
+ int Count = StructDesc.GetMemberCount();
+ for (int i=0;i
}
+
+or it can be use to access the sub-members of a parameter of the type CKPGUID_MYSTRUCT for example:
+
+{html:}
+
+ CKStructHelper MyStruct(param);
+
+ Access sub-members
+ float Priority;
+ VxVector Position;
+ CK_ID ObstacleId;
+
+ MyStruct[0]->GetValue(&Priority);
+ MyStruct[1]->GetValue(&Position);
+ MyStruct[2]->GetValue(&ObstacleId);
+
+{html:
}
+
+See Also: RegisterNewStructure,
+************************************************************/
+class CKStructHelper {
+public:
+ CKStructHelper(CKParameter* Param, CKBOOL Update = TRUE);
+ CKStructHelper(CKContext* ctx,CKGUID PGuid,CK_ID* Data = NULL);
+ CKStructHelper(CKContext* ctx,CKParameterType PType,CK_ID* Data = NULL);
+
+//------- Members description (These methods do not require
+// Data pointer to be valid )
+ char* GetMemberName(int Pos);
+ CKGUID GetMemberGUID(int Pos);
+ int GetMemberCount();
+
+/************************************************************
+Summary: Returns a member of this structure as a parameter
+Arguments:
+ i: Index of the member to return.
+Return Value:
+ A pointer to a CKParameter that holds the ith member.
+Remarks:
+This method does not perform any check concerning the validty of the given index, it is
+the user responsability to ensure it is below GetMemberCount
+See also:GetMemberGUID,GetMemberName,GetMemberCount
+*****************************************************************************/
+CKParameter* operator[] (int i)
+{
+ return (CKParameter*)m_Context->GetObject(m_SubIDS[i]);
+}
+
+protected:
+ CKContext* m_Context;
+ CKStructStruct* m_StructDescription;
+ CK_ID* m_SubIDS;
+};
+
+
+/*************************************************
+Summary: Description of an available parametric operation.
+
+Remarks:
+ + The CKParameterManager::GetAvailableOperationsDesc fills an array
+ of this structure according to search criteria. The 4 CKGUID defines the
+ parameter operation and the Fct member is the function the engine will
+ call to process the operation.
+See also: CKParameterManager::GetAvailableOperationsDesc
+*************************************************/
+typedef struct CKOperationDesc {
+ CKGUID OpGuid; // Operation GUID
+ CKGUID P1Guid; // Input Parameter 1 GUID
+ CKGUID P2Guid; // Input Parameter 2 GUID
+ CKGUID ResGuid; // Output Parameter GUID
+ CK_PARAMETEROPERATION Fct; // Function to call to process the operation.
+ } CKOperationDesc;
+
+
+
+struct TreeCell;
+
+struct OperationCell;
+
+
+/************************************************************************
+Name: CKParameterManager
+
+Summary: Parameter and operation types management
+
+
+Remarks:
+
++ There is only one instance of the CKParameterManager per context, which can
+be accessed using the CKContext::GetParameterManager global function. It manages the list of parameter types,
+and the list of operation types. It gives access to the creation and registration of new operations, and
+overwriting of existing operations.
+
++ Operations are subdivided into families, where members of a family of operations all
+perform the same kind of operations on different types of parameters. For example, you can
+add floats and also imagine adding 3D entities.
+In order to define a new operation type, its family should first be registered, then its function should
+be declared. When a family is unregistered, all the operations of that family are unregistered too. In all
+cases the name argument is provided as a conveniency for debugging and display purposes.
+
+See Also: CKParameterOperation, CKParameter,CKParameterIn, CKParameterOut,ParameterOperation Types,Pre-Registred Parameter Types
+********************************************/
+class CKParameterManager : public CKBaseManager {
+friend class CKParameter;
+public :
+
+//-----------------------------------------------------------------------
+// Parameter Types registration
+CKERROR RegisterParameterType(CKParameterTypeDesc *param_type);
+CKERROR UnRegisterParameterType(CKGUIDCONSTREF guid);
+CKParameterTypeDesc* GetParameterTypeDescription(int type);
+CKParameterTypeDesc* GetParameterTypeDescription(CKGUIDCONSTREF guid);
+ int GetParameterSize(CKParameterType type);
+int GetParameterTypesCount();
+
+CKERROR ChangeParametersGuid(CKGUIDCONSTREF iOldGuid,CKGUIDCONSTREF iNewGuid);
+
+//-----------------------------------------------------------------------
+// Parameter Types <=> Parameter Type Name <=> GUID conversion functions
+CKParameterType ParameterGuidToType(CKGUIDCONSTREF guid);
+CKSTRING ParameterGuidToName(CKGUIDCONSTREF guid);
+CKGUID ParameterTypeToGuid(CKParameterType type);
+CKSTRING ParameterTypeToName(CKParameterType type);
+CKGUID ParameterNameToGuid(CKSTRING name);
+CKParameterType ParameterNameToType(CKSTRING name);
+
+///----------------------------------------------------------------------
+// Dervated types functions
+CKBOOL IsDerivedFrom(CKGUIDCONSTREF guid1,CKGUIDCONSTREF parent);
+CKBOOL IsDerivedFrom(CKParameterType child,CKParameterType parent);
+CKBOOL IsTypeCompatible(CKGUIDCONSTREF guid1,CKGUIDCONSTREF guid2);
+CKBOOL IsTypeCompatible(CKParameterType Ptype1,CKParameterType Ptype2);
+
+//-----------------------------------------------------------------------
+// Parameter Type to Class ID conversions functions
+CK_CLASSID TypeToClassID(CKParameterType type);
+CK_CLASSID GuidToClassID(CKGUIDCONSTREF guid);
+
+CKParameterType ClassIDToType(CK_CLASSID cid);
+CKGUID ClassIDToGuid(CK_CLASSID cid);
+
+//-----------------------------------------------------------------------
+// Special Types : Flags,enums and Structures
+CKERROR RegisterNewFlags(CKGUIDCONSTREF FlagsGuid,CKSTRING FlagsName,CKSTRING FlagsData);
+CKERROR RegisterNewEnum(CKGUIDCONSTREF EnumGuid,CKSTRING EnumName,CKSTRING EnumData);
+CKERROR ChangeEnumDeclaration(CKGUIDCONSTREF EnumGuid,CKSTRING EnumData);
+CKERROR ChangeFlagsDeclaration(CKGUIDCONSTREF FlagsGuid,CKSTRING FlagsData);
+CKERROR RegisterNewStructure(CKGUIDCONSTREF StructGuid,CKSTRING StructName,CKSTRING Structdata,...);
+CKERROR RegisterNewStructure(CKGUIDCONSTREF StructGuid,CKSTRING StructName,CKSTRING StructData,XArray& ListGuid);
+CKERROR GetEnumBuildString(CKParameterType pType,XString& oBuildString);
+CKERROR GetFlagBuildString(CKParameterType pType,XString& oBuildString);
+
+int GetNbFlagDefined();
+int GetNbEnumDefined();
+int GetNbStructDefined();
+CKFlagsStruct* GetFlagsDescByType(CKParameterType pType);
+CKEnumStruct* GetEnumDescByType(CKParameterType pType);
+CKStructStruct* GetStructDescByType(CKParameterType pType);
+
+//------------ Parameter Operations -------------------------------------//
+
+//-----------------------------------------------------------------------
+// Operation Family Registration
+CKOperationType RegisterOperationType(CKGUIDCONSTREF OpCode,CKSTRING name);
+CKERROR UnRegisterOperationType(CKGUIDCONSTREF opguid);
+CKERROR UnRegisterOperationType(CKOperationType opcode);
+
+//-----------------------------------------------------------------------
+// Operation function acces
+#if defined(PSX2) || defined(__MWERKS__)
+ CKERROR RegisterOperationFunction(CKGUID operation,CKGUID type_paramres,CKGUID type_param1,CKGUID type_param2,CK_PARAMETEROPERATION op);
+#else
+ CKERROR RegisterOperationFunction(CKGUIDREF operation,CKGUIDREF type_paramres,CKGUIDREF type_param1,CKGUIDREF type_param2,CK_PARAMETEROPERATION op);
+#endif
+
+CK_PARAMETEROPERATION GetOperationFunction(CKGUIDREF operation,CKGUIDREF type_paramres,CKGUIDREF type_param1,CKGUIDREF type_param2);
+CKERROR UnRegisterOperationFunction(CKGUIDREF operation,CKGUIDREF type_paramres,CKGUIDREF type_param1,CKGUIDREF type_param2);
+
+//-----------------------------------------------------------------------
+// operation type conversion functions : Name <-> GUID <-> internal code for operation
+CKGUID OperationCodeToGuid(CKOperationType type);
+CKSTRING OperationCodeToName(CKOperationType type);
+CKOperationType OperationGuidToCode(CKGUIDCONSTREF guid);
+CKSTRING OperationGuidToName(CKGUIDCONSTREF guid);
+CKGUID OperationNameToGuid(CKSTRING name);
+CKOperationType OperationNameToCode(CKSTRING name);
+
+
+int GetAvailableOperationsDesc(const CKGUID &opGuid,
+ CKParameterOut *res,
+ CKParameterIn *p1,
+ CKParameterIn *p2,
+ CKOperationDesc *list);
+
+int GetParameterOperationCount();
+
+
+
+
+CKBOOL IsParameterTypeToBeShown(CKParameterType type);
+
+CKBOOL IsParameterTypeToBeShown(CKGUIDCONSTREF guid);
+
+CKBOOL CheckParamTypeValidity(CKParameterType type);
+
+ CKParameterManager(CKContext *Context);
+
+ ~CKParameterManager();
+
+ void UpdateParameterEnum();
+
+ CKBOOL m_ParameterTypeEnumUpToDate;
+
+
+//---Called to save manager data. return NULL if nothing to save...
+ virtual CKStateChunk* SaveData(CKFile* SavedFile);
+
+
+//---Called to load manager data.
+ virtual CKERROR LoadData(CKStateChunk *chunk,CKFile* LoadedFile);
+
+protected :
+ XArray m_RegistredTypes;
+
+ int m_NbOperations,m_NbAllocatedOperations;
+ OperationCell* m_OperationTree;
+
+ XHashGuidToType m_ParamGuids;
+ XHashGuidToType m_OpGuids;
+
+ BOOL m_DerivationMasksUpTodate;
+
+ int m_NbFlagsDefined;
+ CKFlagsStruct* m_Flags;
+ int m_NbStructDefined;
+ CKStructStruct* m_Structs;
+ int m_NbEnumsDefined;
+ CKEnumStruct* m_Enums;
+
+ CKBOOL CheckOpCodeValidity(CKOperationType type);
+
+private:
+ CKBOOL GetParameterGuidParentGuid(CKGUID child,CKGUID& parent);
+ void UpdateDerivationTables();
+ void RecurseDeleteParam(TreeCell *cell,CKGUID param);
+ int DichotomicSearch(int start,int end,TreeCell *tab,CKGUID key);
+ void RecurseDelete(TreeCell *cell);
+
+ CKBOOL IsDerivedFromIntern(int child,int parent);
+ CKBOOL RemoveAllParameterTypes();
+ CKBOOL RemoveAllOperations();
+
+ int m_ReplaceDuplicateUserFlagEnum;
+};
+
+
+
+#endif
diff --git a/packages/registry/ref/CKParameterManager.ts b/packages/registry/ref/CKParameterManager.ts
new file mode 100644
index 00000000..2011a4a2
--- /dev/null
+++ b/packages/registry/ref/CKParameterManager.ts
@@ -0,0 +1,335 @@
+type CKGUID = any; // Substitute with actual type
+type CKBOOL = boolean; // Substitute with actual type
+type CKParameterType = any; // Substitute with actual type
+type CKSTRING = string;
+type CK_ID = any; // Substitute with actual type
+type CK_PARAMETEROPERATION = any; // Substitute with actual type
+type CKOperationType = any; // Substitute with actual type
+type CK_CLASSID = any; // Substitute with actual type
+type CKBaseManager = any; // Substitute with actual type
+type CKParameter = any; // Substitute with actual type
+type CKContext = any; // Substitute with actual type
+type CKError = any; // Substitute with actual type
+type CKStateChunk = any; // Substitute with actual type
+type CKFile = any; // Substitute with actual type
+type CKFlagsStruct = any; // Substitute with actual type
+type CKEnumStruct = any; // Substitute with actual type
+type CKStructStruct = any; // Substitute with actual type
+
+class CKStructHelper {
+ m_Context: CKContext;
+ m_StructDescription: CKStructStruct;
+ m_SubIDS: CK_ID[];
+
+ constructor(param: CKParameter | CKContext, guidOrUpdate?: CKGUID | CKBOOL, data?: CK_ID) {
+ if (param instanceof CKParameter) {
+ // Initialization for CKParameter
+ } else {
+ // Initialization for CKContext
+ }
+ }
+
+ GetMemberName(pos: number): string {
+ // Implementation
+ return '';
+ }
+
+ GetMemberGUID(pos: number): CKGUID {
+ // Implementation
+ return {} as CKGUID;
+ }
+
+ GetMemberCount(): number {
+ // Implementation
+ return 0;
+ }
+
+ [i: number]: CKParameter {
+ return this.m_Context.GetObject(this.m_SubIDS[i]) as CKParameter;
+ }
+}
+
+interface CKOperationDesc {
+ OpGuid: CKGUID;
+ P1Guid: CKGUID;
+ P2Guid: CKGUID;
+ ResGuid: CKGUID;
+ Fct: CK_PARAMETEROPERATION;
+}
+
+class CKParameterManager extends CKBaseManager {
+ m_Context: CKContext;
+ m_ParameterTypeEnumUpToDate: CKBOOL;
+ m_RegistredTypes: any[]; // Substitute with actual type
+ m_NbOperations: number;
+ m_NbAllocatedOperations: number;
+ m_OperationTree: OperationCell;
+ m_ParamGuids: XHashTable;
+ m_OpGuids: XHashTable;
+ m_DerivationMasksUpTodate: boolean;
+ m_NbFlagsDefined: number;
+ m_Flags: CKFlagsStruct;
+ m_NbStructDefined: number;
+ m_Structs: CKStructStruct;
+ m_NbEnumsDefined: number;
+ m_Enums: CKEnumStruct;
+ private m_ReplaceDuplicateUserFlagEnum: number;
+
+ constructor(context: CKContext) {
+ super();
+ // Initialization
+ }
+
+ RegisterParameterType(param_type: any): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ UnRegisterParameterType(guid: CKGUID): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ GetParameterTypeDescription(type: number): any {
+ // Implementation
+ return {};
+ }
+ GetParameterTypeDescription(guid: CKGUID): any {
+ // Implementation
+ return {};
+ }
+ GetParameterSize(type: CKParameterType): number {
+ // Implementation
+ return 0;
+ }
+ GetParameterTypesCount(): number {
+ // Implementation
+ return 0;
+ }
+ ChangeParametersGuid(iOldGuid: CKGUID, iNewGuid: CKGUID): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ ParameterGuidToType(guid: CKGUID): CKParameterType {
+ // Implementation
+ return {} as CKParameterType;
+ }
+ ParameterGuidToName(guid: CKGUID): CKSTRING {
+ // Implementation
+ return '';
+ }
+ ParameterTypeToGuid(type: CKParameterType): CKGUID {
+ // Implementation
+ return {} as CKGUID;
+ }
+ ParameterTypeToName(type: CKParameterType): CKSTRING {
+ // Implementation
+ return '';
+ }
+ ParameterNameToGuid(name: CKSTRING): CKGUID {
+ // Implementation
+ return {} as CKGUID;
+ }
+ ParameterNameToType(name: CKSTRING): CKParameterType {
+ // Implementation
+ return {} as CKParameterType;
+ }
+ IsDerivedFrom(guid1: CKGUID, parent: CKGUID): CKBOOL {
+ // Implementation
+ return false;
+ }
+ IsDerivedFrom(child: CKParameterType, parent: CKParameterType): CKBOOL {
+ // Implementation
+ return false;
+ }
+ IsTypeCompatible(guid1: CKGUID, guid2: CKGUID): CKBOOL {
+ // Implementation
+ return false;
+ }
+ IsTypeCompatible(ptype1: CKParameterType, ptype2: CKParameterType): CKBOOL {
+ // Implementation
+ return false;
+ }
+ TypeToClassID(type: CKParameterType): CK_CLASSID {
+ // Implementation
+ return {} as CK_CLASSID;
+ }
+ GuidToClassID(guid: CKGUID): CK_CLASSID {
+ // Implementation
+ return {} as CK_CLASSID;
+ }
+ ClassIDToType(cid: CK_CLASSID): CKParameterType {
+ // Implementation
+ return {} as CKParameterType;
+ }
+ ClassIDToGuid(cid: CK_CLASSID): CKGUID {
+ // Implementation
+ return {} as CKGUID;
+ }
+ RegisterNewFlags(FlagsGuid: CKGUID, FlagsName: CKSTRING, FlagsData: CKSTRING): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ RegisterNewEnum(EnumGuid: CKGUID, EnumName: CKSTRING, EnumData: CKSTRING): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ ChangeEnumDeclaration(EnumGuid: CKGUID, EnumData: CKSTRING): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ ChangeFlagsDeclaration(FlagsGuid: CKGUID, FlagsData: CKSTRING): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ RegisterNewStructure(StructGuid: CKGUID, StructName: CKSTRING, Structdata: CKSTRING, ...args: any[]): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ GetEnumBuildString(pType: CKParameterType, oBuildString: CKSTRING): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ GetFlagBuildString(pType: CKParameterType, oBuildString: CKSTRING): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ GetNbFlagDefined(): number {
+ // Implementation
+ return 0;
+ }
+ GetNbEnumDefined(): number {
+ // Implementation
+ return 0;
+ }
+ GetNbStructDefined(): number {
+ // Implementation
+ return 0;
+ }
+ GetFlagsDescByType(pType: CKParameterType): CKFlagsStruct {
+ // Implementation
+ return {} as CKFlagsStruct;
+ }
+ GetEnumDescByType(pType: CKParameterType): CKEnumStruct {
+ // Implementation
+ return {} as CKEnumStruct;
+ }
+ GetStructDescByType(pType: CKParameterType): CKStructStruct {
+ // Implementation
+ return {} as CKStructStruct;
+ }
+ RegisterOperationType(OpCode: CKGUID, name: CKSTRING): CKOperationType {
+ // Implementation
+ return {} as CKOperationType;
+ }
+ UnRegisterOperationType(opguid: CKGUID): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ UnRegisterOperationType(opcode: CKOperationType): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ RegisterOperationFunction(operation: CKGUID, type_paramres: CKGUID, type_param1: CKGUID, type_param2: CKGUID, op: CK_PARAMETEROPERATION): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ GetOperationFunction(operation: CKGUID, type_paramres: CKGUID, type_param1: CKGUID, type_param2: CKGUID): CK_PARAMETEROPERATION {
+ // Implementation
+ return {} as CK_PARAMETEROPERATION;
+ }
+ UnRegisterOperationFunction(operation: CKGUID, type_paramres: CKGUID, type_param1: CKGUID, type_param2: CKGUID): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ OperationCodeToGuid(type: CKOperationType): CKGUID {
+ // Implementation
+ return {} as CKGUID;
+ }
+ OperationCodeToName(type: CKOperationType): CKSTRING {
+ // Implementation
+ return '';
+ }
+ OperationGuidToCode(guid: CKGUID): CKOperationType {
+ // Implementation
+ return {} as CKOperationType;
+ }
+ OperationGuidToName(guid: CKGUID): CKSTRING {
+ // Implementation
+ return '';
+ }
+ OperationNameToGuid(name: CKSTRING): CKGUID {
+ // Implementation
+ return {} as CKGUID;
+ }
+ OperationNameToCode(name: CKSTRING): CKOperationType {
+ // Implementation
+ return {} as CKOperationType;
+ }
+ GetAvailableOperationsDesc(opGuid: CKGUID, res: any, p1: any, p2: any, list: CKOperationDesc[]): number {
+ // Implementation
+ return 0;
+ }
+ GetParameterOperationCount(): number {
+ // Implementation
+ return 0;
+ }
+ IsParameterTypeToBeShown(type: CKParameterType): boolean {
+ // Implementation
+ return false;
+ }
+ IsParameterTypeToBeShown(guid: CKGUID): boolean {
+ // Implementation
+ return false;
+ }
+ CheckParamTypeValidity(type: CKParameterType): boolean {
+ // Implementation
+ return false;
+ }
+ UpdateParameterEnum(): void {
+ // Implementation
+ }
+ SaveData(SavedFile: CKFile): CKStateChunk | null {
+ // Implementation
+ return null;
+ }
+ LoadData(chunk: CKStateChunk, LoadedFile: CKFile): CKError {
+ // Implementation
+ return {} as CKError;
+ }
+ CheckOpCodeValidity(type: CKOperationType): boolean {
+ // Implementation
+ return false;
+ }
+ GetParameterGuidParentGuid(child: CKGUID, parent: CKGUID): CKBOOL {
+ // Implementation
+ return false;
+ }
+ UpdateDerivationTables(): void {
+ // Implementation
+ }
+ RecurseDeleteParam(cell: TreeCell, param: CKGUID): void {
+ // Implementation
+ }
+ DichotomicSearch(start: number, end: number, tab: TreeCell, key: CKGUID): number {
+ // Implementation
+ return 0;
+ }
+ RecurseDelete(cell: TreeCell): void {
+ // Implementation
+ }
+ IsDerivedFromIntern(child: number, parent: number): CKBOOL {
+ // Implementation
+ return false;
+ }
+ RemoveAllParameterTypes(): CKBOOL {
+ // Implementation
+ return false;
+ }
+ RemoveAllOperations(): CKBOOL {
+ // Implementation
+ return false;
+ }
+ private m_ReplaceDuplicateUserFlagEnum: number; // Implementation
+}
+
+interface TreeCell { /* ... */ }
+interface OperationCell { /* ... */ }
\ No newline at end of file
diff --git a/packages/registry/ref/CKParameterOperation.h b/packages/registry/ref/CKParameterOperation.h
new file mode 100644
index 00000000..30256f33
--- /dev/null
+++ b/packages/registry/ref/CKParameterOperation.h
@@ -0,0 +1,171 @@
+/*************************************************************************/
+/* File : CKParameterOperation.h */
+/* Author : Nicolas Galinotti */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKPARAMETEROPERATION_H
+
+#define CKPARAMETEROPERATION_H "$Id:$"
+
+
+#include "CKObject.h"
+
+/****************************************************************************
+Name: CKParameterOperation
+
+Summary: Performing operations on parameters
+
+Remarks:
+ {Image:ParameterOperation}
+
+ + An operation encapsulates a C++ function that applies on zero, one or two input parameters,
+ and outputs one parameter. Certain operations are predefined in Virtools and you can define your own.
+ The function is called only when necessary (GetValue on the output parameter for example).
+
+ + All the operation's characteristics are defined by the CKParameterManager, and by
+ the GUID of the operation. You can defined your own operation with CKParameterManager::RegisterOperationType
+ and your own operation function with CKParameterManager::RegisterOperationFunction.
+
+ + An operation has zero, one or two input parameters that it owns. These parameters can be plugged into
+ output parameters to retrieve their value for example. The output parameter is also owned by the operation,
+ and is used to make the result of the operation available to the rest of the graph. One can access
+ the parameters with the GetInParameter1, GetInParameter2 and GetOutParameter methods.
+
+ + The execution of the operation is automatically done when needed. You can force it by using the DoOperation method.
+ In any case, the operation checks the update times of the inputs parameters and only does the computation if necessary.
+
+ + The class id of CKParameterOperation is CKCID_PARAMETEROPERATION.
+
+
+See also: CKParameterManager, CKParameterOut, CKParameterIn, CKBehaviorPrototype,ParameterOperation Types
+*********************************************************************************/
+class CKParameterOperation:public CKObject {
+friend class CKBehavior;
+friend class CKParameterIn;
+friend class CKParameterOut;
+public :
+
+ /*************************************************
+ Summary: Accessing the first input parameter of the operation
+ Return Value:
+ A pointer to the first input parameter.
+ Remarks:
+ The parameters of the operation are created with the operation, and are owned by it. These methods
+ give access to these parameters.
+ See Also: GetInParameter2,GetOutParameter
+ *************************************************/
+ CKParameterIn* GetInParameter1() {return m_In1;}
+
+ /*************************************************
+ Summary: Accessing the second input parameter of the operation
+ Return Value:
+ A pointer to the second input parameter.
+ Remarks:
+ The parameters of the operation are created with the operation, and are owned by it. These methods
+ give access to these parameters.
+ See Also: GetInParameter1,GetOutParameter
+ *************************************************/
+ CKParameterIn* GetInParameter2() {return m_In2;}
+
+ /*************************************************
+ Summary: Accessing the output parameter of the operation
+ Return Value:
+ A pointer to the output parameter.
+ Remarks:
+ The parameters of the operation are created with the operation, and are owned by it. These methods
+ give access to these parameters.
+ See Also: GetInParameter1,GetInParameter2
+ *************************************************/
+ CKParameterOut* GetOutParameter() {return m_Out;}
+
+ /*************************************************
+ Summary: Returns the owner behavior.
+ Return Value:
+ A pointer to the CKBehavior that owns this parameter operation.
+ Remarks:
+ + The owner is usually the behavior which owns the graph of which the operation is part of.
+
+ See also: CKBehavior::AddParameterOperation
+ *************************************************/
+ CKBehavior* GetOwner() {
+ return m_Owner;
+ }
+
+ /*************************************************
+ Summary: Owner management
+
+ Remarks:
+ The owner is usually the behavior which owns the graph of which the operation is part of.
+
+ See also: CKBehavior::AddParameterOperation
+ *************************************************/
+ void SetOwner(CKBehavior* beh) {m_Owner = beh;}
+
+ //------------------------------------------------
+ // Execution
+ CKERROR DoOperation();
+
+ //------------------------------------------------
+ // Guid
+ CKGUID GetOperationGuid();
+ void Reconstruct(CKSTRING Name,CKGUID opguid,CKGUID ResGuid, CKGUID p1Guid, CKGUID p2Guid);
+
+//-------------------------------------------------------------------
+#ifdef DOCJETDUMMY // Docjet secret macro
+#else
+ CK_PARAMETEROPERATION GetOperationFunction();
+
+ //------------------------------------------------
+ // Virtual functions
+ CKParameterOperation(CKContext *Context,CKSTRING name=NULL);
+ CKParameterOperation(CKContext *Context,CKSTRING name,CKGUID OpGuid,CKGUID ResGuid,CKGUID P1Guid,CKGUID P2Guid);
+ virtual ~CKParameterOperation();
+ virtual CK_CLASSID GetClassID();
+
+ virtual void PreSave(CKFile *file,CKDWORD flags);
+ virtual CKStateChunk *Save(CKFile *file,CKDWORD flags);
+ virtual CKERROR Load(CKStateChunk *chunk,CKFile* file);
+ virtual void PostLoad();
+
+ virtual void PreDelete();
+
+ virtual int GetMemoryOccupation();
+ virtual int IsObjectUsed(CKObject* o,CK_CLASSID cid);
+ //--------------------------------------------
+ // Dependencies Functions
+ virtual CKERROR PrepareDependencies(CKDependenciesContext& context, CKBOOL iCaller = TRUE);
+ virtual CKERROR RemapDependencies(CKDependenciesContext& context);
+ virtual CKERROR Copy(CKObject& o,CKDependenciesContext& context);
+
+ //--------------------------------------------
+ // Class Registering
+ static CKSTRING GetClassName();
+ static int GetDependenciesCount(int mode);
+ static CKSTRING GetDependencies(int i,int mode);
+ static void Register();
+ static CKParameterOperation* CreateInstance(CKContext *Context);
+ static void ReleaseInstance(CKContext* iContext,CKParameterOperation*);
+ static CK_ID m_ClassID;
+
+ // Dynamic Cast method (returns NULL if the object can't be casted)
+ static CKParameterOperation* Cast(CKObject* iO)
+ {
+ return CKIsChildClassOf(iO,CKCID_PARAMETEROPERATION)?(CKParameterOperation*)iO:NULL;
+ }
+
+ protected :
+ CKParameterIn* m_In1;
+ CKParameterIn* m_In2;
+ CKParameterOut* m_Out;
+ CKBehavior* m_Owner;
+ static CKSTRING m_In1Name;
+ static CKSTRING m_In2Name;
+ static CKSTRING m_OutName;
+
+#endif // docjet secret macro
+};
+
+#endif
+
diff --git a/packages/registry/ref/CKParameterOperation.ts b/packages/registry/ref/CKParameterOperation.ts
new file mode 100644
index 00000000..dc8fe955
--- /dev/null
+++ b/packages/registry/ref/CKParameterOperation.ts
@@ -0,0 +1,118 @@
+class CKParameterOperation extends CKObject {
+ private m_In1: CKParameterIn;
+ private m_In2: CKParameterIn;
+ private m_Out: CKParameterOut;
+ private m_Owner: CKBehavior;
+ static m_In1Name: string;
+ static m_In2Name: string;
+ static m_OutName: string;
+ static m_ClassID: CK_ID;
+
+ constructor(context: CKContext, name: string = null, opGuid?: CKGUID, resGuid?: CKGUID, p1Guid?: CKGUID, p2Guid?: CKGUID) {
+ super();
+ }
+
+ GetInParameter1(): CKParameterIn {
+ return this.m_In1;
+ }
+
+ GetInParameter2(): CKParameterIn {
+ return this.m_In2;
+ }
+
+ GetOutParameter(): CKParameterOut {
+ return this.m_Out;
+ }
+
+ GetOwner(): CKBehavior {
+ return this.m_Owner;
+ }
+
+ SetOwner(beh: CKBehavior) {
+ this.m_Owner = beh;
+ }
+
+ DoOperation(): CKERROR {
+ //
+ }
+
+ GetOperationGuid(): CKGUID {
+ //
+ }
+
+ Reconstruct(name: string, opGuid: CKGUID, resGuid: CKGUID, p1Guid: CKGUID, p2Guid: CKGUID) {
+ //
+ }
+
+ static Cast(iO: CKObject): CKParameterOperation {
+ return CKIsChildClassOf(iO, CKCID_PARAMETEROPERATION) ? iO : null;
+ }
+
+ static GetClassName(): string {
+ //
+ }
+
+ static GetDependenciesCount(mode: number): number {
+ //
+ }
+
+ static GetDependencies(i: number, mode: number): string {
+ //
+ }
+
+ static Register() {
+ //
+ }
+
+ static CreateInstance(context: CKContext): CKParameterOperation {
+ //
+ }
+
+ static ReleaseInstance(iContext: CKContext, instance: CKParameterOperation) {
+ //
+ }
+
+ GetClassID(): CK_CLASSID {
+ //
+ }
+
+ PreSave(file: CKFile, flags: number): void {
+ //
+ }
+
+ Save(file: CKFile, flags: number): CKStateChunk {
+ //
+ }
+
+ Load(chunk: CKStateChunk, file: CKFile): CKERROR {
+ //
+ }
+
+ PostLoad(): void {
+ //
+ }
+
+ PreDelete(): void {
+ //
+ }
+
+ GetMemoryOccupation(): number {
+ //
+ }
+
+ IsObjectUsed(o: CKObject, cid: CK_CLASSID): number {
+ //
+ }
+
+ PrepareDependencies(context: CKDependenciesContext, iCaller: boolean = true): CKERROR {
+ //
+ }
+
+ RemapDependencies(context: CKDependenciesContext): CKERROR {
+ //
+ }
+
+ Copy(o: CKObject, context: CKDependenciesContext): CKERROR {
+ //
+ }
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKParameterOut.h b/packages/registry/ref/CKParameterOut.h
new file mode 100644
index 00000000..3855862f
--- /dev/null
+++ b/packages/registry/ref/CKParameterOut.h
@@ -0,0 +1,128 @@
+/*************************************************************************/
+/* File : CKParameterOut.h */
+/* Author : Nicolas Galinotti */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKPARAMETEROUT_H
+
+#define CKPARAMETEROUT_H
+
+#include "CKParameter.h"
+
+/**************************************************************************
+Name: CKParameterOut
+
+Summary: Output parameter providing a value
+
+Remarks:
+ {Image:ParameterOut}
+
+ + The type of the parameter defines the type of the data provided. These types are maintained by
+the parameter manager. It defines the size of the buffer to use, and also decides what can be plugged
+onto the output parameter. To have the list and definition of predefined parameter types see CKParameterManager.
+
+ + An output parameter may have destinations to which it pushes the data each time it is changed.
+These destinations are other output parameters, which for example provide their value out of the enclosing
+behavior, or local parameters which provide values to other parts of the graph of sub-behaviors.
+These destinations are managed using the AddDestination and related methods.
+When the data of the output parameter changes, it pushes the new value down to
+its destinations.
+
+ + An output parameter will probably also be plugged into input parameters. These input parameters will pull the
+value from the output parameter when needed.
+
+ + An output parameter usually knows how to write its data from and to a string. This is useful for display
+and debugging purposes. When you define a new type of parameter, you can specify the function that converts
+to and from strings.
+
+ + An output parameter can also have an edition window. When you define a new type of parameter, you can specify the
+function that will create the edition window when needed by the interface.
+
+ + A CKParameterOut is created with CKBehavior::CreateOutputParameter or CKContext::CreateCKParameterOut.
+
+ + The class id of CKParameterOut is CKCID_PARAMETEROUT.
+
+
+See also: CKBehavior, CKParameterIn, CKParameterOperation
+**********************************************************************************/
+class CKParameterOut : public CKParameter {
+friend class CKParameterIn;
+friend class CKParameter;
+friend class CKParameterFS;
+friend class CKParameterLocalFS;
+friend class CKParameterManager;
+public :
+//--------------------------------------------
+// Value
+
+virtual CKERROR GetValue(void *buf, CKBOOL update = TRUE);
+virtual CKERROR SetValue(const void *buf,int size = 0);
+virtual CKERROR CopyValue(CKParameter *param,CKBOOL UpdateParam=TRUE);
+virtual void* GetReadDataPtr(CKBOOL update = TRUE);
+virtual int GetStringValue(CKSTRING Value,CKBOOL update = TRUE);
+
+ void CheckClass(CKParameterTypeDesc* iType);
+
+//--------------------------------------------
+// Destinations
+
+void DataChanged();
+CKERROR AddDestination(CKParameter* param,CKBOOL CheckType=TRUE);
+void RemoveDestination(CKParameter* param);
+int GetDestinationCount();
+CKParameter* GetDestination(int pos);
+void RemoveAllDestinations();
+
+//-------------------------------------------------------------------
+// Internal functions
+#ifdef DOCJETDUMMY // Docjet secret macro
+#else
+
+//--------------------------------------------
+// Virtual functions
+ CKParameterOut(CKContext *Context,CKSTRING name = NULL);
+ virtual ~CKParameterOut();
+ virtual CK_CLASSID GetClassID();
+
+ virtual void PreSave(CKFile *file,CKDWORD flags);
+ virtual CKStateChunk *Save(CKFile *file,CKDWORD flags);
+ virtual CKERROR Load(CKStateChunk *chunk,CKFile* file);
+
+ virtual void PreDelete();
+ virtual void CheckPreDeletion();
+
+ virtual int GetMemoryOccupation();
+ virtual int IsObjectUsed(CKObject* o,CK_CLASSID cid);
+
+//--------------------------------------------
+// Dependencies Functions
+ virtual CKERROR RemapDependencies(CKDependenciesContext& context);
+ virtual CKERROR Copy(CKObject& o,CKDependenciesContext& context);
+
+//--------------------------------------------
+// Class Registering
+ static CKSTRING GetClassName();
+ static int GetDependenciesCount(int mode);
+ static CKSTRING GetDependencies(int i,int mode);
+ static void Register();
+ static CKParameterOut* CreateInstance(CKContext *Context);
+ static void ReleaseInstance(CKContext* iContext,CKParameterOut*);
+ static CK_CLASSID m_ClassID;
+
+ // Dynamic Cast method (returns NULL if the object can't be casted)
+ static CKParameterOut* Cast(CKObject* iO)
+ {
+ return CKIsChildClassOf(iO,CKCID_PARAMETEROUT)?(CKParameterOut*)iO:NULL;
+ }
+
+ void Update();
+
+protected:
+
+ XSObjectPointerArray m_Destinations;
+#endif // docjet secret macro
+};
+
+#endif
diff --git a/packages/registry/ref/CKParameterOut.ts b/packages/registry/ref/CKParameterOut.ts
new file mode 100644
index 00000000..5d2ddcfb
--- /dev/null
+++ b/packages/registry/ref/CKParameterOut.ts
@@ -0,0 +1,69 @@
+class CKParameterOut extends CKParameter {
+ constructor(protected context: CKContext, name: string | null = null) {
+ super();
+ }
+
+ CheckClass(iType: CKParameterTypeDesc): void {}
+
+ GetValue(buf: any, update: boolean = true): CKERROR { return CKERROR.NONE; }
+
+ SetValue(buf: any, size: number = 0): CKERROR { return CKERROR.NONE; }
+
+ CopyValue(param: CKParameter, UpdateParam: boolean = true): CKERROR { return CKERROR.NONE; }
+
+ GetReadDataPtr(update: boolean = true): any { return null; }
+
+ GetStringValue(Value: CKSTRING, update: boolean = true): number { return 0; }
+
+ DataChanged(): void {}
+
+ AddDestination(param: CKParameter, CheckType = true): CKERROR { return CKERROR.NONE; }
+
+ RemoveDestination(param: CKParameter): void {}
+
+ GetDestinationCount(): number { return 0; }
+
+ GetDestination(pos: number): CKParameter | null { return null; }
+
+ RemoveAllDestinations(): void {}
+
+ PreSave(file: CKFile, flags: CKDWORD): void {}
+
+ Save(file: CKFile, flags: CKDWORD): CKStateChunk | null { return null; }
+
+ Load(chunk: CKStateChunk, file: CKFile): CKERROR { return CKERROR.NONE; }
+
+ PreDelete(): void {}
+
+ CheckPreDeletion(): void {}
+
+ GetMemoryOccupation(): number { return 0; }
+
+ IsObjectUsed(o: CKObject, cid: CK_CLASSID): number { return 0; }
+
+ RemapDependencies(context: CKDependenciesContext): CKERROR { return CKERROR.NONE; }
+
+ Copy(o: CKObject, context: CKDependenciesContext): CKERROR { return CKERROR.NONE; }
+
+ static GetClassName(): CKSTRING { return ""; }
+
+ static GetDependenciesCount(mode: number): number { return 0; }
+
+ static GetDependencies(i: number, mode: number): CKSTRING { return ""; }
+
+ static Register(): void {}
+
+ static CreateInstance(context: CKContext): CKParameterOut { return new CKParameterOut(context); }
+
+ static ReleaseInstance(iContext: CKContext, instance: CKParameterOut): void {}
+
+ static m_ClassID: CK_CLASSID = 0 as CK_CLASSID;
+
+ static Cast(iO: CKObject): CKParameterOut | null {
+ return CKIsChildClassOf(iO, CKCID_PARAMETEROUT) ? (iO as CKParameterOut) : null;
+ }
+
+ Update(): void {}
+
+ protected m_Destinations: XSObjectPointerArray = new XSObjectPointerArray();
+}
\ No newline at end of file
diff --git a/packages/registry/ref/CKPluginManager.h b/packages/registry/ref/CKPluginManager.h
new file mode 100644
index 00000000..2c8ea048
--- /dev/null
+++ b/packages/registry/ref/CKPluginManager.h
@@ -0,0 +1,318 @@
+/*************************************************************************/
+/* File : CKPluginManager.h */
+/* Author : Aymeric Bard */
+/* */
+/* Virtools SDK */
+/* Copyright (c) Virtools 2000, All Rights Reserved. */
+/*************************************************************************/
+#ifndef CKPLUGINMANAGER_H
+
+#define CKPLUGINMANAGER_H "$Id:$"
+
+#define CKPLUGIN_BITMAP "Bitmap Readers"
+#define CKPLUGIN_SOUND "Sound Readers"
+#define CKPLUGIN_MODEL "Model Readers"
+#define CKPLUGIN_MANAGER "Managers"
+#define CKPLUGIN_BEHAVIOR "BuildingBlocks"
+#define CKPLUGIN_RENDERENGINE "Render Engines"
+#define CKPLUGIN_MOVIE "Movie Readers"
+#define CKPLUGIN_EXTENSIONS "Extensions"
+
+#ifdef CK_LIB
+ /*******************************************
+ + There is only one function a rasterizer Dll is supposed
+ to export :"CKRasterizerGetInfo", it will be used by the render engine
+ to retrieve information about the plugin :
+ {secret}
+ ******************************************/
+ struct CKRasterizerInfo;
+
+ typedef void (*CKRST_GETINFO)(CKRasterizerInfo*);
+#endif
+
+/********************************************************
+Summary: Short description of a DLL that declared plugins
+
+Remarks:
+
+{html:}
+
+ struct CKPluginDll
+ {
+ XString m_DllFileName;
+ INSTANCE_HANDLE m_DllInstance;
+ int m_PluginInfoCount;
+ };
+
+{html:
}
+
+See Also: CKPluginManager::GetPluginDllInfo
+*************************************************************/
+struct CKPluginDll
+{
+ XString m_DllFileName; // DLL Path
+ INSTANCE_HANDLE m_DllInstance; // Instance of the Loaded Dll (as HINSTANCE on windows)
+ int m_PluginInfoCount; // Number of plugins declared by this DLL
+
+
+ CKPluginDll() {
+ m_DllFileName = "";
+ m_DllInstance=0;
+ }
+
+//Summary: Returns a pointer to a function inside the plugin.
+//Arguments:
+// FunctionName: Name of the function which should be returned
+//Return Value:
+// A Pointer to the function or NULL if the function was not found in the DLL.
+ void* GetFunctionPtr(CKSTRING FunctionName) {
+ VxSharedLibrary shl;
+ shl.Attach(m_DllInstance);
+ return shl.GetFunctionPtr(FunctionName);
+ }
+};
+
+
+// Summary: Reader plugin creation function prototype
+//
+// See Also:Creating New Plugins
+typedef CKDataReader *(*CKReaderGetReaderFunction)(int);
+
+
+// Summary: Data Reader (Movie,Bitmap,Sound,Models...) specific options
+//
+struct CKPluginEntryReadersData
+{
+ CKGUID m_SettingsParameterGuid; // Parameter type for options
+ int m_OptionCount; // Number of options for the reader
+ CK_DATAREADER_FLAGS m_ReaderFlags; // Reader Save/Load options
+ CKReaderGetReaderFunction m_GetReaderFct; // A pointer to the function that will create a reader.
+
+
+ CKPluginEntryReadersData() {
+ m_GetReaderFct = NULL;
+ m_OptionCount = 0;
+ m_ReaderFlags = (CK_DATAREADER_FLAGS)0;
+ m_SettingsParameterGuid = CKGUID(0,0);
+ }
+};
+
+// Summary: List of behavior GUID declared by a plugin
+//
+//See Also:CKPluginEntry
+struct CKPluginEntryBehaviorsData
+{
+ XArray m_BehaviorsGUID;
+};
+
+/******************************************************
+Summary: Plugin Description structure
+
+Remarks:
+ + This structure described a registred Virtools plugin :
+
+{html:}
+
+ struct CKPluginEntry
+ {
+ int m_PluginDllIndex;
+ int m_PositionInDll;
+ CKPluginInfo m_PluginInfo;
+ (According to the type of plugin )
+ CKPluginEntryReadersData* m_ReadersInfo;
+ CKPluginEntryBehaviorsData* m_BehaviorsInfo;
+ CKBOOL m_Active;
+ int m_IndexInCategory;
+ CKBOOL m_NeededByFile;
+ }
+
+{html:
}
+
+See Also:CKPluginManager::GetPluginInfo
+********************************************************/
+struct CKPluginEntry
+{
+ int m_PluginDllIndex; // Index of the owner Dll in the list of Dlls
+ int m_PositionInDll; // Position of the PluginInfo inside the DLL (when thery are several plugins inside a same DLL)
+ CKPluginInfo m_PluginInfo; // Base Info on the plugin (Type, Name,Description)
+
+//--- According to the type of plugin
+
+ CKPluginEntryReadersData* m_ReadersInfo; // Reader plugins specific info (optionnal settings + load/save capabilities)
+ CKPluginEntryBehaviorsData* m_BehaviorsInfo; // Behavior plugins specific info (list of declared behavior GUIDS)
+
+ CKBOOL m_Active; // For manager and Render engines TRUE if a manager was created, for other plugins this value is not used.
+ int m_IndexInCategory; // Index of this entry in its category
+ CKBOOL m_NeededByFile; // When saving a file TRUE if at least one object needs this plugin
+
+
+ CKPluginEntry& operator = (const CKPluginEntry& ent);
+
+ CKPluginEntry();
+
+ CKPluginEntry(const CKPluginEntry& ent);
+
+ ~CKPluginEntry();
+};
+
+
+
+struct CKPluginCategory
+{
+ XString m_Name;
+ XArray m_Entries;
+
+ CKPluginCategory(){}
+ CKPluginCategory(const CKPluginCategory& s){
+ m_Name = s.m_Name;
+ m_Entries = s.m_Entries;
+ }
+
+ // Operator
+ CKPluginCategory& operator=(const CKPluginCategory& s){
+ if (&s != this){
+ m_Name = s.m_Name;
+ m_Entries = s.m_Entries;
+ }
+ return *this;
+ }
+};
+
+
+// Summary: Plugin declaration count function prototype
+//
+// See Also:Creating New Plugins
+typedef int (*CKPluginGetInfoCountFunction)();
+
+// Summary: Plugin declaration function prototype
+//
+// See Also:Creating New Plugins
+typedef CKPluginInfo* (*CKPluginGetInfoFunction)(int Index);
+
+
+
+/*****************************************************************************
+Summary: Plugins Manager
+
+Remarks:
+
++ CKPluginManager does not derive from CKBaseManager and there is
+only one instance of the plugin per process (even if there are several CKContext)
+
++ PluginManager init functions must be call before creating any CKContext to
+find the available plugins (ParsePlugins or RegisterPlugin).
+
++ The plugin manager can be retrieve with the CKGetPluginManager function.
+
++ Plugins are sorted by their category, many methods asks to be given a
+category which must be a valid CK_PLUGIN_TYPE identifier or -1 to use all categories.
+
++ Since a Dll can contain several plugins the plugin manager give acces to either
+the list of plugin per category (GetPluginCount,GetPluginInfo) or to the list of Dll
+that were loaded (GetPluginDllCount,GetPluginDllInfo). A plugin is identified by its
+CKPluginEntry which contains its type and other informations along with the index of
+the DLL that declared it.
+
+See Also: CKPluginEntry,CKPluginDll,Creating New Plugins
+**********************************************************************************/
+class CKPluginManager {
+public:
+ CKPluginManager();
+ virtual ~CKPluginManager();
+
+//----- Parse a directory for plugins and returns the number of valid plugins enumerated
+ int ParsePlugins(CKSTRING Directory);
+//------ Registers a specific plugin Dll
+ CKERROR RegisterPlugin(CKSTRING str);
+
+ CKPluginEntry* FindComponent(CKGUID Component,int catIdx=-1); // Search for behaviors,managers,readers,etc.. to see if they exists
+
+
+//---- Category Functions
+ int AddCategory(CKSTRING cat); // Adds a category, category name must be unique
+ CKERROR RemoveCategory(int catIdx); // Removes a category, category name must be unique
+ int GetCategoryCount(); // Gets the number of categories
+ CKSTRING GetCategoryName(int catIdx); // Gets the category name at specified index
+ int GetCategoryIndex(CKSTRING cat); // Gets the category Index in List
+ CKERROR RenameCategory(int catIdx, CKSTRING newName); // Renames a category
+
+//---- PluginDll Functions
+ int GetPluginDllCount(); // Gets the Plugin count
+ CKPluginDll* GetPluginDllInfo(int PluginDllIdx); // Gets the Plugin at index
+ CKPluginDll* GetPluginDllInfo(CKSTRING PluginName,int *idx = NULL); // Search for a Plugin by name
+ CKERROR UnLoadPluginDll(int PluginDllIdx);
+ CKERROR ReLoadPluginDll(int PluginDllIdx);
+
+//---- Plugin Functions
+ int GetPluginCount(int catIdx); // Gets the Plugin count for a category
+ CKPluginEntry* GetPluginInfo(int catIdx, int PluginIdx); // Gets the Plugin at index PluginIdx for a category
+
+//---- Bitmap,Sound,Model or Movie Reader Access
+ BOOL SetReaderOptionData(CKContext* context,void* memdata,CKParameterOut* Param,CKFileExtension ext,CKGUID* guid=NULL);
+ CKParameterOut* GetReaderOptionData(CKContext* context,void* memdata,CKFileExtension ext,CKGUID* guid=NULL);
+
+ CKBitmapReader* GetBitmapReader(CKFileExtension& ext,CKGUID *preferedGUID = NULL);
+ CKSoundReader* GetSoundReader(CKFileExtension& ext,CKGUID *preferedGUID = NULL);
+ CKModelReader* GetModelReader(CKFileExtension& ext,CKGUID *preferedGUID = NULL);
+ CKMovieReader* GetMovieReader(CKFileExtension& ext,CKGUID *preferedGUID = NULL);
+
+//---- Model and Virtools Loading access {secret}
+
+
+ CKERROR Load(CKContext* context,CKSTRING FileName,CKObjectArray *liste,CK_LOAD_FLAGS LoadFlags,CKCharacter *carac=NULL,CKGUID* Readerguid=NULL); // {secret}
+ CKERROR Save(CKContext* context,CKSTRING FileName,CKObjectArray *liste,CKDWORD SaveFlags,CKGUID* Readerguid=NULL); // {secret}
+
+//---- Init {secret}
+ void ReleaseAllPlugins();
+ void InitializePlugins(CKContext* context);
+ void DeInitializePlugins(CKContext* context);
+ void ComputeDependenciesList(CKFile* file);
+ void MarkComponentAsNeeded(CKGUID Component,int catIdx);
+
+#ifdef CK_LIB
+
+//-------------------------------------------------------------------
+#ifdef DOCJETDUMMY // Docjet secret macro
+#else
+
+//---------------- for additionnal plugins to link statically
+ void RegisterPluginInfo(int PositionInDll,CKPluginInfo* info,CKDLL_OBJECTDECLARATIONFUNCTION InfoFct,CKReaderGetReaderFunction GetReaderFunc);
+ void RegisterNewStaticLibAsDll(char* Name,int PluginInfoCount);
+ void AddRenderEngineRasterizer(CKRST_GETINFO RasterizerInfoFunction) { m_StaticRasterizers.PushBack(RasterizerInfoFunction); }
+ const XArray& GetRegistredRasterizers() { return m_StaticRasterizers; }
+#endif // Docjet secret macro
+
+#endif
+
+protected:
+//--- Utils
+ void InitInstancePluginEntry(CKPluginEntry* entry,CKContext* context);
+ void ExitInstancePluginEntry(CKPluginEntry* entry,CKContext* context);
+ void InitializeBehaviors(VxSharedLibrary& lib,CKPluginEntry& entry);
+ void InitializeBehaviors(CKDLL_OBJECTDECLARATIONFUNCTION Fct,CKPluginEntry& entry);
+ void RemoveBehaviors(int PluginIndex);
+
+#ifdef CK_LIB
+
+ XArray m_StaticRasterizers;
+#endif
+
+ int AddPlugin(int catIdx, CKPluginEntry& Plugin); // Adds a Plugin to a category
+ CKERROR RemovePlugin(int catIdx, int PluginIdx); // Removes a Plugin in a category
+
+ CKPluginEntry* EXTFindEntry(CKFileExtension& ext,int Category=-1);
+ CKDataReader *EXTFindReader(CKFileExtension& ext,int Category=-1);
+ CKDataReader *GUIDFindReader(CKGUID& guid,int Category=-1);
+
+
+ XClassArray m_PluginCategories;
+ XClassArray m_PluginDlls;
+ XClassArray m_RunTimeDlls;
+
+ void Clean();
+ void Init();
+
+};
+
+#endif
+
\ No newline at end of file
diff --git a/packages/registry/ref/CKPluginManager.ts b/packages/registry/ref/CKPluginManager.ts
new file mode 100644
index 00000000..c0d175c5
--- /dev/null
+++ b/packages/registry/ref/CKPluginManager.ts
@@ -0,0 +1,104 @@
+const CKPLUGINMANAGER_H = "$Id:$";
+
+const CKPLUGIN_BITMAP = "Bitmap Readers";
+const CKPLUGIN_SOUND = "Sound Readers";
+const CKPLUGIN_MODEL = "Model Readers";
+const CKPLUGIN_MANAGER = "Managers";
+const CKPLUGIN_BEHAVIOR = "BuildingBlocks";
+const CKPLUGIN_RENDERENGINE = "Render Engines";
+const CKPLUGIN_MOVIE = "Movie Readers";
+const CKPLUGIN_EXTENSIONS = "Extensions";
+
+interface CKRasterizerInfo {}
+
+type CKRST_GETINFO = (info: CKRasterizerInfo) => void;
+
+interface CKPluginDll {
+ m_DllFileName: string;
+ m_DllInstance: INSTANCE_HANDLE;
+ m_PluginInfoCount: number;
+ GetFunctionPtr(FunctionName: CKSTRING): void | null;
+}
+
+type CKReaderGetReaderFunction = (type: number) => CKDataReader;
+
+interface CKPluginEntryReadersData {
+ m_SettingsParameterGuid: CKGUID;
+ m_OptionCount: number;
+ m_ReaderFlags: CK_DATAREADER_FLAGS;
+ m_GetReaderFct: CKReaderGetReaderFunction | null;
+}
+
+interface CKPluginEntryBehaviorsData {
+ m_BehaviorsGUID: Array;
+}
+
+interface CKPluginEntry {
+ m_PluginDllIndex: number;
+ m_PositionInDll: number;
+ m_PluginInfo: CKPluginInfo;
+ m_ReadersInfo: CKPluginEntryReadersData | null;
+ m_BehaviorsInfo: CKPluginEntryBehaviorsData | null;
+ m_Active: CKBOOL;
+ m_IndexInCategory: number;
+ m_NeededByFile: CKBOOL;
+}
+
+interface CKPluginCategory {
+ m_Name: string;
+ m_Entries: Array;
+}
+
+type CKPluginGetInfoCountFunction = () => number;
+
+type CKPluginGetInfoFunction = (Index: number) => CKPluginInfo;
+
+class CKPluginManager {
+ constructor() {}
+ ParsePlugins(Directory: CKSTRING): number { return 0; }
+ RegisterPlugin(str: CKSTRING): CKERROR { return CKERROR.FAILURE; }
+ FindComponent(Component: CKGUID, catIdx: number = -1): CKPluginEntry | null { return null; }
+
+ AddCategory(cat: CKSTRING): number { return 0; }
+ RemoveCategory(catIdx: number): CKERROR { return CKERROR.FAILURE; }
+ GetCategoryCount(): number { return 0; }
+ GetCategoryName(catIdx: number): CKSTRING { return ""; }
+ GetCategoryIndex(cat: CKSTRING): number { return 0; }
+ RenameCategory(catIdx: number, newName: CKSTRING): CKERROR { return CKERROR.FAILURE; }
+
+ GetPluginDllCount(): number { return 0; }
+ GetPluginDllInfo(PluginDllIdx: number): CKPluginDll | null { return null; }
+ GetPluginDllInfo(PluginName: CKSTRING, idx?: number): CKPluginDll | null { return null; }
+ UnLoadPluginDll(PluginDllIdx: number): CKERROR { return CKERROR.FAILURE; }
+ ReLoadPluginDll(PluginDllIdx: number): CKERROR { return CKERROR.FAILURE; }
+
+ GetPluginCount(catIdx: number): number { return 0; }
+ GetPluginInfo(catIdx: number, PluginIdx: number): CKPluginEntry | null { return null; }
+
+ SetReaderOptionData(context: CKContext, memdata: any, Param: CKParameterOut, ext: CKFileExtension, guid?: CKGUID): boolean { return false; }
+ GetReaderOptionData(context: CKContext, memdata: any, ext: CKFileExtension, guid?: CKGUID): CKParameterOut | null { return null; }
+
+ GetBitmapReader(ext: CKFileExtension, preferedGUID?: CKGUID): CKBitmapReader | null { return null; }
+ GetSoundReader(ext: CKFileExtension, preferedGUID?: CKGUID): CKSoundReader | null { return null; }
+ GetModelReader(ext: CKFileExtension, preferedGUID?: CKGUID): CKModelReader | null { return null; }
+ GetMovieReader(ext: CKFileExtension, preferedGUID?: CKGUID): CKMovieReader | null { return null; }
+
+ Load(context: CKContext, FileName: CKSTRING, liste: CKObjectArray, LoadFlags: CK_LOAD_FLAGS, carac?: CKCharacter, Readerguid?: CKGUID): CKERROR { return CKERROR.FAILURE; }
+ Save(context: CKContext, FileName: CKSTRING, liste: CKObjectArray, SaveFlags: CKDWORD, Readerguid?: CKGUID): CKERROR { return CKERROR.FAILURE; }
+
+ ReleaseAllPlugins(): void {}
+ InitializePlugins(context: CKContext): void {}
+ DeInitializePlugins(context: CKContext): void {}
+ ComputeDependenciesList(file: CKFile): void {}
+ MarkComponentAsNeeded(Component: CKGUID, catIdx: number): void {}
+
+ AddPlugin(catIdx: number, Plugin: CKPluginEntry): number { return 0; }
+ RemovePlugin(catIdx: number, PluginIdx: number): CKERROR { return CKERROR.FAILURE; }
+
+ EXTFindEntry(ext: CKFileExtension, Category: number = -1): CKPluginEntry | null { return null; }
+ EXTFindReader(ext: CKFileExtension, Category: number = -1): CKDataReader | null { return null; }
+ GUIDFindReader(guid: CKGUID, Category: number = -1): CKDataReader | null { return null; }
+
+ Clean(): void {}
+ Init(): void {}
+}
\ No newline at end of file
diff --git a/packages/registry/ref/to-typescript.md b/packages/registry/ref/to-typescript.md
new file mode 100644
index 00000000..9e134cfe
--- /dev/null
+++ b/packages/registry/ref/to-typescript.md
@@ -0,0 +1,5 @@
+Convert to Typescript
+
+- extract & export all types and interfaces
+- avoid classes whenever possible
+- max. arguments = 2, use options object instead
diff --git a/packages/registry/ref/toTS.sh b/packages/registry/ref/toTS.sh
new file mode 100644
index 00000000..97d1861e
--- /dev/null
+++ b/packages/registry/ref/toTS.sh
@@ -0,0 +1 @@
+kbotd "convert to Typescript, no comments,... just code" --each="*.h" --dst='./${SRC_NAME}.ts' --filters=code --mode=completion --router=openai --model=gpt-4o
\ No newline at end of file
diff --git a/packages/registry/src/.gitignore b/packages/registry/src/.gitignore
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/registry/src/_cli.ts b/packages/registry/src/_cli.ts
new file mode 100644
index 00000000..b064de1d
--- /dev/null
+++ b/packages/registry/src/_cli.ts
@@ -0,0 +1,23 @@
+import { sync as exists } from '@plastichub/fs/exists'
+import { IOptions } from './types'
+import { logger } from './'
+import * as path from 'path'
+
+// tweaks and handlers
+export const defaults = () => {
+ // default command
+ const DefaultCommand = 'info';
+ if (process.argv.length === 2) {
+ process.argv.push(DefaultCommand);
+ }
+
+ // currently no default handler, display only :
+ process.on('unhandledRejection', (reason: string) => {
+ console.error('Unhandled rejection, reason: ', reason);
+ });
+};
+
+export const sanitize = (argv: any): IOptions | boolean => {
+
+ return argv
+}
\ No newline at end of file
diff --git a/packages/registry/src/commands/info.ts b/packages/registry/src/commands/info.ts
new file mode 100644
index 00000000..7803d4b2
--- /dev/null
+++ b/packages/registry/src/commands/info.ts
@@ -0,0 +1,53 @@
+import { logger } from '../'
+import { defaults } from '../_cli'
+
+import * as CLI from 'yargs'
+import * as path from 'path'
+import { CONFIG_DEFAULT } from '@plastichub/osr-commons'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs.option('debug', {
+ default: 'false',
+ describe: 'debug messages'
+ }).option('verb', {
+ description: 'search api: scaleserp',
+ default: 'scaleserp'
+ }).option('location', {
+ description: 'location to be searched from',
+ default: 'Berlin, Germany'
+ }).option('query', {
+ description: 'the query',
+ default: 'Precious Plastic Munich'
+ }).option('dst', {
+ description: 'dst output path, supports XLS|CSV|HTML',
+ default: './tests/data/serpwow.json'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path'
+ });
+};
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs);
+
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('info ', 'Search', options, async (argv: CLI.Arguments) => {
+ defaults()
+ if (argv.help) { return }
+ const args: any = argv
+
+ const config = CONFIG_DEFAULT(args.env_key)
+
+ const opts = {
+ verb: argv.verb,
+ query: argv.query,
+ dst: path.resolve(args.dst)
+ }
+
+ if (!opts.verb) {
+ logger.error('No verb specified');
+ return
+ }
+ logger.debug(`Reading OSR Config with key "${argv.env_key}"`, opts)
+ })
+}
diff --git a/packages/registry/src/commands/test.ts b/packages/registry/src/commands/test.ts
new file mode 100644
index 00000000..617de846
--- /dev/null
+++ b/packages/registry/src/commands/test.ts
@@ -0,0 +1,66 @@
+import * as CLI from 'yargs'
+import * as path from 'path'
+
+import { sync as write } from '@plastichub/fs/write'
+import { sync as read } from '@plastichub/fs/read'
+
+import { substitute } from '@plastichub/core'
+
+import { CONFIG_DEFAULT, DEFAULT_ROOTS } from '@plastichub/osr-commons'
+
+import { logger } from '../'
+import { defaults } from '../_cli'
+
+const defaultOptions = (yargs: CLI.Argv) => {
+ return yargs.option('debug', {
+ default: 'false',
+ describe: 'debug messages'
+ }).option('verb', {
+ description: 'test verb : file|folder'
+ }).option('src', {
+ description: 'raw source file',
+ default: './tests/src.json'
+ }).option('dst', {
+ description: 'dst output path, supports XLS|CSV|HTML',
+ default: './tests/dst.json'
+ }).option('env_key', {
+ default: 'OSR-CONFIG',
+ describe: 'Environment key to the config path'
+ });
+};
+
+let options = (yargs: CLI.Argv) => defaultOptions(yargs);
+
+
+export const register = (cli: CLI.Argv) => {
+ return cli.command('test ', 'Test commands', options, async (argv: CLI.Arguments) => {
+
+ defaults();
+
+ if (argv.help) { return; }
+ const args: any = argv;
+
+ const config = CONFIG_DEFAULT(args.env_key);
+
+ const opts = {
+ verb: argv.verb,
+ src: path.resolve(substitute(args.src, DEFAULT_ROOTS)),
+ dst: path.resolve(substitute(args.dst, DEFAULT_ROOTS))
+ };
+
+ if (!opts.verb) {
+ logger.error('No verb specified');
+ return;
+ }
+
+ if (opts.verb === 'file') {
+
+ const src = read(opts.src, 'json');
+ /*
+ const hashed = await get_cached(opts.src, { a: 1 }, 'tests')
+ const shashed = await set_cached(opts.src, { a: 1 }, 'tests', src)
+ */
+ }
+ logger.debug(`Reading OSR Config with key "${argv.env_key}"`, opts);
+ });
+};
diff --git a/packages/registry/src/constants.ts b/packages/registry/src/constants.ts
new file mode 100644
index 00000000..6f8b0f3d
--- /dev/null
+++ b/packages/registry/src/constants.ts
@@ -0,0 +1 @@
+export const MODULE_NAME = `OSR-REGISTRY`
diff --git a/packages/registry/src/index.ts b/packages/registry/src/index.ts
new file mode 100644
index 00000000..65ab1a90
--- /dev/null
+++ b/packages/registry/src/index.ts
@@ -0,0 +1,9 @@
+
+import { logger as _logger } from '@plastichub/core/debug'
+
+import { MODULE_NAME } from './constants'
+export * from './lib/index'
+
+export const logger = _logger(MODULE_NAME)
+export { sanitize } from './_cli'
+export { MODULE_NAME } from './constants'
\ No newline at end of file
diff --git a/packages/registry/src/lib/index.ts b/packages/registry/src/lib/index.ts
new file mode 100644
index 00000000..2ce4e3bc
--- /dev/null
+++ b/packages/registry/src/lib/index.ts
@@ -0,0 +1,7 @@
+import * as path from 'path'
+import * as fs from 'fs'
+
+import { logger } from '../'
+
+export * from './types'
+export * from './keyv'
diff --git a/packages/registry/src/lib/keyv.ts b/packages/registry/src/lib/keyv.ts
new file mode 100644
index 00000000..ebdf805b
--- /dev/null
+++ b/packages/registry/src/lib/keyv.ts
@@ -0,0 +1,22 @@
+import * as path from 'path'
+import Keyv from 'keyv'
+import KeyvSqlite from '@keyv/sqlite'
+
+import { resolve } from '@plastichub/osr-commons'
+
+export const store = (storePath: string, ns: string = 'ns-unknown', opts: any = {}) => {
+ const keyvSqlite = new KeyvSqlite(path.resolve(resolve(storePath)))
+ return new Keyv({ store: keyvSqlite, ttl: 5000, namespace: ns, ...opts })
+}
+export const get = async (key: string, storePath: string, ns: string = 'ns-unknown', opts: any = {}) => {
+ const keyv = store(storePath, ns, opts)
+ return await keyv.get(key)
+}
+export const set = async (key: string, value: any, storePath: string, ns: string = 'ns-unknown', opts: any = {}) => {
+ const keyv = store(storePath, ns, opts)
+ return await keyv.set(key, value)
+}
+export const list = async (key: string, value: any, storePath: string, ns: string = 'ns-unknown', opts: any = {}) => {
+ const keyv = store(storePath, ns, opts)
+ return await keyv.set(key, value)
+}
diff --git a/packages/registry/src/lib/types.ts b/packages/registry/src/lib/types.ts
new file mode 100644
index 00000000..feaff3ab
--- /dev/null
+++ b/packages/registry/src/lib/types.ts
@@ -0,0 +1,2 @@
+export interface Noop {
+}
diff --git a/packages/registry/src/main.ts b/packages/registry/src/main.ts
new file mode 100644
index 00000000..08fc4d34
--- /dev/null
+++ b/packages/registry/src/main.ts
@@ -0,0 +1,14 @@
+#!/usr/bin/env node
+import { defaults } from './_cli'; defaults()
+import * as cli from 'yargs'
+
+import { register as registerInfo } from './commands/info'; registerInfo(cli)
+
+const argv: any = cli.argv;
+
+if (argv.help) {
+ cli.showHelp();
+ process.exit();
+} else if (argv.v || argv.version) {
+ process.exit();
+}
diff --git a/packages/registry/src/options.ts b/packages/registry/src/options.ts
new file mode 100644
index 00000000..33da43ef
--- /dev/null
+++ b/packages/registry/src/options.ts
@@ -0,0 +1,18 @@
+export * from './lib'
+
+import { IOptions } from './types'
+
+export const clone = (obj) => {
+
+ if (null == obj || "object" != typeof obj) return obj;
+ var copy = obj.constructor();
+ for (var attr in obj) {
+ if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
+ }
+ return copy;
+}
+
+export const parse = (options: IOptions, argv: any): IOptions => {
+
+ return options;
+}
\ No newline at end of file
diff --git a/packages/registry/src/types.ts b/packages/registry/src/types.ts
new file mode 100644
index 00000000..deef6231
--- /dev/null
+++ b/packages/registry/src/types.ts
@@ -0,0 +1,2 @@
+export type IOptions = { }
+
diff --git a/packages/registry/tsconfig.json b/packages/registry/tsconfig.json
new file mode 100644
index 00000000..0c7bbcc4
--- /dev/null
+++ b/packages/registry/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "ESNext",
+ "allowJs": true,
+ "noImplicitAny": false,
+ "noImplicitThis": false,
+ "alwaysStrict": true,
+ "sourceMap": true,
+ "outDir": "./",
+ "experimentalDecorators": true,
+ "emitDecoratorMetadata": true,
+ "pretty": false,
+ "baseUrl": "./src",
+ "rootDir": "./src",
+ "allowSyntheticDefaultImports": true
+ },
+ "compileOnSave": false,
+ "filesGlob": [
+ "./src/**/*.ts"
+ ],
+ "atom": {
+ "rewriteTsconfig": true
+ },
+ "files": [
+ "./src/index.ts",
+ "./src/lib/index.ts",
+ "./src/main.ts"
+ ]
+}
\ No newline at end of file
diff --git a/packages/registry/types.d.ts b/packages/registry/types.d.ts
new file mode 100644
index 00000000..503faf8c
--- /dev/null
+++ b/packages/registry/types.d.ts
@@ -0,0 +1 @@
+export type IOptions = {};
diff --git a/packages/registry/types.js b/packages/registry/types.js
new file mode 100644
index 00000000..3da8b318
--- /dev/null
+++ b/packages/registry/types.js
@@ -0,0 +1,3 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+//# sourceMappingURL=types.js.map
\ No newline at end of file
diff --git a/packages/registry/types.js.map b/packages/registry/types.js.map
new file mode 100644
index 00000000..14058397
--- /dev/null
+++ b/packages/registry/types.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"types.js","sourceRoot":"","sources":["src/types.ts"],"names":[],"mappings":""}
\ No newline at end of file
diff --git a/packages/vfs/.gitignore b/packages/vfs/.gitignore
new file mode 100644
index 00000000..3c373c06
--- /dev/null
+++ b/packages/vfs/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+/coverage
+*.log
+.DS_Store
diff --git a/packages/vfs/.npmignore b/packages/vfs/.npmignore
new file mode 100644
index 00000000..4c9addac
--- /dev/null
+++ b/packages/vfs/.npmignore
@@ -0,0 +1,4 @@
+./docs
+./scripts
+./tests
+./incoming
\ No newline at end of file
diff --git a/packages/vfs/LICENSE b/packages/vfs/LICENSE
new file mode 100644
index 00000000..b0e20f53
--- /dev/null
+++ b/packages/vfs/LICENSE
@@ -0,0 +1,9 @@
+Copyright (c) All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/vfs/README.md b/packages/vfs/README.md
new file mode 100644
index 00000000..9398456b
--- /dev/null
+++ b/packages/vfs/README.md
@@ -0,0 +1,7 @@
+# OSR VFS
+
+### References
+
+- [WinFsp - Windows File Proxy](https://github.com/winfsp/winfsp/wiki)
+- [SQLite - VFS](https://www.sqlite.org/vfs.html)
+- [RClone - RC JS - API](https://github.com/rclone/rclone-js-api/blob/master/src/index.js)
diff --git a/packages/vfs/_cli.js b/packages/vfs/_cli.js
new file mode 100644
index 00000000..47f9d1b2
--- /dev/null
+++ b/packages/vfs/_cli.js
@@ -0,0 +1,16 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.defaults = void 0;
+// tweaks and handlers
+exports.defaults = function () {
+ // default command
+ var DefaultCommand = 'summary';
+ if (process.argv.length === 2) {
+ process.argv.push(DefaultCommand);
+ }
+ // currently no default handler, display only :
+ process.on('unhandledRejection', function (reason) {
+ console.error('Unhandled rejection, reason: ', reason);
+ });
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX2NsaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9fY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNCQUFzQjtBQUNULFFBQUEsUUFBUSxHQUFHO0lBQ3BCLGtCQUFrQjtJQUNsQixJQUFNLGNBQWMsR0FBRyxTQUFTLENBQUM7SUFDakMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDM0IsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7S0FDckM7SUFFRCwrQ0FBK0M7SUFDL0MsT0FBTyxDQUFDLEVBQUUsQ0FBQyxvQkFBb0IsRUFBRSxVQUFDLE1BQWM7UUFDNUMsT0FBTyxDQUFDLEtBQUssQ0FBQywrQkFBK0IsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMzRCxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQyJ9
\ No newline at end of file
diff --git a/packages/vfs/_cli.js.map b/packages/vfs/_cli.js.map
new file mode 100644
index 00000000..d29a04af
--- /dev/null
+++ b/packages/vfs/_cli.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"_cli.js","sourceRoot":"","sources":["src/_cli.ts"],"names":[],"mappings":";;;AAAA,sBAAsB;AACT,QAAA,QAAQ,GAAG;IACpB,kBAAkB;IAClB,IAAM,cAAc,GAAG,SAAS,CAAC;IACjC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;KACrC;IAED,+CAA+C;IAC/C,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,UAAC,MAAc;QAC5C,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"}
\ No newline at end of file
diff --git a/packages/vfs/_package.json b/packages/vfs/_package.json
new file mode 100644
index 00000000..f79cbe03
--- /dev/null
+++ b/packages/vfs/_package.json
@@ -0,0 +1,78 @@
+{
+ "name": "@plastichub/osr-vfs",
+ "version": "0.0.1",
+ "description": "Virtual File System Lib & CLI",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "help": "node build/main.js --help",
+ "build": "tsc -p .",
+ "dev": "tsc -w -p .",
+ "publish": "npm publish --access public"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://git.osr-plastic.org/osr-plastic/osr-vfs.git"
+ },
+ "author": "PlasticHub",
+ "bin": {
+ "osr-vfs": "main.js"
+ },
+ "publishConfig": {
+ "access": "public"
+ },
+ "license": "ISC",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.39",
+ "@plastichub/osr-cache": "^0.3.8",
+ "@plastichub/osr-commons": "file:../osr-commons",
+ "@plastichub/osr-sync": "^0.1.8",
+ "@types/cacache": "^15.0.1",
+ "@types/is-glob": "^4.0.1",
+ "@types/ssh2-sftp-client": "^9.0.0",
+ "add": "^2.0.6",
+ "axios": "^0.21.1",
+ "bluebird": "^3.7.2",
+ "cacache": "^17.0.5",
+ "duration-timestamp": "^2.3.0",
+ "errlop": "^2.1.0",
+ "escape-html": "^1.0.3",
+ "fast-glob": "^3.1.1",
+ "filenamify": "^4.1.0",
+ "glob-base": "^0.3.0",
+ "is-glob": "^4.0.1",
+ "md5": "^2.3.0",
+ "moment": "^2.30.1",
+ "native-promise-pool": "^3.0.0",
+ "parse-glob": "^2.0.1",
+ "regexp.escape": "^1.1.0",
+ "sanitize-filename": "^1.6.3",
+ "slash": "^3.0.0",
+ "slugify": "^1.4.6",
+ "source-map-support": "^0.5.16",
+ "ssh2-sftp-client": "^9.0.4",
+ "tslint": "^5.10.0",
+ "typescript": "^3.9.10",
+ "which": "^2.0.2",
+ "yargonaut": "^1.1.4",
+ "yargs": "^15.4.1"
+ },
+ "devDependencies": {
+ "@bevry/links": "^1.2.0",
+ "@bevry/update-contributors": "^1.23.0",
+ "@types/moment": "^2.13.0",
+ "@types/node": "^13.13.52",
+ "@types/node-fetch": "^2.6.12",
+ "@types/pretty": "^2.0.3",
+ "@types/which": "^1.3.2",
+ "@types/yargs": "^13.0.12",
+ "@typescript-eslint/eslint-plugin": "^2.34.0",
+ "@typescript-eslint/parser": "^2.34.0",
+ "assert-helpers": "^6.19.0",
+ "eslint": "^6.8.0",
+ "eslint-config-bevry": "^3.29.0",
+ "eslint-config-prettier": "^6.15.0",
+ "eslint-plugin-prettier": "^3.4.1",
+ "prettier": "^2.8.8"
+ }
+}
diff --git a/packages/vfs/argv.js b/packages/vfs/argv.js
new file mode 100644
index 00000000..eb5b5186
--- /dev/null
+++ b/packages/vfs/argv.js
@@ -0,0 +1,230 @@
+"use strict";
+var __assign = (this && this.__assign) || function () {
+ __assign = Object.assign || function(t) {
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
+ s = arguments[i];
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
+ t[p] = s[p];
+ }
+ return t;
+ };
+ return __assign.apply(this, arguments);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.sanitize = exports.sanitizeSingle = exports.defaultOptions = void 0;
+var path = require("path");
+var _1 = require("./");
+var osr_cli_commons_1 = require("@plastichub/osr-cli-commons");
+var read_1 = require("@plastichub/fs/read");
+// default options for all commands
+exports.defaultOptions = function (yargs) {
+ return yargs.option('src', {
+ default: './',
+ describe: 'The source directory or source file. Glob patters are supported!',
+ demandOption: true
+ }).option('format', {
+ describe: 'The target format. Multiple formats are allowed as well, use --format=pdf --format=jpg'
+ }).option('dst', {
+ describe: 'Destination folder or file'
+ }).option('view', {
+ default: 'Isometric',
+ describe: 'Sets the target view'
+ }).option('Report', {
+ describe: 'Optional conversion report. Can be JSON, HTML, CSV or Markdown'
+ }).option('debug', {
+ default: false,
+ describe: 'Enable internal debug messages',
+ type: 'boolean'
+ }).option('alt', {
+ default: false,
+ describe: 'Use alternate tokenizer, & instead of $',
+ type: 'boolean'
+ }).option('skip', {
+ default: true,
+ describe: 'Skip existing files',
+ type: 'boolean'
+ }).option('dry', {
+ default: false,
+ describe: 'Run without conversion',
+ type: 'boolean'
+ }).option('verbose', {
+ default: true,
+ describe: 'Show internal messages',
+ type: 'boolean'
+ }).option('sw', {
+ describe: 'Set explicit the path to the Solidworks binaries & scripts.\
+ Otherwise, set it to 2020, 2022 or 2023 to use the built-in binaries',
+ default: '2022'
+ }).option('script', {
+ describe: 'Set explicit the path to the Solidworks script'
+ }).option('hash', {
+ describe: 'To skip already converted files, this option will create a hash file with the extension .hash \
+ using --skip==true will disable it again',
+ default: true,
+ type: 'boolean'
+ }).option('bom-config', {
+ describe: 'Set the Model Configuration to be used',
+ default: 'Default'
+ }).option('bom-template', {
+ describe: 'Path to the BOM template. Default is osr-cad/sw/bom-all.sldbomtbt'
+ }).option('bom-type', {
+ describe: 'Bom Type : default = 2 - PartsOnly = 1 | TopLevelOnly = 2 | Indented = 3',
+ type: "number",
+ default: 2
+ }).option('bom-detail', {
+ describe: 'Bom Numbering : default = 1 - Type_None = 0 | Type_Detailed = 1 | Type_Flat = 2 | BOMNotSet = 3',
+ type: "number",
+ default: 1
+ }).option('bom-images', {
+ describe: 'Add an image in the first colum',
+ type: 'boolean',
+ default: false
+ });
+};
+// Sanitizes faulty user argv options for all commands.
+exports.sanitizeSingle = function (argv) {
+ var src = path.resolve('' + argv.src);
+ var config = argv.config ? read_1.sync(path.resolve('' + argv.config), 'json') : {};
+ var extraVariables = {};
+ for (var key in config) {
+ if (Object.prototype.hasOwnProperty.call(config, key)) {
+ var element = config[key];
+ if (typeof element === 'string') {
+ extraVariables[key] = element;
+ }
+ }
+ }
+ var args = {
+ src: src,
+ dst: '' + argv.dst,
+ report: argv.report ? path.resolve(argv.report) : null,
+ debug: argv.debug,
+ verbose: argv.verbose,
+ dry: argv.dry,
+ skip: argv.skip,
+ alt: argv.alt,
+ glob: argv.glob,
+ sw: argv.sw,
+ script: argv.script || 'pack.exe',
+ variables: __assign({}, extraVariables),
+ args: argv.args || '',
+ hash: argv.hash
+ };
+ if (!args.src) {
+ _1.logger.error('Invalid source, abort');
+ return process.exit();
+ }
+ args.srcInfo = osr_cli_commons_1.pathInfo(argv.src);
+ if (!args.srcInfo.FILES) {
+ _1.logger.error("Invalid source files, abort");
+ return process.exit();
+ }
+ for (var key in args.srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(args.srcInfo, key)) {
+ args.variables['SRC_' + key] = args.srcInfo[key];
+ }
+ }
+ if (argv.dst) {
+ args.dst = path.resolve(args.dst);
+ args.dstInfo = osr_cli_commons_1.pathInfo(args.dst);
+ args.dstInfo.PATH = path.resolve(argv.dst);
+ for (var key in args.dstInfo) {
+ if (Object.prototype.hasOwnProperty.call(args.dstInfo, key)) {
+ args.variables['DST_' + key] = args.dstInfo[key];
+ }
+ }
+ }
+ // check for single file direct conversion
+ if (!args.dstInfo.IS_GLOB && !args.format && args.dstInfo.IS_GLOB) {
+ // args.format = [dstParts.ext.replace('*', '')]
+ }
+ return args;
+};
+// Sanitizes faulty user argv options for all commands.
+exports.sanitize = function (argv) {
+ var src = path.resolve('' + argv.src);
+ var config = argv.config ? read_1.sync(path.resolve('' + argv.config), 'json') : {};
+ /*
+
+ const extraVariables = {};
+ for (const key in config) {
+ if (Object.prototype.hasOwnProperty.call(config, key)) {
+ const element = config[key];
+ if (typeof element === 'string') {
+ extraVariables[key] = element;
+ }
+ }
+ }
+ const args: Options = {
+ src: src,
+ dst: '' + argv.dst as string,
+ report: argv.report ? path.resolve(argv.report as string) : null,
+ debug: argv.debug,
+ verbose: argv.verbose,
+ dry: argv.dry,
+ skip: argv.skip,
+ alt: argv.alt,
+ glob: argv.glob as string,
+ script: argv.script || 'export.cmd',
+ sw: argv.sw || 2022,
+ variables: {
+ ...extraVariables
+ },
+ args: argv.args || '',
+ hash: argv.hash,
+ "bom-config": argv['bom-config'],
+ "bom-detail": argv['bom-detail'],
+ "bom-template": argv['bom-template'],
+ "bom-type": argv['bom-type'],
+ "bom-images": argv['bom-images'],
+ } as Options;
+
+
+ if (!args.src) {
+ logger.error('Invalid source, abort');
+ return process.exit();
+ }
+
+ if (argv.format) {
+ if (typeof argv.format === 'string') {
+ args.format = [argv.format];
+ } else if (argv.source && isArray(argv.format)) {
+ args.format = argv.format;
+ }
+ }
+
+ args.srcInfo = pathInfo(argv.src as string);
+
+ if (!args.srcInfo.FILES) {
+ logger.error(`Invalid source files, abort`, args.srcInfo);
+ return process.exit();
+ }
+
+ for (const key in args.srcInfo) {
+ if (Object.prototype.hasOwnProperty.call(args.srcInfo, key)) {
+ args.variables['SRC_' + key] = args.srcInfo[key];
+ }
+ }
+
+ if (argv.dst) {
+ args.dst = path.resolve(substitute(args.dst, args.variables));
+ args.dstInfo = pathInfo(args.dst as string);
+ args.dstInfo.PATH = argv.dst as string;
+
+ for (const key in args.dstInfo) {
+ if (Object.prototype.hasOwnProperty.call(args.dstInfo, key)) {
+ args.variables['DST_' + key] = args.dstInfo[key];
+ }
+ }
+ }
+
+ (args as SolidworkOptions).view = argv.view as string || "Isometric";
+
+ // check for single file direct conversion
+ if (!args.dstInfo.IS_GLOB && !args.format && args.dstInfo.IS_GLOB) {
+ // args.format = [dstParts.ext.replace('*', '')]
+ }
+ */
+ // return args;
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJndi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9hcmd2LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7O0FBQ0EsMkJBQTZCO0FBRTdCLHVCQUdZO0FBQ1osK0RBQXNEO0FBQ3RELDRDQUFrRDtBQUdsRCxtQ0FBbUM7QUFDdEIsUUFBQSxjQUFjLEdBQUcsVUFBQyxLQUFlO0lBQzFDLE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDdkIsT0FBTyxFQUFFLElBQUk7UUFDYixRQUFRLEVBQUUsa0VBQWtFO1FBQzVFLFlBQVksRUFBRSxJQUFJO0tBQ3JCLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1FBQ2hCLFFBQVEsRUFBRSx3RkFBd0Y7S0FDckcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUU7UUFDYixRQUFRLEVBQUUsNEJBQTRCO0tBQ3pDLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1FBQ2QsT0FBTyxFQUFFLFdBQVc7UUFDcEIsUUFBUSxFQUFFLHNCQUFzQjtLQUNuQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtRQUNoQixRQUFRLEVBQUUsZ0VBQWdFO0tBQzdFLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1FBQ2YsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsZ0NBQWdDO1FBQzFDLElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2IsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUseUNBQXlDO1FBQ25ELElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1FBQ2QsT0FBTyxFQUFFLElBQUk7UUFDYixRQUFRLEVBQUUscUJBQXFCO1FBQy9CLElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFO1FBQ2IsT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsd0JBQXdCO1FBQ2xDLElBQUksRUFBRSxTQUFTO0tBQ2xCLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFO1FBQ2pCLE9BQU8sRUFBRSxJQUFJO1FBQ2IsUUFBUSxFQUFFLHdCQUF3QjtRQUNsQyxJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRTtRQUNaLFFBQVEsRUFBRTs2RUFDMkQ7UUFDckUsT0FBTyxFQUFFLE1BQU07S0FDbEIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUU7UUFDaEIsUUFBUSxFQUFFLGdEQUFnRDtLQUM3RCxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRTtRQUNkLFFBQVEsRUFBRTtpREFDK0I7UUFDekMsT0FBTyxFQUFFLElBQUk7UUFDYixJQUFJLEVBQUUsU0FBUztLQUNsQixDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRTtRQUNwQixRQUFRLEVBQUUsd0NBQXdDO1FBQ2xELE9BQU8sRUFBRSxTQUFTO0tBQ3JCLENBQUMsQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFO1FBQ3RCLFFBQVEsRUFBRSxtRUFBbUU7S0FDaEYsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7UUFDbEIsUUFBUSxFQUFFLDBFQUEwRTtRQUNwRixJQUFJLEVBQUUsUUFBUTtRQUNkLE9BQU8sRUFBRSxDQUFDO0tBQ2IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUU7UUFDcEIsUUFBUSxFQUFFLGtHQUFrRztRQUM1RyxJQUFJLEVBQUUsUUFBUTtRQUNkLE9BQU8sRUFBRSxDQUFDO0tBQ2IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUU7UUFDcEIsUUFBUSxFQUFFLGlDQUFpQztRQUMzQyxJQUFJLEVBQUUsU0FBUztRQUNmLE9BQU8sRUFBRSxLQUFLO0tBQ2pCLENBQUMsQ0FBQTtBQUNOLENBQUMsQ0FBQztBQUVGLHVEQUF1RDtBQUMxQyxRQUFBLGNBQWMsR0FBRyxVQUFDLElBQW1CO0lBRTlDLElBQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN4QyxJQUFNLE1BQU0sR0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxXQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEYsSUFBTSxjQUFjLEdBQUcsRUFBRSxDQUFDO0lBQzFCLEtBQUssSUFBTSxHQUFHLElBQUksTUFBTSxFQUFFO1FBQ3RCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNuRCxJQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDNUIsSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUU7Z0JBQzdCLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUM7YUFDakM7U0FDSjtLQUNKO0lBQ0QsSUFBTSxJQUFJLEdBQVk7UUFDbEIsR0FBRyxFQUFFLEdBQUc7UUFDUixHQUFHLEVBQUUsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFhO1FBQzVCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7UUFDaEUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO1FBQ2pCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztRQUNyQixHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7UUFDYixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7UUFDZixHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7UUFDYixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQWM7UUFDekIsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFO1FBQ1gsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLElBQUksVUFBVTtRQUNqQyxTQUFTLGVBQ0YsY0FBYyxDQUNwQjtRQUNELElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUU7UUFDckIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO0tBQ1AsQ0FBQztJQUViLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ1gsU0FBTSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0tBQ3pCO0lBRUQsSUFBSSxDQUFDLE9BQU8sR0FBRywwQkFBUSxDQUFDLElBQUksQ0FBQyxHQUFhLENBQUMsQ0FBQztJQUU1QyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUU7UUFDckIsU0FBTSxDQUFDLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBQzVDLE9BQU8sT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0tBQ3pCO0lBRUQsS0FBSyxJQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFO1FBQzVCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDekQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNwRDtLQUNKO0lBRUQsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFO1FBQ1YsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNsQyxJQUFJLENBQUMsT0FBTyxHQUFHLDBCQUFRLENBQUMsSUFBSSxDQUFDLEdBQWEsQ0FBQyxDQUFDO1FBQzVDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQWEsQ0FBQyxDQUFDO1FBRXJELEtBQUssSUFBTSxHQUFHLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUM1QixJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxFQUFFO2dCQUN6RCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ3BEO1NBQ0o7S0FDSjtJQUVELDBDQUEwQztJQUMxQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFO1FBQy9ELGdEQUFnRDtLQUNuRDtJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2hCLENBQUMsQ0FBQztBQUVGLHVEQUF1RDtBQUMxQyxRQUFBLFFBQVEsR0FBRyxVQUFDLElBQW1CO0lBRXhDLElBQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUV4QyxJQUFNLE1BQU0sR0FBUSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxXQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O01BZ0ZFO0lBQ0YsZUFBZTtBQUNuQixDQUFDLENBQUMifQ==
\ No newline at end of file
diff --git a/packages/vfs/argv.js.map b/packages/vfs/argv.js.map
new file mode 100644
index 00000000..3e1a90b5
--- /dev/null
+++ b/packages/vfs/argv.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"argv.js","sourceRoot":"","sources":["src/argv.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/packages/vfs/commands/info.js b/packages/vfs/commands/info.js
new file mode 100644
index 00000000..f969bf09
--- /dev/null
+++ b/packages/vfs/commands/info.js
@@ -0,0 +1,52 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (_) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.register = void 0;
+var argv_1 = require("../argv");
+var options = function (yargs) { return argv_1.defaultOptions(yargs); };
+exports.register = function (cli) {
+ return cli.command('info', 'basic env info', options, function (argv) { return __awaiter(void 0, void 0, void 0, function () {
+ return __generator(this, function (_a) {
+ if (argv.help) {
+ return [2 /*return*/];
+ }
+ return [2 /*return*/];
+ });
+ }); });
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5mby5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9jb21tYW5kcy9pbmZvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVBLGdDQUFrRDtBQUVsRCxJQUFJLE9BQU8sR0FBRyxVQUFDLEtBQWUsSUFBSyxPQUFBLHFCQUFjLENBQUMsS0FBSyxDQUFDLEVBQXJCLENBQXFCLENBQUE7QUFFM0MsUUFBQSxRQUFRLEdBQUcsVUFBQyxHQUFhO0lBQ2xDLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLFVBQU8sSUFBbUI7O1lBQzVFLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtnQkFBRSxzQkFBTzthQUFFOzs7U0FFN0IsQ0FBQyxDQUFBO0FBQ04sQ0FBQyxDQUFBIn0=
\ No newline at end of file
diff --git a/packages/vfs/constants.js b/packages/vfs/constants.js
new file mode 100644
index 00000000..b2d38d40
--- /dev/null
+++ b/packages/vfs/constants.js
@@ -0,0 +1,6 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.PACKAGE_NAME = exports.MODULE_NAME = void 0;
+exports.MODULE_NAME = "OSR-VFS";
+exports.PACKAGE_NAME = 'osr-vfs';
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3JjL2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBYSxRQUFBLFdBQVcsR0FBRyxTQUFTLENBQUE7QUFDdkIsUUFBQSxZQUFZLEdBQUcsU0FBUyxDQUFBIn0=
\ No newline at end of file
diff --git a/packages/vfs/constants.js.map b/packages/vfs/constants.js.map
new file mode 100644
index 00000000..d298b439
--- /dev/null
+++ b/packages/vfs/constants.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"constants.js","sourceRoot":"","sources":["src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,SAAS,CAAA;AACvB,QAAA,YAAY,GAAG,SAAS,CAAA"}
\ No newline at end of file
diff --git a/packages/vfs/index.js b/packages/vfs/index.js
new file mode 100644
index 00000000..4cbb0825
--- /dev/null
+++ b/packages/vfs/index.js
@@ -0,0 +1,20 @@
+"use strict";
+var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
+}) : (function(o, m, k, k2) {
+ if (k2 === undefined) k2 = k;
+ o[k2] = m[k];
+}));
+var __exportStar = (this && this.__exportStar) || function(m, exports) {
+ for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.logger = void 0;
+__exportStar(require("./types"), exports);
+__exportStar(require("./_cli"), exports);
+__exportStar(require("./argv"), exports);
+var debug_1 = require("@plastichub/core/debug");
+var constants_1 = require("./constants");
+exports.logger = debug_1.logger(constants_1.MODULE_NAME);
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQUFBLDBDQUF1QjtBQUN2Qix5Q0FBc0I7QUFDdEIseUNBQXNCO0FBRXRCLGdEQUEwRDtBQUMxRCx5Q0FBeUM7QUFFNUIsUUFBQSxNQUFNLEdBQUcsY0FBTyxDQUFDLHVCQUFXLENBQUMsQ0FBQSJ9
\ No newline at end of file
diff --git a/packages/vfs/index.js.map b/packages/vfs/index.js.map
new file mode 100644
index 00000000..4c79cf50
--- /dev/null
+++ b/packages/vfs/index.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,wCAAsB;AACtB,0CAAwB;AACxB,0BAA0B;AAC1B,+CAA6B;AAC7B,yCAAuB;AACvB,yCAAuB;AAGvB,gDAA0D;AAC1D,yCAAyC;AAE5B,QAAA,MAAM,GAAG,cAAO,CAAC,uBAAW,CAAC,CAAA;AAE1C,yCAAgH;AAEnG,QAAA,UAAU,GAAG,UAAC,GAAW,EAAE,QAAe,EAAE,IAAmB,IAAK,OAAA,GAAG,CAAC,CAAC,CAAC,oBAAc,CAAC,QAAQ,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC,iBAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAjE,CAAiE,CAAA"}
\ No newline at end of file
diff --git a/packages/vfs/main.js b/packages/vfs/main.js
new file mode 100644
index 00000000..874b107f
--- /dev/null
+++ b/packages/vfs/main.js
@@ -0,0 +1,18 @@
+#!/usr/bin/env node
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+var _cli_1 = require("./_cli");
+_cli_1.defaults();
+var cli = require("yargs");
+var info_1 = require("./commands/info");
+info_1.register(cli);
+var argv = cli.argv;
+if (argv.h || argv.help) {
+ cli.showHelp();
+ process.exit();
+}
+else if (argv.v || argv.version) {
+ // tslint:disable-next-line:no-var-requires
+ process.exit();
+}
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLCtCQUFrQztBQUFDLGVBQVEsRUFBRSxDQUFBO0FBRTdDLDJCQUE0QjtBQUM1Qix3Q0FBMkQ7QUFBQyxlQUFZLENBQUMsR0FBRyxDQUFDLENBQUE7QUFFN0UsSUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztBQUV0QixJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtJQUNyQixHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDZixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7Q0FDbEI7S0FBTSxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtJQUMvQiwyQ0FBMkM7SUFDM0MsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0NBQ2xCIn0=
\ No newline at end of file
diff --git a/packages/vfs/main.js.map b/packages/vfs/main.js.map
new file mode 100644
index 00000000..d75166e1
--- /dev/null
+++ b/packages/vfs/main.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"main.js","sourceRoot":"","sources":["src/main.ts"],"names":[],"mappings":";;;AACA,+BAAkC;AAAC,eAAQ,EAAE,CAAC;AAE9C,2BAA6B;AAC7B,oCAAuD;AAAC,aAAU,CAAC,GAAG,CAAC,CAAC;AACxE,wCAA2D;AAAC,eAAY,CAAC,GAAG,CAAC,CAAC;AAE9E,IAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;AAEtB,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE;IACrB,GAAG,CAAC,QAAQ,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,EAAE,CAAC;CAClB;KAAM,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE;IAC/B,2CAA2C;IAC3C,OAAO,CAAC,IAAI,EAAE,CAAC;CAClB"}
\ No newline at end of file
diff --git a/packages/vfs/package-lock.json b/packages/vfs/package-lock.json
new file mode 100644
index 00000000..1d7c723b
--- /dev/null
+++ b/packages/vfs/package-lock.json
@@ -0,0 +1,8098 @@
+{
+ "name": "@plastichub/osr-vfs",
+ "version": "0.0.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "@plastichub/osr-vfs",
+ "version": "0.0.1",
+ "license": "ISC",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.39",
+ "@plastichub/osr-cache": "^0.3.8",
+ "@plastichub/osr-commons": "file:../osr-commons",
+ "@plastichub/osr-sync": "^0.1.8",
+ "@types/cacache": "^15.0.1",
+ "@types/is-glob": "^4.0.1",
+ "@types/ssh2-sftp-client": "^9.0.0",
+ "add": "^2.0.6",
+ "axios": "^0.21.1",
+ "bluebird": "^3.7.2",
+ "cacache": "^17.0.5",
+ "duration-timestamp": "^2.3.0",
+ "errlop": "^2.1.0",
+ "escape-html": "^1.0.3",
+ "fast-glob": "^3.1.1",
+ "filenamify": "^4.1.0",
+ "glob-base": "^0.3.0",
+ "is-glob": "^4.0.1",
+ "md5": "^2.3.0",
+ "moment": "^2.30.1",
+ "native-promise-pool": "^3.0.0",
+ "parse-glob": "^2.0.1",
+ "regexp.escape": "^1.1.0",
+ "sanitize-filename": "^1.6.3",
+ "slash": "^3.0.0",
+ "slugify": "^1.4.6",
+ "source-map-support": "^0.5.16",
+ "ssh2-sftp-client": "^9.0.4",
+ "tslint": "^5.10.0",
+ "typescript": "^3.9.10",
+ "which": "^2.0.2",
+ "yargonaut": "^1.1.4",
+ "yargs": "^15.4.1"
+ },
+ "bin": {
+ "osr-vfs": "main.js"
+ },
+ "devDependencies": {
+ "@bevry/links": "^1.2.0",
+ "@bevry/update-contributors": "^1.23.0",
+ "@types/moment": "^2.13.0",
+ "@types/node": "^13.13.52",
+ "@types/node-fetch": "^2.6.12",
+ "@types/pretty": "^2.0.3",
+ "@types/which": "^1.3.2",
+ "@types/yargs": "^13.0.12",
+ "@typescript-eslint/eslint-plugin": "^2.34.0",
+ "@typescript-eslint/parser": "^2.34.0",
+ "assert-helpers": "^6.19.0",
+ "eslint": "^6.8.0",
+ "eslint-config-bevry": "^3.29.0",
+ "eslint-config-prettier": "^6.15.0",
+ "eslint-plugin-prettier": "^3.4.1",
+ "prettier": "^2.8.8"
+ }
+ },
+ "../osr-commons": {
+ "name": "@plastichub/osr-commons",
+ "version": "0.5.3",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.6",
+ "@plastichub/fs": "^0.13.41",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "fast-glob": "^3.3.2",
+ "filenamify": "^4.3.0",
+ "glob": "^11.0.0",
+ "is-glob": "^4.0.3",
+ "parse-glob": "^3.0.4",
+ "sanitize-filename": "^1.6.3",
+ "tslog": "^4.9.3",
+ "typescript": "^5.6.3",
+ "yargs": "^17.7.2",
+ "zod": "^3.24.1",
+ "zod-to-json-schema": "^3.23.5",
+ "zod-to-ts": "^1.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^22.12.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.21.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz",
+ "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==",
+ "dependencies": {
+ "@babel/highlight": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.19.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
+ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bevry/fs-accessible": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@bevry/fs-accessible/-/fs-accessible-2.5.0.tgz",
+ "integrity": "sha512-26z3V6kklpPRQ8M4U4zSRWMgMztsYVxBWM95ZNkFqeMsbNEQoUy8KnxmauhqKHG8FGODd/5hZN4N9fkajJLGYQ==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.21.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-mkdirp": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@bevry/fs-mkdirp/-/fs-mkdirp-1.6.0.tgz",
+ "integrity": "sha512-7oSExHck8ccH13BsZlS5yPHQsitndAlwefIYqohA2tnxWwiNHfQ7glMZtfVKZ633rWyA6azHDei/6Q86deYJ9Q==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/fs-accessible": "^2.5.0",
+ "editions": "^6.21.0",
+ "errlop": "^8.4.0",
+ "version-compare": "^3.10.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-mkdirp/node_modules/errlop": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-8.4.0.tgz",
+ "integrity": "sha512-uTI5IgHMfsuBw9t/NWnKGKGbkMxMfDLceci9Um8Qxe33WqZeBk3IX7ndOBT1Bpo+RRyDBI67KOOb3DYPJwoqyg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.20.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-read": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@bevry/fs-read/-/fs-read-1.6.0.tgz",
+ "integrity": "sha512-ZgF2UdsY4ZiWLaJETFy/JeQu0xH+Xjo60G1gDRc5wzUPllFhFhgbxuqQbfT6+YTn/wpFBzmqsb5+YFJbZdJQ9Q==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/fs-accessible": "^2.5.0",
+ "editions": "^6.21.0",
+ "errlop": "^8.4.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-read/node_modules/errlop": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-8.4.0.tgz",
+ "integrity": "sha512-uTI5IgHMfsuBw9t/NWnKGKGbkMxMfDLceci9Um8Qxe33WqZeBk3IX7ndOBT1Bpo+RRyDBI67KOOb3DYPJwoqyg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.20.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-unlink": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@bevry/fs-unlink/-/fs-unlink-1.6.0.tgz",
+ "integrity": "sha512-QgBbjuhIj4Egc6Anfb9WKJnHTHFGdmznMp19vCHuaT0qEU+2bGLDxQnTbc+mjDUADGY2rXhcSHdeM3euPUE0xA==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/fs-accessible": "^2.5.0",
+ "editions": "^6.21.0",
+ "errlop": "^8.4.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-unlink/node_modules/errlop": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-8.4.0.tgz",
+ "integrity": "sha512-uTI5IgHMfsuBw9t/NWnKGKGbkMxMfDLceci9Um8Qxe33WqZeBk3IX7ndOBT1Bpo+RRyDBI67KOOb3DYPJwoqyg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.20.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-write": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@bevry/fs-write/-/fs-write-1.6.0.tgz",
+ "integrity": "sha512-LldYhDchtX/RY5sg+bloJVhrfHQ/gBzL/4iPD+94zdA31P2xO69B+PJCsgOOrvhejMiPmAhSA5zsoxOGi1Q0Hw==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/fs-accessible": "^2.5.0",
+ "@bevry/fs-mkdirp": "^1.6.0",
+ "editions": "^6.21.0",
+ "errlop": "^8.4.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/fs-write/node_modules/errlop": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-8.4.0.tgz",
+ "integrity": "sha512-uTI5IgHMfsuBw9t/NWnKGKGbkMxMfDLceci9Um8Qxe33WqZeBk3IX7ndOBT1Bpo+RRyDBI67KOOb3DYPJwoqyg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.20.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/github-api": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/@bevry/github-api/-/github-api-10.2.0.tgz",
+ "integrity": "sha512-jmTi25/DumuTbKBSZTrGTnZD2HFOfx6CaJYLxF7jZmlyKmifXPbXAt/Aia9CCAbDBmc1tI4KyN4YYiNEMuGaeg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/wait": "^2.1.0",
+ "simplytyped": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/github-contributors": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@bevry/github-contributors/-/github-contributors-4.2.0.tgz",
+ "integrity": "sha512-dsp9nnmsBdCD3k68pYmVPdskqDF9ZcriydbytIqnoR74Aji5vX0X5/CiLvB0Y6wOz+/tlztMDK2Q5fXMStNfzQ==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/github-api": "^10.2.0",
+ "@bevry/github-repos": "^7.0.0",
+ "fellow": "^6.25.0",
+ "native-promise-pool": "^3.23.0",
+ "simplytyped": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/github-repos": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/@bevry/github-repos/-/github-repos-7.0.0.tgz",
+ "integrity": "sha512-Io8uu1TJmfojkMeHEuURjPRbqHeIkHCzU5kxvaOYU9T09KTPCG7eF04E9rQlaFG7mI/Vov9cG3n1XUh43x2GpQ==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/github-api": "^10.0.0",
+ "@bevry/list": "^1.7.0",
+ "native-promise-pool": "^3.19.0",
+ "simplytyped": "^3.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/json": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@bevry/json/-/json-1.10.0.tgz",
+ "integrity": "sha512-OdAglhqfMDeetuUqZHJe40+sKfWDSbamKimwTyv7eJu6ODWvVJNzi20V7RkgYmzeifODX0rNwCBmPn9b+j54MA==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/fs-read": "^1.1.0",
+ "@bevry/fs-unlink": "^1.1.0",
+ "@bevry/fs-write": "^1.1.0",
+ "errlop": "^7.3.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/json/node_modules/errlop": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-7.5.0.tgz",
+ "integrity": "sha512-a+Gfi8cGPEydVJ61AAflAldvShSW1zoELe39O6fOOi2QBCC9/+kIaNphyg6BIEXZ6fTSvEJBwDG6OeBYiXjZwg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.16.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/links": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@bevry/links/-/links-1.2.0.tgz",
+ "integrity": "sha512-/zEI5jDi8C8cdldjnz4UQmDMExwshP8i+8nYypHFCcVHGEvga42xKbVzzZ9i415i8IqaHBT/j/Z00mN6I5Ji+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/list": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@bevry/list/-/list-1.8.0.tgz",
+ "integrity": "sha512-qkLuLrM+AO2XDX87pySdRX31qXeB0jDBEL0PfY+LJSV56QhfDS1PGrqkCz4Ux+/eq/PfiQ/2hQhNgOHGb2HvSw==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/update-contributors": {
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@bevry/update-contributors/-/update-contributors-1.23.0.tgz",
+ "integrity": "sha512-H3bWFAhZMa22IHMzlyE+JAou7n1ONsrs72Yv6Tt9V5+E/CYAltfQWz/8YJtu2/yEay3LqaW1FSAtvzQiXRu2yg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "@bevry/github-contributors": "^4.1.0",
+ "@bevry/json": "^1.5.0"
+ },
+ "bin": {
+ "update-contributors": "bin.cjs"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@bevry/wait": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@bevry/wait/-/wait-2.6.0.tgz",
+ "integrity": "sha512-RswBYspXtm6WoyMsRbsITxqmMCIa6SJ8kZOMeN303kcD/6dda9KJbEd/Hl1Ft7GXaagr4LeGihRlQ7FvgBD2+g==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz",
+ "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
+ "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
+ "deprecated": "This functionality has been moved to @npmcli/fs",
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@plastichub/core": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@plastichub/core/-/core-0.2.6.tgz",
+ "integrity": "sha512-DF2IUZu6cw8+iVnFv2BFvd+s/7DYfrfXh7o3Uhg0IjbZ/QOIXY21URarnMQoTl9NEwUKN8ZZIHJmOIulT8helg==",
+ "license": "BSD",
+ "dependencies": {
+ "deepmerge": "^4.3.1",
+ "tslog": "^3.3.3"
+ }
+ },
+ "node_modules/@plastichub/fs": {
+ "version": "0.13.39",
+ "resolved": "https://registry.npmjs.org/@plastichub/fs/-/fs-0.13.39.tgz",
+ "integrity": "sha512-Q96zN5LAlTmtj6gIbHbVM0erp2NgP+P4izRzdhqnMz/WopAvD7ZJxjQ/J44e67R6WKQuvcxt/eXPNaFBB5ehlg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.1",
+ "@types/denodeify": "^1.2.31",
+ "@types/glob": "^8.1.0",
+ "@types/minimatch": "^3.0.3",
+ "@types/node": "^14.18.63",
+ "denodeify": "^1.2.1",
+ "errno": "^0.1.4",
+ "glob": "^10.4.1",
+ "mime": "^2.0.3",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "progress-stream": "^1.2.0",
+ "q": "^1.4.1",
+ "rimraf": "^2.7.1",
+ "throttle": "^1.0.3",
+ "trash": "^4.3.0",
+ "typescript": "^4.0.3",
+ "write-file-atomic": "^1.3.1",
+ "yargs": "^17.7.2"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/@types/node": {
+ "version": "14.18.63",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
+ "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
+ "license": "MIT"
+ },
+ "node_modules/@plastichub/fs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/@plastichub/fs/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/fs/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-cache": {
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-cache/-/osr-cache-0.3.8.tgz",
+ "integrity": "sha512-yuUZzsaCCReqq7nziaYrqwLyOhP61LtD9t9/I0lFnjDST13Dz1pmfXZP4/uIIeja0V3kX/0ReFrhjIIjb4wPVw==",
+ "dependencies": {
+ "@plastichub/core": "^0.2.0",
+ "@plastichub/fs": "^0.13.32",
+ "@plastichub/osr-cli-commons": "^0.2.2",
+ "@types/cacache": "^15.0.1",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.2",
+ "cacache": "^17.0.3",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "env-var": "^7.0.1",
+ "md5": "^2.3.0",
+ "typescript": "^4.3.5",
+ "yargs": "^14.2.3",
+ "yargs-parser": "^15.0.3"
+ },
+ "bin": {
+ "osr-cache": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/@types/node": {
+ "version": "14.18.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.43.tgz",
+ "integrity": "sha512-n3eFEaoem0WNwLux+k272P0+aq++5o05bA9CfiwKPdYPB5ZambWKdWoeHy7/OJiizMhzg27NLaZ6uzjLTzXceQ=="
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/@types/yargs": {
+ "version": "17.0.24",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
+ "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dependencies": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@plastichub/osr-cache/node_modules/yargs": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+ "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
+ "dependencies": {
+ "cliui": "^5.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.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": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^15.0.1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-cli-commons/-/osr-cli-commons-0.2.9.tgz",
+ "integrity": "sha512-dAR0kYH6Y8vBrIIXkMldzSdugFfRYU/FgnyNuCY6iR2Wh8tqCGZQDJ/sZwuvk1OaLfGj9+ejAb1iHveMjKB0zQ==",
+ "dependencies": {
+ "@plastichub/core": "^0.2.0",
+ "@plastichub/fs": "^0.13.30",
+ "@plastichub/osr-commons": "^0.1.6",
+ "@types/cacache": "^15.0.1",
+ "@types/node": "^14.17.5",
+ "@types/yargs": "^17.0.2",
+ "cacache": "^16.1.2",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "fast-glob": "^3.2.11",
+ "glob-base": "^0.3.0",
+ "is-glob": "^4.0.3",
+ "parse-glob": "^3.0.4",
+ "rage-edit": "^1.2.0",
+ "typescript": "^4.3.5",
+ "yargs": "^17.5.1"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@npmcli/fs": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
+ "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
+ "dependencies": {
+ "@gar/promisify": "^1.1.3",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@plastichub/osr-commons": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-commons/-/osr-commons-0.1.8.tgz",
+ "integrity": "sha512-wlsol/kSOtGZYRcTPPv3WMhtH5nWckFjv7mSfLrXPTKR9yBHn/j1ZTeUEI8qe0899VKJdtobH5KkkYMpmvnZCg==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@plastichub/core": "^0.2.0",
+ "@plastichub/fs": "^0.13.32",
+ "axios": "^0.27.2",
+ "chalk": "^2.4.1",
+ "convert-units": "^2.3.4",
+ "cryptr": "^6.0.3",
+ "env-var": "^7.1.1",
+ "filenamify": "^4.3.0",
+ "querystring": "^0.2.1",
+ "sanitize-filename": "^1.6.3",
+ "shell-escape": "^0.2.0",
+ "tslog": "^3.3.3",
+ "typescript": "^4.3.5",
+ "yargs": "^17.5.1"
+ },
+ "bin": {
+ "osr-commons": "main.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@types/node": {
+ "version": "14.18.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.43.tgz",
+ "integrity": "sha512-n3eFEaoem0WNwLux+k272P0+aq++5o05bA9CfiwKPdYPB5ZambWKdWoeHy7/OJiizMhzg27NLaZ6uzjLTzXceQ=="
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/@types/yargs": {
+ "version": "17.0.24",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
+ "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/axios": {
+ "version": "0.27.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
+ "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.14.9",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/cacache": {
+ "version": "16.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
+ "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
+ "dependencies": {
+ "@npmcli/fs": "^2.1.0",
+ "@npmcli/move-file": "^2.0.0",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.1.0",
+ "glob": "^8.0.1",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^7.7.1",
+ "minipass": "^3.1.6",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "mkdirp": "^1.0.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^9.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==",
+ "dependencies": {
+ "glob-base": "^0.3.0",
+ "is-dotfile": "^1.0.0",
+ "is-extglob": "^1.0.0",
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/parse-glob/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf/node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/rimraf/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/ssri": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
+ "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/unique-filename": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
+ "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
+ "dependencies": {
+ "unique-slug": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/unique-slug": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
+ "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-cli-commons/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-commons": {
+ "resolved": "../osr-commons",
+ "link": true
+ },
+ "node_modules/@plastichub/osr-sync": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/@plastichub/osr-sync/-/osr-sync-0.1.8.tgz",
+ "integrity": "sha512-+VVSQFz5GA5Ht+oN14O/TkvJRyxsUBIVhNi9EUBIpoCWa5qCYHS7JTws92Odo7nXFHgze079hlHtb0cEVQpxQQ==",
+ "dependencies": {
+ "@plastichub/fs": "^0.13.31",
+ "@types/archiver": "^3.1.0",
+ "archiver": "^5.0.0",
+ "bluebird": "^3.5.1",
+ "escape-html": "^1.0.3",
+ "globby": "^6.1.0",
+ "googleapis": "^59.0.0",
+ "jsome": "^2.3.24",
+ "json2csv": "^5.0.1",
+ "lodash": "^4.16.6",
+ "markdown-table": "^2.0.0",
+ "mkdirp": "^0.5.1",
+ "ora": "^1.3.0",
+ "pkg-dir": "^2.0.0",
+ "q": "^1.4.1",
+ "showdown": "^1.9.1",
+ "tslib": "^1.8.1",
+ "typescript": "^4.7.4",
+ "yargonaut": "^1.1.2",
+ "yargs": "^17.0.1"
+ },
+ "bin": {
+ "osr-sync": "main.js"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@plastichub/osr-sync/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sindresorhus/df": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-2.1.0.tgz",
+ "integrity": "sha512-yozEsK3X8sEjh9fiolh3JntMUuGKe2n2t8gtE3yZ1PqAFFeaSxTrSiEVORy/YkPzUsxQ85RzLcGqmqSOgiFhtg==",
+ "dependencies": {
+ "execa": "^0.2.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/execa": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.2.2.tgz",
+ "integrity": "sha512-zmBGzLd3nhA/NB9P7VLoceAO6vyYPftvl809Vjwe5U2fYI9tYWbeKqP3wZlAw9WS+znnkogf/bhSU+Gcn2NbkQ==",
+ "dependencies": {
+ "cross-spawn-async": "^2.1.1",
+ "npm-run-path": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "path-key": "^1.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/npm-run-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz",
+ "integrity": "sha512-PrGAi1SLlqNvKN5uGBjIgnrTb8fl0Jz0a3JJmeMcGnIBh7UE9Gc4zsAMlwDajOMg2b1OgP6UPvoLUboTmMZPFA==",
+ "dependencies": {
+ "path-key": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@sindresorhus/df/node_modules/path-key": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-1.0.0.tgz",
+ "integrity": "sha512-T3hWy7tyXlk3QvPFnT+o2tmXRzU4GkitkUWLp/WZ0S/FXd7XMx176tRurgTvHTNMJOQzTcesHNpBqetH86mQ9g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@types/ansicolors": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/@types/ansicolors/-/ansicolors-0.0.33.tgz",
+ "integrity": "sha512-dVS1WW/BqYdwbv1H0Cgpq8ChV4VowUXz+R7pYKGEHhF+mdg/MibuE+6Et/GBxg6nfKKFVf2ZsQkyr7XNR2SqxA==",
+ "dev": true
+ },
+ "node_modules/@types/archiver": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-3.1.1.tgz",
+ "integrity": "sha512-TzVZ9204sH1TuFylfr1cw/AA/3/VldAAXswEwKLXUOzA9mDg+m6gHF9EaqKNlozcjc6knX5m1KAqJzksPLSEfw==",
+ "dependencies": {
+ "@types/glob": "*"
+ }
+ },
+ "node_modules/@types/cacache": {
+ "version": "15.0.1",
+ "resolved": "https://registry.npmjs.org/@types/cacache/-/cacache-15.0.1.tgz",
+ "integrity": "sha512-JhL2GFJuHMx4RMg4z0XfXB4ZkKdyiOaOLpjoYMXcyKfrkF3IBXNZBj6/Peo9zX/7PPHyfI63NWVD589cI2YTzg==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/denodeify": {
+ "version": "1.2.35",
+ "resolved": "https://registry.npmjs.org/@types/denodeify/-/denodeify-1.2.35.tgz",
+ "integrity": "sha512-5ixm6RMZKJUMlFKPZj378M/NOCGdodVVzvkYKlYbGp6mQ/r1C7C5KVroSTsZTI75qqmczZeOhhGywcWVURPMMw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-mIenTfsIe586/yzsyfql69KRnA75S8SVXQbTLpDejRrjH0QSJcpu3AUOi/Vjnt9IOsXKxPhJfGpQUNMueIU1fQ==",
+ "dev": true
+ },
+ "node_modules/@types/eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
+ "dev": true
+ },
+ "node_modules/@types/glob": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz",
+ "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==",
+ "dependencies": {
+ "@types/minimatch": "^5.1.2",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/glob/node_modules/@types/minimatch": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
+ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA=="
+ },
+ "node_modules/@types/is-glob": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/is-glob/-/is-glob-4.0.2.tgz",
+ "integrity": "sha512-4j5G9Y5jljDSICQ1R2f/Rcyoj6DZmYGneny+p/cDkjep0rkqNg0W73Ty0bVjMUTZgLXHf8oiMjg1XC3CDwCz+g=="
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+ "dev": true
+ },
+ "node_modules/@types/minimatch": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
+ "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
+ },
+ "node_modules/@types/moment": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/@types/moment/-/moment-2.13.0.tgz",
+ "integrity": "sha512-DyuyYGpV6r+4Z1bUznLi/Y7HpGn4iQ4IVcGn8zrr1P4KotKLdH0sbK1TFR6RGyX6B+G8u83wCzL+bpawKU/hdQ==",
+ "deprecated": "This is a stub types definition for Moment (https://github.com/moment/moment). Moment provides its own type definitions, so you don't need @types/moment installed!",
+ "dev": true,
+ "dependencies": {
+ "moment": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "13.13.52",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.52.tgz",
+ "integrity": "sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ=="
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz",
+ "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/@types/pretty": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/pretty/-/pretty-2.0.3.tgz",
+ "integrity": "sha512-xR96pShNlrxLd3gZqzCnbaAmbYhiRYjW51CDFjektZemqpBZBAAkMwxm4gBraJP/xSgKcsQhLXdlXOwDNWo4VQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/ssh2": {
+ "version": "1.11.11",
+ "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.11.11.tgz",
+ "integrity": "sha512-LdnE7UBpvHCgUznvn2fwLt2hkaENcKPFqOyXGkvyTLfxCXBN6roc1RmECNYuzzbHePzD3PaAov5rri9hehzx9Q==",
+ "dependencies": {
+ "@types/node": "^18.11.18"
+ }
+ },
+ "node_modules/@types/ssh2-sftp-client": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/@types/ssh2-sftp-client/-/ssh2-sftp-client-9.0.0.tgz",
+ "integrity": "sha512-TLrSS/GoU9UwGx9WqTPY/1zQL0TITLw+lmjcT+xGHGjozT+dS/ptwhh/FF1+rY0XJ2P715WDkL/e8yEOnoCR/g==",
+ "dependencies": {
+ "@types/ssh2": "*"
+ }
+ },
+ "node_modules/@types/ssh2/node_modules/@types/node": {
+ "version": "18.16.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.3.tgz",
+ "integrity": "sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q=="
+ },
+ "node_modules/@types/which": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.2.tgz",
+ "integrity": "sha512-8oDqyLC7eD4HM307boe2QWKyuzdzWBj56xI/imSl2cpL+U3tCMaTAkMJ4ee5JBZ/FsOJlvRGeIShiZDAl1qERA==",
+ "dev": true
+ },
+ "node_modules/@types/yargs": {
+ "version": "13.0.12",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz",
+ "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.0",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
+ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "2.34.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz",
+ "integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/experimental-utils": "2.34.0",
+ "functional-red-black-tree": "^1.0.1",
+ "regexpp": "^3.0.0",
+ "tsutils": "^3.17.1"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^2.0.0",
+ "eslint": "^5.0.0 || ^6.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/experimental-utils": {
+ "version": "2.34.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz",
+ "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/typescript-estree": "2.34.0",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^2.0.0"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "2.34.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz",
+ "integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint-visitor-keys": "^1.0.0",
+ "@typescript-eslint/experimental-utils": "2.34.0",
+ "@typescript-eslint/typescript-estree": "2.34.0",
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^5.0.0 || ^6.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "2.34.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz",
+ "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "eslint-visitor-keys": "^1.1.0",
+ "glob": "^7.1.6",
+ "is-glob": "^4.0.1",
+ "lodash": "^4.17.15",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/add": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/add/-/add-2.0.6.tgz",
+ "integrity": "sha512-j5QzrmsokwWWp6kUcJQySpbG+xfOBqqKnup3OIk1pz+kB/80SLorZ9V8zHFLO92Lcd+hbvq8bT+zOGoPkmBV0Q=="
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz",
+ "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ansicolors": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+ "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
+ "dev": true
+ },
+ "node_modules/archiver": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz",
+ "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==",
+ "dependencies": {
+ "archiver-utils": "^2.1.0",
+ "async": "^3.2.3",
+ "buffer-crc32": "^0.2.1",
+ "readable-stream": "^3.6.0",
+ "readdir-glob": "^1.0.0",
+ "tar-stream": "^2.2.0",
+ "zip-stream": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/archiver-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
+ "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
+ "dependencies": {
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.0",
+ "lazystream": "^1.0.0",
+ "lodash.defaults": "^4.2.0",
+ "lodash.difference": "^4.5.0",
+ "lodash.flatten": "^4.4.0",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.union": "^4.6.0",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/archiver-utils/node_modules/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=="
+ },
+ "node_modules/archiver-utils/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+ "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+ "dependencies": {
+ "array-uniq": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-uniq": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+ "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/arrify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
+ "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/assert-helpers": {
+ "version": "6.19.0",
+ "resolved": "https://registry.npmjs.org/assert-helpers/-/assert-helpers-6.19.0.tgz",
+ "integrity": "sha512-2YQ4fNEKXG83AGNgBEnX76z+t/IMlr3mwFQleDLmVQo3ccVeTHFmXFh88GpGhxYV9VEelkiqha1MRkHsuDgJMQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/ansicolors": "^0.0.33",
+ "@types/diff": "^4.0.2",
+ "@types/node": "^14.0.27",
+ "ansicolors": "^0.3.2",
+ "diff": "^4.0.2",
+ "errlop": "^3.14.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/assert-helpers/node_modules/@types/node": {
+ "version": "14.18.43",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.43.tgz",
+ "integrity": "sha512-n3eFEaoem0WNwLux+k272P0+aq++5o05bA9CfiwKPdYPB5ZambWKdWoeHy7/OJiizMhzg27NLaZ6uzjLTzXceQ==",
+ "dev": true
+ },
+ "node_modules/assert-helpers/node_modules/errlop": {
+ "version": "3.17.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-3.17.0.tgz",
+ "integrity": "sha512-TDlb+YMx08OiaLq1g7Hu0nDca/oLo+LpMEgEI2lybBKE1rB8qsqFgXzEbnn1LU6NfDCfIdVcl3073aO3ZLTYNg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "0.21.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+ "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+ "dependencies": {
+ "follow-redirects": "^1.14.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz",
+ "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ },
+ "node_modules/buildcheck": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz",
+ "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==",
+ "optional": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha512-wxXCdllwGhI2kCC0MnvTGYTMvnVZTvqgypkiTI8Pa5tcz2i6VqsqwYGgqwXji+4RgCzms6EajE4IxiUH6HH8nQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cacache": {
+ "version": "17.0.6",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.6.tgz",
+ "integrity": "sha512-ixcYmEBExFa/+ajIPjcwypxL97CjJyOsH9A/W+4qgEPIpJvKlC+HmVY8nkIck6n3PwUTdgq9c489niJGwl+5Cw==",
+ "dependencies": {
+ "@npmcli/fs": "^3.1.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^7.7.1",
+ "minipass": "^5.0.0",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/glob": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz",
+ "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.0.3",
+ "minimatch": "^9.0.0",
+ "minipass": "^5.0.0",
+ "path-scurry": "^1.7.0"
+ },
+ "bin": {
+ "glob": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/minimatch": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz",
+ "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+ "dev": true
+ },
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz",
+ "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/cliui/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cliui/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/code-point-at": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+ "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/compress-commons": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz",
+ "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==",
+ "dependencies": {
+ "buffer-crc32": "^0.2.13",
+ "crc32-stream": "^4.0.2",
+ "normalize-path": "^3.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/concat-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
+ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
+ "engines": [
+ "node >= 6.0"
+ ],
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.0.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/convert-units": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/convert-units/-/convert-units-2.3.4.tgz",
+ "integrity": "sha512-ERHfdA0UhHJp1IpwE6PnFJx8LqG7B1ZjJ20UvVCmopEnVCfER68Tbe3kvN63dLbYXDA2xFWRE6zd4Wsf0w7POg==",
+ "dependencies": {
+ "lodash.foreach": "2.3.x",
+ "lodash.keys": "2.3.x"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/cpu-features": {
+ "version": "0.0.7",
+ "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.7.tgz",
+ "integrity": "sha512-fjzFmsUKKCrC9GrM1eQTvQx18e+kjXFzjRLvJPNEDjk31+bJ6ZiV6uchv/hzbzXVIgbWdrEyyX1IFKwse65+8w==",
+ "hasInstallScript": true,
+ "optional": true,
+ "dependencies": {
+ "buildcheck": "~0.0.6",
+ "nan": "^2.17.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/crc-32": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
+ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
+ "bin": {
+ "crc32": "bin/crc32.njs"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/crc32-stream": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz",
+ "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==",
+ "dependencies": {
+ "crc-32": "^1.2.0",
+ "readable-stream": "^3.4.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/cross-spawn-async": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz",
+ "integrity": "sha512-snteb3aVrxYYOX9e8BabYFK9WhCDhTlw1YQktfTthBogxri4/2r9U2nQc0ffY73ZAxezDc+U8gvHAeU1wy1ubQ==",
+ "deprecated": "cross-spawn no longer requires a build toolchain, use it instead",
+ "dependencies": {
+ "lru-cache": "^4.0.0",
+ "which": "^1.2.8"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/cross-spawn-async/node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="
+ },
+ "node_modules/cross-spawn/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/cross-spawn/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cryptr": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/cryptr/-/cryptr-6.2.0.tgz",
+ "integrity": "sha512-jYi8SxvOFebTT7EYOABiPpHKY6lwWaP9IVcvT/aIVJUVoFdzTgi0ySPCL78q1ig8w2kwfXFCZACXoCXaye57aw=="
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/denodeify": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz",
+ "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg=="
+ },
+ "node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+ "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+ "dependencies": {
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/duration-timestamp": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/duration-timestamp/-/duration-timestamp-2.24.0.tgz",
+ "integrity": "sha512-P16Juw52IfAk7L/6ROVIsc1VFZvFIcyzyiIdYjJkQs+yfRVL2UiXQsKyQgn6wucMFvCZfcLzr1ANHES5D52New==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT"
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/editions": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/editions/-/editions-6.21.0.tgz",
+ "integrity": "sha512-ofkXJtn7z0urokN62DI3SBo/5xAtF0rR7tn+S/bSYV79Ka8pTajIIl+fFQ1q88DQEImymmo97M4azY3WX/nUdg==",
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "version-range": "^4.13.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/env-var": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/env-var/-/env-var-7.3.1.tgz",
+ "integrity": "sha512-Sq9qMnbBApv7SeUOKhw5GZ0VxAwltjFTzXTOvRV9NZEKmMCBZuFCumAvkXwBC5Fo396D7BnOpb5dXud7Vzhliw==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="
+ },
+ "node_modules/errlop": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz",
+ "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==",
+ "engines": {
+ "node": ">=0.8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/errno": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
+ "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+ "dependencies": {
+ "prr": "~1.0.1"
+ },
+ "bin": {
+ "errno": "cli.js"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.21.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
+ "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.0",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ },
+ "node_modules/escape-string-applescript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-applescript/-/escape-string-applescript-2.0.0.tgz",
+ "integrity": "sha512-Z7OsRJUi5+OHT89RRJlkS8cKxIh9AyPmgtEevsSQFCx5WLIiS3hy/HRiiQZzYQMsn6MWyCDZ5elBFa/9dxT0BA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
+ "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "ajv": "^6.10.0",
+ "chalk": "^2.1.0",
+ "cross-spawn": "^6.0.5",
+ "debug": "^4.0.1",
+ "doctrine": "^3.0.0",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^1.4.3",
+ "eslint-visitor-keys": "^1.1.0",
+ "espree": "^6.1.2",
+ "esquery": "^1.0.1",
+ "esutils": "^2.0.2",
+ "file-entry-cache": "^5.0.1",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^5.0.0",
+ "globals": "^12.1.0",
+ "ignore": "^4.0.6",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "inquirer": "^7.0.0",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^3.13.1",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.3.0",
+ "lodash": "^4.17.14",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.8.3",
+ "progress": "^2.0.0",
+ "regexpp": "^2.0.1",
+ "semver": "^6.1.2",
+ "strip-ansi": "^5.2.0",
+ "strip-json-comments": "^3.0.1",
+ "table": "^5.2.3",
+ "text-table": "^0.2.0",
+ "v8-compile-cache": "^2.0.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-bevry": {
+ "version": "3.29.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-bevry/-/eslint-config-bevry-3.29.0.tgz",
+ "integrity": "sha512-YMFtf6pP/icuWlaPIJD3Bziv83GU5ZRbdVtD1VMX1vVy7aW6YnzNmJvZM6Yn7EP+IaOci9UyNij2Fj6Hsp/yCA==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz",
+ "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==",
+ "dev": true,
+ "dependencies": {
+ "get-stdin": "^6.0.0"
+ },
+ "bin": {
+ "eslint-config-prettier-check": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=3.14.1"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz",
+ "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5.0.0",
+ "prettier": ">=1.13.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
+ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-utils": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
+ "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eslint/node_modules/regexpp": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
+ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.5.0"
+ }
+ },
+ "node_modules/eslint/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/espree": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
+ "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^7.1.1",
+ "acorn-jsx": "^5.2.0",
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/execa": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz",
+ "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==",
+ "dependencies": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/execa/node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+ },
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dev": true,
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.12",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-text-encoding": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz",
+ "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w=="
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fellow": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/fellow/-/fellow-6.25.0.tgz",
+ "integrity": "sha512-/eYuI5Cr9hi2Llw5VHIdiDQKe4cL4Qa1a9EE8NxuT/xa7KsfsnF7pBcYXIhmqSLxPbWS1ozF1vzYcN4VTf9OwA==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/figlet": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.6.0.tgz",
+ "integrity": "sha512-31EQGhCEITv6+hi2ORRPyn3bulaV9Fl4xOdR169cBzH/n1UqcxsiSB/noo6SJdD7Kfb1Ljit+IgR1USvF/XbdA==",
+ "bin": {
+ "figlet": "bin/index.js"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+ "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/filename-reserved-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
+ "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/filenamify": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
+ "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
+ "dependencies": {
+ "filename-reserved-regex": "^2.0.0",
+ "strip-outer": "^1.0.1",
+ "trim-repeated": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+ "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==",
+ "dependencies": {
+ "locate-path": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+ "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^2.0.0",
+ "rimraf": "2.6.3",
+ "write": "1.0.3"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/flat-cache/node_modules/rimraf": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
+ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
+ "dev": true
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz",
+ "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+ },
+ "node_modules/fs-extra": {
+ "version": "0.30.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
+ "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^2.1.0",
+ "klaw": "^1.0.0",
+ "path-is-absolute": "^1.0.0",
+ "rimraf": "^2.2.8"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz",
+ "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==",
+ "dependencies": {
+ "minipass": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gaxios": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.3.tgz",
+ "integrity": "sha512-gSaYYIO1Y3wUtdfHmjDUZ8LWaxJQpiavzbF5Kq53akSzvmVg0RfyOcFDbO1KJ/KCGRFz2qG+lS81F0nkr7cRJA==",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^5.0.0",
+ "is-stream": "^2.0.0",
+ "node-fetch": "^2.6.7"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/gcp-metadata": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz",
+ "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==",
+ "dependencies": {
+ "gaxios": "^4.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
+ "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-stdin": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz",
+ "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+ "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==",
+ "dependencies": {
+ "glob-parent": "^2.0.0",
+ "is-glob": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==",
+ "dependencies": {
+ "is-glob": "^2.0.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-base/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob-path-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/glob-path-regex/-/glob-path-regex-1.0.0.tgz",
+ "integrity": "sha512-UFhGeC2+YjfCfCvPmd3XZqHql7gmNt0xVFiK7l+dTETGWQiW+SyR5Ns5X3mpY9WSoB/wUI7+A8jkyfjZqZtjVA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
+ "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+ "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==",
+ "dependencies": {
+ "array-union": "^1.0.1",
+ "glob": "^7.0.3",
+ "object-assign": "^4.0.1",
+ "pify": "^2.0.0",
+ "pinkie-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/google-auth-library": {
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz",
+ "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==",
+ "dependencies": {
+ "arrify": "^2.0.0",
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "fast-text-encoding": "^1.0.0",
+ "gaxios": "^4.0.0",
+ "gcp-metadata": "^4.2.0",
+ "gtoken": "^5.0.4",
+ "jws": "^4.0.0",
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/google-auth-library/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/google-p12-pem": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.4.tgz",
+ "integrity": "sha512-HHuHmkLgwjdmVRngf5+gSmpkyaRI6QmOg77J8tkNBHhNEI62sGHyw4/+UkgyZEI7h84NbWprXDJ+sa3xOYFvTg==",
+ "dependencies": {
+ "node-forge": "^1.3.1"
+ },
+ "bin": {
+ "gp12-pem": "build/src/bin/gp12-pem.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/googleapis": {
+ "version": "59.0.0",
+ "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-59.0.0.tgz",
+ "integrity": "sha512-GV/E4KRN89a4GxSk7D7cwUfRYgcJHR05sOgm/WGdwc/u8dxNXG5lWmz9gF5ZwFGk2yKtVxL4VZNn4zBuZ6rmGg==",
+ "dependencies": {
+ "google-auth-library": "^6.0.0",
+ "googleapis-common": "^4.4.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/googleapis-common": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-4.4.3.tgz",
+ "integrity": "sha512-W46WKCk3QtlCCfmZyQIH5zxmDOyeV5Qj+qs7nr2ox08eRkEJMWp6iwv542R/PsokXaGUSrmif4vCC4+rGzRSsQ==",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "gaxios": "^4.0.0",
+ "google-auth-library": "^6.0.0",
+ "qs": "^6.7.0",
+ "url-template": "^2.0.8",
+ "uuid": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/gtoken": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz",
+ "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==",
+ "dependencies": {
+ "gaxios": "^4.0.0",
+ "google-p12-pem": "^3.1.3",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/inquirer": {
+ "version": "7.3.3",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
+ "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.19",
+ "mute-stream": "0.0.8",
+ "run-async": "^2.4.0",
+ "rxjs": "^6.6.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/inquirer/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inquirer/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/inquirer/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/inquirer/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/inquirer/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/inquirer/node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inquirer/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inquirer/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dependencies": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/invert-kv": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
+ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz",
+ "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
+ "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/jackspeak": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.1.tgz",
+ "integrity": "sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==",
+ "dependencies": {
+ "cliui": "^8.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jackspeak/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jackspeak/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jackspeak/node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jackspeak/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/jackspeak/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/jackspeak/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jackspeak/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsome": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/jsome/-/jsome-2.5.0.tgz",
+ "integrity": "sha512-QBjTpOA9MLO78hrR4V3S6FZpDRdsLhOxA9VZ5Qfum/h7pF/TkaTaq+yYZmWKrov8m+bV6wZgmBTf5m5J2805Pw==",
+ "dependencies": {
+ "chalk": "^2.3.0",
+ "json-stringify-safe": "^5.0.1",
+ "yargs": "^11.0.0"
+ },
+ "bin": {
+ "jsome": "bin/cli.js"
+ }
+ },
+ "node_modules/jsome/node_modules/ansi-regex": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz",
+ "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jsome/node_modules/camelcase": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
+ "integrity": "sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jsome/node_modules/cliui": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
+ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
+ "dependencies": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "node_modules/jsome/node_modules/get-caller-file": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
+ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
+ },
+ "node_modules/jsome/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jsome/node_modules/require-main-filename": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
+ "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug=="
+ },
+ "node_modules/jsome/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jsome/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jsome/node_modules/wrap-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+ "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==",
+ "dependencies": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsome/node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsome/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
+ "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsome/node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
+ "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsome/node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsome/node_modules/y18n": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
+ "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ=="
+ },
+ "node_modules/jsome/node_modules/yargs": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.1.tgz",
+ "integrity": "sha512-PRU7gJrJaXv3q3yQZ/+/X6KBswZiaQ+zOmdprZcouPYtQgvNU35i+68M4b1ZHLZtYFT5QObFLV+ZkmJYcwKdiw==",
+ "dependencies": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^9.0.2"
+ }
+ },
+ "node_modules/jsome/node_modules/yargs-parser": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
+ "integrity": "sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw==",
+ "dependencies": {
+ "camelcase": "^4.1.0"
+ }
+ },
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/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==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
+ },
+ "node_modules/json2csv": {
+ "version": "5.0.7",
+ "resolved": "https://registry.npmjs.org/json2csv/-/json2csv-5.0.7.tgz",
+ "integrity": "sha512-YRZbUnyaJZLZUJSRi2G/MqahCyRv9n/ds+4oIetjDF3jWQA7AG7iSeKTiZiCNqtMZM7HDyt0e/W6lEnoGEmMGA==",
+ "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
+ "dependencies": {
+ "commander": "^6.1.0",
+ "jsonparse": "^1.3.1",
+ "lodash.get": "^4.4.2"
+ },
+ "bin": {
+ "json2csv": "bin/json2csv.js"
+ },
+ "engines": {
+ "node": ">= 10",
+ "npm": ">= 6.13.0"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+ "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/jwa": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
+ "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
+ "dependencies": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
+ "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
+ "dependencies": {
+ "jwa": "^2.0.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/klaw": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
+ "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.9"
+ }
+ },
+ "node_modules/lazystream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
+ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
+ "dependencies": {
+ "readable-stream": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.6.3"
+ }
+ },
+ "node_modules/lazystream/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/lazystream/node_modules/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=="
+ },
+ "node_modules/lazystream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/lcid": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
+ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
+ "dependencies": {
+ "invert-kv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
+ "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
+ "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==",
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash._basebind": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basebind/-/lodash._basebind-2.3.0.tgz",
+ "integrity": "sha512-SHqM7YCuJ+BeGTs7lqpWnmdHEeF4MWxS3dksJctHFNxR81FXPOzA4bS5Vs5CpcGTkBpM8FCl+YEbQEblRw8ABg==",
+ "dependencies": {
+ "lodash._basecreate": "~2.3.0",
+ "lodash._setbinddata": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreate": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-2.3.0.tgz",
+ "integrity": "sha512-vwZaWldZwS2y9b99D8i9+WtgiZXbHKsBsMrpxJEqTsNW20NhJo5W8PBQkeQO9CmxuqEYn8UkMnfEM2MMT4cVrw==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash.isobject": "~2.3.0",
+ "lodash.noop": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreatecallback": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreatecallback/-/lodash._basecreatecallback-2.3.0.tgz",
+ "integrity": "sha512-Ev+pDzzfVfgbiucpXijconLGRBar7/+KNCf05kSnk4CmdDVhAy1RdbU9efCJ/o9GXI08JdUGwZ+5QJ3QX3kj0g==",
+ "dependencies": {
+ "lodash._setbinddata": "~2.3.0",
+ "lodash.bind": "~2.3.0",
+ "lodash.identity": "~2.3.0",
+ "lodash.support": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._basecreatewrapper": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._basecreatewrapper/-/lodash._basecreatewrapper-2.3.0.tgz",
+ "integrity": "sha512-YLycQ7k8AB9Wc1EOvLNxuRWcqipDkMXq2GCgnLWQR6qtgTb3gY3LELzEpnFshrEO4LOLs+R2EpcY+uCOZaLQ8Q==",
+ "dependencies": {
+ "lodash._basecreate": "~2.3.0",
+ "lodash._setbinddata": "~2.3.0",
+ "lodash._slice": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._createwrapper": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._createwrapper/-/lodash._createwrapper-2.3.0.tgz",
+ "integrity": "sha512-XjaI/rzg9W+WO4WJDQ+PRlHD5sAMJ1RhJLuT65cBxLCb1kIYs4U20jqvTDGAWyVT3c34GYiLd9AreHYuB/8yJA==",
+ "dependencies": {
+ "lodash._basebind": "~2.3.0",
+ "lodash._basecreatewrapper": "~2.3.0",
+ "lodash.isfunction": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._objecttypes": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.3.0.tgz",
+ "integrity": "sha512-jbA6QyHt9cw3BzvbWzIcnU3Z12jSneT6xBgz3Y782CJsN1tV5aTBKrFo2B4AkeHBNaxSrbPYZZpi1Lwj3xjdtg=="
+ },
+ "node_modules/lodash._renative": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._renative/-/lodash._renative-2.3.0.tgz",
+ "integrity": "sha512-v44MRirqYqZGK/h5UKoVqXWF2L+LUiLTU+Ogu5rHRVWJUA1uWIlHaMpG8f/OA8j++BzPMQij9+erXHtgFcbuwg=="
+ },
+ "node_modules/lodash._setbinddata": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._setbinddata/-/lodash._setbinddata-2.3.0.tgz",
+ "integrity": "sha512-xMFfbF7dL+sFtrdE49uHFmfpBAEwlFtfgMp86nQRlAF6aizYL+3MTbnYMKJSkP1W501PhsgiBED5kBbZd8kR2g==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash.noop": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._shimkeys": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.3.0.tgz",
+ "integrity": "sha512-9Iuyi7TiWMGa/9+2rqEE+Zwye4b/U2w7Saw6UX1h6Xs88mEER+uz9FZcEBPKMVKsad9Pw5GNAcIBRnW2jNpneQ==",
+ "dependencies": {
+ "lodash._objecttypes": "~2.3.0"
+ }
+ },
+ "node_modules/lodash._slice": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash._slice/-/lodash._slice-2.3.0.tgz",
+ "integrity": "sha512-7C61GhzRUv36gTafr+RIb+AomCAYsSATEoK4OP0VkNBcwvsM022Z22AVgqjjzikeNO1U29LzsJZDvLbiNPUYvA=="
+ },
+ "node_modules/lodash.bind": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-2.3.0.tgz",
+ "integrity": "sha512-goakyOo+FMN8lttMPnZ0UNlr5RlzX4IrUXyTJPT2A0tGCMXySupond9wzvDqTvVmYTcQjIKGrj8naJDS2xWAlQ==",
+ "dependencies": {
+ "lodash._createwrapper": "~2.3.0",
+ "lodash._renative": "~2.3.0",
+ "lodash._slice": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.defaults": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+ "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
+ },
+ "node_modules/lodash.difference": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
+ "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="
+ },
+ "node_modules/lodash.flatten": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+ "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="
+ },
+ "node_modules/lodash.foreach": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-2.3.0.tgz",
+ "integrity": "sha512-yLnyptVRJd0//AbGp480grgQG9iaDIV5uOgSbpurRy1dYybPbjNTLQ3FyLEQ84buVLPG7jyaiyvpzgfOutRB3Q==",
+ "dependencies": {
+ "lodash._basecreatecallback": "~2.3.0",
+ "lodash.forown": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.forown": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.forown/-/lodash.forown-2.3.0.tgz",
+ "integrity": "sha512-dUnCsuQTtq3Y7bxPNoEEqjJjPL2ftLtcz2PTeRKvhbpdM514AvnqCjewHGsm/W+dwspIwa14KoWEZeizJ7smxA==",
+ "dependencies": {
+ "lodash._basecreatecallback": "~2.3.0",
+ "lodash._objecttypes": "~2.3.0",
+ "lodash.keys": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="
+ },
+ "node_modules/lodash.identity": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.identity/-/lodash.identity-2.3.0.tgz",
+ "integrity": "sha512-NYJ2r2cwy3tkx/saqbIZEX6oQUzjWTnGRu7d/zmBjMCZos3eHBxCpbvWFWSetv8jFVrptsp6EbWjzNgBKhUoOA=="
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-2.3.0.tgz",
+ "integrity": "sha512-X5lteBYlCrVO7Qc00fxP8W90fzRp6Ax9XcHANmU3OsZHdSyIVZ9ZlX5QTTpRq8aGY+9I5Rmd0UTzTIIyWPugEQ=="
+ },
+ "node_modules/lodash.isobject": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.3.0.tgz",
+ "integrity": "sha512-jo1pfV61C4TE8BfEzqaHj6EIKiSkFANJrB6yscwuCJMSRw5tbqjk4Gv7nJzk4Z6nFKobZjGZ8Qd41vmnwgeQqQ==",
+ "dependencies": {
+ "lodash._objecttypes": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="
+ },
+ "node_modules/lodash.keys": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.3.0.tgz",
+ "integrity": "sha512-c0UW0ffqMxSCtoVbmVt2lERJLkEqgoOn2ejPsWXzr0ZrqRbl3uruGgwHzhtqXxi6K/ei3Ey7zimOqSwXgzazPg==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0",
+ "lodash._shimkeys": "~2.3.0",
+ "lodash.isobject": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.noop": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.noop/-/lodash.noop-2.3.0.tgz",
+ "integrity": "sha512-NpSm8HRm1WkBBWHUveDukLF4Kfb5P5E3fjHc9Qre9A11nNubozLWD2wH3UBTZbu+KSuX8aSUvy9b+PUyEceJ8g=="
+ },
+ "node_modules/lodash.support": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.support/-/lodash.support-2.3.0.tgz",
+ "integrity": "sha512-etc7VWbB0U3Iya8ixj2xy4sDBN3jvPX7ODi8iXtn4KkkjNpdngrdc7Vlt5jub/Vgqx6/dWtp7Ml9awhCQPYKGQ==",
+ "dependencies": {
+ "lodash._renative": "~2.3.0"
+ }
+ },
+ "node_modules/lodash.union": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
+ "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="
+ },
+ "node_modules/log-symbols": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
+ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "dependencies": {
+ "chalk": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/map-age-cleaner": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
+ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
+ "dependencies": {
+ "p-defer": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/markdown-table": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz",
+ "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==",
+ "dependencies": {
+ "repeat-string": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "dependencies": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
+ "node_modules/mem": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
+ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
+ "dependencies": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-collect/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-flush/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.30.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
+ "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mount-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mount-point/-/mount-point-3.0.0.tgz",
+ "integrity": "sha512-jAhfD7ZCG+dbESZjcY1SdFVFqSJkh/yGbdsifHcPkvuLRO5ugK0Ssmd9jdATu29BTd4JiN+vkpMzVvsUgP3SZA==",
+ "dependencies": {
+ "@sindresorhus/df": "^1.0.1",
+ "pify": "^2.3.0",
+ "pinkie-promise": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mount-point/node_modules/@sindresorhus/df": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/df/-/df-1.0.1.tgz",
+ "integrity": "sha512-1Hyp7NQnD/u4DSxR2DGW78TF9k7R0wZ8ev0BpMAIzA6yTQSHqNb5wTuvtcPYf4FWbVse2rW7RgDsyL8ua2vXHw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+ "dev": true
+ },
+ "node_modules/nan": {
+ "version": "2.17.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
+ "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
+ "optional": true
+ },
+ "node_modules/native-promise-pool": {
+ "version": "3.28.0",
+ "resolved": "https://registry.npmjs.org/native-promise-pool/-/native-promise-pool-3.28.0.tgz",
+ "integrity": "sha512-ixwkLwaF+idXLS/UJlVbmgl4obzQxYKNRU7yiwcIoi3PedVC+MvG476k3Ak0RgPoxCN9RcP/+o/5anJBOneiQw==",
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.21.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/nice-try": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
+ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
+ },
+ "node_modules/node-fetch": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz",
+ "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch/node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/node-fetch/node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/node-fetch/node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
+ "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
+ "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
+ "dependencies": {
+ "path-key": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ora": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-1.4.0.tgz",
+ "integrity": "sha512-iMK1DOQxzzh2MBlVsU42G80mnrvUhqsMh74phHtDlrcTZPK0pH6o7l7DRshK+0YsxDyEuaOkziVdvM3T0QTzpw==",
+ "dependencies": {
+ "chalk": "^2.1.0",
+ "cli-cursor": "^2.1.0",
+ "cli-spinners": "^1.0.1",
+ "log-symbols": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
+ "dependencies": {
+ "restore-cursor": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
+ "dependencies": {
+ "mimic-fn": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ora/node_modules/restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
+ "dependencies": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/os-locale": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
+ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
+ "dependencies": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/os-locale/node_modules/execa": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+ "dependencies": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/os-locale/node_modules/get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/os-locale/node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/p-defer": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
+ "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-finally": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
+ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-is-promise": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
+ "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
+ "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
+ "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==",
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
+ "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz",
+ "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parent-require": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
+ "integrity": "sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/parse-glob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-2.1.1.tgz",
+ "integrity": "sha512-HfktnHihQVy5f1wX9Kcg433LxgrahVfvdrC6t25hWxYyjoQ01WZtmCHxYCMPBU9+hlyCcnP8erQ5CfXRnPVnNA==",
+ "dependencies": {
+ "glob-base": "^0.1.0",
+ "glob-path-regex": "^1.0.0",
+ "is-glob": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/glob-base": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.1.1.tgz",
+ "integrity": "sha512-WUYWUFKryC5FJlPqh6XbgVAKm5Ca9I+PuxeldcoOTv4nZTPuydPP/fZWyYN04lIP8jmeWNrHO1riAniymomJBw==",
+ "dependencies": {
+ "glob-parent": "^1.2.0",
+ "is-glob": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/glob-parent": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-1.3.0.tgz",
+ "integrity": "sha512-hTmuuCjsIMiB85432X8VgmlgWVn99Np49NOWsRyfPkvsFBmsHOoCkOoFGNrMgauLMDD06Mzw+uVTw+oWNCAzgQ==",
+ "dependencies": {
+ "is-glob": "^2.0.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/glob-parent/node_modules/is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "dependencies": {
+ "is-extglob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-glob/node_modules/is-glob": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-1.1.3.tgz",
+ "integrity": "sha512-tKLBgs6hhR6eI0mq8M2b91eUynY27ydu7MbY68IxVE1mlX2r7vbvXJ5qNz/KgDGMXAqMis156hxfvQVh7DcYTA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-type/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
+ "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pinkie-promise": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
+ "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+ "dependencies": {
+ "pinkie": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+ "integrity": "sha512-ojakdnUgL5pzJYWw2AIDEupaQCX5OPbM688ZevubICjdIX01PRSYKqm33fJoCOJBRseYCTUlQRnBNX+Pchaejw==",
+ "dependencies": {
+ "find-up": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/progress-stream": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz",
+ "integrity": "sha512-MIBPjZz6oGNSw5rn2mSp+nP9FGoaVo6QsPyPVEaD4puilz5hZNa3kfnrlqRNYFsugslbU3An4mnkLLtZOaWvrA==",
+ "dependencies": {
+ "speedometer": "~0.1.2",
+ "through2": "~0.2.3"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prr": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
+ "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw=="
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ=="
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
+ "engines": {
+ "node": ">=0.6.0",
+ "teleport": ">=0.2.0"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.11.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.1.tgz",
+ "integrity": "sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystring": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz",
+ "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/rage-edit": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/rage-edit/-/rage-edit-1.2.0.tgz",
+ "integrity": "sha512-0RspBRc2s6We4g7hRCvT5mu7YPEnfjvQK8Tt354a2uUNJCMC7MKLvo/1mLvHUCQ/zbP6siQyp5VRZN7UCpMFZg=="
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdir-glob": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
+ "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
+ "dependencies": {
+ "minimatch": "^5.1.0"
+ }
+ },
+ "node_modules/readdir-glob/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/readdir-glob/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/regexp.escape": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/regexp.escape/-/regexp.escape-1.1.0.tgz",
+ "integrity": "sha512-KVeSRSGxG1oQn9Op7tkDaYo5MRacMciqL5cHzCsvChvFOCtyxLMplXe9p+Z3ItGMLAONUTtnHe+yEyYDDntdxA==",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0",
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
+ "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+ "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
+ "dependencies": {
+ "is-core-module": "^2.11.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-3.2.0.tgz",
+ "integrity": "sha512-Ep0RsvAjnRcBX1p5vogbaBdAGu/8j/ewpvGqnQYunnLd9SM0vWcPJewPKNnWFggf0hF0pwIgwV5XK7qQ7UZ8Qg==",
+ "dependencies": {
+ "execa": "^0.10.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
+ "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.9.0"
+ },
+ "engines": {
+ "npm": ">=2.0.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/sanitize-filename": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
+ "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
+ "dependencies": {
+ "truncate-utf8-bytes": "^1.0.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+ },
+ "node_modules/shebang-command": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
+ "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
+ "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/shell-escape": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/shell-escape/-/shell-escape-0.2.0.tgz",
+ "integrity": "sha512-uRRBT2MfEOyxuECseCZd28jC1AJ8hmqqneWQ4VWUTgCAFvb3wKU1jLqj6egC4Exrr88ogg3dp+zroH4wJuaXzw==",
+ "license": "MIT"
+ },
+ "node_modules/showdown": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz",
+ "integrity": "sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==",
+ "dependencies": {
+ "yargs": "^14.2"
+ },
+ "bin": {
+ "showdown": "bin/showdown.js"
+ }
+ },
+ "node_modules/showdown/node_modules/cliui": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "dependencies": {
+ "string-width": "^3.1.0",
+ "strip-ansi": "^5.2.0",
+ "wrap-ansi": "^5.1.0"
+ }
+ },
+ "node_modules/showdown/node_modules/emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
+ },
+ "node_modules/showdown/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/showdown/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/showdown/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/showdown/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/showdown/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/showdown/node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/showdown/node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/showdown/node_modules/wrap-ansi": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "string-width": "^3.0.0",
+ "strip-ansi": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/showdown/node_modules/yargs": {
+ "version": "14.2.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz",
+ "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==",
+ "dependencies": {
+ "cliui": "^5.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^3.0.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": "^3.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^15.0.1"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
+ "node_modules/simplytyped": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/simplytyped/-/simplytyped-3.3.0.tgz",
+ "integrity": "sha512-mz4RaNdKTZiaKXgi6P1k/cdsxV3gz+y1Wh2NXHWD40dExktLh4Xx/h6MFakmQWODZHj/2rKe59acacpL74ZhQA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "typescript": ">=2.8.0"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
+ "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.0",
+ "astral-regex": "^1.0.0",
+ "is-fullwidth-code-point": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/slide": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
+ "integrity": "sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/slugify": {
+ "version": "1.6.6",
+ "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz",
+ "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/speedometer": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz",
+ "integrity": "sha512-phdEoDlA6EUIVtzwq1UiNMXDUogczp204aYF/yfOhjNePWFfIpBJ1k5wLMuXQhEOOMjuTJEcc4vdZa+vuP+n/Q=="
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+ },
+ "node_modules/ssh2": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.12.0.tgz",
+ "integrity": "sha512-7mcLu8biO6/BjQQ1iCjCmuBiF0hXxo+JlHpJBPDTVsxU7evscWWiRUgYF5XIs4gLKmiPRHA0maund11QLWyDJg==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "asn1": "^0.2.4",
+ "bcrypt-pbkdf": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ },
+ "optionalDependencies": {
+ "cpu-features": "~0.0.6",
+ "nan": "^2.17.0"
+ }
+ },
+ "node_modules/ssh2-sftp-client": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/ssh2-sftp-client/-/ssh2-sftp-client-9.0.4.tgz",
+ "integrity": "sha512-fHAXUgmtmqUq/IdMlN9DBhkzrRFQRfORsQYglZMdnvosr4oo/6js+jxrJgGU+alNLW8ZN1IZFfRSoAejyvr8zg==",
+ "dependencies": {
+ "concat-stream": "^2.0.0",
+ "promise-retry": "^2.0.1",
+ "ssh2": "^1.11.0"
+ },
+ "engines": {
+ "node": ">=10.24.1"
+ }
+ },
+ "node_modules/ssri": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz",
+ "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==",
+ "dependencies": {
+ "minipass": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/stream-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
+ "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
+ "dependencies": {
+ "debug": "2"
+ }
+ },
+ "node_modules/stream-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/stream-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "dependencies": {
+ "ansi-regex": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-eof": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strip-outer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
+ "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/table": {
+ "version": "5.4.6",
+ "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
+ "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.10.2",
+ "lodash": "^4.17.14",
+ "slice-ansi": "^2.1.0",
+ "string-width": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/table/node_modules/emoji-regex": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "dev": true
+ },
+ "node_modules/table/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/table/node_modules/string-width": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^7.0.1",
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.1.13",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz",
+ "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^4.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
+ "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/throttle": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/throttle/-/throttle-1.0.3.tgz",
+ "integrity": "sha512-VYINSQFQeFdmhCds0tTqvQmLmdAjzGX1D6GnRQa4zlq8OpTtWSMddNyRq8Z4Snw/d6QZrWt9cM/cH8xTiGUkYA==",
+ "dependencies": {
+ "readable-stream": ">= 0.3.0",
+ "stream-parser": ">= 0.0.2"
+ },
+ "engines": {
+ "node": ">= v0.8.0"
+ }
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true
+ },
+ "node_modules/through2": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz",
+ "integrity": "sha512-mLa8Bn2mZurjyomGKWRu3Bo2mvoQojFks9NvOK8H+k4kDJNkdEqG522KFZsEFBEl6rKkxTgFbE5+OPcgfvPEHA==",
+ "dependencies": {
+ "readable-stream": "~1.1.9",
+ "xtend": "~2.1.1"
+ }
+ },
+ "node_modules/through2/node_modules/isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ },
+ "node_modules/through2/node_modules/readable-stream": {
+ "version": "1.1.14",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "node_modules/through2/node_modules/string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ },
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dev": true,
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/trash": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/trash/-/trash-4.3.0.tgz",
+ "integrity": "sha512-f36TKwIaBiXm63xSrn8OTNghg5CYHBsFVJvcObMo76LRpgariuRi2CqXQHw1VzfeximD0igdGaonOG6N760BtQ==",
+ "dependencies": {
+ "escape-string-applescript": "^2.0.0",
+ "fs-extra": "^0.30.0",
+ "globby": "^7.1.1",
+ "p-map": "^1.2.0",
+ "p-try": "^1.0.0",
+ "pify": "^3.0.0",
+ "run-applescript": "^3.0.0",
+ "uuid": "^3.1.0",
+ "xdg-trashdir": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/globby": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
+ "integrity": "sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
+ "dependencies": {
+ "array-union": "^1.0.1",
+ "dir-glob": "^2.0.0",
+ "glob": "^7.1.2",
+ "ignore": "^3.3.5",
+ "pify": "^3.0.0",
+ "slash": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/ignore": {
+ "version": "3.3.10",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
+ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug=="
+ },
+ "node_modules/trash/node_modules/p-map": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz",
+ "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/trash/node_modules/slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/trash/node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/trim-repeated": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
+ "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/truncate-utf8-bytes": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
+ "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==",
+ "dependencies": {
+ "utf8-byte-length": "^1.0.1"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/tslint": {
+ "version": "5.20.1",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz",
+ "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^4.0.1",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.13.1",
+ "minimatch": "^3.0.4",
+ "mkdirp": "^0.5.1",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.29.0"
+ },
+ "bin": {
+ "tslint": "bin/tslint"
+ },
+ "engines": {
+ "node": ">=4.8.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev"
+ }
+ },
+ "node_modules/tslint/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "node_modules/tslint/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/tslint/node_modules/tsutils": {
+ "version": "2.29.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
+ "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev"
+ }
+ },
+ "node_modules/tslog": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/tslog/-/tslog-3.3.4.tgz",
+ "integrity": "sha512-N0HHuHE0e/o75ALfkioFObknHR5dVchUad4F0XyFf3gXJYB++DewEzwGI/uIOM216E5a43ovnRNEeQIq9qgm4Q==",
+ "dependencies": {
+ "source-map-support": "^0.5.21"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
+ },
+ "node_modules/type-check": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
+ "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
+ },
+ "node_modules/typescript": {
+ "version": "3.9.10",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
+ "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unique-filename": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+ "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+ "dependencies": {
+ "unique-slug": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+ "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-template": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz",
+ "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw=="
+ },
+ "node_modules/user-home": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz",
+ "integrity": "sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==",
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/utf8-byte-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
+ "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA=="
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/v8-compile-cache": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
+ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
+ "dev": true
+ },
+ "node_modules/version-compare": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/version-compare/-/version-compare-3.11.0.tgz",
+ "integrity": "sha512-sufLk/bD3oq+iLzWk8FOHfYwVIaC3NLJcvMqnggmakwNskyKyM+u8x1F8NdwjlLVgC8oYSTgB0RK68VCT6wQOg==",
+ "dev": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "editions": "^6.21.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/version-range": {
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/version-range/-/version-range-4.14.0.tgz",
+ "integrity": "sha512-gjb0ARm9qlcBAonU4zPwkl9ecKkas+tC2CGwFfptTCWWIVTWY1YUbT2zZKsOAF1jR/tNxxyLwwG0cb42XlYcTg==",
+ "license": "Artistic-2.0",
+ "engines": {
+ "node": ">=4"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
+ "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
+ "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/write": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
+ "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+ "dev": true,
+ "dependencies": {
+ "mkdirp": "^0.5.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/write-file-atomic": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz",
+ "integrity": "sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw==",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "slide": "^1.1.5"
+ }
+ },
+ "node_modules/xdg-basedir": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-2.0.0.tgz",
+ "integrity": "sha512-NF1pPn594TaRSUO/HARoB4jK8I+rWgcpVlpQCK6/6o5PHyLUt2CSiDrpUZbQ6rROck+W2EwF8mBJcTs+W98J9w==",
+ "dependencies": {
+ "os-homedir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/xdg-trashdir": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/xdg-trashdir/-/xdg-trashdir-2.1.1.tgz",
+ "integrity": "sha512-KcVhPaOu2ZurYNHSRTf1+ZHORkTZGCQ+u0JHN17QixRISJq4pXOnjt/lQcehvtHL5QAKhSzKgyjrcNnPdkPBHA==",
+ "dependencies": {
+ "@sindresorhus/df": "^2.1.0",
+ "mount-point": "^3.0.0",
+ "pify": "^2.2.0",
+ "user-home": "^2.0.0",
+ "xdg-basedir": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
+ "integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==",
+ "dependencies": {
+ "object-keys": "~0.4.0"
+ },
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/xtend/node_modules/object-keys": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
+ "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw=="
+ },
+ "node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
+ "node_modules/yargonaut": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz",
+ "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==",
+ "dependencies": {
+ "chalk": "^1.1.1",
+ "figlet": "^1.1.1",
+ "parent-require": "^1.0.0"
+ }
+ },
+ "node_modules/yargonaut/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yargonaut/node_modules/ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yargonaut/node_modules/chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
+ "dependencies": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yargonaut/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/yargonaut/node_modules/supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "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"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "15.0.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz",
+ "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ },
+ "node_modules/yargs/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yargs/node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/yargs/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/zip-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz",
+ "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==",
+ "dependencies": {
+ "archiver-utils": "^2.1.0",
+ "compress-commons": "^4.1.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ }
+ }
+}
diff --git a/packages/vfs/rclone.js/.gitignore b/packages/vfs/rclone.js/.gitignore
new file mode 100644
index 00000000..da15fc0f
--- /dev/null
+++ b/packages/vfs/rclone.js/.gitignore
@@ -0,0 +1,5 @@
+# Dependency directories
+node_modules/
+
+# Binaries
+bin/rclone
diff --git a/packages/vfs/rclone.js/CNAME b/packages/vfs/rclone.js/CNAME
new file mode 100644
index 00000000..2b2c337b
--- /dev/null
+++ b/packages/vfs/rclone.js/CNAME
@@ -0,0 +1 @@
+rclone.js.org
diff --git a/packages/vfs/rclone.js/README.md b/packages/vfs/rclone.js/README.md
new file mode 100644
index 00000000..e7a15447
--- /dev/null
+++ b/packages/vfs/rclone.js/README.md
@@ -0,0 +1,159 @@
+# Rclone.js
+
+The JavaScript API to the "Swiss army knife of cloud storage"
+[rclone](https://rclone.org/).
+
+Besides providing a way to install rclone on different platforms, a CLI and
+a JavaScript API are included.
+
+## Installation
+
+```sh
+npm install rclone.js
+```
+
+After installation, the latest binary of `rclone` is also fetched based on
+your system environment.
+
+If a custom version of `rclone` binary is needed, use `RCLONE_EXECUTABLE`
+environment variable to set the path to that custom binary.
+
+## Usage
+
+### Node.js
+
+Except `selfupdate`, which is used to update `rclone` binary, all API functions
+return a child process whose events we can listen to. Optional flags can be
+passed as an object to the last argument of the function call. Except removing
+the `--` prefix, there is no other conversion to the flag name. JSON values are
+stringified before passed to `rclone`.
+
+Each API functions can also take options for the spawned child process. See
+https://nodejs.org/api/child_process.html#child_processspawncommand-args-options
+for their documentation.
+
+```js
+const rclone = require("rclone.js");
+
+const ls = rclone.ls("source:", {
+ "max-depth": 1,
+ // Spawn options:
+ "env": {
+ RCLONE_CONFIG: "~/.config/rclone/rclone.conf",
+ },
+ "shell": "/bin/sh",
+});
+
+ls.stdout.on("data", (data) => {
+ console.log(data.toString());
+});
+
+ls.stderr.on("data", (data) => {
+ console.error(data.toString());
+});
+```
+
+There is also a Promise-based API:
+
+```js
+const rclone = require("rclone.js").promises;
+
+(async function() {
+ const results = await rclone.ls("source:", {
+ "max-depth": 1,
+ // Spawn options:
+ "env": {
+ RCLONE_CONFIG: "~/.config/rclone/rclone.conf",
+ },
+ "shell": "/bin/sh",
+ });
+
+ console.log(results);
+})();
+```
+
+When the official `rclone` adds new command that has not been provided here,
+we can still use the command through the default exported functions, passing
+the command name as first argument:
+
+```js
+const rclone = require("rclone.js");
+
+rclone("newcommand", "source:", "target:", {
+ "flag": true,
+});
+
+(async function() {
+ const results = await rclone.promises("newcommand", "source:", "target:", {
+ "flag": true,
+ });
+
+ console.log(results);
+})();
+```
+
+### CLI
+
+This simple CLI calls the JS API above and outputs `stdout` and `stderr`.
+
+```sh
+$ npx rclone --version
+rclone v1.54.0
+- os/arch: darwin/amd64
+- go version: go1.15.7
+```
+
+```sh
+$ npx rclone ls source: --max-depth 1
+ -1 2020-12-12 10:01:44 -1 Documents
+ -1 2020-12-11 16:24:20 -1 Pictures
+```
+
+### Custom command
+
+The CLI also supports executing a custom JS-based command to further extend
+usage outside of what the official `rclone` offers:
+
+```sh
+$ npx rclone echo.js arg1 --string value arg2 --boolean
+```
+
+The custom JS file just needs to export a function that takes the arguments and
+flags parsed from the CLI. It can either return a child process, or a `Promise`.
+For a child process, its `stdout` and `stderr` are piped to the caller process.
+
+Inside the function, `this` is set to `rclone.js` module.
+
+```js
+const { spawn } = require("child_process");
+
+module.exports = function echo(arg1, arg2, flags = {}) {
+ return spawn("echo", [arg1, arg2, JSON.stringify(flags)]);
+}
+```
+
+The custom module is loaded through `require`, so it has some nice advantages
+when [locating module](https://nodejs.org/api/modules.html#all-together):
+
+- Does not need to specify `.js` extension, `custom` is same as `custom.js`.
+- Considers both `foobar.js` and `foobar/index.js`.
+- Can be extended through `NODE_PATH` environment variable.
+- Can also use module from `node_modules` by its name.
+
+With that, there are a few things custom commands can be used:
+
+- Wraps existing API to add new functionality, such as `archive`.
+- Defines a module with the same name as existing API to extend it with new
+ flags and/or backends.
+
+For a "real-life" example, check out [selfupdate](rclone/selfupdate.js), which
+overrides the built-in `selfupdate` command to download rclone executable if it
+has not been downloaded yet. Consecutive runs just call `selfupdate` API.
+
+For publishing a custom `rclone` command as NPM package, consider prefixing the
+package name with `rclone-` so it's clearer and not conflicting.
+
+### Example Custom Commands
+
+- [rclone-archive](https://www.npmjs.com/package/rclone-archive):
+ Tracking https://github.com/rclone/rclone/issues/2815.
diff --git a/packages/vfs/rclone.js/_config.yml b/packages/vfs/rclone.js/_config.yml
new file mode 100644
index 00000000..8bbf7943
--- /dev/null
+++ b/packages/vfs/rclone.js/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-hacker
diff --git a/packages/vfs/rclone.js/bin/rclone.exe b/packages/vfs/rclone.js/bin/rclone.exe
new file mode 100644
index 00000000..156d50e0
Binary files /dev/null and b/packages/vfs/rclone.js/bin/rclone.exe differ
diff --git a/packages/vfs/rclone.js/bin/rclone.js b/packages/vfs/rclone.js/bin/rclone.js
new file mode 100644
index 00000000..7cda32ac
--- /dev/null
+++ b/packages/vfs/rclone.js/bin/rclone.js
@@ -0,0 +1,49 @@
+#!/usr/bin/env node
+const { join } = require("path");
+
+const mri = require("mri");
+
+const rclone = require("../");
+
+const {_: args, ...flags} = mri(process.argv.slice(2));
+const [commandName, ...commandArguments] = args;
+
+// Executes rclone command if available.
+let { [commandName]: command } = rclone;
+
+// The current directory has highest priority.
+module.paths.push(".");
+// Then the library's "rclone" folder for `rclone.js` custom commands.
+module.paths.push(join(__dirname, "..", "rclone"));
+
+try {
+ // If the command is a custom module, requires it instead.
+ command = require(commandName);
+} catch(error) {
+ try {
+ // If exact name is not found, maybe one prefixed with `rclone-`?
+ command = require(`rclone-${commandName}`);
+ } catch(error) {
+
+ }
+}
+
+const subprocess = command ?
+ command.call(rclone, ...commandArguments, flags) :
+ rclone(...args, flags);
+
+try {
+ if (subprocess.stdin) {
+ process.stdin.pipe(subprocess.stdin);
+ }
+} catch (error) {
+ console.error(error);
+}
+
+subprocess.stdout?.on("data", (data) => {
+ process.stdout.write(data);
+});
+
+subprocess.stderr?.on("data", (data) => {
+ process.stderr.write(data);
+});
diff --git a/packages/vfs/rclone.js/package-lock.json b/packages/vfs/rclone.js/package-lock.json
new file mode 100644
index 00000000..8f582a81
--- /dev/null
+++ b/packages/vfs/rclone.js/package-lock.json
@@ -0,0 +1,69 @@
+{
+ "name": "rclone.js",
+ "version": "0.6.6",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "rclone.js",
+ "version": "0.6.6",
+ "cpu": [
+ "arm",
+ "arm64",
+ "mips",
+ "mipsel",
+ "x32",
+ "x64"
+ ],
+ "hasInstallScript": true,
+ "license": "MIT",
+ "os": [
+ "darwin",
+ "freebsd",
+ "linux",
+ "openbsd",
+ "sunos",
+ "win32"
+ ],
+ "dependencies": {
+ "adm-zip": "^0.5.9",
+ "mri": "^1.2.0"
+ },
+ "bin": {
+ "rclone": "bin/rclone.js"
+ },
+ "devDependencies": {},
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/adm-zip": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
+ "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg==",
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "engines": {
+ "node": ">=4"
+ }
+ }
+ },
+ "dependencies": {
+ "adm-zip": {
+ "version": "0.5.9",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz",
+ "integrity": "sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg=="
+ },
+ "mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
+ }
+ }
+}
diff --git a/packages/vfs/rclone.js/package.json b/packages/vfs/rclone.js/package.json
new file mode 100644
index 00000000..cf0d06b8
--- /dev/null
+++ b/packages/vfs/rclone.js/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "rclone.js",
+ "version": "0.6.6",
+ "description": "JavaScript API for rclone",
+ "keywords": [
+ "rclone"
+ ],
+ "homepage": "https://rclone.js.org/",
+ "bugs": {
+ "url": "https://github.com/sntran/rclone.js/issues",
+ "email": "rclone.js@sntran.com"
+ },
+ "license": "MIT",
+ "author": {
+ "name": "Sơn Trần-Nguyễn",
+ "email": "rclone.js@sntran.com",
+ "url": "https://sntran.com"
+ },
+ "files": [
+ "bin/rclone.js",
+ "rclone/",
+ "rclone.js"
+ ],
+ "main": "rclone.js",
+ "bin": {
+ "rclone-js": "./bin/rclone.js"
+ },
+ "repository": "github:sntran/rclone.js",
+ "scripts": {
+ "postinstall": "node bin/rclone.js selfupdate",
+ "test": "node test test/*-test.js"
+ },
+ "dependencies": {
+ "adm-zip": "^0.5.9",
+ "mri": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "os": [
+ "darwin",
+ "freebsd",
+ "linux",
+ "openbsd",
+ "sunos",
+ "win32"
+ ],
+ "cpu": [
+ "arm",
+ "arm64",
+ "mips",
+ "mipsel",
+ "x32",
+ "x64"
+ ],
+ "devDependencies": {}
+}
diff --git a/packages/vfs/rclone.js/rclone.js b/packages/vfs/rclone.js/rclone.js
new file mode 100644
index 00000000..c368861e
--- /dev/null
+++ b/packages/vfs/rclone.js/rclone.js
@@ -0,0 +1,205 @@
+const { join } = require("path");
+const { spawn, ChildProcess } = require("child_process");
+
+let { platform } = process;
+
+const RCLONE_DIR = join(__dirname, "bin");
+const DEFAULT_RCLONE_EXECUTABLE = join(RCLONE_DIR, `rclone${ platform === "windows"? ".exe" : "" }`);
+const {
+ RCLONE_EXECUTABLE = DEFAULT_RCLONE_EXECUTABLE,
+} = process.env;
+
+const CHILD_OPTIONS = [
+ "cwd",
+ "env",
+ "argv0",
+ "stdio",
+ "detached",
+ "uid",
+ "gid",
+ "serialization",
+ "shell",
+ "windowsVerbatimArguments",
+ "windowsHide",
+ "signal",
+ "timeout",
+ "killSignal",
+];
+
+/**
+ * Spawns a rclone process to execute with the supplied arguments.
+ *
+ * The last argument can also be an object with all the flags.
+ *
+ * Options for the child process can also be passed into this last argument,
+ * and they will be picked out.
+ *
+ * @param {...string|object} args arguments for the API call.
+ * @returns {ChildProcess} the rclone subprocess.
+ */
+const api = function(...args) {
+ let flags = args.pop();
+ let childOptions = {};
+
+ if (!!flags && flags.constructor === Object) {
+ Object.entries(flags).forEach(([key, value]) => {
+ if (CHILD_OPTIONS.indexOf(key) > -1) {
+ childOptions[key] = value;
+ return;
+ }
+
+ // No need to handle key when value is null or undefined.
+ if (value == null) {
+ return;
+ }
+
+ if (value === false) {
+ key = `no-${ key }`;
+ }
+ const values = Array.isArray(value)? value : [value];
+ values.forEach(value => {
+ args.push(`--${ key }`);
+ if (typeof value === "boolean") return;
+ if (typeof value === "string") {
+ args.push(`${ value }`);
+ } else {
+ args.push(`${ JSON.stringify(value) }`);
+ }
+ });
+ });
+ } else {
+ // Not a flag object, push it back.
+ args.push(flags);
+ }
+
+ return spawn(RCLONE_EXECUTABLE, args, childOptions);
+}
+
+// Promise-based API.
+const promises = api.promises = function(...args) {
+ return new Promise((resolve, reject) => {
+ const subprocess = api(...args);
+
+ subprocess.on("error", (error) => {
+ reject(error);
+ });
+
+ const stdout = [], stderr = [];
+ subprocess.stdout.on("data", (chunk) => {
+ stdout.push(chunk);
+ });
+ subprocess.stdout.on("end", () => {
+ resolve(Buffer.concat(stdout));
+ });
+ subprocess.stderr.on("data", (chunk) => {
+ stderr.push(chunk);
+ });
+ subprocess.stderr.on("end", () => {
+ if (stderr.length) {
+ reject(Buffer.concat(stderr));
+ }
+ });
+ });
+};
+
+const COMMANDS = [
+ "about", // Get quota information from the remote.
+ "authorize", // Remote authorization.
+ "backend", // Run a backend specific command.
+ "cat", // Concatenates any files and sends them to stdout.
+ "check", // Checks the files in the source and destination match.
+ "checksum", // Checks the files in the source against a SUM file.
+ "cleanup", // Clean up the remote if possible.
+ "config", // Enter an interactive configuration session.
+ "config create", // Create a new remote with name, type and options.
+ "config delete", // Delete an existing remote name.
+ "config disconnect", // Disconnects user from remote
+ "config dump", // Dump the config file as JSON.
+ "config edit", // Enter an interactive configuration session.
+ "config file", // Show path of configuration file in use.
+ "config password", // Update password in an existing remote.
+ "config providers", // List in JSON format all the providers and options.
+ "config reconnect", // Re-authenticates user with remote.
+ "config show", // Print (decrypted) config file, or the config for a single remote.
+ "config update", // Update options in an existing remote.
+ "config userinfo", // Prints info about logged in user of remote.
+ "copy", // Copy files from source to dest, skipping already copied.
+ "copyto", // Copy files from source to dest, skipping already copied.
+ "copyurl", // Copy url content to dest.
+ "cryptcheck", // Cryptcheck checks the integrity of a crypted remote.
+ "cryptdecode", // Cryptdecode returns unencrypted file names.
+ "dedupe", // Interactively find duplicate filenames and delete/rename them.
+ "delete", // Remove the contents of path.
+ "deletefile", // Remove a single file from remote.
+ "genautocomplete", // Output completion script for a given shell.
+ "genautocomplete bash", // Output bash completion script for rclone.
+ "genautocomplete fish", // Output fish completion script for rclone.
+ "genautocomplete zsh", // Output zsh completion script for rclone.
+ "gendocs", // Output markdown docs for rclone to the directory supplied.
+ "hashsum", // Produces a hashsum file for all the objects in the path.
+ "help", // Show help for rclone commands, flags and backends.
+ "link", // Generate public link to file/folder.
+ "listremotes", // List all the remotes in the config file.
+ "ls", // List the objects in the path with size and path.
+ "lsd", // List all directories/containers/buckets in the path.
+ "lsf", // List directories and objects in remote:path formatted for parsing.
+ "lsjson", // List directories and objects in the path in JSON format.
+ "lsl", // List the objects in path with modification time, size and path.
+ "md5sum", // Produces an md5sum file for all the objects in the path.
+ "mkdir", // Make the path if it doesn't already exist.
+ "mount", // Mount the remote as file system on a mountpoint.
+ "move", // Move files from source to dest.
+ "moveto", // Move file or directory from source to dest.
+ "ncdu", // Explore a remote with a text based user interface.
+ "obscure", // Obscure password for use in the rclone config file.
+ "purge", // Remove the path and all of its contents.
+ "rc", // Run a command against a running rclone.
+ "rcat", // Copies standard input to file on remote.
+ "rcd", // Run rclone listening to remote control commands only.
+ "rmdir", // Remove the path if empty.
+ "rmdirs", // Remove empty directories under the path.
+ "selfupdate", // Update the rclone binary.
+ "serve", // Serve a remote over a protocol.
+ "serve dlna", // Serve remote:path over DLNA
+ "serve ftp", // Serve remote:path over FTP.
+ "serve http", // Serve the remote over HTTP.
+ "serve restic", // Serve the remote for restic's REST API.
+ "serve sftp", // Serve the remote over SFTP.
+ "serve webdav", // Serve remote:path over webdav.
+ "settier", // Changes storage class/tier of objects in remote.
+ "sha1sum", // Produces an sha1sum file for all the objects in the path.
+ "size", // Prints the total size and number of objects in remote:path.
+ "sync", // Make source and dest identical, modifying destination only.
+ "test", // Run a test command.
+ "touch", // Create new file or change file modification time.
+ "tree", // List the contents of the remote in a tree like fashion.
+ "version", // Show the version number.
+];
+
+COMMANDS.forEach(commandName => {
+ // Normal API command to return a subprocess.
+ Object.defineProperty(api, commandName, {
+ /**
+ * @param {...string|object} args arguments for the API call
+ * @returns {ChildProcess} the rclone subprocess.
+ */
+ value: function(...args) {
+ return api(commandName, ...args);
+ },
+ enumerable: true,
+ });
+
+ // Promise API command to return a Promise.
+ Object.defineProperty(promises, commandName, {
+ /**
+ * @param {...string|object} args arguments for the API call
+ * @returns {Promise} the output of the command.
+ */
+ value: function(...args) {
+ return promises(commandName, ...args);
+ },
+ enumerable: true,
+ });
+});
+
+module.exports = api;
diff --git a/packages/vfs/rclone.js/rclone/selfupdate.js b/packages/vfs/rclone.js/rclone/selfupdate.js
new file mode 100644
index 00000000..371b5c56
--- /dev/null
+++ b/packages/vfs/rclone.js/rclone/selfupdate.js
@@ -0,0 +1,107 @@
+// Custom command to selfupdate rclone binary.
+
+const { existsSync } = require("fs");
+const { join } = require("path");
+const https = require("https");
+
+let { platform, arch } = process;
+
+switch (platform) {
+ case "darwin":
+ platform = "osx";
+ break;
+ case "freebsd":
+ case "linux":
+ case "openbsd":
+ break;
+ case "sunos":
+ platform = "solaris";
+ case "win32":
+ platform = "windows";
+ default:
+ break;
+}
+
+switch (arch) {
+ case "arm":
+ case "arm64":
+ case "mips":
+ case "mipsel":
+ break;
+ case "x32":
+ arch = "386";
+ case "x64":
+ arch = "amd64";
+ default:
+ break;
+}
+
+/**
+ * Fetches a remote URL
+ * @param {string} url the remote URL to fetch.
+ * @returns {Promise} the response as Buffer.
+ */
+async function fetch(url) {
+ return new Promise((resolve, reject) => {
+ https.get(url, (response) => {
+ const chunks = [];
+ response.on("data", (chunk) => chunks.push(chunk));
+ response.on("end", () => {
+ resolve(Buffer.concat(chunks));
+ });
+ }).on("error", reject);
+ });
+}
+
+const RCLONE_DIR = join(__dirname, "..", "bin");
+const DEFAULT_RCLONE_EXECUTABLE = join(RCLONE_DIR, `rclone${ platform === "windows"? ".exe" : "" }`);
+const {
+ RCLONE_EXECUTABLE = DEFAULT_RCLONE_EXECUTABLE,
+} = process.env;
+
+/**
+ * Updates rclone binary based on current OS.
+ * @returns {Promise}
+ */
+module.exports = function(options = {}) {
+ const {
+ beta = false,
+ stable = !beta,
+ version,
+ check = false,
+ } = options;
+
+ // Passes along to `rclone` if exists.
+ if (existsSync(RCLONE_EXECUTABLE)) {
+ return this.selfupdate(options);
+ }
+
+ const baseUrl = stable ? "https://downloads.rclone.org" : "https://beta.rclone.org";
+ const channel = stable ? "current" : "beta-latest";
+
+ if (check) {
+ return fetch(`${ baseUrl }/version.txt`).then(version => {
+ console.log(`The latest version is ${ version }`);
+ });
+ }
+
+ console.log("Downloading rclone...");
+ const archiveName = version ? `${ version }/rclone-${ version }` : `rclone-${ channel }`;
+ return fetch(`${ baseUrl }/${ archiveName }-${ platform }-${ arch }.zip`).then(archive => {
+ console.log("Extracting rclone...");
+ const AdmZip = require("adm-zip");
+ const { chmodSync } = require("fs");
+
+ const zip = new AdmZip(archive);
+ zip.getEntries().forEach((entry) => {
+ const { name, entryName } = entry;
+ if (/rclone(\.exe)?$/.test(name)) {
+ zip.extractEntryTo(entry, RCLONE_DIR, false, true);
+ // Make it executable.
+ chmodSync(DEFAULT_RCLONE_EXECUTABLE, 0o755);
+
+ console.log(`${ entryName.replace(`/${ name }`, "") } is installed.`);
+ }
+ });
+ });
+}
diff --git a/packages/vfs/rclone.js/test/index.js b/packages/vfs/rclone.js/test/index.js
new file mode 100644
index 00000000..9eeb103b
--- /dev/null
+++ b/packages/vfs/rclone.js/test/index.js
@@ -0,0 +1,49 @@
+const { resolve } = require("path");
+
+// `tests` is a singleton variable that will contain all our tests
+const tests = [];
+
+// The test function accepts a name and a function
+function test(name, fn) {
+ // it pushes the name and function as an object to
+ // the `tests` array
+ tests.push({ name, fn });
+}
+
+function run() {
+ // `run` runs all the tests in the `tests` array
+ tests.forEach(t => {
+ // For each test, we try to execute the
+ // provided function.
+ try {
+ t.fn()
+ // If there is no exception
+ // that means it ran correctly
+ console.log('✅', t.name);
+ } catch (e) {
+ // Exceptions, if any, are caught
+ // and the test is considered failed
+ console.log('❌', t.name);
+ // log the stack of the error
+ console.log(e.stack);
+ }
+ });
+}
+
+// Get the list of files from the command line
+// arguments
+const files = process.argv.slice(2);
+
+// expose the test function as a global variable
+global.test = test;
+
+// Load each file using `require`
+files.forEach(file => {
+ // Once a file is loaded, it's tests are
+ // added to the `tests` singleton variable
+ require(resolve(".", file));
+});
+
+// Now that all the tests from all the files are
+// added, run them one after the other
+run();
diff --git a/packages/vfs/rclone.js/test/rclone-test.js b/packages/vfs/rclone.js/test/rclone-test.js
new file mode 100644
index 00000000..8b38e2b0
--- /dev/null
+++ b/packages/vfs/rclone.js/test/rclone-test.js
@@ -0,0 +1,135 @@
+const childProcess = require("child_process");
+const {EventEmitter, Writable, Readable} = require("stream");
+
+childProcess.spawn = function(spawnfile, spawnargs, spwanoptions) {
+ mockChildProcess.spawnfile = spawnfile;
+ mockChildProcess.spawnargs = spawnargs;
+ mockChildProcess.spwanoptions = spwanoptions;
+ return mockChildProcess;
+}
+
+const rclone = require("..");
+
+const assert = require("assert");
+
+const mockChildProcess = new EventEmitter();
+mockChildProcess.stdin = new Writable({
+ write () {
+ // mock out the data to be sent
+ },
+ final () {
+ // for when the processes ends
+ }
+});
+
+mockChildProcess.stdout = new Readable({
+ read () {
+ // mock out the child process writing some data to STDOUT
+ const { spawnfile, spawnargs } = mockChildProcess;
+ this.push(`${ spawnargs }`);
+
+ // null signals that there's nothing left to read from the stream
+ this.push(null);
+ }
+});
+
+mockChildProcess.stderr = new Readable({
+ read () {
+ // collect and verify the data to be read from stderr.
+ }
+});
+
+test("should spawn a child process with rclone executable and arguments", () => {
+ const spawnargs = ["command", "arg1", "--string-flag", "string-value", "arg2"];
+ const subprocess = rclone(...spawnargs);
+ assert.match(subprocess.spawnfile, /bin\/rclone/);
+ assert.deepEqual(subprocess.spawnargs, spawnargs);
+});
+
+test("should take the flags as object in the last argument", () => {
+ const command = "command";
+ const args = ["arg1", "arg2"];
+ const flags = {
+ "string-flag": "string-value"
+ };
+ const spawnargs = [command, ...args, `--${Object.keys(flags)[0]}`, Object.values(flags)[0]];
+ const subprocess = rclone(command, ...args, flags);
+ assert.deepEqual(subprocess.spawnargs, spawnargs);
+});
+
+test("should not set value for boolean flag", () => {
+ const command = "command";
+ const args = ["arg1", "arg2"];
+ const flags = {
+ boolean: true,
+ }
+ const spawnargs = [command, ...args, `--boolean`];
+ const subprocess = rclone(command, ...args, flags);
+ assert.deepEqual(subprocess.spawnargs, spawnargs);
+});
+
+test("should prefix `no-` to false flag", () => {
+ const command = "command";
+ const args = ["arg1", "arg2"];
+ const flags = {
+ boolean: false,
+ }
+ const spawnargs = [command, ...args, `--no-boolean`];
+ const subprocess = rclone(command, ...args, flags);
+ assert.deepEqual(subprocess.spawnargs, spawnargs);
+});
+
+test("should stringify JSON flag", () => {
+ const command = "command";
+ const args = ["arg1", "arg2"];
+ const flags = {
+ json: {
+ "p1": [1,"2",null,4],
+ "p2": { "a":1, "b":2 },
+ "_async": true,
+ },
+ }
+ const spawnargs = [command, ...args, "--json", JSON.stringify(flags.json)];
+ const subprocess = rclone(command, ...args, flags);
+ assert.deepEqual(subprocess.spawnargs, spawnargs);
+});
+
+test("should take options for child process", () => {
+ const command = "command";
+ const args = ["arg1", "arg2"];
+ const spwanoptions = {
+ "cwd": ".",
+ "env": process.env,
+ "argv0": command,
+ "stdio": {},
+ "detached": false,
+ "uid": undefined,
+ "gid": undefined,
+ "serialization": "json",
+ "shell": false,
+ "windowsVerbatimArguments": false,
+ "windowsHide": false,
+ "signal": undefined,
+ "timeout": undefined,
+ "killSignal": "SIGTERM",
+ };
+ const flags = {
+ boolean: false,
+ ...spwanoptions,
+ }
+ const spawnargs = [command, ...args, `--no-boolean`];
+ const subprocess = rclone(command, ...args, flags);
+ assert.deepEqual(subprocess.spawnargs, spawnargs);
+ assert.deepEqual(subprocess.spwanoptions, spwanoptions);
+});
+
+test("should also be able to return promise", async () => {
+ const command = "command";
+ const args = ["arg1", "arg2"];
+ const flags = {
+ "string-flag": "string-value"
+ };
+ const spawnargs = [command, ...args, `--${Object.keys(flags)[0]}`, Object.values(flags)[0]];
+ const result = await rclone.promises(command, ...args, flags);
+ assert.equal(`${ result }`, `${spawnargs}`)
+});
diff --git a/packages/vfs/ref-rclone/api_examples.sh b/packages/vfs/ref-rclone/api_examples.sh
new file mode 100644
index 00000000..620800ad
--- /dev/null
+++ b/packages/vfs/ref-rclone/api_examples.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# Example script for API access using rclone
+
+# Define variables
+LOCAL_DIR="/path/to/local/files"
+S3_BUCKET="s3://my-bucket/backup"
+
+# S3 Examples
+
+# Upload to S3
+rclone copy "${LOCAL_DIR}" "${S3_BUCKET_}" \
+ --progress \
+ --s3-chunk-size 10M \
+ --s3-upload-concurrency 4
+
+# List files in S3 bucket
+rclone ls "${S3_BUCKET}"
+
+# Sync with S3
+rclone sync "${LOCAL_DIR}" "${S3_BUCKET_}" \
+ --progress \
+ --s3-chunk-size 10M \
+ --s3-upload-concurrency 4
+
+# Download from S3
+rclone copy "${S3_BUCKET_}" "${LOCAL_DIR}" \
+ --progress \
+ --transfers 4
+
+# Using server side encryption
+rclone copy "${LOCAL_DIR}" "${S3_BUCKET}" \
+ --progress \
+ --s3-sse-kvs-encryption
diff --git a/packages/vfs/ref-rclone/gdrive_sync.sh b/packages/vfs/ref-rclone/gdrive_sync.sh
new file mode 100644
index 00000000..5d7d249a
--- /dev/null
+++ b/packages/vfs/ref-rclone/gdrive_sync.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# Example script for Google Drive operations using rclone
+
+# Define local and remote paths
+LOCAL_DIR="./test"
+GDRIVE_DIR="gdrive:/"
+
+# Upload files to Google Drive
+#rclone copy "${LOCAL_DIR}" "${GDRIVE_DIR}" --progress --transfers 4
+
+# List files in Google Drive directory
+#rclone ls "${GDRIVE_DIR}"
+
+# Synchronize local directory with Google Drive
+rclone sync "${GDRIVE_DIR}" "${LOCAL_DIR}" --progress --track-renames
+
+# Check for differences
+#rclone check "${LOCAL_DIR}" "${GDRIVE_DIR}" --one-way
+
+# Download from Google Drive
+#rclone copy "${GDRIVE_DIR}" "${LOCAL_DIR}" --progress --transfers 4
diff --git a/packages/vfs/ref-rclone/local_sync.sh b/packages/vfs/ref-rclone/local_sync.sh
new file mode 100644
index 00000000..40f40b0c
--- /dev/null
+++ b/packages/vfs/ref-rclone/local_sync.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# Example script for local filesystem operations using rclone
+
+# Define source and destination directories
+SRC_DIR="/path/to/source"
+DEST_DIR="/path/to/destination"
+
+# Synchronize files
+rclone sync "${SRC_DIR}" "${DEST_DIR}" -v --progress
+
+# List files in destination
+rclone ls "${DEST_DIR}"
+
+# Copy specific files or directories
+rclone copy "${SRC_DIR}/specific-file.txt" "${DEST_DIR}" --progress
+
+# Check for differences
+rclone check "${SRC_DIR}" "${DEST_DIR}" --one-way
diff --git a/packages/vfs/ref-rclone/rclone-examples/README.md b/packages/vfs/ref-rclone/rclone-examples/README.md
new file mode 100644
index 00000000..df3dbf99
--- /dev/null
+++ b/packages/vfs/ref-rclone/rclone-examples/README.md
@@ -0,0 +1,20 @@
+# Rclone Configuration Examples
+
+This directory contains example configuration files for rclone demonstrating different storage backends.
+
+## Files Included
+
+1. `local.conf`: Local filesystem configuration
+2. `s3.conf`: Amazon S3 configuration
+3. `sftp.conf`: SFTP server configuration
+4. `api.conf`: Google Drive API configuration
+
+## How to Use
+
+1. Copy the relevant configuration to your rclone config file (usually `~/.config/rclone/rclone.conf`)
+2. Replace the placeholder values (e.g., `your_access_key_here`) with your actual credentials
+3. Test the configuration using `rclone ls`
+
+### Security Note
+
+These are example configurations only. Never store actual credentials in version control!
diff --git a/packages/vfs/ref-rclone/rclone-examples/api.conf b/packages/vfs/ref-rclone/rclone-examples/api.conf
new file mode 100644
index 00000000..de5f6802
--- /dev/null
+++ b/packages/vfs/ref-rclone/rclone-examples/api.conf
@@ -0,0 +1,10 @@
+# API configuration example - Google Drive API
+[googledrive]
+type = drive
+client_id = your_client_id_here
+client_secret = your_client_secret_here
+scope = drive
+root_folder_id = root
+team_drive =
+service_account_file =
+service_account_credentials =
diff --git a/packages/vfs/ref-rclone/rclone-examples/local.conf b/packages/vfs/ref-rclone/rclone-examples/local.conf
new file mode 100644
index 00000000..cb03f84e
--- /dev/null
+++ b/packages/vfs/ref-rclone/rclone-examples/local.conf
@@ -0,0 +1,8 @@
+# Local configuration example
+[local]
+type = local
+
+# Optional settings
+nopreallocate = true
+one_file_system = true
+case_sensitive = false
diff --git a/packages/vfs/ref-rclone/rclone-examples/s3.conf b/packages/vfs/ref-rclone/rclone-examples/s3.conf
new file mode 100644
index 00000000..91be082e
--- /dev/null
+++ b/packages/vfs/ref-rclone/rclone-examples/s3.conf
@@ -0,0 +1,11 @@
+# Amazon S3 configuration example
+[s3-storage]
+type = s3
+provider = AWS
+env_auth = false
+access_key_id = your_access_key_here
+secret_access_key = your_secret_key_here
+region = us-east-1
+location_constraint = US
+acl = private
+server_side_encryption = AES256
diff --git a/packages/vfs/ref-rclone/rclone-examples/sftp.conf b/packages/vfs/ref-rclone/rclone-examples/sftp.conf
new file mode 100644
index 00000000..f8f8b358
--- /dev/null
+++ b/packages/vfs/ref-rclone/rclone-examples/sftp.conf
@@ -0,0 +1,12 @@
+# SFTP configuration example
+[sftp-remote]
+type = sftp
+host = example.com
+user = username
+port = 22
+# Choose one authentication method:
+# Password authentication
+pass = your_password_here
+# OR SSH key authentication
+#kee_file = /path/to/your/id_rsa
+disable_hashcheck = false
diff --git a/packages/vfs/ref-rclone/rclone.conf b/packages/vfs/ref-rclone/rclone.conf
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/vfs/ref-server/app.module.ts b/packages/vfs/ref-server/app.module.ts
new file mode 100644
index 00000000..12e5be72
--- /dev/null
+++ b/packages/vfs/ref-server/app.module.ts
@@ -0,0 +1,18 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { CoreModule } from './core.module';
+import { entities } from './entities/index';
+import { ContextManager } from './controllers/ContextManager';
+import { AccessGuard } from './guards/access.guard';
+
+const maxListenersExceededWarning = require('max-listeners-exceeded-warning');
+maxListenersExceededWarning();
+@Module({
+ imports:[ContextManager],
+ modules: [
+ TypeOrmModule.forRoot(),
+ CoreModule
+ ],
+ controllers: []
+})
+export class AppModule { }
diff --git a/packages/vfs/ref-server/config.ts b/packages/vfs/ref-server/config.ts
new file mode 100644
index 00000000..4f93aa8a
--- /dev/null
+++ b/packages/vfs/ref-server/config.ts
@@ -0,0 +1,6 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+export const config = (): any => {
+ // data: path.join(process.cwd(), '../user')
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/ContextManager.ts b/packages/vfs/ref-server/controllers/ContextManager.ts
new file mode 100644
index 00000000..cb48d3c7
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/ContextManager.ts
@@ -0,0 +1,27 @@
+import { User } from '../entities/user.entity';
+import { Context } from '../manager/Context'
+import * as lodash from 'lodash';
+import {
+ Component
+} from '@nestjs/common';
+import { inspect, error } from '../log';
+import { EventsGateway } from './events.gateway';
+
+export class ContextManager {
+ contexts: Context[] = [];
+ context(user: User, gateway: EventsGateway): Context {
+ let context: Context = null;
+ this.contexts.forEach((c) => {
+ if (c.user.id = user.id) {
+ context = c;
+ }
+ })
+ if (!context) {
+ context = new Context();
+ this.contexts.push(context);
+ context.init(user, gateway);
+ context.run();
+ }
+ return context;
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/account.controller.ts b/packages/vfs/ref-server/controllers/account.controller.ts
new file mode 100644
index 00000000..8cf3b1fa
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/account.controller.ts
@@ -0,0 +1,79 @@
+import { Body, Controller, HttpCode, HttpStatus, Post, Req, UseGuards } from '@nestjs/common';
+import { ApiBearerAuth, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+
+import { Roles } from '../decorators/roles.decorator';
+import { InAccountLoginDto } from '../dto/in-account-login.dto';
+import { InAccountRegisterDto } from '../dto/in-account-register.dto';
+import { InAccountDto } from '../dto/in-account.dto';
+import { InTokenDto } from '../dto/in-token.dto';
+import { OutAccountTokenDto } from '../dto/out-account-token.dto';
+import { AccessGuard } from '../guards/access.guard';
+import { AccountService } from '../services/account.service';
+import { Permissions } from '../decorators/permissions.decorator';
+
+@ApiUseTags('account')
+@Controller('/api/account')
+@UseGuards(AccessGuard)
+export class AccountController {
+ constructor(
+ private accountService: AccountService
+ ) {
+
+ }
+ @HttpCode(HttpStatus.OK)
+ @Post('/info')
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutAccountTokenDto,
+ description: 'API View that checks the veracity of a token, returning the token if it is valid.'
+ })
+ async info( @Body() tokenDto: InTokenDto) {
+ try {
+ return await this.accountService.info(tokenDto);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @HttpCode(HttpStatus.OK)
+ @Post('/login')
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutAccountTokenDto,
+ description: 'API View that checks the veracity of a token, returning the token if it is valid.'
+ })
+ async login( @Body() accountLoginDto: InAccountLoginDto) {
+ try {
+ return await this.accountService.login(accountLoginDto);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @HttpCode(HttpStatus.CREATED)
+ @Post('/register')
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutAccountTokenDto,
+ description: `API View that receives a POST with a user's username and password.
+ Returns a JSON Web Token that can be used for authenticated requests.`
+ })
+ async register( @Body() accountRegisterDto: InAccountRegisterDto) {
+ try {
+ return await this.accountService.register(accountRegisterDto);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @ApiBearerAuth()
+ @Roles('isActive')
+ @Permissions('change_profile')
+ @HttpCode(HttpStatus.OK)
+ @Post('/update')
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutAccountTokenDto,
+ description: ''
+ })
+ async update( @Req() req, @Body() accountDto: InAccountDto) {
+ try {
+ return await this.accountService.update(req['user'].id, accountDto);
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/base.controller.ts b/packages/vfs/ref-server/controllers/base.controller.ts
new file mode 100644
index 00000000..09f1914f
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/base.controller.ts
@@ -0,0 +1,61 @@
+import * as reflect from 'reflect-metadata';
+
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ HttpCode,
+ HttpStatus,
+ Param,
+ ParseIntPipe,
+ Post,
+ Put,
+ Query,
+ UseGuards,
+ Request,
+ Headers,
+ Session,
+ createRouteParamDecorator,
+ Component,
+ INestApplicationContext,
+ PipeTransform
+
+
+} from '@nestjs/common';
+
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository } from 'typeorm';
+
+import { Roles } from '../decorators/roles.decorator';
+import { InDeviceDto } from '../dto/in-device.dto';
+import { OutDeviceDto } from '../dto/out-device.dto';
+import { OutDevicesDto } from '../dto/out-devices.dto';
+import { Device } from '../entities/device.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { Permissions } from '../decorators/permissions.decorator';
+import { User } from '../entities/user.entity';
+import * as debug from '../log';
+import { COMMANDS, after } from '../shared'
+import { EventsGateway } from './events.gateway';
+import { EventEmitter } from 'events';
+
+export const UserEntity = createRouteParamDecorator((data, req): any => {
+ return req.user;
+});
+
+export class BaseController extends EventEmitter {
+ /*private readonly ws: EventsGateway;*/
+ constructor(
+ ) {
+ super();
+ // console.log('ctor ', Reflect.getMetadata('path', DevicesController));
+ }
+ public broadcast(key: string, data: any) {
+ const ws = this['ws'] as EventsGateway;
+ ws.broadcast(key, data);
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/content-types.controller.ts b/packages/vfs/ref-server/controllers/content-types.controller.ts
new file mode 100644
index 00000000..f0a0b689
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/content-types.controller.ts
@@ -0,0 +1,163 @@
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ HttpCode,
+ HttpStatus,
+ Param,
+ ParseIntPipe,
+ Post,
+ Put,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository, DeleteResult } from 'typeorm';
+
+import { Roles } from '../decorators/roles.decorator';
+import { InContentTypeDto } from '../dto/in-content-type.dto';
+import { OutContentTypeDto } from '../dto/out-content-type.dto';
+import { OutContentTypesDto } from '../dto/out-content-types.dto';
+import { ContentType } from '../entities/content-type.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { Permissions } from '../decorators/permissions.decorator';
+
+@ApiUseTags('content-types')
+@ApiBearerAuth()
+@Controller('/api/content-types')
+@UseGuards(AccessGuard)
+export class ContentTypesController {
+ constructor(
+ @InjectRepository(ContentType)
+ private readonly contentTypeRepository: Repository
+ ) {
+
+ }
+ @Roles('isSuperuser')
+ @Permissions('add_content-type')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutContentTypeDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InContentTypeDto
+ ) {
+ try {
+ let object = plainToClass(ContentType, dto);
+ object = await this.contentTypeRepository.save(object)
+ return plainToClass(OutContentTypeDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('change_content-type')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutContentTypeDto,
+ description: 'The record has been successfully updated.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InContentTypeDto
+ ) {
+ try {
+ let object = plainToClass(ContentType, dto);
+ object.id = id;
+ object = await this.contentTypeRepository.save(object);
+ return plainToClass(OutContentTypeDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_content-type')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ return await this.contentTypeRepository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('read_content-type')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutContentTypeDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Get(':id')
+ async load(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ let object = await this.contentTypeRepository.findOneOrFail(id);
+ return plainToClass(OutContentTypeDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('read_content-type')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutContentTypesDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q
+ ) {
+ try {
+ const objects = await this.contentTypeRepository.findAndCount({
+ skip: (curPage - 1) * perPage,
+ take: perPage
+ });
+ return plainToClass(OutContentTypesDto, {
+ contentTypes: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/devices.controller.ts b/packages/vfs/ref-server/controllers/devices.controller.ts
new file mode 100644
index 00000000..b202127c
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/devices.controller.ts
@@ -0,0 +1,423 @@
+import * as reflect from 'reflect-metadata';
+import * as lodash from 'lodash';
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ HttpCode,
+ HttpStatus,
+ Param,
+ ParseIntPipe,
+ Post,
+ Put,
+ Query,
+ UseGuards,
+ Request,
+ Headers,
+ Session,
+ createRouteParamDecorator,
+ Component,
+ INestApplicationContext,
+ OnModuleInit
+
+
+} from '@nestjs/common';
+
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository, DeleteResult } from 'typeorm';
+
+import { Roles } from '../decorators/roles.decorator';
+import { InDeviceDto } from '../dto/in-device.dto';
+import { OutDeviceDto } from '../dto/out-device.dto';
+import { OutDevicesDto } from '../dto/out-devices.dto';
+import { Device } from '../entities/device.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { Permissions } from '../decorators/permissions.decorator';
+import { User } from '../entities/user.entity';
+import { COMMANDS, after, before, around, SIGNALS } from '../shared';
+import * as debug from '../log';
+import { EventsGateway } from './events.gateway';
+import { BaseController } from './base.controller';
+import { UserEntity } from './utils';
+import { ContextManager } from './ContextManager';
+import { UsersController } from './users.controller';
+import { ModuleRef } from '@nestjs/core';
+import { isArray } from 'util';
+import { DEVICE_STATE, DEVICE_FLAGS, LOGGING_FLAGS, DefaultCommandSettings, DefaultSettings } from '../shared/types';
+import { DeviceDto } from '../dto/device.dto';
+import { isString } from '@xblox/core/primitives';
+@ApiUseTags('devices')
+@ApiBearerAuth()
+@Controller('/api/devices')
+@UseGuards(AccessGuard)
+export class DevicesController extends BaseController implements OnModuleInit {
+ private contextManager: ContextManager;
+ constructor(
+ @InjectRepository(Device)
+ private readonly repository: Repository,
+ @InjectRepository(User)
+ private readonly usersRepository: Repository,
+ private readonly ws: EventsGateway
+ /*private readonly userService:UsersController*/
+ ) {
+ super();
+ this.contextManager = new ContextManager();
+ // console.log('ctor ', Reflect.getMetadata('path', DevicesController));
+ }
+
+ async users() {
+ const _users = await this.usersRepository.findAndCount({
+ id: 1,
+ isActive: true
+ });
+ return _users[0];
+ }
+
+ async boot() {
+
+ let _devices: [Device[], number] = await this.repository.findAndCount({
+ isActive: true
+ });
+ let devices = _devices['0'];
+
+ // debug.inspect('Module initialized...', devices);
+ const users = await this.users();
+ // debug.inspect('Module initialized...users', users);
+ users.forEach((user: User) => {
+ let ctx = this.contextManager.context(user, this.ws);
+ let userDevices = lodash.find(devices, {
+ user: user.id,
+ isActive: true
+ });
+
+ if (userDevices && !isArray(userDevices)) {
+ userDevices = [userDevices];
+ }
+ if (!userDevices) {
+ debug.warn('user ' + user.email + ' has no devices');
+ return;
+ }
+ // debug.inspect('start user devices ', userDevices);
+ userDevices.forEach((device) => {
+ ctx.start(device);
+ })
+ });
+ }
+ async onModuleInit() {
+ const log = (what: any) => {
+ for (var p in what) {
+ if (typeof what[p] !== 'function') {
+ if (typeof what[p] === 'object') {
+ log(what[p]);
+ }
+ }
+ }
+ }
+ // log(this);
+ return await this.boot();
+ }
+
+ //////////////////////////////////////
+ //
+ // Devices logic
+ //
+
+ @Permissions(COMMANDS.START_DEVICE)
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutDeviceDto,
+ description: 'The item has been successfully started'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Post('/start/:id')
+ /*
+ @after((context, args, b) => {
+ console.log('after: ', [args, b]);
+ })
+ @around((context, args, b) => {
+ console.log('around: ', [args, b]);
+ })
+ */
+ start(
+ @Param('id', new ParseIntPipe()) id,
+ @UserEntity() user: any
+ ) {
+ try {
+ return new Promise((resolve, reject) => {
+ this.repository.findOneOrFail(
+ id
+ ).then((object) => {
+ object.isActive = true;
+ let ctx = this.contextManager.context(user, this.ws);
+ if (!isString(object.logging)) {
+ object.logging = JSON.stringify(object.logging, null, 2);
+ }
+ let saved = this.repository.save(object);
+ this.emit(COMMANDS.START_DEVICE, object, user);
+ ctx.start(object).then((device: Device) => {
+ this.broadcast(COMMANDS.DEVICE_UPDATE, {
+ ...device,
+ user
+ });
+ this.repository.save(device);
+ resolve(device);
+ });
+ });
+
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ @Permissions(COMMANDS.START_DEVICE)
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutDeviceDto,
+ description: 'The item has been successfully stopped'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Post('/stop/:id')
+ stop(
+ @Param('id', new ParseIntPipe()) id,
+ @UserEntity() user: any
+ ) {
+
+ try {
+ return new Promise((resolve, reject) => {
+ this.repository.findOneOrFail(
+ id
+ ).then((object) => {
+ object.isActive = false;
+ let ctx = this.contextManager.context(user, this.ws);
+ if (!isString(object.logging)) {
+ object.logging = JSON.stringify(object.logging, null, 2);
+ }
+ let saved = this.repository.save(object);
+ this.emit(COMMANDS.STOP_DEVICE, object, user);
+ ctx.stop(object).then((device: Device) => {
+ device.state = DEVICE_STATE.DISCONNECTED;
+ this.broadcast(COMMANDS.DEVICE_UPDATE, {
+ ...device,
+ user
+ });
+ this.repository.save(device);
+ resolve(device);
+ });
+ });
+
+ });
+ } catch (error) {
+ throw error;
+ }
+ /*
+ try {
+ let object: Device = await this.repository.findOneOrFail(
+ id
+ );
+ object.isActive = false;
+ let ctx = this.contextManager.context(user, this.ws);
+ ctx.stop(object);
+ this.emit(COMMANDS.STOP_DEVICE, object, user);
+ this.broadcast(COMMANDS.DEVICE_UPDATE, {
+ ...object,
+ user
+ });
+ object = await this.repository.save(object);
+ return plainToClass(OutDeviceDto, object);
+ } catch (error) {
+ throw error;
+ }
+ */
+ }
+
+
+
+ @Roles('isSuperuser')
+ @Permissions('change_user')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutDeviceDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InDeviceDto,
+ @UserEntity() user: any
+ ) {
+ try {
+ let object = plainToClass(Device, dto);
+ let newDevice: any = {
+ name: 'Marantz',
+ isActive: true,
+ user: 1,
+ fields: '[]',
+ host: '192.168.1.20',
+ port: '23',
+ protocol: 'Tcp',
+ state: DEVICE_STATE.NONE,
+ flags: DEVICE_FLAGS.DEBUG,
+ logging: LOGGING_FLAGS.NONE,
+ blocks: JSON.stringify('{}'),
+ commandSettings: DefaultCommandSettings(),
+ settings: DefaultSettings()
+ }
+
+ let objectNew = { ...newDevice, ...object };
+ object = await this.repository.save(objectNew);
+ debug.inspect(':create', object);
+ return plainToClass(OutDeviceDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutDeviceDto,
+ description: 'The record has been successfully updated.'
+ })
+ /*@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })*/
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InDeviceDto,
+ @UserEntity() user: any
+ ) {
+ try {
+ let object = plainToClass(Device, dto);
+ object.id = id;
+ object.user = user.id;
+ if (!isString(object.logging)) {
+ debug.inspect('logging', object.logging);
+ object.logging = JSON.stringify(object.logging, null, 2);
+ }
+ object = await this.repository.save(object);
+ this.ws.broadcast(COMMANDS.DEVICE_UPDATE, object);
+ return plainToClass(OutDeviceDto, object);
+ } catch (error) {
+ debug.error('error saving device ', error);
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_user')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ console.log('deleted : ', id);
+ return await this.repository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('load_user')
+ @ApiBearerAuth()
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutDeviceDto,
+ description: '',
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Get(':id')
+ async load(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ let object = await this.repository.findOneOrFail(
+ id,
+ { relations: ['groups'] }
+ );
+ return plainToClass(OutDeviceDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ @Roles('isSuperuser')
+ @Permissions('load_user')
+ @ApiBearerAuth()
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutDevicesDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @ApiImplicitQuery({
+ name: 'group', required: false, type: Number,
+ description: 'Group id for filter data by group. (default: empty)'
+ })
+ @ApiImplicitQuery({
+ name: 'project', required: false, type: Number,
+ description: 'Group id for filter data by group. (default: empty)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q,
+ @Query('group') group,
+ @Query('project', new ParseIntWithDefaultPipe(0)) project
+ ) {
+ try {
+ let objects: [Device[], number];
+ if (!group) {
+ objects = await this.repository.findAndCount({
+ skip: (curPage - 1) * perPage,
+ take: perPage
+ });
+ } else {
+ let qb = this.repository.createQueryBuilder('device');
+ if (group) {
+ qb = qb.leftJoinAndSelect('user.groups', 'group')
+ .where('group.id = :group', { group: group })
+ }
+ qb = qb.skip((curPage - 1) * perPage)
+ .take(perPage);
+ objects = await qb.getManyAndCount();
+ }
+ if (project) {
+ objects[0] = (objects[0].filter((d) => d.project === project));
+ }
+ return plainToClass(OutDevicesDto, {
+ devices: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/events.gateway.ts b/packages/vfs/ref-server/controllers/events.gateway.ts
new file mode 100644
index 00000000..6f9faf0b
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/events.gateway.ts
@@ -0,0 +1,76 @@
+import {
+ WebSocketGateway,
+ SubscribeMessage,
+ WsResponse,
+ WebSocketServer,
+ WsException,
+ OnGatewayConnection,
+ OnGatewayDisconnect
+} from '@nestjs/websockets';
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/observable/from';
+import 'rxjs/add/operator/map';
+
+import { DevicesController } from './devices.controller';
+import { COMMANDS } from '../shared';
+import { debug } from '../log';
+import { ConnectionManager } from '../types';
+
+@WebSocketGateway()
+export class EventsGateway implements OnGatewayConnection, OnGatewayDisconnect {
+ public _clients: Array = [];
+
+ public connectionManager: ConnectionManager;
+
+ public handleConnection(client: any): any {
+ this._clients.push(client);
+ }
+ public handleDisconnect(client: any): any {
+ this._clients.splice(this._clients.indexOf(client), 1);
+ }
+ public OnGatewayConnection(a) {
+ }
+ @WebSocketServer() server;
+ @SubscribeMessage('events')
+ onEvent(client, data): Observable> {
+ const event = 'events';
+ const response = [1, 2, 3];
+ return Observable.from(response).map(res => ({ event, data: res }));
+ }
+
+
+ @SubscribeMessage(COMMANDS.PROTOCOL_METHOD)
+ onProtocolMethod(client, data): void {
+ debug('COMMANDS.PROTOCOL_METHOD', data);
+ const event = 'events';
+ const response = [1, 2, 3];
+ this.connectionManager.protocolMethod(data).then((res) => {
+ client.emit(COMMANDS.PROTOCOL_METHOD, {
+ data: data,
+ response: res
+ });
+ });
+ // return Observable.from({});
+ }
+
+ @SubscribeMessage(COMMANDS.DEVICE_SEND)
+ onDeviceSend(client, data): void {
+ debug(COMMANDS.DEVICE_SEND, data);
+ this.connectionManager.sendToDevice(data).then((res) => {
+ /*
+ client.emit(COMMANDS.PROTOCOL_METHOD, {
+ data: data,
+ response: res
+ });*/
+ });
+ }
+
+ public broadcast(eventKey: string, data: any) {
+ this._clients.forEach((client) => this.send(client, eventKey, data));
+ }
+
+ public send(connection: SocketIO.EngineSocket, eventKey: string, data: any) {
+ connection.emit(eventKey, data);
+ }
+}
+
diff --git a/packages/vfs/ref-server/controllers/groups.controller.ts b/packages/vfs/ref-server/controllers/groups.controller.ts
new file mode 100644
index 00000000..5f708165
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/groups.controller.ts
@@ -0,0 +1,165 @@
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ HttpCode,
+ HttpStatus,
+ Param,
+ ParseIntPipe,
+ Post,
+ Put,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository, DeleteResult } from 'typeorm';
+
+import { Roles } from '../decorators/roles.decorator';
+import { InGroupDto } from '../dto/in-group.dto';
+import { OutGroupDto } from '../dto/out-group.dto';
+import { OutGroupsDto } from '../dto/out-groups.dto';
+import { Group } from '../entities/group.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { Permissions } from '../decorators/permissions.decorator';
+
+@ApiUseTags('groups')
+@ApiBearerAuth()
+@Controller('/api/groups')
+@UseGuards(AccessGuard)
+export class GroupsController {
+ constructor(
+ @InjectRepository(Group)
+ private readonly groupsRepository: Repository
+ ) {
+
+ }
+ @Roles('isSuperuser')
+ @Permissions('add_group')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutGroupDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InGroupDto
+ ) {
+ try {
+ let object = plainToClass(Group, dto);
+ object = await this.groupsRepository.save(object)
+ return plainToClass(OutGroupDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('change_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutGroupDto,
+ description: 'The record has been successfully updated.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InGroupDto
+ ) {
+ try {
+ let object = plainToClass(Group, dto);
+ object.id = id;
+ object = await this.groupsRepository.save(object);
+ return plainToClass(OutGroupDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_group')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ return await this.groupsRepository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('read_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutGroupDto,
+ description: ''
+ })
+ /*@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })*/
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Get(':id')
+ async load(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ let object = await this.groupsRepository.findOneOrFail(id);
+ return plainToClass(OutGroupDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ /*@Roles('isSuperuser')*/
+ @Permissions('read_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutGroupsDto,
+ description: ''
+ })
+ /*@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })*/
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q
+ ) {
+
+ try {
+ const objects = await this.groupsRepository.findAndCount({
+ skip: (curPage - 1) * perPage,
+ take: perPage
+ });
+ return plainToClass(OutGroupsDto, {
+ groups: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/index.ts b/packages/vfs/ref-server/controllers/index.ts
new file mode 100644
index 00000000..2800094e
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/index.ts
@@ -0,0 +1,18 @@
+import { AccountController } from './account.controller';
+import { ContentTypesController } from './content-types.controller';
+import { GroupsController } from './groups.controller';
+import { PermissionsController } from './permissions.controller';
+import { UsersController } from './users.controller';
+import { DevicesController } from './devices.controller';
+import { ProjectController } from './projects.controller';
+import { VFSController } from './vfs.controller';
+export const controllers = [
+ AccountController,
+ ContentTypesController,
+ PermissionsController,
+ UsersController,
+ GroupsController,
+ DevicesController,
+ ProjectController,
+ VFSController
+]
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/permissions.controller.ts b/packages/vfs/ref-server/controllers/permissions.controller.ts
new file mode 100644
index 00000000..4392097f
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/permissions.controller.ts
@@ -0,0 +1,182 @@
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ HttpCode,
+ HttpStatus,
+ Param,
+ ParseIntPipe,
+ Post,
+ Put,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository, DeleteResult } from 'typeorm';
+
+import { Permissions } from '../decorators/permissions.decorator';
+import { Roles } from '../decorators/roles.decorator';
+import { InPermissionDto } from '../dto/in-permission.dto';
+import { OutPermissionDto } from '../dto/out-permission.dto';
+import { OutPermissionsDto } from '../dto/out-permissions.dto';
+import { Permission } from '../entities/permission.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+
+@ApiUseTags('permissions')
+@ApiBearerAuth()
+@Controller('/api/permissions')
+@UseGuards(AccessGuard)
+export class PermissionsController {
+ constructor(
+ @InjectRepository(Permission)
+ private readonly permissionsRepository: Repository
+ ) {
+
+ }
+ @Roles('isSuperuser')
+ @Permissions('add_permission')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutPermissionDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InPermissionDto
+ ) {
+ try {
+ let object = plainToClass(Permission, dto);
+ object = await this.permissionsRepository.save(object)
+ return plainToClass(OutPermissionDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('change_permission')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutPermissionDto,
+ description: 'The record has been successfully updated.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InPermissionDto
+ ) {
+ try {
+ let object = plainToClass(Permission, dto);
+ object.id = id;
+ object = await this.permissionsRepository.save(object);
+ return plainToClass(OutPermissionDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_permission')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ return await this.permissionsRepository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('read_permission')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutPermissionDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Get(':id')
+ async load(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ let object = await this.permissionsRepository.findOneOrFail(id);
+ return plainToClass(OutPermissionDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('read_permission')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutPermissionsDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @ApiImplicitQuery({
+ name: 'group', required: false, type: Number,
+ description: 'Group id for filter data by group. (default: empty)'
+ })
+ @ApiImplicitQuery({
+ name: 'content_type', required: false, type: Number,
+ description: 'Content type id for filter data by content type. (default: empty)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q,
+ @Query('group') group,
+ @Query('content_type') contentType
+ ) {
+ try {
+ let objects: [Permission[], number];
+ let qb = this.permissionsRepository.createQueryBuilder('permission');
+ if (group) {
+ qb = qb.leftJoin('permission.groups', 'group')
+ .where('group.id = :group', { group: group });
+ }
+ if (contentType) {
+ qb = qb.leftJoin('permission.content_type', 'content_type')
+ .where('content_type.id = :contentType', { contentType: contentType });
+ }
+ qb = qb.skip((curPage - 1) * perPage)
+ .take(perPage);
+ objects = await qb.getManyAndCount();
+ return plainToClass(OutPermissionsDto, {
+ permissions: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/projects.controller.ts b/packages/vfs/ref-server/controllers/projects.controller.ts
new file mode 100644
index 00000000..03977579
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/projects.controller.ts
@@ -0,0 +1,164 @@
+import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, Query, UseGuards } from '@nestjs/common';
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository } from 'typeorm';
+import { Permissions } from '../decorators/permissions.decorator';
+import { Roles } from '../decorators/roles.decorator';
+import { InProjectDto } from '../dto/in-project.dto';
+import { OutProjectDto } from '../dto/out-project.dto';
+import { Device } from '../entities/device.entity';
+import { Project } from '../entities/project.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { UserEntity } from './utils';
+@ApiUseTags('projects')
+@ApiBearerAuth()
+@Controller('/api/projects')
+@UseGuards(AccessGuard)
+export class ProjectController {
+ constructor(
+ @InjectRepository(Project)
+ private readonly projectsRepository: Repository,
+ @InjectRepository(Device)
+ private readonly deviceRepository: Repository,
+ ) {
+
+ }
+ @Roles('isSuperuser')
+ @Permissions('add_group')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutProjectDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InProjectDto
+ ) {
+ try {
+ let object = plainToClass(Project, dto);
+ object = await this.projectsRepository.save(object)
+ return plainToClass(OutProjectDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('change_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutProjectDto,
+ description: 'The record has been successfully updated.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InProjectDto
+ ) {
+ try {
+ let object = plainToClass(Project, dto);
+ object.id = id;
+ object = await this.projectsRepository.save(object);
+ return plainToClass(OutProjectDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_group')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ return await this.projectsRepository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('read_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutProjectDto,
+ description: ''
+ })
+ /*@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })*/
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Get(':id')
+ async load(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ let object = await this.projectsRepository.findOneOrFail(id);
+ return plainToClass(OutProjectDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ /*@Roles('isSuperuser')*/
+ @Permissions('read_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutProjectDto,
+ description: ''
+ })
+ /*@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })*/
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q,
+ @UserEntity() user: any
+ ) {
+ try {
+ const objects = await this.projectsRepository.findAndCount({
+ skip: (curPage - 1) * perPage,
+ take: perPage
+ });
+ objects[0] = objects[0].filter((p) => p.user === user.id);
+
+ const devices = await this.deviceRepository.find({
+ user: user.id
+ });
+
+ objects[0].forEach((p) => {
+ p['devices'] = devices.filter((d) => d.project === p.id);
+ });
+
+ // console.log('all', user, objects[0]);
+ return plainToClass(OutProjectDto, {
+ groups: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/users.controller.ts b/packages/vfs/ref-server/controllers/users.controller.ts
new file mode 100644
index 00000000..d7ae100f
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/users.controller.ts
@@ -0,0 +1,188 @@
+import {
+ Body,
+ Controller,
+ Delete,
+ Get,
+ HttpCode,
+ HttpStatus,
+ Param,
+ ParseIntPipe,
+ Post,
+ Put,
+ Query,
+ UseGuards,
+} from '@nestjs/common';
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository, DeleteResult } from 'typeorm';
+
+import { Roles } from '../decorators/roles.decorator';
+import { InUserDto } from '../dto/in-user.dto';
+import { OutUserDto } from '../dto/out-user.dto';
+import { OutUsersDto } from '../dto/out-users.dto';
+import { User } from '../entities/user.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { Permissions } from '../decorators/permissions.decorator';
+
+@ApiUseTags('users')
+@ApiBearerAuth()
+@Controller('/api/users')
+@UseGuards(AccessGuard)
+export class UsersController {
+ constructor(
+ @InjectRepository(User)
+ private readonly usersRepository: Repository
+ ) {
+
+ }
+ @Roles('isSuperuser')
+ @Permissions('add_user')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutUserDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InUserDto
+ ) {
+ try {
+ let object = plainToClass(User, dto);
+ object.setPassword(object.password);
+ object = await this.usersRepository.save(object)
+ return plainToClass(OutUserDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('change_user')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutUserDto,
+ description: 'The record has been successfully updated.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InUserDto
+ ) {
+ try {
+ let object = plainToClass(User, dto);
+ object.id = id;
+ object.setPassword(object.password);
+ object = await this.usersRepository.save(object);
+ return plainToClass(OutUserDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_user')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ return await this.usersRepository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('load_user')
+ @ApiBearerAuth()
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutUserDto,
+ description: '',
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Get(':id')
+ async load(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+
+ try {
+ let object = await this.usersRepository.findOneOrFail(
+ id,
+ { relations: ['groups'] }
+ );
+ return plainToClass(OutUserDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('load_user')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutUsersDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @ApiImplicitQuery({
+ name: 'group', required: false, type: Number,
+ description: 'Group id for filter data by group. (default: empty)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q,
+ @Query('group') group
+ ) {
+ try {
+ let objects: [User[], number];
+ if (!group) {
+ objects = await this.usersRepository.findAndCount({
+ skip: (curPage - 1) * perPage,
+ take: perPage,
+ relations: ['groups']
+ });
+ } else {
+ let qb = this.usersRepository.createQueryBuilder('user');
+ if (group) {
+ qb = qb.leftJoinAndSelect('user.groups', 'group')
+ .where('group.id = :group', { group: group })
+ }
+ qb = qb.skip((curPage - 1) * perPage)
+ .take(perPage);
+ objects = await qb.getManyAndCount();
+ }
+ return plainToClass(OutUsersDto, {
+ users: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/controllers/utils.ts b/packages/vfs/ref-server/controllers/utils.ts
new file mode 100644
index 00000000..ed38ff74
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/utils.ts
@@ -0,0 +1,10 @@
+import * as reflect from 'reflect-metadata';
+import { User } from '../entities/user.entity';
+import {
+ createRouteParamDecorator,
+ PipeTransform
+} from '@nestjs/common';
+
+export const UserEntity = createRouteParamDecorator((data, req): User => {
+ return req.user;
+});
diff --git a/packages/vfs/ref-server/controllers/vfs.controller.ts b/packages/vfs/ref-server/controllers/vfs.controller.ts
new file mode 100644
index 00000000..d5048546
--- /dev/null
+++ b/packages/vfs/ref-server/controllers/vfs.controller.ts
@@ -0,0 +1,197 @@
+import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post, Put, Query, UseGuards, createRouteParamDecorator, Request } from '@nestjs/common';
+import { ApiBearerAuth, ApiImplicitParam, ApiImplicitQuery, ApiResponse, ApiUseTags } from '@nestjs/swagger';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository } from 'typeorm';
+import { Permissions } from '../decorators/permissions.decorator';
+import { Roles } from '../decorators/roles.decorator';
+import { InFileDto } from '../dto/in-file.dto';
+import { OutFileDto } from '../dto/out-file.dto';
+import { File } from '../entities/file.entity';
+import { Project } from '../entities/project.entity';
+import { AccessGuard } from '../guards/access.guard';
+import { ParseIntWithDefaultPipe } from '../pipes/parse-int-with-default.pipe';
+import { UserEntity } from './utils';
+import { inspect } from '../log';
+
+import { config } from '../config';
+import { User } from '../entities/user.entity';
+
+
+export const PathEntity = createRouteParamDecorator((data, req: any): string => {
+ return req._parsedUrl.path;
+});
+
+@ApiUseTags('vfs')
+@ApiBearerAuth()
+@Controller('/api/vfs')
+@UseGuards(AccessGuard)
+export class VFSController {
+ constructor(
+ @InjectRepository(File)
+ private readonly vfsepository: Repository
+ ) {
+
+ }
+ @Roles('isSuperuser')
+ @Permissions('add_group')
+ @HttpCode(HttpStatus.CREATED)
+ @ApiResponse({
+ status: HttpStatus.CREATED, type: OutFileDto,
+ description: 'The record has been successfully created.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Post()
+ async create(
+ @Body() dto: InFileDto
+ ) {
+ try {
+ let object = plainToClass(Project, dto);
+ object = await this.vfsepository.save(object)
+ return plainToClass(OutFileDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('change_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutFileDto,
+ description: 'The record has been successfully updated.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Put(':id')
+ async update(
+ @Param('id', new ParseIntPipe()) id,
+ @Body() dto: InFileDto
+ ) {
+ try {
+ let object = plainToClass(Project, dto);
+ object.id = id;
+ object = await this.vfsepository.save(object);
+ return plainToClass(OutFileDto, object);
+ } catch (error) {
+ throw error;
+ }
+ }
+ @Roles('isSuperuser')
+ @Permissions('delete_group')
+ @HttpCode(HttpStatus.NO_CONTENT)
+ @ApiResponse({
+ status: HttpStatus.NO_CONTENT,
+ description: 'The record has been successfully deleted.'
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @ApiImplicitParam({ name: 'id', type: Number })
+ @Delete(':id')
+ async delete(
+ @Param('id', new ParseIntPipe()) id
+ ) {
+ try {
+ return await this.vfsepository.delete(id);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ @ApiBearerAuth()
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutFileDto,
+ description: ''
+ })
+ @ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })
+ @Get('/*/')
+ async load(
+ @UserEntity() user: any,
+ @PathEntity() path: any
+ ) {
+ const objects = await this.vfsepository.findAndCount({
+ path: path
+ });
+
+ // objects[0] = objects[0].filter((f) => f.path === path);
+ // inspect('o2', objects[0]);
+ //objects[0] = objects[0].filter((f) => f.path === path && f.user === user.id);
+ //inspect('o2', objects);
+ /*
+ let object = await this.vfsepository.findOneOrFail(1);
+ */
+ // console.log('o', objects[0]);
+ if(objects[0][0]){
+ return (objects[0][0] as any).content;
+ }
+ return 'asdf ' + path;
+ }
+ /*
+ console.log('1');
+ try {
+ let object = await this.vfsepository.findOneOrFail(id);
+ return plainToClass(OutFileDto, object);
+ } catch (error) {
+ throw error;
+ }-9
+
+}
+
+
+
+
+/*@Roles('isSuperuser')*/
+ @Permissions('read_group')
+ @HttpCode(HttpStatus.OK)
+ @ApiResponse({
+ status: HttpStatus.OK, type: OutFileDto,
+ description: ''
+ })
+ /*@ApiResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden.' })*/
+ @ApiImplicitQuery({ name: 'q', required: false, type: String, description: 'Text for search (default: empty)' })
+ @ApiImplicitQuery({
+ name: 'per_page', required: false, type: Number,
+ description: 'Number of results to return per page. (default: 10)'
+ })
+ @ApiImplicitQuery({
+ name: 'cur_page', required: false, type: Number,
+ description: 'A page number within the paginated result set. (default: 1)'
+ })
+ @Get()
+ async loadAll(
+ @Query('cur_page', new ParseIntWithDefaultPipe(1)) curPage,
+ @Query('per_page', new ParseIntWithDefaultPipe(10)) perPage,
+ @Query('q') q,
+ @UserEntity() user: any
+ ) {
+ try {
+ /*
+ const objects = await this.projectsRepository.findAndCount({
+ skip: (curPage - 1) * perPage,
+ take: perPage
+ });
+ objects[0] = objects[0].filter((p) => p.user === user.id);
+
+ const devices = await this.deviceRepository.find({
+ user: user.id
+ });
+
+ objects[0].forEach((p) => {
+ p['devices'] = devices.filter((d) => d.project === p.id);
+ });
+
+ // console.log('all', user, objects[0]);
+ return plainToClass(OutFileDto, {
+ groups: objects[0],
+ meta: {
+ perPage: perPage,
+ totalPages: perPage > objects[1] ? 1 : (objects[1] / perPage),
+ totalResults: objects[1],
+ curPage: curPage
+ }
+ });
+ */
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/core.module.ts b/packages/vfs/ref-server/core.module.ts
new file mode 100644
index 00000000..2df22e92
--- /dev/null
+++ b/packages/vfs/ref-server/core.module.ts
@@ -0,0 +1,21 @@
+import { Module } from '@nestjs/common';
+import { ContextManager } from './controllers/ContextManager';
+import { controllers } from './controllers/index';
+import { services } from './services/index';
+import { TypeOrmModule } from '@nestjs/typeorm';
+import { entities } from './entities/index';
+import { EventsGateway } from './controllers/events.gateway';
+@Module({
+ imports: [
+ TypeOrmModule.forFeature([...entities])
+ ],
+ controllers: [
+ ...controllers
+ ],
+ components: [
+ ...services,
+ EventsGateway
+ ],
+})
+export class CoreModule {
+}
diff --git a/packages/vfs/ref-server/decorators/permissions.decorator.ts b/packages/vfs/ref-server/decorators/permissions.decorator.ts
new file mode 100644
index 00000000..05607e13
--- /dev/null
+++ b/packages/vfs/ref-server/decorators/permissions.decorator.ts
@@ -0,0 +1,3 @@
+import { ReflectMetadata } from '@nestjs/common';
+
+export const Permissions = (...permissions: string[]) => ReflectMetadata('permissions', permissions);
\ No newline at end of file
diff --git a/packages/vfs/ref-server/decorators/roles.decorator.ts b/packages/vfs/ref-server/decorators/roles.decorator.ts
new file mode 100644
index 00000000..91407a6e
--- /dev/null
+++ b/packages/vfs/ref-server/decorators/roles.decorator.ts
@@ -0,0 +1,3 @@
+import { ReflectMetadata } from '@nestjs/common';
+
+export const Roles = (...roles: string[]) => ReflectMetadata('roles', roles);
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/account.dto.ts b/packages/vfs/ref-server/dto/account.dto.ts
new file mode 100644
index 00000000..c02aeae5
--- /dev/null
+++ b/packages/vfs/ref-server/dto/account.dto.ts
@@ -0,0 +1,12 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { GroupWithPermissionsDto } from './group-with-permissions.dto';
+import { UserDto } from './user.dto';
+
+export class AccountDto extends UserDto {
+
+ @Type(() => GroupWithPermissionsDto)
+ @ApiModelProperty({ type: GroupWithPermissionsDto, isArray: true })
+ groups: GroupWithPermissionsDto[]
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/content-type.dto.ts b/packages/vfs/ref-server/dto/content-type.dto.ts
new file mode 100644
index 00000000..30b132bb
--- /dev/null
+++ b/packages/vfs/ref-server/dto/content-type.dto.ts
@@ -0,0 +1,14 @@
+import { MaxLength } from 'class-validator';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class ContentTypeDto {
+
+ @ApiModelProperty({ type: Number })
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/device.dto.ts b/packages/vfs/ref-server/dto/device.dto.ts
new file mode 100644
index 00000000..01dfaa80
--- /dev/null
+++ b/packages/vfs/ref-server/dto/device.dto.ts
@@ -0,0 +1,55 @@
+import { Exclude, Type } from 'class-transformer';
+import { MaxLength } from 'class-validator';
+
+import { ApiModelProperty, ApiModelPropertyOptional, } from '@nestjs/swagger';
+import { LOGGING_FLAGS, DEVICE_STATE, DEVICE_FLAGS, RETRY_SETTINGS, DefaultRetry } from '../types';
+export class DeviceDto {
+
+ @ApiModelProperty({ type: Number, required: false })
+ id: number;
+
+ @ApiModelProperty({ type: Boolean, required: false })
+ isActive: boolean;
+
+ @ApiModelProperty({ type: String, default:'My Device' })
+ name: string;
+
+ @ApiModelProperty({ type: String,required:false, default:'[]' })
+ fields: string;
+
+ @ApiModelProperty({ type: Number, required: false })
+ user: number;
+
+ @ApiModelProperty({ type: Number, required: false })
+ project: number;
+
+ @ApiModelProperty({ type: Number, required: false })
+ flags: number = DEVICE_FLAGS.NONE;
+
+ @ApiModelProperty({ type: String, required: false })
+ state: number = DEVICE_FLAGS.NONE;
+
+ @ApiModelProperty({ type: String, required: false })
+ host: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ port: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ protocol: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ logging: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ retry: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ blocks: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ commandSettings: string;
+
+ @ApiModelProperty({ type: String, required: false })
+ settings: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/file.dto.ts b/packages/vfs/ref-server/dto/file.dto.ts
new file mode 100644
index 00000000..8f753640
--- /dev/null
+++ b/packages/vfs/ref-server/dto/file.dto.ts
@@ -0,0 +1,5 @@
+import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
+export class FileDto {
+ @ApiModelProperty({ type: String, default: 'My Project' })
+ path: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/group-with-permissions.dto.ts b/packages/vfs/ref-server/dto/group-with-permissions.dto.ts
new file mode 100644
index 00000000..af4174b8
--- /dev/null
+++ b/packages/vfs/ref-server/dto/group-with-permissions.dto.ts
@@ -0,0 +1,20 @@
+import { Type } from 'class-transformer';
+import { MaxLength } from 'class-validator';
+
+import { PermissionDto } from './permission.dto';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class GroupWithPermissionsDto {
+
+ @ApiModelProperty({ type: Number })
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+ @Type(() => PermissionDto)
+ @ApiModelProperty({ type: PermissionDto, isArray: true })
+ permissions: PermissionDto[]
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/group.dto.ts b/packages/vfs/ref-server/dto/group.dto.ts
new file mode 100644
index 00000000..237cb3dd
--- /dev/null
+++ b/packages/vfs/ref-server/dto/group.dto.ts
@@ -0,0 +1,15 @@
+import { IsNotEmpty, MaxLength } from 'class-validator';
+import { Exclude } from 'class-transformer';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class GroupDto {
+
+ @ApiModelProperty({ type: Number })
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-account-login.dto.ts b/packages/vfs/ref-server/dto/in-account-login.dto.ts
new file mode 100644
index 00000000..d9d2dd42
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-account-login.dto.ts
@@ -0,0 +1,16 @@
+import { IsEmail, IsNotEmpty, MaxLength } from 'class-validator';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class InAccountLoginDto {
+
+ @IsNotEmpty()
+ @IsEmail()
+ @MaxLength(254)
+ @ApiModelProperty()
+ email: string;
+
+ @IsNotEmpty()
+ @MaxLength(128)
+ @ApiModelProperty()
+ password: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-account-register.dto.ts b/packages/vfs/ref-server/dto/in-account-register.dto.ts
new file mode 100644
index 00000000..2df974ea
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-account-register.dto.ts
@@ -0,0 +1,17 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { IsEmail, IsNotEmpty, MaxLength } from 'class-validator';
+
+
+export class InAccountRegisterDto {
+
+ @IsNotEmpty()
+ @IsEmail()
+ @MaxLength(254)
+ @ApiModelProperty()
+ email: string;
+
+ @IsNotEmpty()
+ @MaxLength(128)
+ @ApiModelProperty()
+ password: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-account.dto.ts b/packages/vfs/ref-server/dto/in-account.dto.ts
new file mode 100644
index 00000000..fbca00eb
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-account.dto.ts
@@ -0,0 +1,26 @@
+import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
+import { Type, Expose } from 'class-transformer';
+import { IsOptional, MaxLength } from 'class-validator';
+
+import { GroupDto } from './group.dto';
+import { UserDto } from './user.dto';
+
+export class InAccountDto {
+
+ @IsOptional()
+ id: number;
+ @MaxLength(128)
+ @IsOptional()
+ @ApiModelPropertyOptional()
+ password: string;
+
+ @MaxLength(150)
+ @ApiModelProperty()
+ username: string;
+ @MaxLength(30)
+ @ApiModelProperty()
+ firstName: string;
+ @MaxLength(30)
+ @ApiModelProperty()
+ lastName: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-content-type.dto.ts b/packages/vfs/ref-server/dto/in-content-type.dto.ts
new file mode 100644
index 00000000..d02a3d4f
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-content-type.dto.ts
@@ -0,0 +1,14 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { IsOptional, MaxLength } from 'class-validator';
+
+export class InContentTypeDto {
+
+ @IsOptional()
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-device.dto.ts b/packages/vfs/ref-server/dto/in-device.dto.ts
new file mode 100644
index 00000000..c794d979
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-device.dto.ts
@@ -0,0 +1,10 @@
+import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { IsOptional, MaxLength } from 'class-validator';
+
+import { GroupDto } from './group.dto';
+import { DeviceDto } from './device.dto';
+
+export class InDeviceDto extends DeviceDto {
+
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-file.dto.ts b/packages/vfs/ref-server/dto/in-file.dto.ts
new file mode 100644
index 00000000..1f10723f
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-file.dto.ts
@@ -0,0 +1,3 @@
+import { FileDto } from './file.dto';
+export class InFileDto extends FileDto {
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-group.dto.ts b/packages/vfs/ref-server/dto/in-group.dto.ts
new file mode 100644
index 00000000..dfe37f79
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-group.dto.ts
@@ -0,0 +1,14 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { IsOptional, MaxLength } from 'class-validator';
+
+export class InGroupDto {
+
+ @IsOptional()
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-permission.dto.ts b/packages/vfs/ref-server/dto/in-permission.dto.ts
new file mode 100644
index 00000000..cb1626a1
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-permission.dto.ts
@@ -0,0 +1,20 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { IsOptional, MaxLength } from 'class-validator';
+
+import { ContentTypeDto } from './content-type.dto';
+
+export class InPermissionDto {
+
+ @IsOptional()
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+ @Type(() => ContentTypeDto)
+ @ApiModelProperty({ type: ContentTypeDto })
+ contentType: ContentTypeDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-project.dto.ts b/packages/vfs/ref-server/dto/in-project.dto.ts
new file mode 100644
index 00000000..198d704c
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-project.dto.ts
@@ -0,0 +1,4 @@
+import { ProjectDto } from './project.dto';
+export class InProjectDto extends ProjectDto {
+
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-token.dto.ts b/packages/vfs/ref-server/dto/in-token.dto.ts
new file mode 100644
index 00000000..a54c769d
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-token.dto.ts
@@ -0,0 +1,9 @@
+import { IsNotEmpty } from 'class-validator';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class InTokenDto {
+
+ @ApiModelProperty()
+ @IsNotEmpty()
+ token: string;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/in-user.dto.ts b/packages/vfs/ref-server/dto/in-user.dto.ts
new file mode 100644
index 00000000..642afa12
--- /dev/null
+++ b/packages/vfs/ref-server/dto/in-user.dto.ts
@@ -0,0 +1,44 @@
+import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { IsOptional, MaxLength } from 'class-validator';
+
+import { GroupDto } from './group.dto';
+import { UserDto } from './user.dto';
+
+export class InUserDto extends UserDto {
+
+ @IsOptional()
+ id: number;
+ @MaxLength(128)
+ @IsOptional()
+ @ApiModelPropertyOptional()
+ password: string;
+
+ @ApiModelPropertyOptional({ type: String })
+ lastLogin: Date;
+ @ApiModelProperty({ type: Boolean })
+ isSuperuser: boolean;
+ @MaxLength(150)
+ @ApiModelProperty()
+ username: string;
+ @MaxLength(30)
+ @ApiModelProperty()
+ firstName: string;
+ @MaxLength(30)
+ @ApiModelProperty()
+ lastName: string;
+ @MaxLength(254)
+ @ApiModelProperty()
+ email: string;
+ @ApiModelProperty({ type: Boolean })
+ isStaff: boolean;
+ @ApiModelProperty({ type: Boolean })
+ isActive: boolean;
+ @ApiModelProperty({ type: String })
+ dateJoined: Date;
+ @ApiModelPropertyOptional({ type: String })
+ dateOfBirth: Date;
+ @Type(() => GroupDto)
+ @ApiModelProperty({ type: GroupDto, isArray: true })
+ groups: GroupDto[]
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/meta.dto.ts b/packages/vfs/ref-server/dto/meta.dto.ts
new file mode 100644
index 00000000..39c42e4e
--- /dev/null
+++ b/packages/vfs/ref-server/dto/meta.dto.ts
@@ -0,0 +1,12 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class MetaDto {
+ @ApiModelProperty({ type: Number })
+ perPage: number;
+ @ApiModelProperty({ type: Number })
+ totalPages: number;
+ @ApiModelProperty({ type: Number })
+ totalResults: number;
+ @ApiModelProperty({ type: Number })
+ curPage: number;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-account-token.dto.ts b/packages/vfs/ref-server/dto/out-account-token.dto.ts
new file mode 100644
index 00000000..a0358725
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-account-token.dto.ts
@@ -0,0 +1,14 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { AccountDto } from './account.dto';
+
+export class OutAccountTokenDto {
+
+ @ApiModelProperty()
+ token: string;
+
+ @Type(() => AccountDto)
+ @ApiModelProperty({ type: AccountDto })
+ user: AccountDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-content-type.dto.ts b/packages/vfs/ref-server/dto/out-content-type.dto.ts
new file mode 100644
index 00000000..bcc0d458
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-content-type.dto.ts
@@ -0,0 +1,10 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { ContentTypeDto } from './content-type.dto';
+
+export class OutContentTypeDto {
+ @Type(() => ContentTypeDto)
+ @ApiModelProperty({ type: ContentTypeDto })
+ contentType: ContentTypeDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-content-types.dto.ts b/packages/vfs/ref-server/dto/out-content-types.dto.ts
new file mode 100644
index 00000000..7205ec1c
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-content-types.dto.ts
@@ -0,0 +1,14 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { ContentTypeDto } from './content-type.dto';
+import { MetaDto } from './meta.dto';
+
+export class OutContentTypesDto {
+ @Type(() => ContentTypeDto)
+ @ApiModelProperty({ type: ContentTypeDto, isArray: true })
+ contentTypes: ContentTypeDto[];
+ @Type(() => MetaDto)
+ @ApiModelProperty({ type: MetaDto })
+ meta: MetaDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-device.dto.ts b/packages/vfs/ref-server/dto/out-device.dto.ts
new file mode 100644
index 00000000..ab196bbd
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-device.dto.ts
@@ -0,0 +1,9 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { DeviceDto } from './device.dto';
+
+export class OutDeviceDto {
+ @Type(() => DeviceDto)
+ @ApiModelProperty({ type: DeviceDto })
+ device: DeviceDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-devices.dto.ts b/packages/vfs/ref-server/dto/out-devices.dto.ts
new file mode 100644
index 00000000..468ee495
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-devices.dto.ts
@@ -0,0 +1,14 @@
+import { Type } from 'class-transformer';
+
+import { MetaDto } from './meta.dto';
+import { DeviceDto } from './device.dto';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class OutDevicesDto {
+ @Type(() => DeviceDto)
+ @ApiModelProperty({ type: DeviceDto, isArray: true })
+ devices: DeviceDto[];
+ @Type(() => MetaDto)
+ @ApiModelProperty({ type: MetaDto })
+ meta: MetaDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-file.dto.ts b/packages/vfs/ref-server/dto/out-file.dto.ts
new file mode 100644
index 00000000..21666cd6
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-file.dto.ts
@@ -0,0 +1,9 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { FileDto } from './file.dto';
+
+export class OutFileDto {
+ @Type(() => FileDto)
+ @ApiModelProperty({ type: FileDto })
+ file: FileDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-group.dto.ts b/packages/vfs/ref-server/dto/out-group.dto.ts
new file mode 100644
index 00000000..2298ce7b
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-group.dto.ts
@@ -0,0 +1,10 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { GroupDto } from './group.dto';
+
+export class OutGroupDto {
+ @Type(() => GroupDto)
+ @ApiModelProperty({ type: GroupDto })
+ group: GroupDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-groups.dto.ts b/packages/vfs/ref-server/dto/out-groups.dto.ts
new file mode 100644
index 00000000..38795192
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-groups.dto.ts
@@ -0,0 +1,14 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { GroupDto } from './group.dto';
+import { MetaDto } from './meta.dto';
+
+export class OutGroupsDto {
+ @Type(() => GroupDto)
+ @ApiModelProperty({ type: GroupDto, isArray: true })
+ groups: GroupDto[];
+ @Type(() => MetaDto)
+ @ApiModelProperty({ type: MetaDto })
+ meta: MetaDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-permission.dto.ts b/packages/vfs/ref-server/dto/out-permission.dto.ts
new file mode 100644
index 00000000..7d41bccc
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-permission.dto.ts
@@ -0,0 +1,11 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { PermissionDto } from './permission.dto';
+
+
+export class OutPermissionDto {
+ @Type(() => PermissionDto)
+ @ApiModelProperty({ type: PermissionDto })
+ permission: PermissionDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-permissions.dto.ts b/packages/vfs/ref-server/dto/out-permissions.dto.ts
new file mode 100644
index 00000000..9fdb7553
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-permissions.dto.ts
@@ -0,0 +1,14 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { PermissionDto } from './permission.dto';
+import { MetaDto } from './meta.dto';
+
+export class OutPermissionsDto {
+ @Type(() => PermissionDto)
+ @ApiModelProperty({ type: PermissionDto, isArray: true })
+ permissions: PermissionDto[];
+ @Type(() => MetaDto)
+ @ApiModelProperty({ type: MetaDto })
+ meta: MetaDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-project.dto.ts b/packages/vfs/ref-server/dto/out-project.dto.ts
new file mode 100644
index 00000000..be2acfe1
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-project.dto.ts
@@ -0,0 +1,9 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { ProjectDto } from './project.dto';
+
+export class OutProjectDto {
+ @Type(() => ProjectDto)
+ @ApiModelProperty({ type: ProjectDto })
+ project: ProjectDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-user.dto.ts b/packages/vfs/ref-server/dto/out-user.dto.ts
new file mode 100644
index 00000000..17057f37
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-user.dto.ts
@@ -0,0 +1,10 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+
+import { UserDto } from './user.dto';
+
+export class OutUserDto {
+ @Type(() => UserDto)
+ @ApiModelProperty({ type: UserDto })
+ user: UserDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/out-users.dto.ts b/packages/vfs/ref-server/dto/out-users.dto.ts
new file mode 100644
index 00000000..7ae678e5
--- /dev/null
+++ b/packages/vfs/ref-server/dto/out-users.dto.ts
@@ -0,0 +1,14 @@
+import { Type } from 'class-transformer';
+
+import { MetaDto } from './meta.dto';
+import { UserDto } from './user.dto';
+import { ApiModelProperty } from '@nestjs/swagger';
+
+export class OutUsersDto {
+ @Type(() => UserDto)
+ @ApiModelProperty({ type: UserDto, isArray: true })
+ users: UserDto[];
+ @Type(() => MetaDto)
+ @ApiModelProperty({ type: MetaDto })
+ meta: MetaDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/permission.dto.ts b/packages/vfs/ref-server/dto/permission.dto.ts
new file mode 100644
index 00000000..360d16c7
--- /dev/null
+++ b/packages/vfs/ref-server/dto/permission.dto.ts
@@ -0,0 +1,20 @@
+import { ApiModelProperty } from '@nestjs/swagger';
+import { Type } from 'class-transformer';
+import { MaxLength } from 'class-validator';
+
+import { ContentTypeDto } from './content-type.dto';
+
+export class PermissionDto {
+
+ @ApiModelProperty({ type: Number })
+ id: number;
+ @MaxLength(100)
+ @ApiModelProperty()
+ name: string;
+ @MaxLength(255)
+ @ApiModelProperty()
+ title: string;
+ @Type(() => ContentTypeDto)
+ @ApiModelProperty({ type: ContentTypeDto })
+ contentType: ContentTypeDto;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/project.dto.ts b/packages/vfs/ref-server/dto/project.dto.ts
new file mode 100644
index 00000000..7821d440
--- /dev/null
+++ b/packages/vfs/ref-server/dto/project.dto.ts
@@ -0,0 +1,21 @@
+import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
+export class ProjectDto {
+
+ @ApiModelProperty({ type: Number, required: false })
+ id: number;
+
+ @ApiModelProperty({ type: Number, required: false })
+ user: number;
+
+ @ApiModelProperty({ type: String, default:'My Project' })
+ name: string;
+
+ @ApiModelProperty({ type: String, required: false, default:'{}' })
+ settings: string;
+
+ @ApiModelPropertyOptional({ type: String })
+ created: Date;
+
+ @ApiModelPropertyOptional({ type: String })
+ lastEdited: Date;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/dto/user.dto.ts b/packages/vfs/ref-server/dto/user.dto.ts
new file mode 100644
index 00000000..1b765f26
--- /dev/null
+++ b/packages/vfs/ref-server/dto/user.dto.ts
@@ -0,0 +1,41 @@
+import { Exclude, Type } from 'class-transformer';
+import { MaxLength } from 'class-validator';
+
+import { ApiModelProperty, ApiModelPropertyOptional } from '@nestjs/swagger';
+import { GroupDto } from './group.dto';
+
+export class UserDto {
+
+ @ApiModelProperty({ type: Number })
+ id: number;
+ @Exclude()
+ @ApiModelPropertyOptional()
+ password: string;
+ @ApiModelPropertyOptional({ type: String })
+ lastLogin: Date;
+ @ApiModelProperty({ type: Boolean })
+ isSuperuser: boolean;
+ @MaxLength(150)
+ @ApiModelProperty()
+ username: string;
+ @MaxLength(30)
+ @ApiModelProperty()
+ firstName: string;
+ @MaxLength(30)
+ @ApiModelProperty()
+ lastName: string;
+ @MaxLength(254)
+ @ApiModelProperty()
+ email: string;
+ @ApiModelProperty({ type: Boolean })
+ isStaff: boolean;
+ @ApiModelProperty({ type: Boolean })
+ isActive: boolean;
+ @ApiModelProperty({ type: String })
+ dateJoined: Date;
+ @ApiModelPropertyOptional({ type: String })
+ dateOfBirth: Date;
+ @Type(() => GroupDto)
+ @ApiModelProperty({ type: GroupDto, isArray: true })
+ groups: GroupDto[]
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/content-type.entity.ts b/packages/vfs/ref-server/entities/content-type.entity.ts
new file mode 100644
index 00000000..59ab0cd0
--- /dev/null
+++ b/packages/vfs/ref-server/entities/content-type.entity.ts
@@ -0,0 +1,40 @@
+import { IsNotEmpty, MaxLength, validateSync } from 'class-validator';
+import { BeforeInsert, BeforeUpdate, Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
+
+import { Permission } from './permission.entity';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+@Entity({ name: 'content_type' })
+export class ContentType {
+ @PrimaryGeneratedColumn()
+ id: number;
+
+ @Column({ length: 100 })
+ @IsNotEmpty()
+ @MaxLength(100)
+ name: string;
+
+ @Column({ length: 255 })
+ @IsNotEmpty()
+ @MaxLength(255)
+ title: string;
+
+ @OneToMany(type => Permission, permission => permission.contentType)
+ permissions: Permission[];
+
+ @BeforeInsert()
+ doBeforeInsertion() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/device.entity.ts b/packages/vfs/ref-server/entities/device.entity.ts
new file mode 100644
index 00000000..2ff72334
--- /dev/null
+++ b/packages/vfs/ref-server/entities/device.entity.ts
@@ -0,0 +1,151 @@
+import { IsString, IsEmail, IsNotEmpty, IsOptional, MaxLength, validateSync, IsNumber } from 'class-validator';
+import {
+ BeforeInsert,
+ BeforeUpdate,
+ Column,
+ CreateDateColumn,
+ Entity,
+ JoinTable,
+ ManyToMany,
+ PrimaryGeneratedColumn,
+ UpdateDateColumn,
+ ColumnType,
+ AfterLoad
+} from 'typeorm';
+
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+import {
+ LOGGING_FLAGS,
+ DEVICE_STATE,
+ DEVICE_FLAGS,
+ RETRY_SETTINGS,
+ DefaultRetry,
+ DefaultBlocks,
+ DefaultSettings,
+ DefaultCommandSettings
+} from '../shared/types';
+import { ValueTransformer } from 'typeorm/decorator/options/ValueTransformer';
+import { isString } from '@xblox/core/primitives';
+import { debug } from '../log';
+
+export const JSON_TRANSFORMER: ValueTransformer = {
+ to(value: any): string {
+ if (!isString(value)) {
+ return JSON.stringify(value, null, 2);
+ } else {
+ return value;
+ }
+ },
+ from(value: string): any {
+ if (isString(value)) {
+ return JSON.parse(value);
+ }
+ return value;
+ }
+}
+
+@Entity()
+export class Device {
+
+ public scope: any;
+
+ @IsOptional()
+ @PrimaryGeneratedColumn()
+ id: number;
+
+
+ @Column({ length: 150 })
+ @IsNotEmpty()
+ @MaxLength(150)
+ name: string;
+
+ @Column()
+ @IsNotEmpty()
+ host: string;
+
+ @Column()
+ @IsNotEmpty()
+ port: string;
+
+ @Column()
+ @IsNotEmpty()
+ protocol: string;
+
+ @Column()
+ @IsString()
+ @IsOptional()
+ state: string = DEVICE_STATE.NONE;
+
+ @Column()
+ @IsNumber()
+ @IsOptional()
+ flags: number = DEVICE_FLAGS.NONE;
+
+ @Column()
+ @IsString()
+ @IsOptional()
+ logging: string = "{\n \"Device Connected\": 47,\n \"Response\": 35,\n \"Send Command\": 51,\n \"Device Disonnected\": 39,\n \"Device Error\": 1\n}";
+
+ @Column({ name: 'fields' })
+ @IsString()
+ fields: string;
+
+
+ @Column({ name: 'is_active' })
+ @IsNotEmpty()
+ isActive: boolean;
+
+ @Column({
+ transformer: JSON_TRANSFORMER
+ })
+ @IsOptional()
+ retry: string = JSON.stringify(DefaultRetry());
+
+ @Column({ name: 'user' })
+ @IsNotEmpty()
+ user: number;
+
+ @Column({ name: 'project' })
+ @IsNotEmpty()
+ project: number;
+
+ @Column({
+ transformer: JSON_TRANSFORMER
+ })
+ @IsOptional()
+ blocks: string = JSON.stringify(DefaultBlocks());
+
+ @Column({
+ transformer: JSON_TRANSFORMER
+ })
+ @IsOptional()
+ settings: string = JSON.stringify(DefaultSettings());
+
+ @Column({
+ transformer: JSON_TRANSFORMER
+ })
+ @IsOptional()
+ commandSettings: string = JSON.stringify(DefaultCommandSettings());
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ console.error('validation error', errors);
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ @AfterLoad()
+ doAfter() {
+ this.retry = JSON_TRANSFORMER.from(this.retry);
+ this.blocks = JSON_TRANSFORMER.from(this.blocks);
+ this.settings = JSON_TRANSFORMER.from(this.settings);
+ this.commandSettings = JSON_TRANSFORMER.from(this.commandSettings);
+ this.logging = JSON_TRANSFORMER.from(this.logging);
+ }
+
+ public toString() {
+ return `${this.protocol}://${this.host}:${this.port}`
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/file.entity.ts b/packages/vfs/ref-server/entities/file.entity.ts
new file mode 100644
index 00000000..26dc6fa5
--- /dev/null
+++ b/packages/vfs/ref-server/entities/file.entity.ts
@@ -0,0 +1,50 @@
+import { isString } from '@xblox/core/primitives';
+import { IsNotEmpty, IsOptional, MaxLength, validateSync } from 'class-validator';
+import { AfterLoad, BeforeUpdate, Column, Entity, PrimaryGeneratedColumn, UpdateDateColumn, CreateDateColumn } from 'typeorm';
+import { ValueTransformer } from 'typeorm/decorator/options/ValueTransformer';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+export const JSON_TRANSFORMER: ValueTransformer = {
+ to(value: any): string {
+ return JSON.stringify(value, null, 2);
+ },
+ from(value: string): any {
+ if (isString(value)) {
+ return JSON.parse(value);
+ }
+ return value;
+ }
+}
+
+@Entity()
+export class File {
+ @PrimaryGeneratedColumn()
+ id: number;
+
+ @Column()
+ path: string;
+
+ @Column()
+ user: number;
+
+ @Column({ type: 'blob' })
+ content: string;
+
+ @Column({ type: 'integer' })
+ type: string;
+
+ @Column({ type: Date, nullable: true })
+ date: Date;
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ public toString() {
+ return `${this.path}`
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/group.entity.ts b/packages/vfs/ref-server/entities/group.entity.ts
new file mode 100644
index 00000000..c43a9272
--- /dev/null
+++ b/packages/vfs/ref-server/entities/group.entity.ts
@@ -0,0 +1,70 @@
+import { IsNotEmpty, MaxLength, validateSync } from 'class-validator';
+import { BeforeInsert, BeforeUpdate, Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';
+
+import { Permission } from './permission.entity';
+import { User } from './user.entity';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+@Entity()
+export class Group {
+ @PrimaryGeneratedColumn()
+ id: number;
+
+ @Column({ length: 100, unique: true })
+ @IsNotEmpty()
+ @MaxLength(100)
+ name: string;
+
+ @Column({ length: 255, unique: true })
+ @IsNotEmpty()
+ @MaxLength(255)
+ title: string;
+
+ @ManyToMany(type => Permission, {
+ cascade: ['remove']
+ })
+ @JoinTable({
+ //not work on run cli migration:
+ name: 'group_permissions',
+ joinColumn: {
+ name: 'group_id',
+ referencedColumnName: 'id'
+ },
+ inverseJoinColumn: {
+ name: 'permission_id',
+ referencedColumnName: 'id'
+ }
+ })
+ permissions: Permission[];
+
+ @ManyToMany(type => User)
+ @JoinTable({
+ //not work on run cli migration:
+ name: 'user_groups',
+ joinColumn: {
+ name: 'group_id',
+ referencedColumnName: 'id'
+ },
+ inverseJoinColumn: {
+ name: 'user_id',
+ referencedColumnName: 'id'
+ }
+ })
+ users: User[];
+
+ @BeforeInsert()
+ doBeforeInsertion() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/index.ts b/packages/vfs/ref-server/entities/index.ts
new file mode 100644
index 00000000..26ae1732
--- /dev/null
+++ b/packages/vfs/ref-server/entities/index.ts
@@ -0,0 +1,9 @@
+import { ContentType } from './content-type.entity';
+import { Group } from './group.entity';
+import { User } from "./user.entity";
+import { Permission } from './permission.entity';
+import { Device } from './device.entity';
+import { Project } from './project.entity';
+import { File } from './file.entity';
+
+export const entities = [Permission, ContentType, Group, User, Device, Project, File];
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/permission.entity.ts b/packages/vfs/ref-server/entities/permission.entity.ts
new file mode 100644
index 00000000..3b45f2e8
--- /dev/null
+++ b/packages/vfs/ref-server/entities/permission.entity.ts
@@ -0,0 +1,67 @@
+import { IsNotEmpty, MaxLength, validateSync } from 'class-validator';
+import {
+ BeforeInsert,
+ BeforeUpdate,
+ Column,
+ Entity,
+ JoinColumn,
+ JoinTable,
+ ManyToMany,
+ ManyToOne,
+ PrimaryGeneratedColumn,
+} from 'typeorm';
+
+import { ContentType } from './content-type.entity';
+import { Group } from './group.entity';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+@Entity()
+export class Permission {
+ @PrimaryGeneratedColumn()
+ id: number;
+
+ @Column({ length: 100 })
+ @IsNotEmpty()
+ @MaxLength(100)
+ name: string;
+
+ @Column({ length: 255 })
+ @IsNotEmpty()
+ @MaxLength(255)
+ title: string;
+
+ @ManyToOne(type => ContentType, { eager: true, nullable: true })
+ @JoinColumn({ name: "content_type_id" })
+ contentType: ContentType;
+
+ @ManyToMany(type => Group)
+ @JoinTable({
+ //not work on run cli migration:
+ name: 'group_permissions',
+ joinColumn: {
+ name: 'permission_id',
+ referencedColumnName: 'id'
+ },
+ inverseJoinColumn: {
+ name: 'group_id',
+ referencedColumnName: 'id'
+ }
+ })
+ groups: Group[];
+
+ @BeforeInsert()
+ doBeforeInsertion() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/project.entity.ts b/packages/vfs/ref-server/entities/project.entity.ts
new file mode 100644
index 00000000..b94c7dfd
--- /dev/null
+++ b/packages/vfs/ref-server/entities/project.entity.ts
@@ -0,0 +1,64 @@
+import { isString } from '@xblox/core/primitives';
+import { IsNotEmpty, IsOptional, MaxLength, validateSync } from 'class-validator';
+import { AfterLoad, BeforeUpdate, Column, Entity, PrimaryGeneratedColumn, UpdateDateColumn, CreateDateColumn } from 'typeorm';
+import { ValueTransformer } from 'typeorm/decorator/options/ValueTransformer';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+export const JSON_TRANSFORMER: ValueTransformer = {
+ to(value: any): string {
+ return JSON.stringify(value, null, 2);
+ },
+ from(value: string): any {
+ if (isString(value)) {
+ return JSON.parse(value);
+ }
+ return value;
+ }
+}
+
+@Entity()
+export class Project {
+
+ @CreateDateColumn({ name:'created_date', nullable: true })
+ created: Date;
+
+ @CreateDateColumn({ name: 'last_edited', nullable: true })
+ lastEdited: Date;
+
+ @IsOptional()
+ @PrimaryGeneratedColumn()
+ id: number;
+
+ @Column()
+ @IsNotEmpty()
+ @IsOptional()
+ user: number;
+
+ @Column({ length: 150 })
+ @IsNotEmpty()
+ @MaxLength(150)
+ name: string;
+ @Column({
+ transformer: JSON_TRANSFORMER
+ })
+
+ @IsOptional()
+ settings: string = JSON.stringify({});
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ @AfterLoad()
+ doAfter() {
+ this.settings = JSON_TRANSFORMER.from(this.settings);
+ }
+
+ public toString() {
+ return `${this.name}`
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/entities/user.entity.ts b/packages/vfs/ref-server/entities/user.entity.ts
new file mode 100644
index 00000000..6955dba5
--- /dev/null
+++ b/packages/vfs/ref-server/entities/user.entity.ts
@@ -0,0 +1,130 @@
+import { IsEmail, IsNotEmpty, IsOptional, MaxLength, validateSync } from 'class-validator';
+import * as hashers from 'node-django-hashers';
+import {
+ BeforeInsert,
+ BeforeUpdate,
+ Column,
+ CreateDateColumn,
+ Entity,
+ JoinTable,
+ ManyToMany,
+ PrimaryGeneratedColumn,
+ UpdateDateColumn
+} from 'typeorm';
+
+import { Group } from './group.entity';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+@Entity()
+export class User {
+ @PrimaryGeneratedColumn()
+ id: number;
+
+ @Column({ length: 128 })
+ @MaxLength(128)
+ @IsOptional()
+ password: string;
+
+ @UpdateDateColumn({ name: 'last_login', nullable: true })
+ lastLogin: Date;
+
+ @Column({ name: 'is_superuser' })
+ @IsNotEmpty()
+ isSuperuser: boolean;
+
+ @Column({ length: 150, unique: true })
+ @IsNotEmpty()
+ @MaxLength(150)
+ username: string;
+
+ @Column({ name: 'first_name', length: 30 })
+ @IsNotEmpty()
+ @MaxLength(30)
+ firstName: string;
+
+ @Column({ name: 'last_name', length: 30 })
+ @IsNotEmpty()
+ @MaxLength(30)
+ lastName: string;
+
+ @Column({ length: 254 })
+ @IsNotEmpty()
+ @IsEmail()
+ @MaxLength(254)
+ email: string;
+
+ @Column({ name: 'is_staff' })
+ @IsNotEmpty()
+ isStaff: boolean;
+
+ @Column({ name: 'is_active' })
+ @IsNotEmpty()
+ isActive: boolean;
+
+ @CreateDateColumn({ name: 'date_joined' })
+ dateJoined: Date;
+
+ @Column({ type: Date, name: 'date_of_birth', nullable: true })
+ dateOfBirth: Date;
+
+ @ManyToMany(type => Group, {
+ cascade: ['remove']
+ })
+ @JoinTable({
+ //not work on run cli migration:
+ name: 'user_groups',
+ joinColumn: {
+ name: 'user_id',
+ referencedColumnName: 'id'
+ },
+ inverseJoinColumn: {
+ name: 'group_id',
+ referencedColumnName: 'id'
+ }
+ })
+ groups: Group[];
+
+ @BeforeInsert()
+ doBeforeInsertion() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ @BeforeUpdate()
+ doBeforeUpdate() {
+ const errors = validateSync(this, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ }
+
+ makePassword(password: string) {
+ var h = new hashers.PBKDF2PasswordHasher();
+ var hash = h.encode(password, h.salt());
+ return hash;
+ }
+
+ verifyPassword(password: string) {
+ var h = new hashers.PBKDF2PasswordHasher();
+ return h.verify(password, this.password);
+ }
+
+ setPassword(password: string) {
+ if (password) {
+ this.password = this.makePassword(password);
+ } else {
+ this.password = undefined;
+ }
+ }
+
+ checkPermissions(permissions: string[]) {
+ permissions = permissions.map(permission => permission.toLowerCase());
+ return this.groups.filter(group =>
+ group.permissions.filter(permission =>
+ permissions.indexOf(permission.name.toLowerCase()) !== -1
+ ).length > 0
+ ).length > 0
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/errors.ts b/packages/vfs/ref-server/errors.ts
new file mode 100644
index 00000000..3cb2fd45
--- /dev/null
+++ b/packages/vfs/ref-server/errors.ts
@@ -0,0 +1,332 @@
+import * as lodash from 'lodash';
+export const ERRORS = {
+ ECONNREFUSED: 'ECONNREFUSED',
+ EHOSTUNREACH: 'EHOSTUNREACH',
+ // The specified resource didn't exist:
+ ENOENT: 'ENOENT',
+ // The process didn't have necessary privileges to run some command:
+ EPERM: 'EPERM',
+ ESOCKETTIMEDOUT: 'ESOCKETTIMEDOUT',
+ ETIMEDOUT: 'ETIMEDOUT'
+}
+
+export const ERROR_CODES = [
+ {
+ errno: -2,
+ code: 'ENOENT',
+ description: 'no such file or directory'
+ },
+ {
+ errno: -1,
+ code: 'UNKNOWN',
+ description: 'unknown error'
+ },
+ {
+ errno: 0,
+ code: 'OK',
+ description: 'success'
+ },
+ {
+ errno: 1,
+ code: 'EOF',
+ description: 'end of file'
+ },
+ {
+ errno: 2,
+ code: 'EADDRINFO',
+ description: 'getaddrinfo error'
+ },
+ {
+ errno: 3,
+ code: 'EACCES',
+ description: 'permission denied'
+ },
+ {
+ errno: 4,
+ code: 'EAGAIN',
+ description: 'resource temporarily unavailable'
+ },
+ {
+ errno: 5,
+ code: 'EADDRINUSE',
+ description: 'address already in use'
+ },
+ {
+ errno: 6,
+ code: 'EADDRNOTAVAIL',
+ description: 'address not available'
+ },
+ {
+ errno: 7,
+ code: 'EAFNOSUPPORT',
+ description: 'address family not supported'
+ },
+ {
+ errno: 8,
+ code: 'EALREADY',
+ description: 'connection already in progress'
+ },
+ {
+ errno: 9,
+ code: 'EBADF',
+ description: 'bad file descriptor'
+ },
+ {
+ errno: 10,
+ code: 'EBUSY',
+ description: 'resource busy or locked'
+ },
+ {
+ errno: 11,
+ code: 'ECONNABORTED',
+ description: 'software caused connection abort'
+ },
+ {
+ errno: 12,
+ code: 'ECONNREFUSED',
+ description: 'connection refused'
+ },
+ {
+ errno: 13,
+ code: 'ECONNRESET',
+ description: 'connection reset by peer'
+ },
+ {
+ errno: 14,
+ code: 'EDESTADDRREQ',
+ description: 'destination address required'
+ },
+ {
+ errno: 15,
+ code: 'EFAULT',
+ description: 'bad address in system call argument'
+ },
+ {
+ errno: 16,
+ code: 'EHOSTUNREACH',
+ description: 'host is unreachable'
+ },
+ {
+ errno: 17,
+ code: 'EINTR',
+ description: 'interrupted system call'
+ },
+ {
+ errno: 18,
+ code: 'EINVAL',
+ description: 'invalid argument'
+ },
+ {
+ errno: 19,
+ code: 'EISCONN',
+ description: 'socket is already connected'
+ },
+ {
+ errno: 20,
+ code: 'EMFILE',
+ description: 'too many open files'
+ },
+ {
+ errno: 21,
+ code: 'EMSGSIZE',
+ description: 'message too long'
+ },
+ {
+ errno: 22,
+ code: 'ENETDOWN',
+ description: 'network is down'
+ },
+ {
+ errno: 23,
+ code: 'ENETUNREACH',
+ description: 'network is unreachable'
+ },
+ {
+ errno: 24,
+ code: 'ENFILE',
+ description: 'file table overflow'
+ },
+ {
+ errno: 25,
+ code: 'ENOBUFS',
+ description: 'no buffer space available'
+ },
+ {
+ errno: 26,
+ code: 'ENOMEM',
+ description: 'not enough memory'
+ },
+ {
+ errno: 27,
+ code: 'ENOTDIR',
+ description: 'not a directory'
+ },
+ {
+ errno: 28,
+ code: 'EISDIR',
+ description: 'illegal operation on a directory'
+ },
+ {
+ errno: 29,
+ code: 'ENONET',
+ description: 'machine is not on the network'
+ },
+ {
+ errno: 31,
+ code: 'ENOTCONN',
+ description: 'socket is not connected'
+ },
+ {
+ errno: 32,
+ code: 'ENOTSOCK',
+ description: 'socket operation on non-socket'
+ },
+ {
+ errno: 33,
+ code: 'ENOTSUP',
+ description: 'operation not supported on socket'
+ },
+ {
+ errno: 34,
+ code: 'ENOENT',
+ description: 'no such file or directory'
+ },
+ {
+ errno: 35,
+ code: 'ENOSYS',
+ description: 'function not implemented'
+ },
+ {
+ errno: 36,
+ code: 'EPIPE',
+ description: 'broken pipe'
+ },
+ {
+ errno: 37,
+ code: 'EPROTO',
+ description: 'protocol error'
+ },
+ {
+ errno: 38,
+ code: 'EPROTONOSUPPORT',
+ description: 'protocol not supported'
+ },
+ {
+ errno: 39,
+ code: 'EPROTOTYPE',
+ description: 'protocol wrong type for socket'
+ },
+ {
+ errno: 40,
+ code: 'ETIMEDOUT',
+ description: 'connection timed out'
+ },
+ {
+ errno: 41,
+ code: 'ECHARSET',
+ description: 'invalid Unicode character'
+ },
+ {
+ errno: 42,
+ code: 'EAIFAMNOSUPPORT',
+ description: 'address family for hostname not supported'
+ },
+ {
+ errno: 44,
+ code: 'EAISERVICE',
+ description: 'servname not supported for ai_socktype'
+ },
+ {
+ errno: 45,
+ code: 'EAISOCKTYPE',
+ description: 'ai_socktype not supported'
+ },
+ {
+ errno: 46,
+ code: 'ESHUTDOWN',
+ description: 'cannot send after transport endpoint shutdown'
+ },
+ {
+ errno: 47,
+ code: 'EEXIST',
+ description: 'file already exists'
+ },
+ {
+ errno: 48,
+ code: 'ESRCH',
+ description: 'no such process'
+ },
+ {
+ errno: 49,
+ code: 'ENAMETOOLONG',
+ description: 'name too long'
+ },
+ {
+ errno: 50,
+ code: 'EPERM',
+ description: 'operation not permitted'
+ },
+ {
+ errno: 51,
+ code: 'ELOOP',
+ description: 'too many symbolic links encountered'
+ },
+ {
+ errno: 52,
+ code: 'EXDEV',
+ description: 'cross-device link not permitted'
+ },
+ {
+ errno: 53,
+ code: 'ENOTEMPTY',
+ description: 'directory not empty'
+ },
+ {
+ errno: 54,
+ code: 'ENOSPC',
+ description: 'no space left on device'
+ },
+ {
+ errno: 55,
+ code: 'EIO',
+ description: 'i/o error'
+ },
+ {
+ errno: 56,
+ code: 'EROFS',
+ description: 'read-only file system'
+ },
+ {
+ errno: 57,
+ code: 'ENODEV',
+ description: 'no such device'
+ },
+ {
+ errno: 58,
+ code: 'ESPIPE',
+ description: 'invalid seek'
+ },
+ {
+ errno: 59,
+ code: 'ECANCELED',
+ description: 'operation canceled'
+ }
+];
+export const description = (code: number) => {
+ // console.log('descr', code);
+ let found = lodash.find(ERROR_CODES, {
+ code: code
+ });
+ if (!found) {
+ found = lodash.find(ERROR_CODES, {
+ errno: code
+ })
+ }
+
+ if (found) {
+ return found.description;
+ } else {
+ console.error('cant find error description', code);
+ }
+ return 'Unknown Error';
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/exceptions/custom-exception.filter.ts b/packages/vfs/ref-server/exceptions/custom-exception.filter.ts
new file mode 100644
index 00000000..ffde8ebc
--- /dev/null
+++ b/packages/vfs/ref-server/exceptions/custom-exception.filter.ts
@@ -0,0 +1,38 @@
+import { ExceptionFilter, Catch, HttpStatus } from '@nestjs/common';
+import { HttpException } from '@nestjs/core';
+import { ValidationError } from 'class-validator';
+import { JsonWebTokenError } from 'jsonwebtoken';
+import { CustomValidationError } from './custom-validation.error';
+
+@Catch(SyntaxError, CustomValidationError, JsonWebTokenError, Error)
+export class CustomExceptionFilter implements ExceptionFilter {
+ catch(exception: CustomValidationError | JsonWebTokenError, response) {
+ const errors = {};
+ if (exception instanceof CustomValidationError) {
+ exception.errors.forEach((error: ValidationError) => {
+ Object.keys(error.constraints).forEach(
+ (key: string) => {
+ if (!errors[error.property]) {
+ errors[error.property] = [];
+ }
+ errors[error.property].push(error.constraints[key]);
+ }
+ );
+ });
+ response.status(HttpStatus.BAD_REQUEST).json(errors);
+ return;
+ }
+ if (exception instanceof JsonWebTokenError) {
+ response.status(HttpStatus.BAD_REQUEST).json({
+ nonFieldErrors: [exception.message]
+ });
+ return;
+ }
+ if (process.env.DEBUG === 'true' || process.env.DEBUG === '1') {
+ console.error(exception);
+ response.status(HttpStatus.BAD_REQUEST).json({ message: String(exception) });
+ return;
+ }
+ response.status(HttpStatus.BAD_REQUEST).json(exception);
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/exceptions/custom-validation.error.ts b/packages/vfs/ref-server/exceptions/custom-validation.error.ts
new file mode 100644
index 00000000..1718f800
--- /dev/null
+++ b/packages/vfs/ref-server/exceptions/custom-validation.error.ts
@@ -0,0 +1,9 @@
+import { ValidationError } from "class-validator";
+
+export class CustomValidationError extends Error {
+ errors: ValidationError[];
+ constructor(errors: ValidationError[]) {
+ super();
+ this.errors = errors;
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/extensions/Evented.ts b/packages/vfs/ref-server/extensions/Evented.ts
new file mode 100644
index 00000000..f23ac188
--- /dev/null
+++ b/packages/vfs/ref-server/extensions/Evented.ts
@@ -0,0 +1,24 @@
+import { SyncEvent } from 'ts-events';
+export class Evented {
+ events: any = {};
+ private _event(event: string) {
+ let _event: SyncEvent = this.events[event];
+ if (!_event) {
+ _event = new SyncEvent();
+ this.events[event] = _event;
+ }
+ return _event;
+ }
+ public emit(event: string, data: any): void {
+ const seven: SyncEvent = this._event(event);
+ seven.post(data);
+ }
+ public on(event: string, handler: any): void {
+ let _event: SyncEvent = this.events[event];
+ if (!_event) {
+ _event = new SyncEvent();
+ this.events[event] = _event;
+ }
+ _event.attach(handler);
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/extensions/Logged.ts b/packages/vfs/ref-server/extensions/Logged.ts
new file mode 100644
index 00000000..81976ea2
--- /dev/null
+++ b/packages/vfs/ref-server/extensions/Logged.ts
@@ -0,0 +1,15 @@
+/*import { Tcp } from '../protocols/Tcp';*/
+import { DeviceInfo } from '../types';
+/*import { IProtocolHandler, ConnectionManager } from '../manager/ConnectionManager';*/
+export const main = () => {
+ /*
+ mgr = new ConnectionManager();
+ const options: DeviceInfo = {
+ host: '192.168.1.20',
+ port: '22',
+ protocol: 'tcp'
+ }
+ tcp = new Tcp(options, mgr);
+ tcp.connect();
+ */
+}
diff --git a/packages/vfs/ref-server/guards/access.guard.ts b/packages/vfs/ref-server/guards/access.guard.ts
new file mode 100644
index 00000000..23b86c57
--- /dev/null
+++ b/packages/vfs/ref-server/guards/access.guard.ts
@@ -0,0 +1,57 @@
+import { CanActivate, ExecutionContext, Guard } from '@nestjs/common';
+import { Reflector } from '@nestjs/core';
+import { plainToClass } from 'class-transformer';
+import { IncomingMessage } from 'http';
+
+import { User } from '../entities/user.entity';
+import { GroupsService } from '../services/groups.service';
+import { TokenService } from '../services/token.service';
+
+@Guard()
+export class AccessGuard implements CanActivate {
+
+ constructor(
+ private readonly reflector: Reflector,
+ private readonly tokenService: TokenService,
+ private readonly groupsService: GroupsService
+ ) {
+ //workaround
+ this.groupsService.loadAll();
+ }
+
+ canActivate(req: IncomingMessage, context: ExecutionContext): boolean {
+ const { parent, handler } = context;
+
+ const authorizationHeader = req.headers['authorization'] ?
+ String(req.headers['authorization']) : null;
+
+ if (authorizationHeader && authorizationHeader.indexOf(process.env.JWT_AUTH_HEADER_PREFIX) === 0) {
+ let token =
+ process.env.JWT_AUTH_HEADER_PREFIX ?
+ authorizationHeader.split(process.env.JWT_AUTH_HEADER_PREFIX)[1] :
+ authorizationHeader;
+ token = token.trim();
+
+ if (token && this.tokenService.verify(token)) {
+ const data: any = this.tokenService.decode(token);
+ req['user'] = plainToClass(User, data);
+ req['user'].groups = data.groups.map(group =>
+ this.groupsService.getGroupByName(group.name)
+ );
+ }
+ }
+ const roles = this.reflector.get('roles', handler);
+ const permissions = this.reflector.get('permissions', handler);
+
+ const hasRole = roles ? roles.filter(roleName =>
+ req['user'] &&
+ req['user'][roleName]
+ ).length > 0 : null;
+ const hasPermission = permissions ?
+ req['user'] &&
+ req['user'] instanceof User &&
+ req['user'].checkPermissions(permissions) : null;
+
+ return hasRole === true || hasPermission === true || (hasRole === null && hasPermission === null);
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/interfaces.ts b/packages/vfs/ref-server/interfaces.ts
new file mode 100644
index 00000000..82a7541a
--- /dev/null
+++ b/packages/vfs/ref-server/interfaces.ts
@@ -0,0 +1,51 @@
+// tslint:disable-next-line:interface-name
+export interface Hash {
+ [id: string]: T;
+}
+// tslint:disable-next-line:interface-name
+export interface List {
+ [index: number]: T;
+ length: number;
+}
+/**
+ * Interface of the simple literal object with any string keys.
+ */
+export interface IObjectLiteral {
+ [key: string]: any;
+}
+/**
+ * Represents some Type of the Object.
+ */
+export type ObjectType = { new(): T } | Function;
+/**
+ * Same as Partial but goes deeper and makes Partial all its properties and sub-properties.
+ */
+export type DeepPartial = {
+ [P in keyof T]?: DeepPartial;
+};
+
+export interface IDelimitter {
+ begin: string;
+ end: string;
+}
+
+export type JSONPathExpression = string;
+
+export enum EPlatform {
+ Linux = 'linux',
+ Windows = 'win32',
+ OSX = 'darwin'
+}
+export enum EArch {
+ x64 = '64',
+ x32 = '32'
+}
+
+export enum EDeviceScope {
+ USER_DEVICES = 'user_devices',
+ SYSTEM_DEVICES = 'system_devices'
+}
+export enum EDriverScope {
+ USER_DRIVERS = 'user_drivers',
+ SYSTEM_DRIVERS = 'system_drivers'
+}
diff --git a/packages/vfs/ref-server/lib.ts b/packages/vfs/ref-server/lib.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/vfs/ref-server/log.ts b/packages/vfs/ref-server/log.ts
new file mode 100644
index 00000000..d0d46c82
--- /dev/null
+++ b/packages/vfs/ref-server/log.ts
@@ -0,0 +1,19 @@
+/*import * as chalk from 'chalk';*/
+import { default as chalk } from 'chalk';
+import * as util from 'util';
+import * as _ora from 'ora';
+// tslint:disable-next-line:no-var-requires
+const jsome = require('jsome');
+jsome.level.show = true;
+const glog = console.log;
+export const log = (msg: string, ...rest) => glog(chalk.magenta(msg), ...rest);
+export const info = (msg: string, d?: any) => glog(chalk.green(msg), d || '');
+export const error = (msg: string, ...rest) => glog(chalk.red(msg), ...rest);
+export const warn = (msg: string, d?: any) => glog(chalk.yellow(msg), d || '');
+export const debug = (msg: string, d?: any) => glog(chalk.blue(msg), d || '');
+export const stack = (msg: string, d?: any) => glog(chalk.red(msg), new Error().stack);
+export const inspect = (msg: string, d: any = null, pretty: boolean = true) => {
+ glog(chalk.blue(msg));
+ d && jsome(d);
+};
+export const spinner = (msg: string): any => _ora(msg);
diff --git a/packages/vfs/ref-server/manager/ConnectionManager.ts b/packages/vfs/ref-server/manager/ConnectionManager.ts
new file mode 100644
index 00000000..f871b452
--- /dev/null
+++ b/packages/vfs/ref-server/manager/ConnectionManager.ts
@@ -0,0 +1,218 @@
+import { DeviceInfo, Connection, Protocol, Tcp, EVENTS, DEVICE_STATE, ERROR_CODES, ERRORS, RETRY_SETTINGS, RETRY_MODE } from '../types';
+import * as debug from '../log';
+import { Device } from '../entities/device.entity';
+import { User } from '../entities/user.entity';
+import * as lodash from 'lodash';
+import { Context } from './Context';
+import { EventEmitter } from 'events';
+import { parse } from 'error-stack-parser';
+import { description } from '../types';
+import { remove } from '@xblox/core/arrays';
+import { DeviceDto } from '../dto/device.dto';
+
+
+const protocol = (protocol: string) => {
+ switch (protocol) {
+ case 'Tcp': return Tcp;
+ }
+}
+
+export interface IProtocolHandler {
+ onData: (connection: Protocol, data: Buffer) => void;
+ onError: (connection: Protocol, error: Error) => void;
+ onTimeout: (connection: Protocol) => void;
+ onClose: (connection: Protocol, data?: Buffer) => void;
+}
+export class ConnectionManager extends EventEmitter {
+ connected: boolean = false;
+ _info: DeviceInfo;
+ id: string;
+ connections: Connection[] = [];
+ constructor(private readonly context: Context) {
+ super();
+ }
+ info = (): DeviceInfo => { return this._info };
+
+ sendToDevice(data: any): Promise {
+ return new Promise((resolve, reject) => {
+ const device = data.device as DeviceDto;
+ const connection = this.connectionByHost(device.host, device.port, device.protocol);
+ if (connection) {
+ // debug.log('send to device', data);
+ try {
+ connection.instance.send(data).then(resolve, (e) => {
+ debug.error('error sending command', e);
+ });
+ } catch (e) {
+ debug.error('error sending command', e);
+ }
+ } else {
+ debug.error('Send to device, no such connection ' + this.connections.length);
+ reject('No such device');
+ }
+ });
+ }
+
+ protocolMethod(data: any): Promise {
+ return new Promise((resolve, reject) => {
+ data = data.data;
+ const method = data.method;
+ const args = data.args;
+ const prot = protocol(data.protocol);
+ if (prot) {
+ if (prot[method]) {
+ const ret = prot[method].apply(prot, args);
+ if (ret && ret.then) {
+ ret.then((d) => {
+ resolve(d);
+ })
+ } else {
+ debug.error('protocol method ' + method + ' in ' + prot + ' has no result');;
+ reject('protocol method ' + method + ' in ' + prot + ' has no result');
+ }
+ } else {
+ debug.error('no such protocol method ' + method + ' in ' + prot);
+ reject('no such protocol method ' + method + ' in ' + prot);
+ }
+ } else {
+ debug.error('no such protocol ' + method, data);
+ reject('no such protocol ' + method);
+ }
+ });
+ }
+ onData(connection: Protocol, data: Buffer) {
+ debug.inspect('on data', data.toString());
+
+ this.emit(EVENTS.ON_DEVICE_MESSAGE, {
+ device: connection.device,
+ data: data.toString(),
+ bytes: data.join(',')
+ });
+ }
+ onConnected(instance: Protocol, data: Buffer) {
+ instance.connection.device.state = DEVICE_STATE.CONNECTED;
+ instance.connection.connectingResolve(instance.connection.device);
+ instance.connection.connectingResolve = null;
+ debug.inspect('on connected', data ? data.toString() : {});
+
+ this.emit(EVENTS.ON_DEVICE_CONNECTED, {
+ device: instance.connection.device
+ });
+
+ }
+ onError(instance: Protocol, error: NodeJS.ErrnoException) {
+ const device = instance.device;
+ const err = {
+ code: error.code,
+ description: description(error.errno),
+ stack: error.stack ? parse(error) : null,
+ device: device
+ };
+ this.emit(EVENTS.ON_DEVICE_ERROR, err);
+ // console.log('err', err);
+ switch (err.code) {
+ case ERRORS.EHOSTUNREACH: {
+ const retry = ((device.retry as any) as RETRY_SETTINGS);
+ switch (retry.mode) {
+ case RETRY_MODE.ABORT_AFTER_TRIALS: {
+
+ // did hit the max
+ if (retry.counter > retry.value) {
+ debug.info('retry trials max limit reached ', instance.connection.toString());
+ device.state = DEVICE_STATE.UNREACHABLE;
+ break;
+ }
+ retry.counter++;
+ setTimeout(() => {
+ debug.info('reconnect ', instance.connection.toString());
+ this.connect(instance.connection.user, device);
+ }, retry.interval);
+ }
+ }
+ // debug.error('unreach', retry);
+ break;
+ }
+ }
+ // debug.inspect('Error', err);
+ };
+ onTimeout(connection: Protocol) { };
+ onClose(connection: Protocol, data?: Buffer) {
+ console.log('connection closed');
+ };
+
+ connect(user: User, device: Device) {
+ try {
+ const id = Connection.id(user, device);
+ let connection: Connection = lodash.find(this.connections, {
+ id: id
+ });
+ if (!connection) {
+ // debug.log('no connection yet ');
+ }
+
+ if (!connection) {
+ const tcp = new Tcp(device, this);
+ connection = new Connection();
+ connection.id = id;
+ connection.user = user;
+ connection.instance = tcp;
+ connection.device = device;
+ connection.instance.connection = connection;
+ connection.init();
+ connection.connecting = new Promise((resolve, reject) => {
+ connection.connectingResolve = resolve;
+ });
+ connection.instance.connect();
+ device.state = DEVICE_STATE.CONNECTING;
+ this.connections.push(connection);
+ return connection.connecting;
+ } else {
+ return Promise.resolve(device);
+ }
+
+ } catch (e) {
+ debug.error('error connecting device', e);
+ }
+ }
+
+ public connectionByHost(host: string, port: string, protocol: string): Connection | undefined {
+ let connection: Connection = lodash.find(this.connections, {
+ device: {
+ host: host,
+ port: port,
+ protocol: protocol
+ }
+ }
+ );
+ return connection;
+ }
+
+ public connectionByDevice(host: string, port: string, protocol: string): Connection | undefined {
+ let connection: Connection = lodash.find(this.connections, {
+ host,
+ port,
+ protocol
+ });
+ return connection;
+ }
+
+ disconnect(user: User, device: Device) {
+ try {
+ const id = Connection.id(user, device);
+ let connection: Connection = lodash.find(this.connections, {
+ id: id
+ });
+ if (connection) {
+ connection.instance.destroy();
+ remove(this.connections, connection);
+ connection.device.state = DEVICE_STATE.DISCONNECTED;
+ this.emit(EVENTS.ON_DEVICE_DISCONNECTED, { device });
+ } else {
+ console.log('no such connection', device.toString());
+ }
+ return device;
+ } catch (e) {
+ debug.error('error disconnecting device ' + device.toString(), e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/manager/Context.ts b/packages/vfs/ref-server/manager/Context.ts
new file mode 100644
index 00000000..4b1fe72e
--- /dev/null
+++ b/packages/vfs/ref-server/manager/Context.ts
@@ -0,0 +1,67 @@
+import { Model, ConnectionManager, DeviceInfo, Tcp, EVENTS } from '../types';
+import { User } from '../entities/user.entity';
+import { Device } from '../entities/device.entity';
+import * as debug from '../log';
+import { EventsGateway } from '../controllers/events.gateway';
+
+export interface Options {
+ user: User
+}
+
+export class Context extends Model {
+ user: User;
+ _options: Options;
+ gateway: EventsGateway;
+
+ public key = (): string => '';
+ public options = (): Options => this._options;
+ public connectionManager: ConnectionManager;
+ constructor(
+ ) {
+ super();
+ this.connectionManager = new ConnectionManager(this);
+
+ }
+
+ public init(user: User, gateway: EventsGateway) {
+ this.user = user;
+ this.gateway = gateway;
+
+ this.gateway.connectionManager = this.connectionManager;
+
+ // forward to everybody
+ [
+ EVENTS.ON_DEVICE_CONNECTED,
+ EVENTS.ON_DEVICE_DISCONNECTED,
+ EVENTS.ON_DEVICE_CONNECTING,
+ EVENTS.ON_DEVICE_ERROR,
+ EVENTS.ON_DEVICE_MESSAGE
+ ].forEach((key) => {
+ this.connectionManager.on(key, (data) => {
+ console.log('broadcast device event ' + key);
+ this.gateway.broadcast(key, data);
+ })
+ });
+ }
+ public run = () => {
+ // debug.inspect('run context', this.user);
+ const cm = this.connectionManager;
+ }
+
+ public start(device: Device) {
+ return new Promise((resolve, reject) => {
+ debug.log('start user device ', device.toString());
+ this.connectionManager.connect(this.user, device).then((device) => {
+ resolve(device);
+ });
+ });
+ }
+
+ public stop(device: Device) {
+ return new Promise((resolve, reject) => {
+ debug.log('stop user device ', device.toString());
+ this.connectionManager.disconnect(this.user, device);
+ resolve(device);
+ });
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/migrations/FillData1514404694792.ts b/packages/vfs/ref-server/migrations/FillData1514404694792.ts
new file mode 100644
index 00000000..0e81828f
--- /dev/null
+++ b/packages/vfs/ref-server/migrations/FillData1514404694792.ts
@@ -0,0 +1,240 @@
+import { MigrationInterface, QueryRunner } from 'typeorm';
+
+import { ContentType } from '../entities/content-type.entity';
+import { Group } from '../entities/group.entity';
+import { plainToClass } from 'class-transformer';
+import { Permission } from '../entities/permission.entity';
+import { User } from '../entities/user.entity';
+import { Device } from '../entities/device.entity';
+import { Project } from '../entities/project.entity';
+import { File } from '../entities/file.entity';
+import { COMMANDS } from '../shared';
+import { DEVICE_STATE, DEVICE_FLAGS, LOGGING_FLAGS, DefaultCommandSettings, DefaultSettings } from '../types';
+
+const marantz = require('./marantz.json');
+
+export class FillData1514404694792 implements MigrationInterface {
+
+ public async up(queryRunner: QueryRunner): Promise {
+ const ctPermission = await queryRunner.manager.getRepository(ContentType).save(
+ plainToClass(ContentType, { name: 'permission', title: 'Permission' })
+ );
+ const ctGroup = await queryRunner.manager.getRepository(ContentType).save(
+ plainToClass(ContentType, { name: 'group', title: 'Group' })
+ );
+ const ctContentTtype = await queryRunner.manager.getRepository(ContentType).save(
+ plainToClass(ContentType, { name: 'content-type', title: 'Content type' })
+ );
+ const ctUser = await queryRunner.manager.getRepository(ContentType).save(
+ plainToClass(ContentType, { name: 'user', title: 'User' })
+ );
+
+ const ctDevice = await queryRunner.manager.getRepository(ContentType).save(
+ plainToClass(ContentType, { name: 'device', title: 'Device' })
+ );
+
+ const pPermissions = await queryRunner.manager.getRepository(Permission).save(
+ plainToClass(Permission,
+ [{
+ title: 'Can add permission',
+ name: 'add_permission',
+ contentType: ctPermission
+ },
+ {
+ title: 'Can change permission',
+ name: 'change_permission',
+ contentType: ctPermission
+ },
+ {
+ title: 'Can delete permission',
+ name: 'delete_permission',
+ contentType: ctPermission
+ },
+ {
+ title: 'Can add group',
+ name: 'add_group',
+ contentType: ctGroup
+ },
+ {
+ title: 'Can change group',
+ name: 'change_group',
+ contentType: ctGroup
+ },
+ {
+ title: 'Can delete group',
+ name: 'delete_group',
+ contentType: ctGroup
+ },
+ {
+ title: 'Can add content type',
+ name: 'add_content-type',
+ contentType: ctContentTtype
+ },
+ {
+ title: 'Can change content type',
+ name: 'change_content-type',
+ contentType: ctContentTtype
+ },
+ {
+ title: 'Can delete content type',
+ name: 'delete_content-type',
+ contentType: ctContentTtype
+ },
+ {
+ title: 'Can add user',
+ name: 'add_user',
+ contentType: ctUser
+ },
+ {
+ title: 'Can change user',
+ name: 'change_user',
+ contentType: ctUser
+ },
+ {
+ title: 'Can delete user',
+ name: 'delete_user',
+ contentType: ctUser
+ },
+ {
+ title: 'Can read user',
+ name: 'read_user',
+ contentType: ctUser
+ },
+ {
+ title: 'Can read group',
+ name: 'read_group',
+ contentType: ctGroup
+ },
+ {
+ title: 'Can read permission',
+ name: 'read_permission',
+ contentType: ctPermission
+ },
+ {
+ title: 'Can read content type',
+ name: 'read_content-type',
+ contentType: ctContentTtype
+ },
+ {
+ title: 'Can change profile',
+ name: 'change_profile',
+ contentType: ctUser
+ },
+ {
+ title: 'Can start device',
+ name: COMMANDS.START_DEVICE,
+ contentType: ctDevice
+ }
+ ]
+ )
+ );
+ const gUser = await queryRunner.manager.getRepository(Group).save(
+ plainToClass(Group,
+ {
+ name: 'user', title: 'User',
+ permissions: pPermissions.filter(item =>
+ item.name === 'change_profile'
+ )
+ }
+ )
+ );
+ const gAdmin = await queryRunner.manager.getRepository(Group).save(
+ plainToClass(Group,
+ {
+ name: 'admin', title: 'Admin',
+ permissions: pPermissions
+ }
+ )
+ );
+ const tempUser = new User();
+ const uUsers = await queryRunner.manager.getRepository(User).save(
+ plainToClass(User,
+ [{
+ username: 'admin',
+ email: 'admin@admin.com',
+ password: tempUser.makePassword('12345678'),
+ firstName: 'AdminFirstName',
+ lastName: 'AdminLastName',
+ isSuperuser: true,
+ isStaff: false,
+ isActive: true,
+ groups: [gAdmin]
+ },
+ {
+ username: 'user1',
+ email: 'user1@user1.com',
+ password: tempUser.makePassword('12345678'),
+ firstName: 'User1FirstName',
+ lastName: 'User1LastName',
+ isSuperuser: false,
+ isStaff: false,
+ isActive: true,
+ groups: [gUser]
+ },
+ {
+ username: 'user2',
+ email: 'user2@user2.com',
+ password: tempUser.makePassword('12345678'),
+ firstName: 'User2FirstName',
+ lastName: 'User2LastName',
+ isSuperuser: false,
+ isStaff: false,
+ isActive: true,
+ groups: [gUser]
+ }]
+ )
+ );
+
+ const uDevices = await queryRunner.manager.getRepository(Device).save(
+ plainToClass(Device,
+ [{
+ name: 'Marantz',
+ isActive: true,
+ user: 1,
+ fields: '[]',
+ host: '192.168.1.20',
+ port: '23',
+ protocol: 'Tcp',
+ state: DEVICE_STATE.NONE,
+ flags: DEVICE_FLAGS.DEBUG,
+ logging: "{\n \"Device Connected\": 47,\n \"Response\": 35,\n \"Send Command\": 51,\n \"Device Disonnected\": 39,\n \"Device Error\": 1\n}",
+ blocks: JSON.stringify(marantz),
+ commandSettings: DefaultCommandSettings(),
+ settings: DefaultSettings(),
+ project: 1
+ }]
+ )
+ );
+
+ const uProject = await queryRunner.manager.getRepository(Project).save(
+ plainToClass(Project,
+ [{
+ name: 'Project Title',
+ user: 1
+ },
+ {
+ name: 'Project Title 2',
+ user: 2
+ }
+ ]
+ )
+ );
+
+ const uFile = await queryRunner.manager.getRepository(File).save(
+ plainToClass(Project,
+ [{
+ user: 1,
+ content: 'test',
+ path: '/myscene.html',
+ type: 1,
+ date: new Date()
+ }
+ ]
+ )
+ );
+ }
+
+ public async down(queryRunner: QueryRunner): Promise {
+ }
+
+}
diff --git a/packages/vfs/ref-server/migrations/marantz.json b/packages/vfs/ref-server/migrations/marantz.json
new file mode 100644
index 00000000..f3bd4dd8
--- /dev/null
+++ b/packages/vfs/ref-server/migrations/marantz.json
@@ -0,0 +1,817 @@
+{
+ "blocks": [
+ {
+ "_containsChildrenIds": [],
+ "id": "83de87c0-f8c7-74da-161d-8e9cf51d67b1",
+ "name": "value",
+ "type": "added",
+ "group": "processVariables",
+ "gui": false,
+ "cmd": false,
+ "declaredClass": "xcf.model.Variable",
+ "save": false,
+ "target": "None",
+ "register": true,
+ "readOnly": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Set TV",
+ "group": "basic",
+ "id": "3ed330bb-700e-c76b-62e2-0c56c69027f3",
+ "send": "SITV",
+ "waitForResponse": false,
+ "type": "added",
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "interval": 0,
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "PowerOn",
+ "send": "PWON",
+ "group": "basic",
+ "id": "53a10527-709b-4c7d-7a90-37f58f17c8db",
+ "auto": false,
+ "type": "added",
+ "icon": "text-success fa-circle",
+ "interval": "0",
+ "waitForResponse": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Volume",
+ "type": "added",
+ "value": 35,
+ "enumType": "VariableType",
+ "initialize": "",
+ "group": "basicVariables",
+ "id": "3403a69e-252a-30dc-b130-40a028d1cde4",
+ "icon": "fa-automobile",
+ "save": false,
+ "register": true,
+ "readOnly": false,
+ "declaredClass": "xcf.model.Variable",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "gui": "off",
+ "cmd": "off",
+ "target": "None",
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "PowerOff",
+ "send": "PWSTANDBY",
+ "group": "basic",
+ "id": "84961334-9cd2-d384-25dc-a6b943e8cb8e",
+ "auto": false,
+ "type": "added",
+ "icon": "text-danger fa-power-off",
+ "interval": "",
+ "waitForResponse": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "VolumeUp",
+ "send": "return 'MV' + (this.getVariable('Volume') +2);",
+ "group": "basic",
+ "id": "6d0c5e0e-5c04-bb98-44a0-705c8269de07",
+ "auto": true,
+ "type": "added",
+ "icon": "fa-arrow-up",
+ "interval": "0",
+ "waitForResponse": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "name": "Fade-Volume-Down",
+ "group": "conditional",
+ "id": "1f969cc6-89c4-f559-e824-daf7dfff35cf",
+ "items": [
+ "c6bc0ef4-5b85-b543-4df7-3c00dd73a9eb"
+ ],
+ "type": "added",
+ "waitForResponse": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "send": "",
+ "interval": 0,
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "condition": "[Volume]>20",
+ "parentId": "1f969cc6-89c4-f559-e824-daf7dfff35cf",
+ "id": "c6bc0ef4-5b85-b543-4df7-3c00dd73a9eb",
+ "wait": "10",
+ "description": "No Description sdfsdf",
+ "type": "added",
+ "items": [
+ "0caac742-956e-de6b-6b53-36fb8174e5e0"
+ ],
+ "declaredClass": "xblox.model.loops.WhileBlock",
+ "loopLimit": 1500,
+ "name": "While",
+ "icon": "",
+ "enabled": true,
+ "shareTitle": "",
+ "order": 0,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "name": "Fade-Volume-Up",
+ "group": "conditional",
+ "id": "48a83acf-f2ef-ccdf-44a7-621fb635e3c4",
+ "interval": "0",
+ "type": "added",
+ "items": [
+ "0a561903-9422-f97d-8a76-0757177a7471"
+ ],
+ "waitForResponse": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "send": "",
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "condition": "[Volume]<80",
+ "parentId": "48a83acf-f2ef-ccdf-44a7-621fb635e3c4",
+ "id": "0a561903-9422-f97d-8a76-0757177a7471",
+ "wait": "10",
+ "type": "added",
+ "items": [
+ "660a553b-ff5d-ca79-c114-955800c8de76"
+ ],
+ "declaredClass": "xblox.model.loops.WhileBlock",
+ "loopLimit": 1500,
+ "name": "While",
+ "icon": "",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "PowerState",
+ "send": "nada",
+ "group": "basicVariables",
+ "id": "31c98cdd-02a8-3af1-3a49-11955c0fad48",
+ "type": "added",
+ "value": "off",
+ "declaredClass": "xcf.model.Variable",
+ "gui": "off",
+ "cmd": "off",
+ "save": false,
+ "target": "None",
+ "register": true,
+ "readOnly": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "name": "VolumeDown",
+ "send": "return 'MV' + (this.getVariable('Volume') - 2);",
+ "group": "basic",
+ "id": "69f6d4fb-4300-0498-9bbf-27554f5f1fa4",
+ "auto": "-1",
+ "type": "added",
+ "icon": "fa-arrow-down",
+ "interval": "0",
+ "waitForResponse": false,
+ "items": [
+ "57024e67-bc95-0e99-0e97-3355e8b0e04f"
+ ],
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "VolumeNormal",
+ "send": "MV35",
+ "group": "basic",
+ "id": "963944c2-c0b0-fe8a-504e-1b8bedd2a3cf",
+ "auto": false,
+ "type": "added",
+ "interval": "2000",
+ "waitForResponse": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "group": "conditionalProcess",
+ "id": "007e54b9-9d9a-df86-4693-9ea627443700",
+ "method": "console.log('run script2 ' + arguments[0]);",
+ "enabled": false,
+ "type": "added",
+ "declaredClass": "xblox.model.code.RunScript",
+ "name": "Run Script",
+ "args": "",
+ "deferred": false,
+ "icon": "fa-code",
+ "shareTitle": "",
+ "order": 0,
+ "outlet": 0,
+ "description": "No Description"
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Volume-Loud",
+ "group": "basicVariables",
+ "id": "b16bfc09-e449-d514-dc98-10b8afbb14f8",
+ "value": "61",
+ "type": "added",
+ "declaredClass": "xcf.model.Variable",
+ "gui": "off",
+ "cmd": "off",
+ "save": false,
+ "target": "None",
+ "register": true,
+ "readOnly": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Test",
+ "group": "basicVariables",
+ "id": "487b9e80-ca4c-c096-0950-91aad9dd4612",
+ "value": "return [Volume] + 2;",
+ "type": "added",
+ "declaredClass": "xcf.model.Variable",
+ "gui": "off",
+ "cmd": "off",
+ "save": false,
+ "target": "None",
+ "register": true,
+ "readOnly": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "condition": "",
+ "parentId": "c6bc0ef4-5b85-b543-4df7-3c00dd73a9eb",
+ "id": "0caac742-956e-de6b-6b53-36fb8174e5e0",
+ "command": "69f6d4fb-4300-0498-9bbf-27554f5f1fa4",
+ "type": "added",
+ "declaredClass": "xblox.model.functions.CallBlock",
+ "icon": "",
+ "_timeout": 100,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "startup": false,
+ "send": "",
+ "name": "No Title",
+ "interval": 0,
+ "flags": 2048
+ },
+ {
+ "_containsChildrenIds": [],
+ "condition": "",
+ "parentId": "0a561903-9422-f97d-8a76-0757177a7471",
+ "id": "660a553b-ff5d-ca79-c114-955800c8de76",
+ "command": "6d0c5e0e-5c04-bb98-44a0-705c8269de07",
+ "type": "added",
+ "declaredClass": "xblox.model.functions.CallBlock",
+ "icon": "",
+ "_timeout": 100,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "startup": false,
+ "send": "",
+ "name": "No Title",
+ "interval": 0,
+ "flags": 2048
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Set Master Volume",
+ "group": "basic",
+ "id": "ad01c68d-cdbb-7ba7-0046-c9f4c9113f4b",
+ "send": "return \"MV \" + [Volume];",
+ "interval": "0",
+ "waitForResponse": false,
+ "type": "added",
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "group": "init",
+ "id": "79fcb092-2465-6561-c1f7-4ceb81bee04a",
+ "event": "onDriverVariableChanged",
+ "enabled": false,
+ "type": "added",
+ "filterValue": "Volume",
+ "items": [
+ "8c824b5b-8daf-0290-8b88-2a268da926ad"
+ ],
+ "reference": "",
+ "declaredClass": "xblox.model.events.OnEvent",
+ "name": "On Event",
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "filterPath": "item.name",
+ "valuePath": "item.value",
+ "outlet": 0,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "parentId": "79fcb092-2465-6561-c1f7-4ceb81bee04a",
+ "id": "8c824b5b-8daf-0290-8b88-2a268da926ad",
+ "method": "console.log(\"variable changed\" ,arguments[0]);",
+ "enabled": false,
+ "type": "added",
+ "declaredClass": "xblox.model.code.RunScript",
+ "name": "Run Script",
+ "args": "",
+ "deferred": false,
+ "icon": "fa-code",
+ "shareTitle": "",
+ "order": 0,
+ "description": "No Description",
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Source",
+ "group": "basicVariables",
+ "id": "a95618a6-93b3-de15-6eec-2893e2eb2527",
+ "value": "TV",
+ "type": "added",
+ "declaredClass": "xcf.model.Variable",
+ "gui": "off",
+ "cmd": "off",
+ "save": false,
+ "target": "None",
+ "register": true,
+ "readOnly": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Ping - Volume",
+ "group": "basic",
+ "id": "dec01610-0355-f038-71c8-a46b2cde5fd2",
+ "send": "MV?",
+ "interval": "",
+ "waitForResponse": false,
+ "type": "added",
+ "auto": false,
+ "startup": true,
+ "declaredClass": "xcf.model.Command",
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Ping - Power",
+ "group": "basic",
+ "id": "a5423bf7-7b99-023d-c637-363fbf9a7f18",
+ "startup": true,
+ "send": "PW?",
+ "interval": "",
+ "waitForResponse": false,
+ "icon": "fa-bell",
+ "type": "added",
+ "auto": false,
+ "declaredClass": "xcf.model.Command",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Ping - Source",
+ "group": "basic",
+ "id": "13bd8c70-9cf3-28c9-8c5c-315e54f3cc9d",
+ "send": "SI?",
+ "interval": "",
+ "waitForResponse": false,
+ "icon": "fa-bell",
+ "type": "added",
+ "auto": false,
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Last Value",
+ "group": "basicVariables",
+ "id": "611b5637-dd3e-760e-dcd4-0d21faaaeeff",
+ "type": "added",
+ "declaredClass": "xcf.model.Variable",
+ "gui": "off",
+ "cmd": "off",
+ "save": false,
+ "target": "None",
+ "value": -1,
+ "register": true,
+ "readOnly": false,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "isVariable": true,
+ "flags": 4096,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "dstField": "elseIfBlocks",
+ "parentId": "980b8fd2-3538-4003-85f9-7f70e2b92cb6",
+ "id": "e3720be6-741c-96f4-de07-7edce704264b",
+ "condition": "[value]=='END'",
+ "type": "added",
+ "items": [
+ "d99f0616-ab67-efd7-f4c1-01fa0168c1f8"
+ ],
+ "name": "else if",
+ "declaredClass": "xblox.model.logic.ElseIfBlock",
+ "icon": "",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "dstField": "elseIfBlocks",
+ "parentId": "980b8fd2-3538-4003-85f9-7f70e2b92cb6",
+ "id": "63b534b4-2607-2749-20c5-b109c9c3df3d",
+ "type": "added",
+ "items": [
+ "733c68ae-b22b-c40c-a215-e5a80c8f6dc3"
+ ],
+ "name": "else if",
+ "declaredClass": "xblox.model.logic.ElseIfBlock",
+ "condition": "",
+ "icon": "",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items",
+ "elseIfBlocks",
+ "consequent"
+ ],
+ "group": "conditionalProcess",
+ "condition": "return [value]=='PW';",
+ "id": "980b8fd2-3538-4003-85f9-7f70e2b92cb6",
+ "items": [
+ "e3720be6-741c-96f4-de07-7edce704264b",
+ "63b534b4-2607-2749-20c5-b109c9c3df3d"
+ ],
+ "enabled": false,
+ "type": "added",
+ "elseIfBlocks": [
+ "e3720be6-741c-96f4-de07-7edce704264b",
+ "63b534b4-2607-2749-20c5-b109c9c3df3d"
+ ],
+ "declaredClass": "xblox.model.logic.IfBlock",
+ "name": "if",
+ "icon": "",
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "consequent": [
+ "b45e388f-bfa9-9472-c93c-aa3f101e3a80"
+ ]
+ },
+ {
+ "_containsChildrenIds": [],
+ "id": "d99f0616-ab67-efd7-f4c1-01fa0168c1f8",
+ "enabled": false,
+ "type": "added",
+ "parentId": "e3720be6-741c-96f4-de07-7edce704264b",
+ "declaredClass": "xblox.model.logging.Log",
+ "name": "Log Message",
+ "level": "info",
+ "message": "return \"Message: \" + arguments[0];",
+ "_type": "XBlox",
+ "host": "this host",
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "id": "733c68ae-b22b-c40c-a215-e5a80c8f6dc3",
+ "enabled": false,
+ "type": "added",
+ "parentId": "63b534b4-2607-2749-20c5-b109c9c3df3d",
+ "declaredClass": "xblox.model.logging.Log",
+ "name": "Log Message",
+ "level": "info",
+ "message": "return \"Message: \" + arguments[0];",
+ "_type": "XBlox",
+ "host": "this host",
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "id": "b45e388f-bfa9-9472-c93c-aa3f101e3a80",
+ "enabled": false,
+ "type": "added",
+ "parentId": "980b8fd2-3538-4003-85f9-7f70e2b92cb6",
+ "declaredClass": "xblox.model.logging.Log",
+ "name": "Log Message",
+ "level": "info",
+ "message": "return \"Message: \" + arguments[0];",
+ "_type": "XBlox",
+ "host": "this host",
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0,
+ "icon": "fa-play"
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Set TV",
+ "group": "basic",
+ "id": "e4d05d14-1798-a168-e984-8588d7463b75",
+ "send": "SITV",
+ "waitForResponse": false,
+ "type": "added",
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "interval": 0,
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "group": "init",
+ "id": "ee4d83cc-b3a4-c2eb-9f32-344fb476d646",
+ "send": "PW?",
+ "name": "PingPower",
+ "type": "added",
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "interval": 0,
+ "flags": 2048,
+ "icon": "fa-exclamation",
+ "outlet": 0,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0
+ },
+ {
+ "_containsChildrenIds": [
+ "items"
+ ],
+ "group": "init",
+ "id": "e63cba29-0cf3-7839-a631-75fb9424ab8e",
+ "send": "MV?",
+ "name": "PingVolume",
+ "interval": "0",
+ "type": "added",
+ "items": [
+ "7a0bc101-6a7e-1de5-7dab-bc787953022a"
+ ],
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "flags": 2048,
+ "icon": "fa-exclamation",
+ "outlet": 0,
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "parentId": "e63cba29-0cf3-7839-a631-75fb9424ab8e",
+ "id": "7a0bc101-6a7e-1de5-7dab-bc787953022a",
+ "method": "console.error('init');",
+ "type": "added",
+ "declaredClass": "xblox.model.code.RunScript",
+ "name": "Run Script",
+ "args": "",
+ "deferred": false,
+ "icon": "fa-code",
+ "outlet": 0,
+ "enabled": true,
+ "shareTitle": "",
+ "order": 0,
+ "description": "No Description"
+ },
+ {
+ "_containsChildrenIds": [],
+ "name": "Set Blue-Ray",
+ "id": "c9bc7af6-0de9-0aa7-e6de-6a635cd50ea7",
+ "send": "SIBD",
+ "waitForResponse": false,
+ "type": "added",
+ "group": "basic",
+ "declaredClass": "xcf.model.Command",
+ "startup": false,
+ "interval": 0,
+ "icon": "fa-exclamation",
+ "enabled": true,
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "flags": 2048,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "group": "conditionalProcess",
+ "id": "43062d7e-6cfd-040c-34bf-7a01c428c057",
+ "variable": "31c98cdd-02a8-3af1-3a49-11955c0fad48",
+ "enabled": false,
+ "type": "added",
+ "_stopped": false,
+ "declaredClass": "xblox.model.variables.VariableSwitch",
+ "name": "Switch on Variable",
+ "icon": "",
+ "shareTitle": "",
+ "description": "No Description",
+ "order": 0,
+ "outlet": 0
+ },
+ {
+ "_containsChildrenIds": [],
+ "parentId": "69f6d4fb-4300-0498-9bbf-27554f5f1fa4",
+ "id": "57024e67-bc95-0e99-0e97-3355e8b0e04f",
+ "declaredClass": "xblox.model.functions.SetProperties",
+ "command": "command://deviceScope=user_devices&device=e5a06e24-6aa4-c8c5-3ffc-9d84d8528a91&driver=235eb680-cb87-11e3-9c1a-0800200c9a66&driverScope=user_drivers&block=6d0c5e0e-5c04-bb98-44a0-705c8269de07",
+ "icon": "",
+ "_timeout": 100,
+ "description": "test2sd ",
+ "order": 0,
+ "outlet": 0,
+ "enabled": true,
+ "shareTitle": "",
+ "type": "added",
+ "props": "{\n \"auto\": true\n}"
+ }
+ ],
+ "variables": null
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/model/Connection.ts b/packages/vfs/ref-server/model/Connection.ts
new file mode 100644
index 00000000..9016d638
--- /dev/null
+++ b/packages/vfs/ref-server/model/Connection.ts
@@ -0,0 +1,34 @@
+import { DeviceInfo } from '../shared/types';
+import { Protocol } from '../protocols/Protocol'
+import { v4 } from 'uuid';
+import { Device } from '../entities/device.entity';
+import { User } from '../entities/user.entity';
+import { DriverInstance } from '../shared/driver/DriverInstance';
+import * as md5 from 'md5';
+
+export class Connection {
+ connected: boolean = false;
+ id: string;
+ public instance: Protocol;
+ public device: Device;
+ public user: User;
+ public connecting: Promise = null;
+ public connectingResolve: any;
+ public disconnecting: Promise = null;
+ public driver: DriverInstance = null;
+ public init() {
+ this.driver = new DriverInstance(this.device, null);
+ }
+ static id(user: User, device: Device) {
+ const data = {
+ host: device.host,
+ port: device.port,
+ protocol: device.protocol
+ }
+ return md5(JSON.stringify(data));
+ }
+ public toString() {
+ return `${this.device.protocol}://${this.device.host}:${this.device.port}`
+ }
+
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/pipes/parse-int-with-default.pipe.ts b/packages/vfs/ref-server/pipes/parse-int-with-default.pipe.ts
new file mode 100644
index 00000000..9d66ceb6
--- /dev/null
+++ b/packages/vfs/ref-server/pipes/parse-int-with-default.pipe.ts
@@ -0,0 +1,21 @@
+import { HttpException } from '@nestjs/common';
+import {
+ PipeTransform,
+ Pipe,
+ ArgumentMetadata,
+ HttpStatus,
+} from '@nestjs/common';
+
+@Pipe()
+export class ParseIntWithDefaultPipe implements PipeTransform {
+ constructor(private readonly defaultValue: number) {
+
+ }
+ async transform(value: string, metadata: ArgumentMetadata) {
+ let val = parseInt(value, 10);
+ if (isNaN(val)) {
+ val = this.defaultValue;
+ }
+ return val;
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/pipes/validation.pipe.ts b/packages/vfs/ref-server/pipes/validation.pipe.ts
new file mode 100644
index 00000000..58a08636
--- /dev/null
+++ b/packages/vfs/ref-server/pipes/validation.pipe.ts
@@ -0,0 +1,26 @@
+import { Pipe } from '@nestjs/common';
+import { ArgumentMetadata, PipeTransform } from '@nestjs/common/interfaces';
+import { plainToClass } from 'class-transformer';
+import { validate } from 'class-validator';
+import { CustomValidationError } from '../exceptions/custom-validation.error';
+
+@Pipe()
+export class ValidationPipe implements PipeTransform {
+ public async transform(value, metadata: ArgumentMetadata) {
+ const { metatype } = metadata;
+ if (!metatype || !this.toValidate(metatype)) {
+ return value;
+ }
+ const entity = plainToClass(metatype, value);
+ const errors = await validate(entity, { validationError: { target: false } });
+ if (errors.length > 0) {
+ throw new CustomValidationError(errors)
+ }
+ return entity;
+ }
+
+ private toValidate(metatype): boolean {
+ const types = [String, Boolean, Number, Array, Object];
+ return !types.find(type => metatype === type) && metatype;
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/protocols/Protocol.ts b/packages/vfs/ref-server/protocols/Protocol.ts
new file mode 100644
index 00000000..3ed140c8
--- /dev/null
+++ b/packages/vfs/ref-server/protocols/Protocol.ts
@@ -0,0 +1,79 @@
+import * as utils from '../shared/utils';
+import { DeviceInfo, Connection, DRIVER_FLAGS, DEVICE_FLAGS, IDeviceCommand } from '../types';
+import { ConnectionManager } from '../manager/ConnectionManager';
+import { Model } from '../shared/model/Model';
+import { Device } from '../entities/device.entity';
+import * as debug from '../log';
+
+export type ProtocolMethod = any;
+
+export interface IProtocol {
+ init: () => ProtocolMethod;
+ send: (data: IDeviceCommand) => ProtocolMethod;
+ destroy: () => ProtocolMethod;
+ connect: () => ProtocolMethod;
+ onConnect: (evt?: any) => ProtocolMethod;
+ onDisconnect: (evt?: any) => ProtocolMethod;
+ onError: (evt?: any) => ProtocolMethod;
+ // introspection
+ name: () => string;
+ handler: () => ConnectionManager;
+}
+
+export class Protocol extends Model implements IProtocol {
+ _name: string = 'none';
+ device: Device;
+ connection: Connection;
+ _handler: ConnectionManager;
+ connected: boolean = false;
+ constructor(info: Device, handler: ConnectionManager) {
+ super();
+ this.device = info;
+ this._handler = handler;
+ }
+ delegate = () => { return this._handler };
+ name = () => { return this._name };
+ handler = () => { return this._handler };
+ init() { }
+ send(data: IDeviceCommand): Promise { return Promise.resolve(); }
+ connect() { }
+ onDisconnect(evt?: any) { }
+ onConnect(evt?: any) { }
+ onError(evt?: any) { }
+ // utils
+ toString(cmd: string, encoding) {
+ const intArray = utils.bufferFromDecString(cmd);
+ const buffer = new Buffer(intArray);
+ const str = buffer.toString(encoding);
+ return str;
+ }
+ public isDebug() { return this._hasFlag(DEVICE_FLAGS.DEBUG); }
+ public isServer = () => this._hasFlag(DEVICE_FLAGS.SERVER);
+ public runAsServer = () => this._hasFlag(DEVICE_FLAGS.RUNS_ON_SERVER);
+
+
+ private _hasFlag(flag: number) {
+ const connection = this.connection;
+ if (connection) {
+ const device = connection.device;
+ if (device) {
+ const driverFlags = device.flags;
+ if (driverFlags) {
+ if (driverFlags & flag) {
+ return true;
+ }
+ } else {
+ debug.error('has flag : have no flags');
+ }
+ } else {
+ debug.error('has flag : have no device');
+ }
+ } else {
+ debug.error('has flag : have no connection');
+ }
+ }
+
+ public destroy() {
+ return super.destroy();
+ }
+}
diff --git a/packages/vfs/ref-server/protocols/Tcp.ts b/packages/vfs/ref-server/protocols/Tcp.ts
new file mode 100644
index 00000000..8b8aebcb
--- /dev/null
+++ b/packages/vfs/ref-server/protocols/Tcp.ts
@@ -0,0 +1,450 @@
+import { Protocol } from './Protocol';
+import * as utils from '../shared/utils';
+import { mixin } from '@xblox/core/objects';
+import { remove } from '@xblox/core/arrays';
+import * as _ from 'lodash';
+import * as net from 'net';
+import { DeviceInfo, EVENTS } from './../shared/types';
+import { Connection } from '../model/Connection'
+import * as debug from '../log';
+import { IProtocolHandler, ConnectionManager } from '../manager/ConnectionManager';
+import * as os from 'os';
+import { IDeviceCommand, ERRORS } from '../types';
+const ipaddr = require('ipaddr.js');
+const evilscan = require('evilscan');
+const _debug = false;
+
+export class Tcp extends Protocol {
+ _name = 'tcp';
+ _socket: net.Socket;
+ _server: net.Server;
+ _clients: Connection[] = [];
+ _creatingServer: boolean;
+ _handler: ConnectionManager;
+ connections: any[] = [];
+ _handleSocketEmits(socket: any) {
+ /*
+ var self = this;
+ var connection = self.connection;
+ var scope = this.blockScope;
+ var responseVariable = scope.getVariable('value');
+ var responseVariables = scope.getVariables({
+ group: types.BLOCK_GROUPS.CF_DRIVER_RESPONSE_VARIABLES
+ });
+ var responseBlocks = scope.getBlocks({
+ group: types.BLOCK_GROUPS.CF_DRIVER_RESPONSE_BLOCKS
+ });
+ socket.on('connection', (conn) =>{
+ this.socket = conn;
+ this.clients.push(conn);
+ conn.on('data', function (data) {
+ const messages = [{
+ string: data.toString(),
+ bytes: data.join(",")
+ }];
+
+ for (var i = 0; i < messages.length; i++) {
+ if (messages[i].length === 0) {
+ continue;
+ }
+ responseVariable.value = new String(messages[i].string);
+ responseVariable.value.setBytes(messages[i].bytes);
+
+ //now run each top variable block in 'conditional process'
+ for (var j = 0; j < responseVariables.length; j++) {
+ var _var = responseVariables[j];
+ if (responseVariables[j].title == 'value') {
+ continue;
+ }
+
+ var _varResult = null;
+ var _cValue = responseVariable.value;
+
+
+ if (!(typeof _cValue == "number")) {
+ _cValue = '' + _cValue;
+ _cValue = "'" + _cValue + "'";
+ }
+ var prefix = "var value = " + _cValue + ";";
+
+ _varResult = _cValue;
+ if (_var.target && _var.target != 'None' && _varResult !== null && _varResult != 'null' && _varResult != "'null'") {
+ var targetVariable = scope.getVariable(_var.target);
+ if (targetVariable) {
+ targetVariable.value = _varResult;
+ this.publish(types.EVENTS.ON_DRIVER_VARIABLE_CHANGED, {
+ item: targetVariable,
+ scope: scope,
+ owner: this,
+ save: false,
+ source: types.MESSAGE_SOURCE.BLOX //for prioritizing
+ });
+ }
+ }
+ }
+
+ for (var k = 0; k < messages.length; k++) {
+ var __message = messages[k];
+ if (_.isObject(__message)) {
+ if (__message.src) {
+ var block = scope.getBlockById(__message.src);
+ if (block && block.onData) {
+ block.onData(__message);
+ }
+ }
+ }
+ }
+
+
+ for (var l = 0; l < responseBlocks.length; l++) {
+ var block = responseBlocks[l];
+ if (block.enabled === false) {
+ continue;
+ }
+ block.override = {
+ args: [responseVariable.value]
+ };
+ try {
+ scope.solveBlock(responseBlocks[l], {
+ highlight: false
+ });
+ } catch (e) {
+ console.log('----solving response block crashed ', e);
+ console.trace();
+ }
+ }
+ }
+ });
+ conn.on('close', function () {
+ debug && console.info('close client connection ');
+ });
+ });
+ */
+ }
+ makeServer() {
+ if (this._creatingServer) {
+ return;
+ }
+ this._creatingServer = true;
+ /*
+ try {
+
+ var options = this.info();
+ var port = options.port;
+ var host = options.host;
+
+ var connectionManager = this.owner;
+ var context = connectionManager.ctx;
+
+ var driverManager = context.getDriverManager();
+ var dfd = driverManager.createDriverInstance(options);
+ var self = this;
+
+ dfd.then(function (data) {
+ self.blockScope = data.blockScope;
+ self.driverInstance = data.driverInstance;
+ });
+
+ var server = new net.Server();
+ server.listen(port, host);
+ self._socket = server;
+ server.writable = true;
+ self._handleSocketEmits(server);
+ self.connection.connected = true;
+ self.delegate.onConnect2(self.connection);
+ this.subscribe(types.EVENTS.ON_DEVICE_CONNECTED, this.onDeviceConnected);
+ this.subscribe(types.EVENTS.ON_DEVICE_DISCONNECTED, this.onDeviceDisconnected);
+ } catch (e) {
+ console.error('error creating server', e);
+ }
+ return this;
+ */
+ }
+
+ onConnect(evt: any) {
+ var connection = evt.connection;
+ if (!connection) {
+ return;
+ }
+ var cOptions = connection.options;
+ var options = this.device;
+ if (!this.connections) {
+ this.connections = [];
+ }
+ if (connection.id === this.connection.id) {
+ return;
+ }
+ var exists = false;//this.delegate.getConnectionById(connection.id);
+
+ if (exists && options.host === cOptions.host && options.port === cOptions.port && options.protocol === cOptions.protocol && !connection.isServer()) {
+ if (this.connections.indexOf(connection) === -1) {
+ this.connections.push(connection);
+ }
+ }
+ }
+ onDisconnect(evt: any) {
+ var connection = evt.connection;
+
+ if (!connection) {
+ return;
+ }
+ remove(this.connections, connection);
+ }
+ connect() {
+
+ const isServer = this.isServer();
+ if (isServer) {
+ return this.makeServer();
+ }
+ const options = this.device;
+ const port = options.port;
+ const host = options.host;
+ this._clients = [];
+
+ this._socket = new net.Socket(mixin({
+ allowHalfOpen: true,
+ writable: true,
+ readable: true
+ }, {
+
+ }));
+ const self = this;
+ this.isDebug() && console.log('TCP-Client->Connect to ' + options.host + ' : ' + options.port + ' @ ' + this.name());
+ this._socket.connect(parseInt(port), host, () => {
+ this.connected = true;
+ this.handler().onConnected(this, new Buffer(this.device.name));
+ });
+ this._socket.setNoDelay(true);
+ this._socket.setKeepAlive(true, 0);
+ this.listen(this._socket, this.handler());
+ // (this._socket as any).owner = this;
+ // this._setupEventListeners(this._socket, this.delegate);
+ return this;
+ }
+ listen(socket: net.Socket, handler:ConnectionManager) {
+
+ var self = this;
+
+ //var connection = this.connection;
+ /*
+ socket.handle = function (data) {
+ handler.onHandle(connection, data);
+ };*/
+
+ const toArrayBuffer = (buffer) => {
+ var ab = new ArrayBuffer(buffer.length);
+ var view = new Uint8Array(ab);
+ for (var i = 0; i < buffer.length; ++i) {
+ view[i] = buffer[i];
+ }
+ return ab;
+ }
+
+ socket.on('data', (data) => {
+ handler.onData(this, data);
+ });
+
+ if (!handler) {
+ debug.stack('have no handler');
+ }
+
+ /*
+ if (!connection) {
+ console.error('have no connection');
+ debug.stack('have no connect');
+ }
+ */
+
+ socket.on('error', (exception) => {
+ this.isDebug() && debug.error('socket error : ', exception);
+ handler.onError(this, exception);
+ });
+ socket.on('timeout', () => {
+ handler.onTimeout(this);
+ });
+
+ // Add a 'close' event handler for the client client
+ socket.on('close', (data) => {
+ handler.onClose(this);
+ });
+
+ }
+ broadCastMessage(eventName, _data) {
+ const data = _data;
+ const connections = this.connections;
+ this.connections.forEach((connection) => {
+ if (!connection) {
+ return;
+ }
+ if (connection._destroyed) {
+ remove(connections, Connection);
+ }
+ if (connection.client) {
+ connection.client.delegate.onData(connection, data.toString(), data);
+ } else {
+ debug.error('not at a real connection', connection);
+ }
+ });
+
+ }
+ send(data: IDeviceCommand) {
+ return new Promise((resolve, reject) => {
+ const cmd = data.command;
+ if (cmd == null) {
+ debug.error('TCP : invalid command');
+ return;
+ }
+ const intArray = utils.bufferFromDecString(cmd);
+ const buffer = new Buffer(intArray);
+ if (this.isServer()) {
+ this.broadCastMessage(EVENTS.ON_DEVICE_MESSAGE, buffer);
+ } else {
+ debug.log('send device command ' + buffer.toString());
+ if (this._socket.writable) {
+ try {
+ if (this._socket.write(buffer)) {
+ resolve();
+ } else {
+ reject('send failed');
+ };
+ } catch (e) {
+ debug.error('error send TCP command', e);
+ }
+ } else {
+ debug.error('Socket not writeable ' + this.debug());
+ const e = {
+ code: ERRORS.EHOSTUNREACH,
+ errno: 16,
+ message: 'Socket not writeable'
+ } as NodeJS.ErrnoException
+ this.handler().onError(this, e);
+ }
+ }
+ });
+ }
+ debug = () => `Protocol ${this.name()} @ ${this.device.host} : ${this.device.port} | Id : ${this.id}`;
+ destroy() {
+ if (this.isDestroyed()) {
+ debug.warn('already destroyed: ' + this.debug());
+ return;
+ }
+ if (!this.isServer()) {
+ this._socket.end();
+ } else {
+ this._server.close();
+ }
+ /*
+ this.blockScope && this.blockScope.destroy();
+ this.driverInstance && this.driverInstance.destroy();
+ delete this.blockScope;
+ delete this.driverInstance;
+ delete this.connections;
+ delete this.clients;
+ delete this._socket;
+ this._destroyed = true;
+ */
+ super.destroy();
+ }
+ close() {
+ if (!this.isServer()) {
+ this._socket.end();
+ } else {
+ this._server.close();
+ this.destroy();
+ }
+ }
+ static ls(query: any = {}) {
+ return new Promise((resolve, reject) => {
+ try {
+
+ const ifaces = os.networkInterfaces();
+ const ips = [];
+ Object.keys(ifaces).forEach(function (ifname) {
+ let alias = 0;
+ ifaces[ifname].forEach(function (iface) {
+ if ('IPv4' !== iface.family || iface.internal !== false) {
+ // skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
+ return;
+ }
+ if (alias >= 1) {
+ // this single interface has multiple ipv4 addresses
+ ips.push({
+ face: ifname + alias,
+ ip: iface.address
+ })
+ } else {
+ ips.push({
+ face: ifname,
+ ip: iface.address
+ })
+ }
+ ++alias;
+ });
+ });
+ let results = {}
+
+ function checkResults() {
+ var done = true;
+ _.each(results, function (item) {
+ if (!item.done) {
+ done = false;
+ }
+ })
+ if (done) {
+ var result = [];
+ results = _.filter(results, function (result) {
+ return result.list.length > 0
+ });
+ _.each(results, function (item) {
+ result = result.concat(item.list);
+ });
+ resolve(result);
+ }
+ }
+ _.each(ips, function (ip) {
+ const range = ipaddr.parse(ip.ip);
+ const octets = range.octets;
+ octets[octets.length - 1] = 0;
+ const target = octets.join('.') + '-254';
+ const testPorts = [query.ports || '80'];
+ const options = {
+ target: target,
+ port: testPorts.join(','),
+ status: 'Open', // Timeout, Refused, Open, Unreachable
+ timeout: 500,
+ banner: false
+ }
+ const scanner = new evilscan(options);
+ if (!results[target]) {
+ results[target] = {
+ done: false
+ };
+ results[target].list = [];
+ }
+ scanner.on('result', function (data) {
+ // fired when item is matching options
+ if (data.status === 'open') {
+ results[target].list.push({
+ host: data.ip,
+ port: data.port,
+ description: ip.face + ' ' + ip.ip,
+ "interface": ip.face
+ });
+ }
+ });
+ scanner.on('error', function (err) {
+ reject("error scanning tcp");
+ });
+ scanner.on('done', function () {
+ //console.log('done');
+ results[target].done = true;
+ checkResults();
+ });
+ scanner.run();
+ });
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+}
diff --git a/packages/vfs/ref-server/server.ts b/packages/vfs/ref-server/server.ts
new file mode 100644
index 00000000..8ec94e4d
--- /dev/null
+++ b/packages/vfs/ref-server/server.ts
@@ -0,0 +1,66 @@
+import { NestFactory } from '@nestjs/core';
+import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
+import { config } from 'dotenv';
+
+import { AppModule } from './app.module';
+import { CustomExceptionFilter } from './exceptions/custom-exception.filter';
+import { ValidationPipe } from './pipes/validation.pipe';
+import * as path from 'path';
+import * as express from 'express';
+import * as fs from 'fs';
+import * as cors from 'cors';
+
+async function bootstrap() {
+ config();
+ const packageBody = require('../package.json');
+
+ const WWW_ROOT = path.resolve(__dirname, '..', 'www');
+ const server = express();
+
+ const app = await NestFactory.create(AppModule, server);
+
+
+ const options2 = {
+ "origin": "*",
+ "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
+ "preflightContinue": true,
+ "optionsSuccessStatus": 204
+ }
+ server.use(express.static(WWW_ROOT));
+ server.options('*', cors(options2)) // include before other routes
+ app.use(cors(options2));
+ app.useGlobalFilters(new CustomExceptionFilter());
+ app.useGlobalPipes(new ValidationPipe());
+
+ const options = new DocumentBuilder()
+ .setTitle(packageBody.name)
+ .setDescription(packageBody.description)
+ .setContactEmail(packageBody.author.email)
+ .setExternalDoc('Project on Github', packageBody.repository)
+ .setLicense('MIT', '')
+ .setSchemes('http')
+ .setVersion(packageBody.version)
+ .addBearerAuth('Authorization', 'header')
+ .build();
+
+ const document = SwaggerModule.createDocument(app, options);
+
+ server.use('/json', (req, res, next) => res.send(document));
+
+
+ /*
+ const stt = require('swagger-test-templates');
+ const testsConfig = {
+ assertionFormat: 'should',
+ testModule: 'request'
+ };
+ const tests = stt.testGen(document, testsConfig);
+ tests.forEach(test => {
+ fs.writeFileSync(path.resolve(__dirname, '..', 'tests', test.name), test.test);
+ });
+*/
+ SwaggerModule.setup('/swagger', app, document);
+
+ await app.listen(process.env.PORT && !isNaN(+process.env.PORT) ? +process.env.PORT : 3010);
+}
+bootstrap();
diff --git a/packages/vfs/ref-server/services/DeviceService.ts b/packages/vfs/ref-server/services/DeviceService.ts
new file mode 100644
index 00000000..097ee1de
--- /dev/null
+++ b/packages/vfs/ref-server/services/DeviceService.ts
@@ -0,0 +1,4 @@
+export class DeviceService {
+ public socket: any;
+ public sendDeviceCommand: any;
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/services/account.service.ts b/packages/vfs/ref-server/services/account.service.ts
new file mode 100644
index 00000000..349d892b
--- /dev/null
+++ b/packages/vfs/ref-server/services/account.service.ts
@@ -0,0 +1,93 @@
+import { Component } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass, plainToClassFromExist } from 'class-transformer';
+import { Repository } from 'typeorm';
+
+import { InAccountLoginDto } from '../dto/in-account-login.dto';
+import { InAccountRegisterDto } from '../dto/in-account-register.dto';
+import { InTokenDto } from '../dto/in-token.dto';
+import { OutAccountTokenDto } from '../dto/out-account-token.dto';
+import { User } from '../entities/user.entity';
+import { TokenService } from './token.service';
+import { InAccountDto } from '../dto/in-account.dto';
+
+@Component()
+export class AccountService {
+ constructor(
+ @InjectRepository(User)
+ private readonly usersRepository: Repository,
+ private readonly tokenService: TokenService
+ ) {
+
+ }
+ async info(dto: InTokenDto) {
+ try {
+ if (this.tokenService.verify(dto.token)) {
+ let tokenData: any = this.tokenService.decode(dto.token);
+ let object = await this.usersRepository.findOneOrFail(
+ tokenData.id,
+ { relations: ['groups', 'groups.permissions'] }
+ );
+ if (this.tokenService.getSecretKey(tokenData) === this.tokenService.getSecretKey(object)) {
+ object = await this.usersRepository.save(object);
+ return plainToClass(OutAccountTokenDto, { user: object, token: this.tokenService.sign(object) });
+ } else {
+ throw new Error('Invalid token');
+ }
+ }
+ } catch (error) {
+ throw error;
+ }
+ }
+ async login(dto: InAccountLoginDto) {
+ // console.log('this', this.ws.server);
+ try {
+ let object = plainToClass(User, dto);
+ object = await this.usersRepository.findOneOrFail({
+ where: {
+ email: object.email
+ },
+ relations: ['groups', 'groups.permissions']
+ });
+ if (!object.verifyPassword(dto.password)) {
+ throw new Error('Wrong password');
+ }
+ object = await this.usersRepository.save(object);
+ return plainToClass(OutAccountTokenDto, { user: object, token: this.tokenService.sign(object) });
+ } catch (error) {
+ throw error;
+ }
+ }
+ async register(dto: InAccountRegisterDto) {
+ try {
+ let object = plainToClass(User, dto);
+ object.isActive = false;
+ object.isStaff = false;
+ object.isSuperuser = false;
+ object.username = object.email;
+ object.firstName = object.email;
+ object.firstName = object.email;
+ object.lastName = object.email;
+ object.setPassword(object.password);
+ object = await this.usersRepository.save(object);
+ object = await this.usersRepository.findOneOrFail(
+ object.id,
+ { relations: ['groups', 'groups.permissions'] }
+ );
+ return plainToClass(OutAccountTokenDto, { user: object, token: this.tokenService.sign(object) })
+ } catch (error) {
+ throw error;
+ }
+ }
+ async update(id: number, dto: InAccountDto) {
+ try {
+ let object = await this.usersRepository.findOneOrFail(id, { relations: ['groups', 'groups.permissions'] });
+ object = plainToClassFromExist(object, dto);
+ object.setPassword(object.password);
+ object = await this.usersRepository.save(object);
+ return plainToClass(OutAccountTokenDto, { user: object, token: this.tokenService.sign(object) });
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/services/groups.service.ts b/packages/vfs/ref-server/services/groups.service.ts
new file mode 100644
index 00000000..9eb7ab2d
--- /dev/null
+++ b/packages/vfs/ref-server/services/groups.service.ts
@@ -0,0 +1,42 @@
+import { Component } from '@nestjs/common';
+import { InjectRepository } from '@nestjs/typeorm';
+import { plainToClass } from 'class-transformer';
+import { Repository } from 'typeorm';
+
+import { Group } from '../entities/group.entity';
+
+@Component()
+export class GroupsService {
+ groups: Group[] = null;
+ constructor(
+ @InjectRepository(Group)
+ private readonly groupsRepository: Repository
+ ) {
+ this.loadAll();
+ }
+ loadAll() {
+ if (this.groups === null) {
+ this.loadGroups().then((groups) => {
+ this.groups = groups;
+ });
+ }
+ }
+ getGroupByName(name: string) {
+ let groups = this.groups.filter(group => group.name === name);
+ if (groups.length) {
+ return groups[0];
+ }
+ return null;
+ }
+ async loadGroups() {
+ try {
+ return (await this.groupsRepository.createQueryBuilder('group')
+ .leftJoinAndSelect('group.permissions', 'permission')
+ .getMany()).map(
+ object => plainToClass(Group, object)
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/services/index.ts b/packages/vfs/ref-server/services/index.ts
new file mode 100644
index 00000000..4f2bad71
--- /dev/null
+++ b/packages/vfs/ref-server/services/index.ts
@@ -0,0 +1,8 @@
+import { AccountService } from './account.service';
+import { GroupsService } from './groups.service';
+import { TokenService } from './token.service';
+export const services = [
+ TokenService,
+ AccountService,
+ GroupsService
+]
\ No newline at end of file
diff --git a/packages/vfs/ref-server/services/token.service.ts b/packages/vfs/ref-server/services/token.service.ts
new file mode 100644
index 00000000..3f3f8db2
--- /dev/null
+++ b/packages/vfs/ref-server/services/token.service.ts
@@ -0,0 +1,50 @@
+import { decode, sign, verify } from 'jsonwebtoken';
+import { Component } from '@nestjs/common';
+
+@Component()
+export class TokenService {
+ sign(user: any) {
+ return sign(
+ {
+ id: user.id,
+ isStaff: user.isStaff,
+ isActive: user.isActive,
+ isSuperuser: user.isSuperuser,
+ groups: user.groups.map(group => {
+ return { name: group.name };
+ })
+ },
+ this.getSecretKey({
+ id: user.id,
+ isStaff: user.isStaff,
+ isActive: user.isActive,
+ isSuperuser: user.isSuperuser,
+ groups: user.groups
+ }),
+ {
+ expiresIn: process.env.JWT_EXPIRATION_DELTA
+ }
+ )
+ }
+ verify(token: string) {
+ const data: any = decode(
+ token
+ );
+ return verify(token, this.getSecretKey(data));
+ }
+ decode(token: string) {
+ return decode(
+ token
+ )
+ }
+ getSecretKey(data: any) {
+ return process.env.SECRET_KEY +
+ (data ? (
+ '$' + data.id +
+ '$' + data.isStaff +
+ '$' + data.isActive +
+ '$' + data.isSuperuser +
+ (data.groups ? data.groups.map(group => '$' + group.name) : '')
+ ) : '');
+ }
+}
\ No newline at end of file
diff --git a/packages/vfs/ref-server/types.ts b/packages/vfs/ref-server/types.ts
new file mode 100644
index 00000000..5b7594ee
--- /dev/null
+++ b/packages/vfs/ref-server/types.ts
@@ -0,0 +1,53 @@
+import { DeviceDto } from './dto/device.dto';
+
+export * from './shared/model/Model';
+export * from './shared/model/Device';
+export * from './shared/model/Driver';
+export * from './model/Connection';
+export * from './extensions/Evented';
+export * from './protocols/Protocol';
+export * from './protocols/Tcp';
+export * from './manager/ConnectionManager';
+export * from './shared/enums';
+export * from './errors';
+export { Device } from './entities/device.entity';
+
+export interface IDeviceCommand {
+ command: string;
+ device_command: string;
+ device: DeviceDto;
+ params: any;
+}
+
+// tslint:disable-next-line:interface-name
+export interface Hash {
+ [id: string]: T;
+}
+// tslint:disable-next-line:interface-name
+export interface List {
+ [index: number]: T;
+ length: number;
+}
+/**
+ * Interface of the simple literal object with any string keys.
+ */
+export interface IObjectLiteral {
+ [key: string]: any;
+}
+/**
+ * Represents some Type of the Object.
+ */
+export type ObjectType = { new(): T } | Function;
+/**
+ * Same as Partial but goes deeper and makes Partial all its properties and sub-properties.
+ */
+export type DeepPartial = {
+ [P in keyof T]?: DeepPartial;
+};
+
+export interface IDelimitter {
+ begin: '%';
+ end: '%';
+}
+
+export type JSONPathExpression = string;
diff --git a/packages/vfs/ref/LICENSE b/packages/vfs/ref/LICENSE
new file mode 100644
index 00000000..09d493bf
--- /dev/null
+++ b/packages/vfs/ref/LICENSE
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2017,
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/vfs/ref/Makefile b/packages/vfs/ref/Makefile
new file mode 100644
index 00000000..d69d8a10
--- /dev/null
+++ b/packages/vfs/ref/Makefile
@@ -0,0 +1,28 @@
+PROJECT = "My Fancy Node.js project"
+
+all: install test server
+
+debug: ;@echo "Debugging ${PROJECT}.....http://0.0.0.0:8080/debug?port=5858 to start debugging"; \
+ export NODE_PATH=.; \
+ node-inspector & coffee --nodejs --debug app.coffee;
+
+test: ;@echo "Testing ${PROJECT}....."; \
+ export NODE_PATH=.; \
+ ./node_modules/mocha/bin/mocha;
+
+server : ;@echo "Starting ${PROJECT}....."; \
+ export NODE_PATH=.; \
+ coffee app.coffee
+
+install: ;@echo "Installing ${PROJECT}....."; \
+ npm install
+
+update: ;@echo "Updating ${PROJECT}....."; \
+ git pull --rebase; \
+ npm install
+
+clean : ;
+ rm -rf node_modules
+
+
+.PHONY: test server install clean update
diff --git a/packages/vfs/ref/acl/ACLC.ts b/packages/vfs/ref/acl/ACLC.ts
new file mode 100644
index 00000000..b33d1bb9
--- /dev/null
+++ b/packages/vfs/ref/acl/ACLC.ts
@@ -0,0 +1,745 @@
+/*
+ ACL System inspired on Zend_ACL.
+ All functions accept strings, objects or arrays unless specified otherwise.
+
+ '*' is used to express 'all'
+
+ Database structure in Redis (using default prefix 'acl')
+
+ Users:
+
+ acl_roles_{userid} = set(roles)
+
+ Roles:
+
+ acl_roles = {roleNames} // Used to remove all the permissions associated to ONE resource.
+
+ acl_parents_{roleName} = set(parents)
+ acl_resources_{roleName} = set(resourceNames)
+
+ Permissions:
+ acl_allows_{resourceName}_{roleName} = set(permissions)
+ Note: user ids, role names and resource names are all case sensitive.
+
+ Roadmap:
+ - Add support for locking resources. If a user has roles that gives him permissions to lock
+ a resource, then he can get exclusive write operation on the locked resource.
+ This lock should expire if the resource has not been accessed in some time.
+*/
+import * as _ from 'lodash';
+import * as bluebird from 'bluebird';
+import { contract } from './contract';
+import { ILogger, IAcl, IBucketsOption, IBackend, Action } from './interfaces';
+import { Value, Values, strings, Callback, AnyCallback, AllowedCallback } from './interfaces';
+contract.debug = true;
+
+function makeArray(arr: any | Object): Array {
+ return Array.isArray(arr) ? arr : [arr];
+}
+
+function allowsBucket(role: string): string {
+ return 'allows_' + role;
+}
+
+function keyFromAllowsBucket(str: string): string {
+ return str.replace(/^allows_/, '');
+}
+
+export class ACL implements IAcl {
+ logger: any;
+ backend: any;
+ options: any;
+ constructor(backend: IBackend, logger: ILogger | any, options?: any) {
+ const buckets: IBucketsOption = {
+ meta: 'meta',
+ parents: 'parents',
+ permissions: 'permissions',
+ resources: 'resources',
+ roles: 'roles',
+ users: 'users'
+ };
+
+ options = _.extend({
+ buckets: buckets
+ }, options);
+
+ this.logger = logger;
+ this.backend = backend;
+ this.options = options;
+ }
+
+ public allow(roles: Values, resources: strings, permissions: strings, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string|array', 'string|array', 'string|array', 'function')
+ .params('string|array', 'string|array', 'string|array')
+ .params('array', 'function')
+ .params('array')
+ .end();
+
+ if ((arguments.length === 1) || ((arguments.length === 2) && _.isObject(roles) && _.isFunction(resources))) {
+ return this._allowEx(roles).nodeify(resources);
+ } else {
+ let _this = this;
+ roles = makeArray(roles);
+ resources = makeArray(resources);
+ let backend = _this.backend;
+ let transaction = _this.backend.begin();
+ backend.add(transaction, _this.options.buckets.meta, 'roles', roles);
+ resources.forEach(function (resource) {
+ _.each(roles, (role) => {
+ backend.add(transaction, allowsBucket(resource), role, permissions);
+ });
+ });
+ roles.forEach(function (role) {
+ _this.backend.add(transaction, _this.options.buckets.resources, role, resources);
+ });
+ return backend.endAsync(transaction).nodeify(cb);
+ }
+ }
+ /* addUserRoles( userId, roles, function(err) )
+ * Adds roles to a given user id.
+ @param {String|Number} User id.
+ @param {String|Array} Role(s) to add to the user id.
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved when finished
+ */
+ public addUserRoles(userId: Value, roles: strings, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string|number', 'string|array', 'function')
+ .params('string|number', 'string|array')
+ .end();
+
+ let transaction = this.backend.begin();
+ this.backend.add(transaction, this.options.buckets.meta, 'users', userId);
+ this.backend.add(transaction, this.options.buckets.users, userId, roles);
+
+ if (Array.isArray(roles)) {
+ let _this = this;
+
+ roles.forEach(function (role) {
+ _this.backend.add(transaction, _this.options.buckets.roles, role, userId);
+ });
+ }
+ else {
+ this.backend.add(transaction, this.options.buckets.roles, roles, userId);
+ }
+
+ return this.backend.endAsync(transaction).nodeify(cb);
+ }
+ /*
+ removeUserRoles( userId, roles, function(err) )
+ Remove roles from a given user.
+ @param {String|Number} User id.
+ @param {String|Array} Role(s) to remove to the user id.
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved when finished
+ */
+ public removeUserRoles(userId: Value, roles: strings, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string|number', 'string|array', 'function')
+ .params('string|number', 'string|array')
+ .end();
+
+ let transaction = this.backend.begin();
+ this.backend.remove(transaction, this.options.buckets.users, userId, roles);
+
+ if (Array.isArray(roles)) {
+ let _this = this;
+
+ roles.forEach(function (role) {
+ _this.backend.remove(transaction, _this.options.buckets.roles, role, userId);
+ });
+ }
+ else {
+ this.backend.remove(transaction, this.options.buckets.roles, roles, userId);
+ }
+
+ return this.backend.endAsync(transaction).nodeify(cb);
+ }
+ /*
+ userRoles( userId, function(err, roles) )
+ Return all the roles from a given user.
+
+ @param {String|Number} User id.
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved with an array of user roles
+ */
+ public userRoles(userId: Value, cb?: (err: Error, roles: string[]) => any): bluebird {
+ return this.backend.getAsync(this.options.buckets.users, userId).nodeify(cb);
+ }
+ /*
+ roleUsers( roleName, function(err, users) )
+ Return all users who has a given role.
+ @param {String|Number} rolename.
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved with an array of users
+ */
+ public roleUsers(role: Value, cb?: (err: Error, users: Values) => any): Promise {
+ return this.backend.getAsync(this.options.buckets.roles, role).nodeify(cb);
+ }
+ /*
+ hasRole( userId, rolename, function(err, is_in_role) )
+ Return boolean whether user is in the role
+ @param {String|Number} User id.
+ @param {String|Number} rolename.
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved with boolean of whether user is in role
+ */
+ public hasRole(userId: Value, role: string, cb?: (err: Error, isInRole: boolean) => any): bluebird {
+ return this.userRoles(userId).then(function (roles) {
+ return roles.indexOf(role) !== -1;
+ }).nodeify(cb);
+ }
+
+ /*
+ addRoleParents( role, parents, function(err) )
+ Adds a parent or parent list to role.
+ @param {String} Child role.
+ @param {String|Array} Parent role(s) to be added.
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved when finished
+ */
+ public addRoleParents(role: string, parents: Values, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string|number', 'string|array', 'function')
+ .params('string|number', 'string|array')
+ .end();
+
+ let transaction = this.backend.begin();
+ this.backend.add(transaction, this.options.buckets.meta, 'roles', role);
+ this.backend.add(transaction, this.options.buckets.parents, role, parents);
+ return this.backend.endAsync(transaction).nodeify(cb);
+ };
+
+ /*
+ removeRoleParents( role, parents, function(err) )
+
+ Removes a parent or parent list from role.
+
+ If `parents` is not specified, removes all parents.
+
+ @param {String} Child role.
+ @param {String|Array} Parent role(s) to be removed [optional].
+ @param {Function} Callback called when finished [optional].
+ @return {Promise} Promise resolved when finished.
+ */
+ public removeRoleParents(role: any, parents: Function, cb: Function) {
+ contract(arguments)
+ .params('string', 'string|array', 'function')
+ .params('string', 'string|array')
+ .params('string', 'function')
+ .params('string')
+ .end();
+
+ if (!cb && _.isFunction(parents)) {
+ cb = parents;
+ parents = null;
+ }
+
+ let transaction = this.backend.begin();
+ if (parents) {
+ this.backend.remove(transaction, this.options.buckets.parents, role, parents);
+ } else {
+ this.backend.del(transaction, this.options.buckets.parents, role);
+ }
+ return this.backend.endAsync(transaction).nodeify(cb);
+ }
+ /*
+ removeRole( role, function(err) )
+
+ Removes a role from the system.
+
+ @param {String} Role to be removed
+ @param {Function} Callback called when finished.
+ */
+ public removeRole(role: string, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string', 'function')
+ .params('string').end();
+
+ let _this = this;
+ // Note that this is not fully transactional.
+ return this.backend.getAsync(this.options.buckets.resources, role).then((resources) => {
+ let transaction = _this.backend.begin();
+ resources.forEach((resource) => {
+ let bucket = allowsBucket(resource);
+ _this.backend.del(transaction, bucket, role);
+ });
+ _this.backend.del(transaction, _this.options.buckets.resources, role);
+ _this.backend.del(transaction, _this.options.buckets.parents, role);
+ _this.backend.del(transaction, _this.options.buckets.roles, role);
+ _this.backend.remove(transaction, _this.options.buckets.meta, 'roles', role);
+
+ // `users` collection keeps the removed role
+ // because we don't know what users have `role` assigned.
+ return _this.backend.endAsync(transaction);
+ }).nodeify(cb);
+ };
+ /*
+ removeResource( resource, function(err) )
+ Removes a resource from the system
+ @param {String} Resource to be removed
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved when finished
+ */
+ public removeResource(resource: string, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string', 'function')
+ .params('string')
+ .end();
+
+ let _this = this;
+ return this.backend.getAsync(this.options.buckets.meta, 'roles').then(function (roles: Array) {
+ let transaction = _this.backend.begin();
+ _this.backend.del(transaction, allowsBucket(resource), roles);
+ roles.forEach((role) => {
+ _this.backend.remove(transaction, _this.options.buckets.resources, role, resource);
+ });
+ return _this.backend.endAsync(transaction);
+ }).nodeify(cb);
+ }
+ /*
+ allow( roles, resources, permissions, function(err) )
+ Adds the given permissions to the given roles over the given resources.
+
+ @param {String|Array} role(s) to add permissions to.
+ @param {String|Array} resource(s) to add permisisons to.
+ @param {String|Array} permission(s) to add to the roles over the resources.
+ @param {Function} Callback called when finished.
+
+ allow( permissionsArray, function(err) )
+
+ @param {Array} Array with objects expressing what permissions to give.
+
+ [{roles:{String|Array}, allows:[{resources:{String|Array}, permissions:{String|Array}]]
+
+ @param {Function} Callback called when finished.
+ @return {Promise} Promise resolved when finished
+ */
+ public removeAllow(role: string, resources: strings, permissions: strings, cb?: Callback): Promise {
+ contract(arguments)
+ .params('string', 'string|array', 'string|array', 'function')
+ .params('string', 'string|array', 'string|array')
+ .params('string', 'string|array', 'function')
+ .params('string', 'string|array')
+ .end();
+
+ resources = makeArray(resources);
+ if (cb || (permissions && !_.isFunction(permissions))) {
+ permissions = makeArray(permissions);
+ } else {
+ cb = (permissions as any);
+ permissions = null;
+ }
+
+ return this.removePermissions(role, resources, permissions, cb);
+ };
+ /*
+ removePermissions( role, resources, permissions)
+ Remove permissions from the given roles owned by the given role.
+ Note: we loose atomicity when removing empty role_resources.
+ @param {String}
+ @param {String|Array}
+ @param {String|Array}
+ */
+ public removePermissions(role: string, resources: strings, permissions: strings, cb?: Function): Promise {
+ let _this = this;
+ let transaction = _this.backend.begin();
+ _.each(resources, resource => {
+ let bucket = allowsBucket(resource);
+ if (permissions) {
+ _this.backend.remove(transaction, bucket, role, permissions);
+ } else {
+ _this.backend.del(transaction, bucket, role);
+ _this.backend.remove(transaction, _this.options.buckets.resources, role, resource);
+ }
+ });
+
+ // Remove resource from role if no rights for that role exists.
+ // Not fully atomic...
+ return _this.backend.endAsync(transaction).then(function () {
+ let transaction = _this.backend.begin();
+ return bluebird.all(_.map(resources, resource => {
+ let bucket = allowsBucket(resource);
+ return _this.backend.getAsync(bucket, role).then(function (permissions) {
+ if (permissions.length === 0) {
+ _this.backend.remove(transaction, _this.options.buckets.resources, role, resource);
+ }
+ });
+ })).then(function () {
+ return _this.backend.endAsync(transaction);
+ });
+ }).nodeify(cb);
+ };
+ /*
+ allowedPermissions( userId, resources, function(err, obj) )
+ Returns all the allowable permissions a given user have to
+ access the given resources.
+ It returns an array of objects where every object maps a
+ resource name to a list of permissions for that resource.
+
+ @param {String|Number} User id.
+ @param {String|Array} resource(s) to ask permissions for.
+ @param {Function} Callback called when finished.
+ */
+ public allowedPermissions(userId: Value, resources: strings, cb?: AnyCallback): bluebird {
+ if (!userId) {
+ return cb(null, {});
+ }
+
+ contract(arguments)
+ .params('string|number', 'string|array', 'function')
+ .params('string|number', 'string|array')
+ .end();
+
+ if (this.backend.unionsAsync) {
+ return this.optimizedAllowedPermissions(userId, resources, cb);
+ }
+
+ let _this = this;
+ resources = makeArray(resources);
+ return this.userRoles(userId).then(roles => {
+ let result = {};
+
+ return bluebird.all(_.map(resources, resource => {
+ return _this._resourcePermissions(roles, resource).then(function (permissions) {
+ result[resource] = permissions;
+ });
+ })).then(function () {
+ return result;
+ });
+
+ }).nodeify(cb);
+ }
+ /*
+ optimizedAllowedPermissions( userId, resources, function(err, obj) )
+
+ Returns all the allowable permissions a given user have to
+ access the given resources.
+
+ It returns a map of resource name to a list of permissions for that resource.
+
+ This is the same as allowedPermissions, it just takes advantage of the unions
+ function if available to reduce the number of backend queries.
+
+ @param {String|Number} User id.
+ @param {String|Array} resource(s) to ask permissions for.
+ @param {Function} Callback called when finished.
+ */
+ public optimizedAllowedPermissions(userId, resources, cb) {
+ if (!userId) {
+ return cb(null, {});
+ }
+
+ contract(arguments)
+ .params('string|number', 'string|array', 'function|undefined')
+ .params('string|number', 'string|array')
+ .end();
+
+ resources = makeArray(resources);
+ let self = this;
+
+ return this._allUserRoles(userId).then(function (roles) {
+ let buckets = resources.map(allowsBucket);
+ if (roles.length === 0) {
+ let emptyResult = {};
+ buckets.forEach(function (bucket) {
+ emptyResult[bucket] = [];
+ });
+ return bluebird.resolve(emptyResult);
+ }
+
+ return self.backend.unionsAsync(buckets, roles);
+ }).then(function (response) {
+ let result = {};
+ Object.keys(response).forEach(function (bucket) {
+ result[keyFromAllowsBucket(bucket)] = response[bucket];
+ });
+
+ return result;
+ }).nodeify(cb);
+ }
+ /*
+ isAllowed( userId, resource, permissions, function(err, allowed) )
+
+ Checks if the given user is allowed to access the resource for the given
+ permissions (note: it must fulfill all the permissions).
+
+ @param {String|Number} User id.
+ @param {String|Array} resource(s) to ask permissions for.
+ @param {String|Array} asked permissions.
+ @param {Function} Callback called wish the result.
+ */
+ public isAllowed(userId: Value, resource: strings, permissions: strings, cb?: AllowedCallback): Promise {
+ contract(arguments)
+ .params('string|number', 'string', 'string|array', 'function')
+ .params('string|number', 'string', 'string|array')
+ .end();
+
+ let _this = this;
+ return this.backend.getAsync(this.options.buckets.users, userId).then(function (roles) {
+ if (roles.length) {
+ return _this.areAnyRolesAllowed(roles, resource, permissions);
+ } else {
+ return false;
+ }
+ }).nodeify(cb);
+ }
+
+ /*
+ areAnyRolesAllowed( roles, resource, permissions, function(err, allowed) )
+
+ Returns true if any of the given roles have the right permissions.
+
+ @param {String|Array} Role(s) to check the permissions for.
+ @param {String} resource(s) to ask permissions for.
+ @param {String|Array} asked permissions.
+ @param {Function} Callback called with the result.
+ */
+ public areAnyRolesAllowed(roles: strings, resource: strings, permissions: strings, cb?: AllowedCallback): Promise {
+ contract(arguments)
+ .params('string|array', 'string', 'string|array', 'function')
+ .params('string|array', 'string', 'string|array')
+ .end();
+
+ roles = makeArray(roles);
+ permissions = makeArray(permissions);
+
+ if (roles.length === 0) {
+ return (bluebird as any).resolve(false).nodeify(cb);
+ } else {
+ return this._checkPermissions(roles, resource, permissions).nodeify(cb);
+ }
+ }
+ /*
+ whatResources(role, function(err, {resourceName: [permissions]})
+
+ Returns what resources a given role or roles have permissions over.
+
+ whatResources(role, permissions, function(err, resources) )
+
+ Returns what resources a role has the given permissions over.
+
+ @param {String|Array} Roles
+ @param {String[Array} Permissions
+ @param {Function} Callback called wish the result.
+ */
+ public whatResources(roles: strings, permissions: strings, cb?: AnyCallback): Promise {
+ contract(arguments)
+ .params('string|array')
+ .params('string|array', 'string|array')
+ .params('string|array', 'function')
+ .params('string|array', 'string|array', 'function')
+ .end();
+
+ roles = makeArray(roles);
+ if (_.isFunction(permissions)) {
+ cb = (permissions);
+ permissions = undefined;
+ } else if (permissions) {
+ permissions = makeArray(permissions);
+ }
+
+ return this.permittedResources(roles, permissions, cb);
+ }
+
+ public permittedResources(roles: strings, permissions: strings, cb?: Function): Promise {
+ let _this = this;
+ let result: any = _.isUndefined(permissions) ? {} : [];
+ return this._rolesResources(roles).then(function (resources) {
+ return bluebird.all(resources.map(function (resource) {
+ return _this._resourcePermissions(roles, resource).then(function (p) {
+ if (permissions) {
+ let commonPermissions = _.intersection(permissions, p);
+ if (commonPermissions.length > 0) {
+ result.push(resource);
+ }
+ } else {
+ result[resource] = p;
+ }
+ });
+ })).then(function () {
+ return result;
+ });
+ }).nodeify(cb);
+ }
+
+ // -----------------------------------------------------------------------------
+ //
+ // Private methods
+ //
+ // -----------------------------------------------------------------------------
+
+ //
+ // Same as allow but accepts a more compact input.
+ //
+ private _allowEx(objs): any {
+ let _this = this;
+ objs = makeArray(objs);
+
+ let demuxed = [];
+ objs.forEach(function (obj) {
+ let roles = obj.roles;
+ obj.allows.forEach(function (allow) {
+ demuxed.push({
+ roles: roles,
+ resources: allow.resources,
+ permissions: allow.permissions
+ });
+ });
+ });
+
+ return bluebird.reduce(demuxed, function (values, obj) {
+ const roles: Values = obj.roles;
+ const resources: strings = obj.resources;
+ const permissions: strings = obj.permissions;
+ return _this.allow(roles, resources, permissions, null);
+ }, null);
+ }
+
+ //
+ // Returns the parents of the given roles
+ //
+ private _rolesParents(roles) {
+ return this.backend.unionAsync(this.options.buckets.parents, roles);
+ }
+ //
+ // Return all roles in the hierarchy including the given roles.
+ //
+ /*
+ Acl.prototype._allRoles = function(roleNames, cb){
+ var _this = this, roles;
+
+ _this._rolesParents(roleNames, function(err, parents){
+ roles = _.union(roleNames, parents);
+ async.whilst(
+ function (){
+ return parents.length >0;
+ },
+ function (cb) {
+ _this._rolesParents(parents, function(err, result){
+ if(!err){
+ roles = _.union(roles, parents);
+ parents = result;
+ }
+ cb(err);
+ });
+ },
+ function(err){
+ cb(err, roles);
+ }
+ );
+ });
+ };
+ */
+ //
+ // Return all roles in the hierarchy including the given roles.
+ //
+ private _allRoles(roleNames) {
+ let _this = this;
+
+ return this._rolesParents(roleNames).then(function (parents) {
+ if (parents.length > 0) {
+ return _this._allRoles(parents).then(function (parentRoles) {
+ return _.union(roleNames, parentRoles);
+ });
+ } else {
+ return roleNames;
+ }
+ });
+ }
+
+ //
+ // Return all roles in the hierarchy of the given user.
+ //
+ private _allUserRoles(userId) {
+ let _this = this;
+
+ return this.userRoles(userId).then(function (roles) {
+ if (roles && roles.length > 0) {
+ return _this._allRoles(roles);
+ } else {
+ return [];
+ }
+ });
+ }
+
+ //
+ // Returns an array with resources for the given roles.
+ //
+ private _rolesResources(roles) {
+ let _this = this;
+ roles = makeArray(roles);
+
+ return this._allRoles(roles).then(function (allRoles) {
+ let result = [];
+
+ // check if bluebird.map simplifies this code
+ return bluebird.all(allRoles.map(function (role) {
+ return _this.backend.getAsync(_this.options.buckets.resources, role).then(function (resources) {
+ result = result.concat(resources);
+ });
+ })).then(function () {
+ return result;
+ });
+ });
+ }
+
+ //
+ // Returns the permissions for the given resource and set of roles
+ //
+ private _resourcePermissions(roles, resource): any {
+ let _this = this;
+
+ if (roles.length === 0) {
+ return bluebird.resolve([]);
+ } else {
+ return this.backend.unionAsync(allowsBucket(resource), roles).then(function (resourcePermissions) {
+ return _this._rolesParents(roles).then(function (parents) {
+ if (parents && parents.length) {
+ return _this._resourcePermissions(parents, resource).then(function (morePermissions) {
+ return _.union(resourcePermissions, morePermissions);
+ });
+ } else {
+ return resourcePermissions;
+ }
+ });
+ });
+ }
+ }
+
+ //
+ // NOTE: This function will not handle circular dependencies and result in a crash.
+ //
+ private _checkPermissions(roles, resource, permissions): any {
+ let _this = this;
+ return this.backend.unionAsync(allowsBucket(resource), roles).then(function (resourcePermissions) {
+ if (resourcePermissions.indexOf('*') !== -1) {
+ return true;
+ } else {
+ permissions = permissions.filter(function (p) {
+ return resourcePermissions.indexOf(p) === -1;
+ });
+
+ if (permissions.length === 0) {
+ return true;
+ } else {
+ return _this.backend.unionAsync(_this.options.buckets.parents, roles).then(function (parents) {
+ if (parents && parents.length) {
+ return _this._checkPermissions(parents, resource, permissions);
+ } else {
+ return false;
+ }
+ });
+ }
+ }
+ });
+ }
+
+};
+
+// -----------------------------------------------------------------------------
+//
+// Helpers
+//
+// -----------------------------------------------------------------------------
diff --git a/packages/vfs/ref/acl/backend.ts b/packages/vfs/ref/acl/backend.ts
new file mode 100644
index 00000000..daa53838
--- /dev/null
+++ b/packages/vfs/ref/acl/backend.ts
@@ -0,0 +1,87 @@
+/*
+ Backend Interface.
+
+ Implement this API for providing a backend for the acl module.
+*/
+
+import { contract } from './contract';
+import { IBucketsOption, Action, Value, Values, IBackend } from './interfaces';
+
+export let Backend = {
+ /*
+ Begins a transaction.
+ */
+ begin: function () {
+ // returns a transaction object
+ },
+
+ /*
+ Ends a transaction (and executes it)
+ */
+ end: function (transaction, cb) {
+ contract(arguments).params('object', 'function').end();
+ // Execute transaction
+ },
+
+ /*
+ Cleans the whole storage.
+ */
+ clean: function (cb) {
+ contract(arguments).params('function').end();
+ },
+
+ /*
+ Gets the contents at the bucket's key.
+ */
+ get: function (bucket, key, cb) {
+ contract(arguments)
+ .params('string', 'string|number', 'function')
+ .end();
+ },
+
+ /*
+ Gets the union of contents of the specified keys in each of the specified buckets and returns
+ a mapping of bucket to union.
+ */
+ unions: function (bucket, keys, cb) {
+ contract(arguments)
+ .params('array', 'array', 'function')
+ .end();
+ },
+
+ /*
+ Returns the union of the values in the given keys.
+ */
+ union: function (bucket, keys, cb) {
+ contract(arguments)
+ .params('string', 'array', 'function')
+ .end();
+ },
+
+ /*
+ Adds values to a given key inside a bucket.
+ */
+ add: function (transaction, bucket, key, values) {
+ contract(arguments)
+ .params('object', 'string', 'string|number', 'string|array|number')
+ .end();
+ },
+
+ /*
+ Delete the given key(s) at the bucket
+ */
+ del: function (transaction, bucket, keys) {
+ contract(arguments)
+ .params('object', 'string', 'string|array')
+ .end();
+ },
+
+ /*
+ Removes values from a given key inside a bucket.
+ */
+ remove: function (transaction, bucket, key, values) {
+ contract(arguments)
+ .params('object', 'string', 'string|number', 'string|array|number')
+ .end();
+ }
+};
diff --git a/packages/vfs/ref/acl/data/File.ts b/packages/vfs/ref/acl/data/File.ts
new file mode 100644
index 00000000..ec0af771
--- /dev/null
+++ b/packages/vfs/ref/acl/data/File.ts
@@ -0,0 +1,51 @@
+import { IObjectLiteral } from '../../interfaces/index';
+import { IStoreIO } from '../../interfaces/Store';
+import { Memory } from './Memory';
+import * as fs from 'fs';
+import * as mkdirp from 'mkdirp';
+import * as _path from 'path';
+const writeFileAtomic = require('write-file-atomic');
+const permissionError = 'You don\'t have access to this file.';
+const defaultPathMode: number = parseInt('0700', 8);
+const writeFileOptions: IObjectLiteral = { mode: parseInt('0600', 8) };
+export class File extends Memory implements IStoreIO {
+ configPath: string;
+ read(path?: string): any {
+ path = path || this.configPath;
+ try {
+ this._buckets = JSON.parse(fs.readFileSync(path, 'utf8'));
+ } catch (err) {
+ // create dir if it doesn't exist
+ if (err.code === 'ENOENT') {
+ mkdirp.sync(_path.dirname(path), defaultPathMode);
+ return {};
+ }
+ // improve the message of permission errors
+ if (err.code === 'EACCES') {
+ err.message = err.message + '\n' + permissionError + '\n';
+ }
+ // empty the file if it encounters invalid JSON
+ if (err.name === 'SyntaxError') {
+ writeFileAtomic.sync(path, '', writeFileOptions);
+ return {};
+ }
+ throw err;
+ }
+ }
+ write(path?: string): any {
+ path = path || this.configPath;
+ const data = this.data();
+ try {
+ // make sure the folder exists as it
+ // could have been deleted in the meantime
+ mkdirp.sync(_path.dirname(path), defaultPathMode);
+ writeFileAtomic.sync(path, JSON.stringify(data, null, 4), writeFileOptions);
+ } catch (err) {
+ // improve the message of permission errors
+ if (err.code === 'EACCES') {
+ err.message = err.message + '\n' + permissionError + '\n';
+ }
+ throw err;
+ }
+ }
+}
diff --git a/packages/vfs/ref/acl/data/Memory.ts b/packages/vfs/ref/acl/data/Memory.ts
new file mode 100644
index 00000000..3ee31f89
--- /dev/null
+++ b/packages/vfs/ref/acl/data/Memory.ts
@@ -0,0 +1,178 @@
+/*
+ Memory Backend.
+ In-memory implementation of the storage.
+*/
+import * as _ from 'lodash';
+import { contract } from '../contract';
+import { Action, IBackend, Value, Values } from '../interfaces';
+import { IObjectLiteral, List } from '../../interfaces/index';
+import * as bluebird from 'bluebird';
+function makeArray(arr) {
+ return Array.isArray(arr) ? arr : [arr];
+}
+export class Memory implements IBackend {
+ endAsync = bluebird.promisify(this.end);
+ getAsync = bluebird.promisify(this.get);
+ cleanAsync = bluebird.promisify(this.clean);
+ unionAsync = bluebird.promisify(this.union);
+ unionsAsync = bluebird.promisify(this.unions);
+ _buckets: IObjectLiteral;
+ data() {
+ return this._buckets as Action[];
+ }
+ constructor() {
+ this._buckets = {};
+ }
+ /*
+ Begins a transaction.
+ */
+ begin() {
+ // returns a transaction object(just an array of functions will do here.)
+ return [];
+ };
+
+ /*
+ Ends a transaction (and executes it)
+ */
+ end(transaction: Action[], cb: Action) {
+ contract(arguments).params('array', 'function').end();
+ // Execute transaction
+ for (let i = 0, len = transaction.length; i < len; i++) {
+ transaction[i]();
+ }
+ cb();
+ }
+ /*
+ Cleans the whole storage.
+ */
+ clean(cb: Action) {
+ contract(arguments).params('function').end();
+ this._buckets = {};
+ cb();
+ }
+ /*
+ Gets the contents at the bucket's key.
+ */
+ get(bucket: string, key: Value, cb: Action) {
+ contract(arguments)
+ .params('string', 'string|number', 'function')
+ .end();
+
+ if (this._buckets[bucket]) {
+ (cb as Function)(null, this._buckets[bucket][key] || []);
+ } else {
+ (cb as Function)(null, []);
+ }
+ }
+ /*
+ Gets the union of the keys in each of the specified buckets
+ */
+ unions(buckets, keys, cb) {
+ contract(arguments)
+ .params('array', 'array', 'function')
+ .end();
+
+ const self = this;
+ let results = {};
+
+ buckets.forEach(function (bucket) {
+ if (self._buckets[bucket]) {
+ results[bucket] = _.uniq(_.flatten(_.values(_.pick(self._buckets[bucket], keys))));
+ } else {
+ results[bucket] = [];
+ }
+ });
+ cb(null, results);
+ }
+ /*
+ Returns the union of the values in the given keys.
+ */
+ union(bucket: string, keys: Values[], cb: Action): void {
+ contract(arguments)
+ .params('string', 'array', 'function')
+ .end();
+
+ let match;
+ let re;
+ if (!this._buckets[bucket]) {
+ Object.keys(this._buckets).some(function (b) {
+ re = new RegExp("^" + b + "$");
+ match = re.test(bucket);
+ if (match) { bucket = b; }
+ return match;
+ });
+ }
+
+ if (this._buckets[bucket]) {
+ const keyArrays = [];
+ for (let i = 0, len = keys.length; i < len; i++) {
+ if (this._buckets[bucket][keys[i] as Value]) {
+ keyArrays.push.apply(keyArrays, this._buckets[bucket][keys[i] as Value]);
+ }
+ }
+ (cb as Function)(undefined, _.union(keyArrays));
+ } else {
+ (cb as Function)(undefined, []);
+ }
+ }
+
+ /*
+ Adds values to a given key inside a bucket.
+ */
+ add(transaction: Action[], bucket: string, key: Value, values: Values) {
+ contract(arguments)
+ .params('array', 'string', 'string|number', 'string|array|number')
+ .end();
+
+ const self = this;
+ values = makeArray(values);
+
+ transaction.push(function () {
+ if (!self._buckets[bucket]) {
+ self._buckets[bucket] = {};
+ }
+ if (!self._buckets[bucket][key]) {
+ self._buckets[bucket][key] = values;
+ } else {
+ self._buckets[bucket][key] = _.union(values as List, self._buckets[bucket][key]);
+ }
+ });
+ }
+
+ /*
+ Delete the given key(s) at the bucket
+ */
+ del(transaction: Action[], bucket: string, keys: Values) {
+ contract(arguments)
+ .params('array', 'string', 'string|array')
+ .end();
+
+ const self = this;
+ keys = makeArray(keys);
+ transaction.push(function () {
+ if (self._buckets[bucket]) {
+ for (let i = 0, len = (keys as List).length; i < len; i++) {
+ delete self._buckets[bucket][keys[i]];
+ }
+ }
+ });
+ }
+
+ /*
+ Removes values from a given key inside a bucket.
+ */
+ remove(transaction: Action[], bucket: string, key: Value, values: Values) {
+ contract(arguments)
+ .params('array', 'string', 'string|number', 'string|array|number')
+ .end();
+
+ const self = this;
+ values = makeArray(values);
+ transaction.push(function () {
+ let old;
+ if (self._buckets[bucket] && (old = self._buckets[bucket][key])) {
+ self._buckets[bucket][key] = _.difference(old, values as List);
+ }
+ });
+ }
+}
diff --git a/packages/vfs/ref/acl/interfaces.ts b/packages/vfs/ref/acl/interfaces.ts
new file mode 100644
index 00000000..d414f29a
--- /dev/null
+++ b/packages/vfs/ref/acl/interfaces.ts
@@ -0,0 +1,90 @@
+export type strings = string | string[];
+export type Value = string | number;
+export type Values = Value | Value[];
+export type Action = () => any;
+export type Callback = (err: Error) => any;
+export type AnyCallback = (err: Error, obj: any) => any;
+export type AllowedCallback = (err: Error, allowed: boolean) => any;
+import * as bluebird from 'bluebird';
+
+export interface IOption {
+ buckets?: IBucketsOption;
+}
+
+export interface IBucketsOption {
+ meta?: string;
+ parents?: string;
+ permissions?: string;
+ resources?: string;
+ roles?: string;
+ users?: string;
+}
+
+export interface IAclSet {
+ roles: strings;
+ allows: IAclAllow[];
+}
+
+export interface IAclAllow {
+ resources: strings;
+ permissions: strings;
+}
+
+export interface IAcl {
+ addUserRoles: (userId: Value, roles: strings, cb?: Callback) => Promise;
+ removeUserRoles: (userId: Value, roles: strings, cb?: Callback) => Promise;
+ userRoles: (userId: Value, cb?: (err: Error, roles: string[]) => any) => bluebird;
+ roleUsers: (role: Value, cb?: (err: Error, users: Values) => any) => Promise;
+ hasRole: (userId: Value, role: string, cb?: (err: Error, isInRole: boolean) => any) => bluebird;
+ addRoleParents: (role: string, parents: Values, cb?: Callback) => Promise;
+ removeRole: (role: string, cb?: Callback) => Promise;
+ removeResource: (resource: string, cb?: Callback) => Promise;
+ allow: (roles: Values, resources: strings, permissions: strings, cb?: Callback) => Promise;
+ removeAllow: (role: string, resources: strings, permissions: strings, cb?: Callback) => Promise;
+ removePermissions: (role: string, resources: strings, permissions: strings, cb?: Function) => Promise;
+ allowedPermissions: (userId: Value, resources: strings, cb?: AnyCallback) => bluebird;
+ isAllowed: (userId: Value, resources: strings, permissions: strings, cb?: AllowedCallback) => Promise;
+ areAnyRolesAllowed: (roles: strings, resource: strings, permissions: strings, cb?: AllowedCallback) => Promise;
+ whatResources: (roles: strings, permissions: strings, cb?: AnyCallback) => Promise;
+ permittedResources: (roles: strings, permissions: strings, cb?: Function) => Promise;
+ // middleware: (numPathComponents?: number, userId?: Value | GetUserId, actions?: strings) => express.RequestHandler;
+}
+//
+// For internal use
+//
+export interface IBackend {
+ begin: () => T;
+ end: (transaction: T, cb?: Action) => void;
+ clean: (cb?: Action) => void;
+ get: (bucket: string, key: Value, cb?: Action) => void;
+ union: (bucket: string, keys: Value[], cb?: Action) => void;
+ add: (transaction: T, bucket: string, key: Value, values: Values) => void;
+ del: (transaction: T, bucket: string, keys: Value[]) => void;
+ remove: (transaction: T, bucket: string, key: Value, values: Values) => void;
+ unions(buckets, keys, cb);
+ endAsync?: Function;
+ getAsync?: Function;
+ cleanAsync?: Function;
+ unionAsync: Function;
+ unionsAsync?: Function;
+ data: () => T;
+}
+export type IDefaultBackend = IBackend;
+
+export interface IContract {
+ (args: IArguments): IContract | INoOp;
+ debug: boolean;
+ fulfilled: boolean;
+ args: any[];
+ checkedParams: string[];
+ params: (...types: string[]) => IContract | INoOp;
+ end: () => void;
+}
+
+export interface INoOp {
+ params: (...types: string[]) => INoOp;
+ end: () => void;
+}
+export interface ILogger {
+ debug: (msg: string) => any;
+}
diff --git a/packages/vfs/ref/applications/ControlFreak/services/Directory.ts b/packages/vfs/ref/applications/ControlFreak/services/Directory.ts
new file mode 100644
index 00000000..e76f858b
--- /dev/null
+++ b/packages/vfs/ref/applications/ControlFreak/services/Directory.ts
@@ -0,0 +1,48 @@
+import { DirectoryService as Base } from '../../../services/Directory';
+import { EResourceType, FileResource } from '../../../interfaces/Resource';
+import { create as createLocalVFS } from '../../../vfs/Local';
+import { EEKey } from '../../../applications/Base';
+import * as fs from 'fs';
+import * as path from 'path';
+export class DirectoryService extends Base {
+ _userDir(userRoot: string, what: string) {
+ return path.resolve(path.join(userRoot + path.sep + what));
+ }
+ _resolveUserMount(mount: string, request: any, _default?: string): string {
+ const user = this._getUser(request);
+ if (user) {
+ switch (mount) {
+ case 'workspace_user': {
+ return this._userDir(user, 'workspace');
+ }
+ case 'user_drivers': {
+ return this._userDir(user, 'drivers');
+ }
+ case 'user_devices': {
+ return this._userDir(user, 'devices');
+ }
+ case 'user': {
+ return this._userDir(user, '');
+ }
+ }
+ }
+ return _default;
+ }
+ public getVFS(mount: string, request?: any) {
+ const resource = this.getResourceByTypeAndName(EResourceType.FILE_PROXY, mount);
+ if (resource) {
+ let root = this._resolveUserMount(mount, request) || this.resolveAbsolute(resource as FileResource);
+ try {
+ if (fs.lstatSync(root)) {
+ return createLocalVFS({
+ root: root,
+ nopty: true
+ });
+ }
+ } catch (e) {
+ console.warn('cant get VFS for ' + mount + ' for root ' + root);
+ }
+ }
+ return null;
+ }
+}
diff --git a/packages/vfs/ref/components/Component.ts b/packages/vfs/ref/components/Component.ts
new file mode 100644
index 00000000..168e8132
--- /dev/null
+++ b/packages/vfs/ref/components/Component.ts
@@ -0,0 +1,30 @@
+// similar as ApplicationBase, we have routes and services.
+import { ApplicationBase } from '../applications/Base';
+import { BaseService } from '../services/Base';
+import { IServiceConfiguration } from '../interfaces/Service';
+import * as Router from 'koa-router';
+export interface IComponent {
+ application: ApplicationBase;
+ label(): string;
+ services(config: IServiceConfiguration): BaseService[];
+ routes(): Router[];
+ destroy(): void;
+}
+export class Component implements IComponent {
+ application: ApplicationBase;
+ serviceConfig: IServiceConfiguration;
+ destroy(): void { }
+ constructor(application: ApplicationBase, serviceConfig: IServiceConfiguration) {
+ this.application = application;
+ this.serviceConfig = serviceConfig;
+ }
+ label(): string {
+ return "Component";
+ }
+ services(config: IServiceConfiguration): BaseService[] {
+ return [];
+ }
+ routes(): Router[] {
+ return [];
+ }
+}
diff --git a/packages/vfs/ref/components/xfile/xfile.ts b/packages/vfs/ref/components/xfile/xfile.ts
new file mode 100644
index 00000000..dbcf54c6
--- /dev/null
+++ b/packages/vfs/ref/components/xfile/xfile.ts
@@ -0,0 +1,188 @@
+import { Component } from '../Component';
+import { BaseService } from '../../services/Base';
+import { ApplicationBase } from '../../applications/Base';
+import { IServiceConfiguration } from '../../interfaces/Service';
+import * as Router from 'koa-router';
+
+import { IConflictSettings, ICopyOptions, ItemProgressCallback, INode, ECopyFlags } from '../../fs/interfaces';
+import { IOptions as IMatcherOptions } from '../../fs/utils/matcher';
+import { DirectoryService } from '../../services/Directory';
+
+import { async as copyAsync } from '../../fs/copy';
+import * as path from 'path';
+import { createUUID } from '../../utils/StringUtils';
+import { IObjectLiteral } from '../../interfaces/index';
+import { containsPath } from '../../vfs/utils';
+let pathToRegexp = require('path-to-regexp');
+
+
+interface Options {
+ id: string;
+ client: any;
+ delegate: any;
+}
+
+export class XFILE extends Component {
+ options: Options;
+ abort: boolean = false;
+ running: Promise;
+ constructor(application: ApplicationBase, serviceConfig: IServiceConfiguration, options: any) {
+ super(application, serviceConfig);
+ this.options = options;
+ }
+ label(): string {
+ return "xfile";
+ }
+ services(config: IServiceConfiguration): BaseService[] {
+ return [];
+ }
+ routes(): Router[] {
+ return [];
+ }
+ cancel() {
+ this.abort = true;
+ }
+ waiting: IObjectLiteral = {};
+ answer(data: any) {
+ const waiting = this.waiting[data.iid];
+ if (waiting) {
+ waiting['resolve'](data.answer);
+ delete this.waiting[data.iid];
+ }
+ }
+ _cp(src: string, dst: string) {
+
+ }
+
+ cp(src: string, dst: string) {
+
+ const directoryService: DirectoryService = this.application['directoryService'];
+ // console.log('dir', directoryService);
+
+ const selection = ['workspace_user/ClayCenter/init.css'];
+ const srcMount = directoryService.resolveShort(selection[0]).mount;
+ const srcVFS = directoryService.getVFS(srcMount);
+ const root = directoryService.resolvePath(srcMount, '');
+ const checkFilesInRoot = (dirService: DirectoryService, srcMount: string, selection: string[]) => {
+ let result = true;
+ selection.forEach((item: string) => {
+ const rel = dirService.resolveShort(item).path;
+ const abs = dirService.resolvePath(srcMount, rel);
+ if (!containsPath(abs, rel)) {
+ result = false;
+ }
+ });
+ return result;
+ };
+ const relatives = (dirService: DirectoryService, selection: string[]) => {
+ return selection.map((item: string) => {
+ return dirService.resolveShort(item).path;
+ });
+ };
+
+ const absolutes = (dirService: DirectoryService, selection: string[]) => {
+ return selection.map((item: string) => {
+ const rel = dirService.resolveShort(item).path;
+ const abs = dirService.resolvePath(srcMount, rel);
+ return abs;
+ });
+ };
+
+ // console.log('contains : ', checkFilesInRoot(directoryService, srcMount, ['workspace_user/A-VLC.css']));
+
+ // const _matcher = matcher('', relatives(directoryService, selection), matcherOptions);
+
+ // console.log('as regex : ', pathToRegexp('./ClayCenter/init.css'));
+ // console.log('as regex : ', pathToRegexp('ClayCenter/init.css'));
+
+ // console.log('rels : ', relatives(directoryService, selection));
+
+ // console.log('matcher ', _matcher('**/ClayCenter/init.css'));
+ // console.log('matcher 2 ', _matcher('./ClayCenter/init.css'));
+ // console.log('matcher 3 ', _matcher('**/*/init.css'));
+ // console.log('matcher 4 ', _matcher('./**/*/*.css'));
+ // console.log('matcher 5 ', _matcher('**/*.css'));
+ // console.log('matcher 6 ', _matcher('ClayCenter/init.css'));
+
+ // const _matcherAbs = matcher(root + '/', absolutes(directoryService, selection), matcherOptions);
+ // console.log('abs : ' + root, absolutes(directoryService, selection));
+ // console.log('matcher abs ', _matcherAbs('**/ClayCenter/init.css'));
+ // console.log('matcher abs 2 ', _matcherAbs('./ClayCenter/init.css'));
+ // console.log('matcher abs 3 ', _matcherAbs('**/*/*.css'));
+ // console.log('matcher abs 4 ', _matcherAbs('/PMaster/projects/x4mm/user/workspace/ClayCenter/init.css'));
+
+ // console.log('matcher abs 4 ', _matcherAbs('/PMaster/projects/x4mm/user/workspace/ClayCenter/init.css'));
+
+
+ let c = 0;
+ let done: any[] = [];
+ let delegate = this.options.delegate;
+ let self = this;
+
+ const progress: ItemProgressCallback = function (path: string, current: number, total: number, item?: INode) {
+ done.push({ item: item, path: path });
+ c++;
+ if (c >= 1) {
+ delegate.onProgress(done);
+ done = [];
+ c = 0;
+ }
+ return !self.abort;
+ };
+
+ const conflictCallback = function (path: string, item: INode, err: string): Promise {
+ const iid: string = createUUID();
+ self.waiting[iid] = {};
+ const promise = new Promise((resolve, reject) => {
+ delegate.onInterrupt({
+ path: path,
+ error: err,
+ iid: iid,
+ item: item
+ });
+ self.waiting[iid].resolve = resolve;
+ });
+
+ self.waiting[iid].promise = promise;
+ return promise;
+ };
+
+ let options: ICopyOptions = {
+ progress: progress,
+ conflictCallback: conflictCallback,
+ // overwrite: true,
+ matching: ['**/*.ts'],
+ debug: false,
+ flags: ECopyFlags.FOLLOW_SYMLINKS | ECopyFlags.REPORT,
+ writeProgress: (path: string, current: number, total: number) => {
+ delegate.onProgress([
+ {
+ path: path,
+ current: current,
+ total: total
+ }
+ ]);
+ }
+ };
+
+ src = path.resolve('./src/fs/');
+ dst = '/tmp/node_modules_fs/';
+
+ this.running = copyAsync(src, dst, options).then(function (res) {
+ console.log('done', res);
+ delegate.onFinish({});
+ }).catch(function (e) {
+ console.error('error copyAsync', e);
+ });
+ }
+};
+
+//
+// ─── flow ───────────────────────────────────────────────────────────────────────
+//
+// client:
+// runAppServerComponentMethod(component,method,args)
+// server:
+// runComponentMethod(component,method,args)
+// component:
+// method(...,delegate)
diff --git a/packages/vfs/ref/components/xideve/ExportOptions.ts b/packages/vfs/ref/components/xideve/ExportOptions.ts
new file mode 100644
index 00000000..80b224a8
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/ExportOptions.ts
@@ -0,0 +1,76 @@
+import { IObjectLiteral } from '../../interfaces/index';
+import { read, write } from '../../io/file';
+import { serialize } from '../../io/json';
+import { getDevices } from '../../services/Devices';
+import { getDrivers } from '../../services/Drivers';
+import { pathinfo, EPATH_PARTS } from '../../utils/FileUtils';
+import { replace } from '../../utils/StringUtils';
+import { console } from '../../console';
+import * as _ from 'lodash';
+//import * as views from 'co-views';
+import * as path from 'path';
+const fs = require('fs');
+const util = require('util');
+const jet = require('fs-jetpack');
+const cheerio = require('cheerio');
+const debugPaths: boolean = false;
+
+export interface IDelegate {
+ data: any;
+ clear();
+ onProgress(progress, data);
+ onFinish(finish, data);
+ onError(error, data);
+};
+
+function resolve(_path: string): string | null {
+ let here = path.resolve(_path);
+ try {
+ if (fs.statSync(here)) {
+ return here;
+ }
+ } catch (e) {
+ return here;
+ }
+
+ try {
+ if (fs.statSync(_path)) {
+ return _path;
+ } else {
+ const test = process.cwd() + path.sep + _path;
+ if (fs.statSync(test)) {
+ return test;
+ }
+ }
+ } catch (e) {
+ }
+ return null;
+}
+export default class ExportOptions {
+ delegate: any = null;
+ constructor(args: any, delegate: IDelegate) {
+ this.delegate = delegate;
+ }
+ /**
+ * @member {string|null} serverTemplates the path to the server templates. Defaults to
+ * this.root + 'server-template'
+ */
+ onProgress(msg: string) {
+ this.delegate && this.delegate.onProgress(msg);
+ console.log('Progress: ' + msg);
+ }
+ onError(msg: string) {
+ console.error('error export ', msg);
+ this.delegate && this.delegate.onError(msg);
+ }
+ onFinish(msg: string): void {
+ this.delegate && this.delegate.onFinish(msg);
+ console.log('Finish: ' + msg);
+ }
+ /**
+ * @param options {module:nxapp/model/ExportOptions}
+ */
+ run() {
+
+ }
+}
diff --git a/packages/vfs/ref/components/xideve/Exporter.ts b/packages/vfs/ref/components/xideve/Exporter.ts
new file mode 100644
index 00000000..b613909e
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/Exporter.ts
@@ -0,0 +1,637 @@
+import { IObjectLiteral } from '../../interfaces/index';
+import { read, write } from '../../io/file';
+import { serialize } from '../../io/json';
+import { getDevices } from '../../services/Devices';
+import { getDrivers } from '../../services/Drivers';
+import { pathinfo, EPATH_PARTS } from '../../utils/FileUtils';
+import { replace } from '../../utils/StringUtils';
+import { console } from '../../console';
+import * as _ from 'lodash';
+//import * as views from 'co-views';
+import * as path from 'path';
+const fs = require('fs');
+const util = require('util');
+const jet = require('fs-jetpack');
+const cheerio = require('cheerio');
+const debugPaths: boolean = false;
+
+let io = {
+ read: read,
+ write: write
+};
+export interface IOptions {
+ serverTemplates: string;
+ linux32: boolean;
+ linux64: boolean;
+ osx: boolean;
+ arm: boolean;
+ windows: boolean;
+ root: string;
+ system: string;
+ user: string;
+ client: string;
+ target: string;
+ nodeServers: string;
+ debug: boolean;
+ deviceServerPort: number;
+ mongo_port: number;
+ mqtt_port: number;
+ http_port: number;
+ serverSide: true,
+ updateDevice: true
+}
+
+export interface IDelegate {
+ data: any;
+ clear();
+ onProgress(progress, data);
+ onFinish(finish, data);
+ onError(error, data);
+};
+
+function resolve(_path: string): string | null {
+ let here = path.resolve(_path);
+ try {
+ if (fs.statSync(here)) {
+ return here;
+ }
+ } catch (e) {
+ return here;
+ }
+
+ try {
+ if (fs.statSync(_path)) {
+ return _path;
+ } else {
+ const test = process.cwd() + path.sep + _path;
+ if (fs.statSync(test)) {
+ return test;
+ }
+ }
+ } catch (e) {
+ }
+ return null;
+}
+
+function cleanUrl(str: string) {
+ if (str) {
+ str = str.replace('//', '/');
+ str = str.replace('./', '/');
+ return str;
+ }
+ return str;
+}
+
+/**
+ * This class creates a stand-alone package of a "Control-Freak" created application.
+ * Essentially it takes a bunch of paths and options and outputs a folder on disc.
+ *
+ *
+ * @export
+ * @class Exporter
+ */
+export default class Exporter {
+ options: IOptions = null;
+ profile: IObjectLiteral = null;
+ delegate: any = null;
+ constructor(args: any, delegate: IDelegate) {
+ this.options = args.options;
+ this.delegate = delegate;
+ }
+ /**
+ * @member {string|null} serverTemplates the path to the server templates. Defaults to
+ * this.root + 'server-template'
+ */
+ onProgress(msg: string) {
+ this.delegate && this.delegate.onProgress(msg);
+ console.log('Progress: ' + msg);
+ }
+ onError(msg: string) {
+ console.error('error export ', msg);
+ this.delegate && this.delegate.onError(msg);
+ }
+ onFinish(msg: string): void {
+ this.delegate && this.delegate.onFinish(msg);
+ console.log('Finish: ' + msg);
+ }
+ /**
+ * @param options {module:nxapp/model/ExportOptions}
+ */
+ run() {
+ const options = this.options;
+ console.log('run;', options);
+ this.onProgress('Export Manager: begin export');
+ if (!options.root) {
+ this.onError('Export Manager: have no root');
+ throw new Error('Export Manager: have no root');
+ }
+
+ if (!options.system) {
+ this.onError('Export Manager: have no data');
+ throw new Error('Export Manager: have no data');
+ }
+
+ if (!options.user) {
+ this.onError('Export Manager: have no user');
+ return;
+ }
+ options.serverSide = true;
+ if (!options.client) {
+ /*
+ if (has('debug')) {
+ this.client = xutils.resolve(this.root + '/dist/windows/Code/client/');
+ } else {
+ this.client = xutils.resolve(this.root + '/Code/client/');
+ }
+ */
+ }
+ try {
+ if (!options.serverTemplates) {
+ options.serverTemplates = resolve(options.root + '/server-template');
+ }
+
+ debugPaths && console.log('export with \n', {
+ "System Data": options.system,
+ "User Data": options.user + ' = ' + path.resolve(options.user),
+ "Root": path.resolve(options.root),
+ "Server-Templates": options.serverTemplates,
+ "Target": path.resolve(options.target),
+ "Node Servers": path.resolve(options.nodeServers),
+ "Client": options.client,
+ "Export Windows": options.windows,
+ "Export Linux - 32 ": options.linux32,
+ "Export Linux - 64 ": options.linux64,
+ "Export OSX": options.osx,
+ "Export ARM": options.arm
+ });
+ } catch (e) {
+ console.error('Error export ', e);
+ }
+ const d = false;
+ if (d) {
+ return;
+ }
+ let all = true;
+ if (all) {
+
+ if (!options.deviceServerPort) {
+ options.deviceServerPort = 9997;
+ }
+ if (!options.mongo_port) {
+ options.mongo_port = 27018;
+ }
+ if (!options.mqtt_port) {
+ options.mqtt_port = 1884;
+ }
+
+ if (!options.http_port) {
+ options.http_port = 5556;
+ }
+
+ //this.exportMongo(options);
+ this.createDirectoryLayout(options);
+ this.exportServer(options);
+ this.onProgress('Exported Servers');
+ this.exportUser(options);
+ this.onProgress('Exported User');
+ this.exportSystem(options);
+ this.onProgress('Exported System Data');
+ this.exportMisc(options);
+ this.onProgress('Exported Misc Data');
+ this.onProgress('Exporting User Workspace HTML');
+ this.exportHTML(options);
+ this.onProgress('Exported User Workspace HTML');
+ this.exportDevices(options);
+ this.onProgress('Exported Devices');
+ this.exportDrivers(options);
+ this.onProgress('Exported Drivers');
+ const forceDist: boolean = true;
+ if (options.client) {
+ this.exportClientEx(options);
+ } else {
+ if (!options.debug) {
+ this.exportClient(options);
+ } else {
+ this.exportClientDist(options);
+ }
+ }
+ this.onProgress('Exported Client Application Assets');
+ console.log('Export Done! Your application can be found at ' + options.target);
+ this.onProgress('Export Done');
+ this.onFinish('Export Done! Your application can be found at ' + options.target);
+
+ } else {
+ this.exportHTML(options);
+ }
+ }
+ exportHTML(options: IOptions) {
+ try {
+ let source = jet.dir(options.target + '/user/workspace/');
+ let thiz = this;
+ function parseDirectory(_path, name) {
+ // name = directory abs
+ let dirItems = fs.readdirSync(_path);
+ if (dirItems.length) {
+ _.each(dirItems, function (file) {
+ // file = file name
+ if (file.indexOf('.dhtml') !== -1) {
+ let root = name.replace(source.path() + '/', '');
+ thiz.exportHTMLFile2(_path + '/' + file, root, options);
+ }
+ });
+ }
+ }
+
+ function _walk(dir) {
+ let results = [];
+ if (fs.existsSync(dir)) {
+ let list = fs.readdirSync(dir);
+ list.forEach(function (file) {
+ file = dir + '/' + file;
+ let stat = fs.statSync(file);
+ if (stat) {
+ let root = file.replace(path + '/', '');
+ if (stat.isDirectory()) {
+ parseDirectory(file, root);
+ } else {
+ if (file.indexOf('.dhtml') !== -1) {
+ root = root.replace(dir + '/', '');
+ thiz.exportHTMLFile2(file, root, options);
+ }
+
+ }
+ } else {
+ console.error('cant get stat for ' + file);
+ }
+ });
+ } else {
+ console.error('device path ' + dir + ' doesnt exists');
+ }
+ return results;
+ }
+
+ _walk(source.path());
+ } catch (e) {
+ console.error('Error exporting HTML', e);
+ }
+ }
+ exportHTMLFile2(file, folder, options: IOptions) {
+ let exportRoot = jet.dir(options.root + '/export/');
+ let template = io.read(path.resolve(exportRoot.path() + '/app.template.html'));
+ let path_parts = pathinfo(file, EPATH_PARTS.PATHINFO_ALL);
+
+ const dirName = path.dirname(file);
+ const fileName = path.basename(file);
+
+ if (folder === fileName) {
+ folder = "";
+ }
+ let templateVariables = {
+ libRoot: '/Code/client/src/lib',
+ lodashUrl: '/Code/client/src/lib/external/lodash.min.js',
+ requireBaseUrl: "/Code/client/src/lib/xibm/ibm",
+ jQueryUrl: "/Code/client/src/lib/external/jquery-1.9.1.min.js",
+ data: "",
+ user: "/user",
+ css: './' + cleanUrl(fileName.replace('.dhtml', '.css')),
+ theme: "bootstrap",
+ blox_file: "./" + folder + '/' + fileName.replace('.dhtml', '.xblox'),
+ scene_file: "./" + folder + '/' + fileName,
+ mount: "workspace",
+ "VFS_VARS": serialize({
+ "user_drivers": './user/drivers',
+ "system_drivers": './system/drivers'
+ }, null, 2)
+ };
+
+ //console.log('export HTML' + folder + '/' + fileName);
+
+ template = replace(template, null, templateVariables, {
+ begin: '%',
+ end: '%'
+ });
+ let content = io.read(file);
+ content = content.replace(' ', template);
+ content = content.replace(/\burl\s*\(\s*["']?([^"'\r\n\)\(]+)["']?\s*\)/gi,
+ function (matchstr, parens) {
+ let parts = parens.split('://');
+ let mount = parts[0];
+ let path = parts[1];
+ if (mount && path) {
+ return "url('./" + path + "')";
+ }
+ return parens;
+ }
+ );
+
+ let dom = cheerio.load(content);
+ let extra = '\n';
+ dom('HEAD').append(dom(extra));
+ io.write(file.replace('.dhtml', '.html'), dom.html());
+ }
+ exportHTMLFile(options: IOptions) {
+ let exportRoot = jet.dir(options.root + '/export/');
+ let source = jet.dir(options.target + '/user/workspace/');
+ let file = path.resolve(source.path() + '/ascene.dhtml');
+ let template = io.read(path.resolve(exportRoot.path() + '/app.template.html'));
+ let templateVariables = _.mixin({
+ libRoot: '/Code/client/src/lib',
+ lodashUrl: '/Code/client/src/lib/external/lodash.min.js',
+ requireBaseUrl: "/Code/client/src/lib/xibm/ibm",
+ jQueryUrl: "/Code/client/src/lib/external/jquery-1.9.1.min.js",
+ data: "",
+ user: "/user",
+ css: "./ascene.css",
+ theme: "bootstrap",
+ blox_file: "./ascene.xblox",
+ mount: "workspace",
+ "VFS_VARS": serialize({
+ "user_drivers": './user/drivers',
+ "system_drivers": './system/drivers'
+ }, null, 2)
+ }, options as any);
+
+ template = replace(template, null, templateVariables, {
+ begin: '%',
+ end: '%'
+ });
+ let content = io.read(file);
+ content = content.replace(' ', template);
+ let did = false;
+ content = content.replace(/\burl\s*\(\s*["']?([^"'\r\n\)\(]+)["']?\s*\)/gi,
+ function (matchstr, parens) {
+ let parts = parens.split('://');
+ let mount = parts[0];
+ let path = parts[1];
+ if (mount && path) {
+ did = true;
+ return "url('./" + path + "')";
+ }
+ return parens;
+ }
+ );
+ let dom = cheerio.load(content);
+ let extra = '\n';
+ dom('HEAD').append(dom(extra));
+ io.write(file.replace('.dhtml', '.html'), dom.html());
+ }
+
+ async exportDevices(options: IOptions) {
+ try {
+ let userDevicesPath = path.resolve(options.target + '/user/devices');
+
+ let devices = await getDevices(userDevicesPath, 'user_devices', options) as any[];
+ io.write(userDevicesPath + '/user_devices.json', serialize({
+ items: devices
+ }, null, 2));
+
+ devices.forEach(device => {
+ if (device.user) {
+ io.write(path.join(options.target, '/user/devices/' + device.path), serialize({
+ inputs: device.user.inputs
+ }, null, 2))
+ }
+ });
+
+ let systemDevicesPath = path.resolve(options.target + '/data/system/devices');
+ devices = await getDevices(systemDevicesPath, 'system_devices', options) as any[];
+
+ devices.forEach(device => {
+ if (device.user) {
+ io.write(path.join(options.target, '/data/system/devices/' + device.path), serialize({
+ inputs: device.user.inputs
+ }, null, 2))
+ }
+ });
+
+ io.write(systemDevicesPath + '/system_devices.json', serialize({
+ items: devices
+ }, null, 2));
+ } catch (e) {
+ console.error('error exporting devices:', e);
+ }
+ }
+ exportDrivers(options: IOptions) {
+ let userDriversPath = path.resolve(options.target + '/user/drivers');
+ let drivers = getDrivers(userDriversPath, 'user_drivers');
+ io.write(userDriversPath + '/user_drivers.json', serialize({
+ items: drivers
+ }, null, 2));
+
+ let systemDriversPath = path.resolve(options.target + '/data/system/drivers');
+ drivers = getDrivers(systemDriversPath, 'system_drivers');
+ io.write(systemDriversPath + '/system_drivers.json', serialize({
+ items: drivers
+ }, null, 2));
+ }
+
+ exportMisc(options: IOptions) {
+ let source = jet.dir(options.root + '/export');
+ let target = jet.dir(options.target);
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+
+ /**
+ * update config
+ */
+ let template = io.read(path.resolve(source.path() + '/profile_device_server.json'));
+ let content = replace(template, null, options, {
+ begin: '%',
+ end: '%'
+ });
+
+
+ if (options.linux32) {
+ jet.exists(target.path() +
+ path.sep + '/server/linux_32/nxappmain/profile_device_server.json') && io.write(target.path() + path.sep +
+ '/server/linux_32/nxappmain/profile_device_server.json', content);
+ }
+
+ if (options.linux64) {
+ jet.exists(target.path() +
+ path.sep + '/server/linux_64/nxappmain/profile_device_server.json') && io.write(target.path() + path.sep +
+ '/server/linux_64/nxappmain/profile_device_server.json', content);
+ }
+
+ if (options.windows) {
+ jet.exists(target.path() +
+ path.sep + '/server/windows/nxappmain/profile_device_server.json') && io.write(target.path() + path.sep +
+ '/server/windows/nxappmain/profile_device_server.json', content);
+ }
+ if (options.arm) {
+ jet.exists(target.path() +
+ path.sep + '/server/arm/nxappmain/profile_device_server.json') && io.write(target.path() + path.sep +
+ '/server/arm/nxappmain/profile_device_server.json', content);
+ }
+ if (options.osx) {
+ jet.exists(target.path() +
+ path.sep + '/server/osx_64/nxappmain/profile_device_server.json') && io.write(target.path() + path.sep + '/server/osx_64/nxappmain/profile_device_server.json', content);
+ }
+
+ /**
+ * update boot start.js
+ */
+ template = io.read(path.resolve(source.path() + '/start.js'));
+ content = replace(template, null, options, {
+ begin: '%',
+ end: '%'
+ });
+
+ options.linux32 !== false && jet.exists(target.path() + '/server/linux_32/start.js') && io.write(target.path() + '/server/linux_32/start.js', content);
+ options.linux64 !== false && jet.exists(target.path() + '/server/linux_64/start.js') && io.write(target.path() + '/server/linux_64/start.js', content);
+ options.windows !== false && io.write(target.path() + '/server/windows/start.js', content);
+ options.arm !== false && jet.exists(target.path() + '/server/arm/start.js') && io.write(target.path() + '/server/arm/start.js', content);
+ options.osx !== false && jet.exists(target.path() + '/server/osx_64/start.js') && io.write(target.path() + '/server/osx_64/start.js', content);
+ }
+ exportClientEx(options: IOptions) {
+ let source = jet.dir(path.resolve(options.client) + '');
+ let target = jet.dir(options.target + '/Code/client');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ }
+ exportClient(options: IOptions) {
+ let source = jet.dir(options.root + '/Code/client');
+ let target = jet.dir(options.target + '/Code/client');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ }
+ exportClientDist(options: IOptions) {
+ let source = jet.dir(options.root + '/dist/windows/Code/client/');
+ let target = jet.dir(options.target + '/Code/client');
+
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ }
+ exportUser(options: IOptions) {
+ let source = jet.dir(options.user);
+ let target = jet.dir(options.target + '/user');
+ console.log('export user from ' + source.path() + ' to ' + target.path());
+ try {
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**',
+ '!./.git/**/*',
+ '!**/**claycenter',
+ '!./claycenter',
+ '!**claycenter'
+
+ ],
+ overwrite: true
+ });
+ } catch (err) {
+ if (err.code === 'EEXIST') {
+ console.error('Error copying, file exists!', err);
+ }
+
+ if (err.code === 'EACCES') {
+ console.error('Error copying, file access perrmissions!', err);
+ }
+ console.error('error : ', err);
+ }
+ }
+ exportSystem(options: IOptions) {
+ let source = jet.dir(options.system + '/system');
+ let target = jet.dir(options.target + '/data/system');
+ console.log('export system data from ' + source.path() + ' to ' + target.path());
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ }
+ clean() {
+ // let dir = 'leveldown';
+ // let files = ['*.lib', '*.pdb'];
+ }
+ copyServer(options: IOptions, platform: string) {
+ let target = jet.dir(options.target + '/server/' + platform);
+ let isDebug = false;
+ let source: any = "";
+ if (options.nodeServers) {
+ if (!jet.exists(options.nodeServers + '/' + platform)) {
+ return;
+ }
+ source = jet.dir(options.nodeServers + '/' + platform);
+ } else {
+ if (!isDebug) {
+ source = jet.dir(options.root + '/server/' + platform);
+ } else {
+ source = jet.dir(options.root + '/server/nodejs/dist/' + platform);
+ }
+ }
+
+ if (!jet.exists(source.path())) {
+ return;
+ }
+ console.info('export Device-Server ' + platform + ' from : ' + source.path());
+ try {
+
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ } catch (err) {
+ if (err.code === 'EEXIST') {
+ console.error('Error copying, file exists!', err);
+ }
+ if (err.code === 'EACCES') {
+ console.error('Error copying, file access perrmissions!', err);
+ }
+ }
+ }
+ exportServer(options: IOptions) {
+ options.windows !== false && this.copyServer(options, 'windows');
+ options.linux32 !== false && this.copyServer(options, 'linux_32');
+ options.linux64 !== false && this.copyServer(options, 'linux_64');
+ options.arm !== false && this.copyServer(options, 'arm');
+ options.osx !== false && this.copyServer(options, 'osx_64');
+ }
+ /**
+ * Create the default directory layout
+ */
+ createDirectoryLayout(options: IOptions) {
+ //jet.dir(options.target + '/www/');
+ }
+ /**
+ *
+ * @param options
+ */
+ exportMongo(options: IOptions) {
+ let source = jet.dir(options.serverTemplates + '/mongo');
+ let target = jet.dir(options.target + '/mongo');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ 'mongod-arm',
+ 'mongod-linux_32',
+ 'mongod-linux_64',
+ 'mongod-windows.exe',
+ 'mongod-32.exe',
+ 'mongod-osx'
+ ],
+ overwrite: true
+ });
+ }
+}
diff --git a/packages/vfs/ref/components/xideve/export/export.js b/packages/vfs/ref/components/xideve/export/export.js
new file mode 100644
index 00000000..a2374312
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/export/export.js
@@ -0,0 +1,641 @@
+/** @module nxapp/manager/ExportManager */
+define([
+ "dcl/dcl",
+ 'nxapp/manager/ManagerBase',
+ 'nxapp/manager/_Drivers_Devices',
+ 'nxapp/utils/_LogMixin',
+ "nxapp/utils/_console",
+ "xide/utils",
+ "nxapp/utils",
+ "dojo/node!path",
+ "dojo/node!fs-jetpack",
+ "dojo/node!cheerio",
+ "dojo/node!fs",
+ "dojo/has"
+], function (dcl, ManagerBase, _Drivers_Devices, _LogMixin, _console, utils, xutils, path, jet, cheerio, fs,has) {
+
+ var console = _console;
+ var debugPaths = true;
+
+ /**
+ * Common base class for protocol connections
+ * @class module:nxapp/manager/ExportManager
+ * @extends module:nxapp/manager/ManagerBase
+ */
+ return dcl([ManagerBase, _LogMixin, _Drivers_Devices], {
+ declaredClass: "nxapp.manager.ExportManager",
+ options: null,
+ /**
+ * @member {string|null} serverTemplates the path to the server templates. Defaults to
+ * this.root + 'server-template'
+ */
+ serverTemplates: null,
+ linux32:true,
+ linux64:true,
+ osx:true,
+ arm:true,
+ windows:true,
+ nginxOptions:null,
+ mongoOptions:null,
+ serverOptions:null,
+ init: function (profile) {
+ this.profile = profile;
+ },
+ run:function(delegate){
+ this.delegate = delegate;
+ this.initWithOptions(this.options);
+ },
+ onProgress:function(msg){
+ this.delegate && this.delegate.onProgress(msg);
+ console.log('Progress: ' + msg);
+ },
+ onError:function(msg){
+ this.delegate && this.delegate.onError(msg);
+ },
+ onFinish:function(msg){
+ this.delegate && this.delegate.onFinish(msg);
+ console.log('Finish: ' + msg);
+ },
+ /**
+ * @param options {module:nxapp/model/ExportOptions}
+ */
+ initWithOptions: function (options) {
+ this.options = options;
+ utils.mixin(this, options);
+ this.onProgress('Export Manager: begin export',{
+ progress:0
+ });
+ if(!this.root){
+ this.onError('Export Manager: have no root');
+ throw new Error('Export Manager: have no root');
+ }
+
+ if(!this.data){
+ this.onError('Export Manager: have no data');
+ throw new Error('Export Manager: have no data');
+ }
+
+ if(!this.user){
+ this.onError('Export Manager: have no user');
+ return;
+ }
+
+
+ if(!this.client){
+ if(has('debug')) {
+ this.client = xutils.resolve(this.root + '/dist/windows/Code/client/');
+ }else{
+ this.client = xutils.resolve(this.root + '/Code/client/');
+ }
+ }
+
+ if (!this.serverTemplates) {
+ this.serverTemplates = xutils.resolve(this.root + '/server-template');
+ }
+
+ if (!this.dist) {
+ this.dist = xutils.resolve(this.root + '/dist/all/server/');
+ }
+
+ debugPaths && console.log('export with \n', utils.inspect({
+ "System Data": this.data,
+ "User Data": this.user +' = ' +path.resolve(this.user),
+ "Root": path.resolve(this.root),
+ "Server-Templates": this.serverTemplates,
+ "Target": path.resolve(this.target),
+ "Node Servers": path.resolve(this.dist),
+ "Client": this.client,
+ "Export Windows":this.windows,
+ "Export Linux - 32 ":this.linux32,
+ "Export Linux - 64 ":this.linux64,
+ "Export OSX":this.osx,
+ "Export ARM":this.arm
+ }));
+
+ var NGINX_OPTIONS = utils.mixin({
+ port: 8889,
+ templatePath: xutils.resolve(this.serverTemplates + '/nginx/all/conf/nginx.app.template.conf')
+ },this.nginxOptions);
+
+ var serverOptions = utils.mixin({
+ port: 9997,
+ mongo_port: 27018,
+ mqtt_port: 1884
+ },this.serverOptions);
+
+ var all = true;
+ if (all) {
+ this.exportNGINX(NGINX_OPTIONS);
+ var MONGO_OPTIONS = this.mongoOptions || {};
+ this.exportMongo(MONGO_OPTIONS);
+ this.createDirectoryLayout();
+
+ this.exportServer();
+
+ this.onProgress('Exported Servers',{
+ progress:0.2
+ });
+
+ this.exportUser();
+
+ this.onProgress('Exported User',{
+ progress:0.3
+ });
+
+ this.exportSystem();
+ this.onProgress('Exported System Data',{
+ progress:0.4
+ });
+ this.exportMisc(serverOptions);
+ this.onProgress('Exported Misc Data',{
+ progress:0.5
+ });
+ this.exportHTML(serverOptions);
+ this.onProgress('Exported User Workspace HTML',{
+ progress:0.6
+ });
+ this.exportDevices({serverSide: true});
+ this.onProgress('Exported Devices',{
+ progress:0.7
+ });
+ this.exportDrivers({});
+ this.onProgress('Exported Drivers',{
+ progress:0.8
+ });
+ if(this.client){
+ this.exportClientEx();
+ }else {
+ if (has('debug')) {
+ this.exportClient();
+ } else {
+ this.exportClientDist();
+ }
+ }
+
+ this.onProgress('Exported Client Application Assets',{
+ progress:0.9
+ });
+ console.log('Export Done! Your application can be found at '+this.target);
+
+ this.onProgress('Export Done',{
+ progress:1.2
+ });
+
+ this.onFinish('Export Done! Your application can be found at '+this.target);
+
+ } else {
+ this.exportHTML(serverOptions);
+ }
+ },
+ exportHTML: function (options) {
+
+ var source = jet.dir(this.target + '/www/user/workspace/');
+ var thiz = this;
+
+ function parseDirectory(_path, name) {
+ //name = directory abs
+
+ var dirItems = fs.readdirSync(_path);
+ if (dirItems.length) {
+ _.each(dirItems, function (file) {
+ //file = file name
+ if (file.indexOf('.dhtml') !== -1) {
+ var root = name.replace(source.path() + '/', '');
+ thiz.exportHTMLFile2(_path + '/' + file, root, options);
+ }
+ });
+ }
+ }
+
+ function _walk(dir) {
+ var results = [];
+
+ if (fs.existsSync(dir)) {
+
+ var list = fs.readdirSync(dir);
+
+ list.forEach(function (file) {
+ file = dir + '/' + file;
+ var stat = fs.statSync(file);
+ if (stat) {
+ var root = file.replace(path + '/', '');
+ if (stat.isDirectory()) {
+ parseDirectory(file, root);
+ } else {
+ if (file.indexOf('.dhtml') !== -1) {
+ root = root.replace(dir + '/', '');
+ thiz.exportHTMLFile2(file, root, options);
+ }
+
+ }
+ } else {
+ console.error('cant get stat for ' + file);
+ }
+ });
+ } else {
+ console.error('device path ' + dir + ' doesnt exists');
+ }
+ return results;
+ }
+
+ _walk(source.path());
+
+ },
+ exportHTMLFile2: function (file, folder, options) {
+
+ var exportRoot = jet.dir(this.root + '/export/');
+ var template = utils.readFile(path.resolve(exportRoot.path() + '/app.template.html'));
+ var path_parts = utils.pathinfo(file);
+ if (folder === path_parts.basename) {
+ folder = "";
+ }
+
+ var templateVariables = utils.mixin({
+ libRoot: '/Code/client/src/lib',
+ lodashUrl: '/Code/client/src/lib/external/lodash.min.js',
+ requireBaseUrl: "/Code/client/src/lib/xibm/ibm",
+ jQueryUrl: "/Code/client/src/lib/external/jquery-1.9.1.min.js",
+ data: "",
+ user: "/user",
+ css: './' + utils.cleanUrl(path_parts.filename + ".css"),
+ theme: "bootstrap",
+ blox_file: "./" + folder + '/' + path_parts.filename + ".xblox",
+ scene_file: "./" + folder + '/' + path_parts.filename + ".dhtml",
+ mount: "workspace",
+ "VFS_VARS": JSON.stringify({
+ "user_drivers": './www/user/drivers',
+ "system_drivers": './www/system/drivers'
+ }, null, 2)
+ }, options);
+
+ template = utils.replace(template, null, templateVariables, {
+ begin: '%',
+ end: '%'
+ });
+ var content = utils.readFile(file);
+ content = content.replace(' ', template);
+ content = content.replace(/\burl\s*\(\s*["']?([^"'\r\n\)\(]+)["']?\s*\)/gi,
+ function (matchstr, parens) {
+ var parts = parens.split('://');
+ var mount = parts[0];
+ var path = parts[1];
+ if(mount && path) {
+ return "url('./" + path + "')";
+ }
+ return parens;
+ }
+ );
+
+ var dom = cheerio.load(content);
+ var extra = '\n';
+ dom('HEAD').append(dom(extra));
+ utils.writeFile(file.replace('.dhtml', '.html'), dom.html());
+ },
+ exportHTMLFile: function (options) {
+ var exportRoot = jet.dir(this.root + '/export/');
+ var source = jet.dir(this.target + '/www/user/workspace/');
+ var file = path.resolve(source.path() + '/ascene.dhtml');
+ var template = utils.readFile(path.resolve(exportRoot.path() + '/app.template.html'));
+ var templateVariables = utils.mixin({
+ libRoot: '/Code/client/src/lib',
+ lodashUrl: '/Code/client/src/lib/external/lodash.min.js',
+ requireBaseUrl: "/Code/client/src/lib/xibm/ibm",
+ jQueryUrl: "/Code/client/src/lib/external/jquery-1.9.1.min.js",
+ data: "",
+ user: "/user",
+ css: "./ascene.css",
+ theme: "bootstrap",
+ blox_file: "./ascene.xblox",
+ mount: "workspace",
+ "VFS_VARS": JSON.stringify({
+ "user_drivers": './www/user/drivers',
+ "system_drivers": './www/system/drivers'
+ }, null, 2)
+ }, options);
+
+ template = utils.replace(template, null, templateVariables, {
+ begin: '%',
+ end: '%'
+ });
+ var content = utils.readFile(file);
+ content = content.replace(' ', template);
+ var did = false;
+ content = content.replace(/\burl\s*\(\s*["']?([^"'\r\n\)\(]+)["']?\s*\)/gi,
+ function (matchstr, parens) {
+ var parts = parens.split('://');
+ var mount = parts[0];
+ var path = parts[1];
+ if(mount && path) {
+ console.error('----'+path);
+ did = true;
+ return "url('./" + path + "')";
+ }
+ return parens;
+ }
+ );
+
+
+ var dom = cheerio.load(content);
+ var extra = '\n';
+
+ dom('HEAD').append(dom(extra));
+
+ utils.writeFile(file.replace('.dhtml', '.html'), dom.html());
+ },
+ exportDevices: function (options) {
+ var user_devices_path = path.resolve(this.target + '/www/user/devices');
+ var devices = this.getDevices(user_devices_path, 'user_devices', options);
+
+ utils.writeFile(user_devices_path + '/user_devices.json', JSON.stringify({
+ items: devices
+ }, null, 2));
+
+ var system_devices_path = path.resolve(this.target + '/www/system/devices');
+ devices = this.getDevices(system_devices_path, 'system_devices', options);
+ utils.writeFile(system_devices_path + '/system_devices.json', JSON.stringify({
+ items: devices
+ }, null, 2));
+ },
+ exportDrivers: function (options) {
+
+ var user_drivers_path = path.resolve(this.target + '/www/user/drivers');
+ var drivers = this.getDrivers(user_drivers_path, 'user_drivers');
+ utils.writeFile(user_drivers_path + '/user_drivers.json', JSON.stringify({
+ items: drivers
+ }, null, 2));
+
+ var system_drivers_path = path.resolve(this.target + '/www/system/drivers');
+ drivers = this.getDrivers(system_drivers_path, 'system_drivers');
+ utils.writeFile(system_drivers_path + '/system_drivers.json', JSON.stringify({
+ items: drivers
+ }, null, 2));
+ },
+ exportMisc: function (options) {
+ var source = jet.dir(this.root + '/export');
+ var target = jet.dir(this.target);
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+
+ /**
+ * update config
+ */
+ var template = xutils.readFile(path.resolve(source.path() + '/profile_device_server.json'));
+ var content = utils.replace(template, null, options, {
+ begin: '%',
+ end: '%'
+ });
+
+
+ this.linux32 !=='false' && jet.exists(target.path() + path.sep + '/server/linux_32/nxappmain/profile_device_server.json') && utils.writeFile(target.path() + path.sep + '/server/linux_32/nxappmain/profile_device_server.json', content);
+ this.linux64 !=='false' && jet.exists(target.path() + path.sep + '/server/linux_64/nxappmain/profile_device_server.json') && utils.writeFile(target.path() + path.sep + '/server/linux_64/nxappmain/profile_device_server.json', content);
+ this.windows !=='false' && jet.exists(target.path() + path.sep + '/server/windows/nxappmain/profile_device_server.json') && this.windows !=='false' && utils.writeFile(target.path() + path.sep + '/server/windows/nxappmain/profile_device_server.json', content);
+ this.arm !=='false' && jet.exists(target.path() + path.sep + '/server/arm/nxappmain/profile_device_server.json') && utils.writeFile(target.path() + path.sep + '/server/arm/nxappmain/profile_device_server.json', content);
+ this.osx !=='false' && jet.exists(target.path() + path.sep + '/server/osx_64/nxappmain/profile_device_server.json') && utils.writeFile(target.path() + path.sep + '/server/osx_64/nxappmain/profile_device_server.json', content);
+
+
+ /**
+ * update boot start.js
+ */
+ template = xutils.readFile(path.resolve(source.path() + '/start.js'));
+ content = utils.replace(template, null, options, {
+ begin: '%',
+ end: '%'
+ });
+
+ this.linux32 !=='false' && jet.exists(target.path() + '/server/linux_32/start.js') && utils.writeFile(target.path() + '/server/linux_32/start.js', content);
+ this.linux64 !=='false' && jet.exists(target.path() + '/server/linux_64/start.js') && utils.writeFile(target.path() + '/server/linux_64/start.js', content);
+ this.windows !=='false' && utils.writeFile(target.path() + '/server/windows/start.js', content);
+ this.arm !=='false' && jet.exists(target.path() + '/server/arm/start.js') && utils.writeFile(target.path() + '/server/arm/start.js', content);
+ this.osx !=='false' && jet.exists(target.path() + '/server/osx_64/start.js') && utils.writeFile(target.path() + '/server/osx_64/start.js', content);
+
+ },
+ exportClientEx: function () {
+ var source = jet.dir(path.resolve(this.client) + '');
+ var target = jet.dir(this.target + '/www/Code/client');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ },
+ exportClient: function () {
+ var source = jet.dir(this.root + '/Code/client');
+ var target = jet.dir(this.target + '/www/Code/client');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ },
+ exportClientDist: function () {
+ var source = jet.dir(this.root + '/dist/all/Code/client/');
+ var target = jet.dir(this.target + '/www/Code/client');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ },
+ exportUser: function () {
+
+ var source = jet.dir(this.user);
+ var target = jet.dir(this.target + '/www/user');
+
+ console.log('export user from ' + source.path() + ' to ' + target.path() );
+
+ try {
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**',
+ '!./.git/**/*',
+ '!**/**claycenter',
+ '!./claycenter',
+ '!**claycenter'
+
+ ],
+ overwrite: true
+ });
+ } catch (err) {
+ if (err.code === 'EEXIST') {
+ console.error('Error copying, file exists!', err);
+ }
+
+ if (err.code === 'EACCES') {
+ console.error('Error copying, file access perrmissions!', err);
+ }
+ console.error('error : ',err);
+ }
+ },
+ exportSystem: function () {
+ var source = jet.dir(this.data + '/system');
+ var target = jet.dir(this.target + '/www/system');
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ },
+ clean: function () {
+ var dir = 'leveldown';
+ var files = ['*.lib', '*.pdb'];
+ },
+ copyServer: function (platform) {
+ var target = jet.dir(this.target + '/server/' + platform);
+ var isDebug = false;
+ var source = "";
+ if (this.dist) {
+ if(!jet.exists(this.dist + '/' + platform)){
+ return;
+ }
+ source = jet.dir(this.dist + '/' + platform);
+ } else {
+ if (!isDebug) {
+ source = jet.dir(this.root + '/server/' + platform);
+ } else {
+ source = jet.dir(this.root + '/server/nodejs/dist/' + platform);
+ }
+ }
+
+ if(!jet.exists(source.path())){
+ return;
+ }
+ console.info('export Device-Server ' + platform + ' from : ' + source.path());
+ try {
+
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ '**'
+ ],
+ overwrite: true
+ });
+ } catch (err) {
+ if (err.code === 'EEXIST') {
+ console.error('Error copying, file exists!', err);
+ }
+ if (err.code === 'EACCES') {
+ console.error('Error copying, file access perrmissions!', err);
+ }
+ }
+ },
+ exportServer: function (options) {
+ this.windows !=='false' && this.copyServer('windows');
+ this.linux32 !=='false' && this.copyServer('linux_32');
+ this.linux64 !=='false' && this.copyServer('linux_64');
+ this.arm !=='false' && this.copyServer('arm');
+ this.osx !=='false' && this.copyServer('osx_64');
+ },
+ /**
+ * Create the default directory layout
+ */
+ createDirectoryLayout: function () {
+ jet.dir(this.target + '/data/_MONGO');
+ jet.dir(this.target + '/www/');
+ jet.dir(this.target + '/nginx/logs');
+ },
+ /**
+ *
+ * @param options
+ */
+ exportMongo: function (options) {
+ /**
+ * copy nginx
+ */
+ var source = jet.dir(this.serverTemplates + '/mongo');
+ var target = jet.dir(this.target + '/mongo');
+
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ 'mongod-arm',
+ 'mongod-linux_32',
+ 'mongod-linux_64',
+ 'mongod-windows.exe',
+ 'mongod-32.exe',
+ 'mongod-osx'
+ ],
+ overwrite: true
+ });
+ },
+ /**
+ * @param options {object}
+ * @param options.port {int|string} The port nginx will listen
+ * @param options.templatePath {string} Path to the NGINX conf template
+ */
+ exportNGINX: function (options) {
+ /**
+ * copy nginx
+ */
+ var source = jet.dir(this.serverTemplates + '/nginx');
+ var target = jet.dir(this.target + '/nginx');
+
+ try {
+ jet.copy(source.path(), target.path(), {
+ matching: [
+ 'nginx-arm',
+ 'nginx-linux_32',
+ 'nginx-linux_64',
+ 'nginx-windows.exe',
+ 'nginx-osx',
+ 'msvcr110.dll'
+ ],
+
+ overwrite: true
+ });
+ } catch (err) {
+
+ if (err.code === 'EEXIST') {
+ console.error('Error copying, file exists!', err);
+ }
+
+ if (err.code === 'EACCES') {
+ console.error('Error copying, file access perrmissions!', err);
+ }
+
+ if (err.code === 'ETXTBSY') {
+ console.error('Error copying, file is busy', err);
+ }
+ }
+
+
+ /**
+ * Copy meta files
+ */
+ source = jet.dir(this.serverTemplates + '/nginx/all/conf');
+ target = jet.dir(this.target + '/nginx');
+
+ jet.copy(source.path(), target.path(), {
+ overwrite: true
+ });
+
+ source = jet.dir(this.serverTemplates + '/nginx/temp');
+ target = jet.dir(this.target + '/nginx/temp');
+ jet.copy(source.path(), target.path(), {
+ overwrite: true
+ });
+
+
+ /**
+ * create config
+ */
+ var template = xutils.readFile(options.templatePath);
+ var content = utils.replace(template, null, options, {
+ begin: '%%',
+ end: '%%'
+ });
+ source = jet.dir(this.serverTemplates + '/nginx/all/conf');
+ target = jet.dir(this.target + '/nginx/');
+ utils.writeFile(target.path() + path.sep + 'nginx.conf', content);
+ }
+ });
+});
\ No newline at end of file
diff --git a/packages/vfs/ref/components/xideve/routes/Preview.ts b/packages/vfs/ref/components/xideve/routes/Preview.ts
new file mode 100644
index 00000000..15568a70
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/routes/Preview.ts
@@ -0,0 +1,92 @@
+import { EEKey, ELayout } from '../../../applications/Base';
+import { ControlFreak as app } from '../../../applications/ControlFreak/index';
+import { IObjectLiteral } from '../../../interfaces/index';
+import { serialize } from '../../../io/json';
+import * as views from 'co-views';
+import * as Router from 'koa-router';
+import * as _ from 'lodash';
+import * as path from 'path';
+import * as fs from 'fs';
+import { serveIndex } from '../../../server/index';
+const PreviewRouter = new Router({ prefix: '/xideve' });
+PreviewRouter.get('/:preview/:mount/*', async (ctx: Router.IRouterContext, next: any) => {
+
+ let render = null;
+ const rtConfig = ctx.request.query.debug === 'true' ? 'debug' : 'release';
+ const mount = ctx.params.mount;
+ const filePath = ctx.params[0].replace('./', '/');
+ const app: app = (ctx.app);
+ const directoryService = app.directoryService;
+ const workspacePath = directoryService.resolve(mount, '', ctx.request);
+ let stat;
+ try {
+ stat = fs.statSync(path.join(workspacePath, filePath));
+ } catch (err) {
+ }
+
+ if (!filePath || stat.isDirectory()) {
+ return serveIndex(workspacePath, {
+ remove: '/xideve/preview/' + mount + '/',
+ icons: true,
+ view: 'details'
+ })(ctx, next);
+ }
+ const dir = path.dirname(filePath).replace('.', '');
+ if (app.options.type === ELayout.OFFLINE_RELEASE) {
+ render = views(path.join(app.path(EEKey.NODE_ROOT), '/_build/components/xideve/views'), { ext: 'ejs' });
+ } else {
+ render = views(path.join(__dirname, '../views'), { ext: 'ejs' });
+ }
+ const config = (app)['config'];
+ const variables = _.extend({}, config.relativeVariables);
+ app.variables(ctx, variables);
+ const tplParams = {
+ BASE_URL: variables[EEKey.BASE_URL],
+ APP_URL: variables[EEKey.APP_URL],
+ MOUNT: mount,
+ FILE: filePath,
+ THEME: 'bootstrap',
+ ROOT: variables[EEKey.ROOT],
+ RPC_URL: variables[EEKey.RPC_URL],
+ VFS_URL: variables[EEKey.VFS_URL],
+ VFS_VARS: serialize(variables['VFS_CONFIG'], null, 2),
+ CSS: variables[EEKey.VFS_URL] + mount + '/' + filePath.replace('.dhtml', '.css'),
+ DOC_BASE_URL: variables[EEKey.VFS_URL] + mount + '/' + dir,
+ USER_DIRECTORY: encodeURIComponent(app.directoryService._getUser(ctx.request) || variables['VFS_CONFIG'].user)
+ };
+ let templateResolved = null;
+ let content = null;
+ let error = null;
+ try {
+ templateResolved = await render(rtConfig, tplParams);
+ } catch (e) {
+ error = 'Error rendering EJS template for ' + mount + '://' + filePath;
+ ctx.body = error;
+ console.error(error, e);
+ }
+
+ try {
+ content = await app.directoryService.get(mount + '://' + filePath, false, false, null, ctx.request) as string;
+ } catch (e) {
+ error = 'cant get file ' + mount + '://' + filePath;
+ ctx.body = error;
+ return;
+ }
+ // fileContent.match(~\bbackground(-image)?\s*:(.*?)\(\s*('|")?(?.*?)\3?\s*\)~i);
+ content = content.replace(/\burl\s*\(\s*["']?([^"'\r\n\)\(]+)["']?\s*\)/gi,
+ function (matchstr, parens) {
+ let parts = parens.split('://');
+ let mount = parts[0];
+ let _path = parts[1];
+ if (mount && _path) {
+ _path = variables[EEKey.VFS_URL] + mount + '/' + _path;
+ return "url('" + _path + "')";
+ }
+ return parens;
+ }
+ );
+
+ const result = content.replace(' ', templateResolved);
+ ctx.body = result;
+});
+export default PreviewRouter;
diff --git a/packages/vfs/ref/components/xideve/services/Workbench.ts b/packages/vfs/ref/components/xideve/services/Workbench.ts
new file mode 100644
index 00000000..e2707d7e
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/services/Workbench.ts
@@ -0,0 +1,73 @@
+import { RpcMethod } from '../../../services/Base';
+import { BeanService } from './../../../services/Bean';
+import * as AnyPromise from 'any-promise';
+//import * from '../export/Exporter';
+export class WorkbenchService extends BeanService {
+ // implement Base#method
+ public method = 'XApp_XIDE_Workbench_Service';
+ // implement VFS#ls
+ @RpcMethod
+ async getInfo(path: string) {
+ return new AnyPromise((resolve, reject) => {
+ resolve({
+ "themeDefaultSet": null,
+ "dojoOptions": null,
+ "widgetPalette": null,
+ "userInfo": {
+ "email": "noemail@noemail.com",
+ "isLocalInstall": false,
+ "userDisplayName": "A",
+ "userId": "A"
+ },
+ "workbenchState": {
+ "activeEditor": null,
+ "editors": [],
+ "nhfo": [],
+ "project": null,
+ "id": "",
+ "Fields": [],
+ "admin": {
+ "settings": [{
+ "id": "driverView",
+ "value": {
+ "basic": {
+ "showHeader": false,
+ "selection": { "selected": ["9627cb05-2f23-8846-0721-5abcc7d3afbb"] },
+ "toolbar": false,
+ "properties": true
+ },
+ "conditionalProcess": {
+ "showHeader": false,
+ "selection": { "selected": [] },
+ "toolbar": true,
+ "properties": true
+ },
+ "basicVariables": {
+ "showHeader": false,
+ "selection": { "selected": [] },
+ "toolbar": false,
+ "properties": true
+ }
+ }
+ }, { "id": "theme", "value": "blue" }]
+ }
+ },
+ "project": null,
+ "id": "",
+ "Fields": []
+ });
+ });
+ }
+
+ //
+ // ─── DECORATORS ─────────────────────────────────────────────────────────────────
+ //
+ public getRpcMethods(): string[] {
+ throw new Error("Should be implemented by decorator");
+ }
+
+ methods() {
+ const methods = this.getRpcMethods();
+ return this.toMethods(methods);
+ }
+}
diff --git a/packages/vfs/ref/components/xideve/views/debug.ejs b/packages/vfs/ref/components/xideve/views/debug.ejs
new file mode 100644
index 00000000..443d89b7
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/views/debug.ejs
@@ -0,0 +1,417 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/vfs/ref/components/xideve/views/release.ejs b/packages/vfs/ref/components/xideve/views/release.ejs
new file mode 100644
index 00000000..5cb48132
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/views/release.ejs
@@ -0,0 +1,304 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/vfs/ref/components/xideve/xideve.ts b/packages/vfs/ref/components/xideve/xideve.ts
new file mode 100644
index 00000000..df345d5f
--- /dev/null
+++ b/packages/vfs/ref/components/xideve/xideve.ts
@@ -0,0 +1,22 @@
+import { Component } from '../Component';
+import { BaseService } from '../../services/Base';
+import { WorkbenchService } from '../xideve/services/Workbench';
+import { LibraryService } from '../xideve/services/Library';
+import { IServiceConfiguration } from '../../interfaces/Service';
+import * as Router from 'koa-router';
+import { IDelegate } from './Exporter';
+import { IDelegate as IDelegateOptions } from './ExportOptions';
+import Preview from './routes/Preview';
+const d = {} as IDelegate;
+const e = {} as IDelegateOptions;
+export class XIDEVE extends Component {
+ label(): string {
+ return "xideve";
+ }
+ services(config: IServiceConfiguration): BaseService[] {
+ return [new WorkbenchService(config), new LibraryService('')];
+ }
+ routes(): Router[] {
+ return [Preview];
+ }
+};
diff --git a/packages/vfs/ref/console.ts b/packages/vfs/ref/console.ts
new file mode 100644
index 00000000..12806b03
--- /dev/null
+++ b/packages/vfs/ref/console.ts
@@ -0,0 +1,24 @@
+const tracer = require('tracer');
+const util = require('util');
+import * as global from './global';
+
+let console = tracer.colorConsole({
+ format: "<{{title}}> {{message}} ",
+ dateformat: "HH:MM:ss.L"
+});
+
+if (typeof global['logError'] === 'undefined') {
+ global['logError'] = function (e, reason) {
+ console.error('Error ' + reason, e);
+ };
+}
+
+export function stack() {
+ let stack = new Error().stack;
+ console.log(stack);
+};
+console.clear = function () {
+ util.print("\u001b[2J\u001b[0;0H");
+};
+
+export { console as console };
diff --git a/packages/vfs/ref/debug.ts b/packages/vfs/ref/debug.ts
new file mode 100644
index 00000000..2f7fe01e
--- /dev/null
+++ b/packages/vfs/ref/debug.ts
@@ -0,0 +1,64 @@
+export { debug } from 'debug';
+export function hookStream(obj: any) {
+ if (obj.hook || obj.unhook) {
+ throw new Error('Object already has properties hook and/or unhook');
+ }
+
+ obj.hook = function (methName, _fn, isAsync) {
+ let self = this,
+ methodRef;
+
+ // Make sure method exists
+ if (!(Object.prototype.toString.call(self[methName]) === '[object Function]')) {
+ throw new Error('Invalid method: ' + methName);
+ }
+
+ // We should not hook a hook
+ if (self.unhook.methods[methName]) {
+ throw new Error('Method already hooked: ' + methName);
+ }
+
+ // Reference default method
+ methodRef = (self.unhook.methods[methName] = self[methName]);
+
+ self[methName] = function () {
+ let args = Array.prototype.slice.call(arguments);
+
+ // Our hook should take the same number of arguments
+ // as the original method so we must fill with undefined
+ // optional args not provided in the call
+ while (args.length < methodRef.length) {
+ args.push(undefined);
+ }
+
+ // Last argument is always original method call
+ args.push(function () {
+ let args = arguments;
+
+ if (isAsync) {
+ process.nextTick(function () {
+ methodRef.apply(self, args);
+ });
+ } else {
+ methodRef.apply(self, args);
+ }
+ });
+
+ _fn.apply(self, args);
+ };
+ };
+
+ obj.unhook = function (method) {
+ let self = this,
+ ref = self.unhook.methods[method];
+
+ if (ref) {
+ self[method] = self.unhook.methods[method];
+ delete self.unhook.methods[method];
+ } else {
+ throw new Error('Method not hooked: ' + method);
+ }
+ };
+
+ obj.unhook.methods = {};
+};
diff --git a/packages/vfs/ref/di/README.md b/packages/vfs/ref/di/README.md
new file mode 100644
index 00000000..c9e34e64
--- /dev/null
+++ b/packages/vfs/ref/di/README.md
@@ -0,0 +1,20 @@
+Agent Framework for TypeScript
+------------------------------
+
+Aha, I got you
+
+This is a new experimental library which bring Agent Framework into TypeScript world.
+
+Required to add `--experimentalDecorators` option to `tsc` or update `tsconfig.json`
+
+```json
+{
+ "compilerOptions": {
+ "experimentalDecorators": true
+ }
+}
+```
+
+### Known Issue
+
+We can not intercept the method call inside class constructor
diff --git a/packages/vfs/ref/di/agent.spec.ts b/packages/vfs/ref/di/agent.spec.ts
new file mode 100644
index 00000000..167e634e
--- /dev/null
+++ b/packages/vfs/ref/di/agent.spec.ts
@@ -0,0 +1,63 @@
+import { agent } from './agent'
+import { success } from './extra/success';
+
+@agent()
+class Agent {
+
+ @success('count1', 100)
+ count1: number;
+
+ @success('tested', true)
+ test(): boolean {
+ return true;
+ // throw new Error('debug');
+ }
+}
+
+@agent()
+class AnotherAgent extends Agent {
+
+ @success('count2', 200)
+ count2: number;
+
+ @success('getter2num', 300)
+ get getter2(): number {
+ return 10;
+ }
+
+ @success('isready', true)
+ ready(): boolean {
+ return this.test();
+ }
+}
+
+describe('@agent', () => {
+
+ describe('# should able to', () => {
+
+ it('new instance', () => {
+ const agent = new Agent();
+ expect(Reflect.getPrototypeOf(agent)).toBe(Agent.prototype);
+ expect(agent instanceof Agent).toBe(true);
+ agent.test();
+ expect(agent['tested']).toBe(true);
+ });
+
+ it('new ', () => {
+ const agent = new AnotherAgent();
+ expect(Reflect.getPrototypeOf(agent)).toBe(AnotherAgent.prototype);
+ expect(agent instanceof AnotherAgent).toBe(true);
+ expect(typeof agent.ready).toBe('function');
+ expect(agent.ready()).toBe(true);
+ expect(agent['isready']).toBe(true);
+ });
+
+ it('construct instance', () => {
+ const agent = Reflect.construct(Agent, []);
+ expect(Reflect.getPrototypeOf(agent)).toBe(Agent.prototype);
+ expect(agent instanceof Agent).toBe(true);
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/agent.ts b/packages/vfs/ref/di/agent.ts
new file mode 100644
index 00000000..c7cff4a6
--- /dev/null
+++ b/packages/vfs/ref/di/agent.ts
@@ -0,0 +1,98 @@
+import { decorateClass, IAttribute, IInterceptor, IInvocation } from './core';
+import { AddProxyInterceptor } from './core/interceptors/proxy';
+import { ORIGIN_INSTANCE, AGENT_DOMAIN } from './core/utils';
+import { ReadyAttribute } from './extra/ready';
+import { Reflection } from './core/reflection';
+import { Metadata } from './core/metadata';
+
+// ===========================================
+// ES2015 or before
+if (typeof Reflect !== 'object' || typeof Proxy !== 'function') {
+ throw new Error('Agent Framework requires ES2016 support');
+}
+
+// ===========================================
+// ES2016
+if (typeof Reflect['metadata'] !== 'function') {
+ // Install Reflect.metadata for tsc only
+ // tsc will add following code to the generated js file. in order to utilize these information.
+ // we create and method of Reflect.metadata to inject these information to Reflection object
+ // Reflect.metadata("design:type", Function),
+ // Reflect.metadata("design:paramtypes", []),
+ // Reflect.metadata("design:returntype", String)
+ Reflect['metadata'] = function (key: string, value: any) {
+ return function (target: Object | Function, propertyKey?: string | symbol, descriptor?: PropertyDescriptor | number): void {
+ Reflection.addMetadata(key, value, target, propertyKey, descriptor);
+ };
+ };
+}
+export type Agent = new (...parameters: Array) => Constructor;
+/**
+ * Define an agent
+ * @returns {(target:Constructor)=>(void|Constructor)}
+ */
+export function agent(identifier?: any) {
+ return decorateClass(new AgentAttribute(identifier));
+}
+
+/**
+ * AgentAttribute
+ */
+export class AgentAttribute implements IAttribute, IInterceptor {
+ constructor(private _identifier?: string) {}
+ get identifier(): string | null {
+ return this._identifier;
+ }
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ let originalAgent = invocation.invoke(parameters);
+ // // NOTE: In order to improve the performance, do not proxy if no field interceptors detected
+ // // intercept by overloading ES5 prototype (static intercept)
+ // const interceptorDefinitions = Reflection.metadata.getAll(invocation.target.prototype);
+ // if (interceptorDefinitions) {
+ //
+ // const fieldInterceptors = [...interceptorDefinitions.values()]
+ // .filter(reflection => !reflection.descriptor)
+ // .filter(reflection => reflection.hasAttributes());
+ //
+ // // do not proxy if no field interceptors detected
+ // if (fieldInterceptors.length) {
+ // // Proxy the current agent object
+ // agent = AddProxyInterceptor(agent);
+ // }
+ //
+ // }
+
+ // only proxy one time
+ if (!Reflect.has(originalAgent, ORIGIN_INSTANCE)) {
+ // intercept by implement ES6 proxy (dynamic intercept)
+ const domain = Reflect.get(originalAgent, AGENT_DOMAIN);
+ const upgradedAgent = AddProxyInterceptor(originalAgent);
+ Reflect.set(upgradedAgent, ORIGIN_INSTANCE, originalAgent);
+ Reflect.set(upgradedAgent, AGENT_DOMAIN, domain);
+
+ const readyList = [];
+
+ // find metadata
+ Metadata.getAll(Reflect.getPrototypeOf(originalAgent)).forEach((reflection: Reflection, key: string) => {
+ if (reflection.getAttributes(ReadyAttribute).length) {
+ readyList.push(key);
+ }
+ });
+ // execute agent hook: -> READY
+ if (readyList.length) {
+ readyList.forEach(ready => {
+ const readyFn = Reflect.get(upgradedAgent, ready);
+ if (typeof readyFn === 'function') {
+ Reflect.apply(readyFn, upgradedAgent, []);
+ }
+ });
+ }
+ return upgradedAgent;
+ }
+ return originalAgent;
+ }
+}
+
diff --git a/packages/vfs/ref/di/core/attribute.ts b/packages/vfs/ref/di/core/attribute.ts
new file mode 100644
index 00000000..8c29eee0
--- /dev/null
+++ b/packages/vfs/ref/di/core/attribute.ts
@@ -0,0 +1,40 @@
+import { IInterceptor } from './interceptor';
+
+export interface IAttribute {
+ /**
+ * Fired before decoration of this attribute
+ * @param target
+ * @param targetKey
+ */
+ beforeDecorate?(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean;
+
+ /**
+ * Get interceptor for this _invocation
+ */
+ getInterceptor(): IInterceptor;
+}
+
+export interface IBeforeDecorateAttribute extends IAttribute {
+ /**
+ * Fired before decoration of this attribute
+ * @param target
+ * @param targetKey
+ */
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean;
+
+}
+
+export function CanDecorate(attribute: IAttribute, target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return !attribute.beforeDecorate || attribute.beforeDecorate(target, targetKey, descriptor);
+}
+
+export function GetInterceptor(attribute: IAttribute): IInterceptor | undefined {
+ const interceptor = attribute.getInterceptor();
+ // do not intercept when got false, null, ''
+ if (!!interceptor && typeof interceptor.intercept === 'function' && interceptor.intercept.length === 2) {
+ return interceptor;
+ }
+ else {
+ return undefined;
+ }
+}
diff --git a/packages/vfs/ref/di/core/chain.ts b/packages/vfs/ref/di/core/chain.ts
new file mode 100644
index 00000000..34ec2734
--- /dev/null
+++ b/packages/vfs/ref/di/core/chain.ts
@@ -0,0 +1,28 @@
+import { IInvocation } from './invocation';
+import { IAttribute, GetInterceptor } from './attribute';
+import { IInterceptor } from './interceptor';
+
+export function createInvocationChainFromAttribute(origin: IInvocation, attributes: Array) {
+ let invocation: IInvocation = origin;
+ // make invocation chain of interceptors
+ attributes.forEach(function (attribute) {
+ const interceptor = GetInterceptor(attribute);
+ if (interceptor) {
+ invocation = new InceptionInvocation(invocation, interceptor);
+ }
+ });
+ return invocation;
+}
+
+/**
+ * InceptionInvocation will call next interceptor in the chain
+ */
+export class InceptionInvocation implements IInvocation {
+ constructor(private _invocation: IInvocation, private _interceptor: IInterceptor) {}
+ get target(): any {
+ return this._invocation.target;
+ }
+ invoke(parameters: ArrayLike): any {
+ return this._interceptor.intercept(this._invocation, parameters);
+ }
+}
diff --git a/packages/vfs/ref/di/core/decorator.ts b/packages/vfs/ref/di/core/decorator.ts
new file mode 100644
index 00000000..753c81bd
--- /dev/null
+++ b/packages/vfs/ref/di/core/decorator.ts
@@ -0,0 +1,110 @@
+import { IAttribute, CanDecorate } from './attribute';
+import { Reflection } from './reflection';
+import { AddConstructProxyInterceptor } from './interceptors/construct';
+import { LocalDomain } from '../domain';
+import { AgentAttribute, Agent } from '../agent';
+import { ORIGIN_CONSTRUCTOR } from './utils';
+/**
+ * Decorate class
+ * @param attribute
+ * @returns {(target:Constructor)=>(void|Constructor)}
+ */
+export function decorateClass(attribute: IAttribute): ClassDecorator {
+
+ // upgrade prototype
+ return (target: Constructor): Constructor | void => {
+
+ // // check the parents
+ // let upgrade = true;
+ // for (let current = target; !!current.name; current = Object.getPrototypeOf(current)) {
+ // console.log('check ====> name :', current.name);
+ // console.log(' symbols:', Object.getOwnPropertySymbols(current));
+ // console.log(' props :', Object.getOwnPropertyNames(current));
+ // const origin = current[ORIGIN_CONSTRUCTOR];
+ // if (origin) {
+ // console.log(' ORIGIN :', origin.name, '(do not upgrade)');
+ // upgrade = true;
+ // break;
+ // }
+ // }
+
+ const proxied = Reflect.has(target, ORIGIN_CONSTRUCTOR);
+ const originalTarget = proxied ? Reflect.get(target, ORIGIN_CONSTRUCTOR) : target;
+
+ if (CanDecorate(attribute, originalTarget)) {
+
+ Reflection.addAttribute(attribute, originalTarget);
+
+ let upgradedTarget;
+
+ if (proxied) {
+ upgradedTarget = target;
+ }
+ else {
+ // intercept by implement ES6 proxy (dynamic intercept)
+ upgradedTarget = AddConstructProxyInterceptor(target);
+ Reflect.set(upgradedTarget, ORIGIN_CONSTRUCTOR, originalTarget);
+ }
+ // console.log('add class', typeof originTarget, typeof originTarget.prototype);
+
+ // intercept by overloading ES5 prototype (static intercept)
+ // AddPrototypeInterceptor(upgradedConstructor);
+
+ // always register agent type in LocalDomain
+ if (attribute instanceof AgentAttribute) {
+ LocalDomain.registerAgentType(attribute, upgradedTarget);
+ }
+
+ return upgradedTarget;
+ }
+
+ return target;
+ }
+}
+
+/**
+ * Decorate class members
+ * @param attribute
+ * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+ */
+export function decorateClassMember(attribute: IAttribute) {
+ return (target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void => {
+ if (CanDecorate(attribute, target, propertyKey, descriptor)) {
+ Reflection.addAttribute(attribute, target, propertyKey, descriptor)
+ }
+ };
+}
+
+/**
+ * Decorate class property
+ * @param attribute
+ * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+ */
+export function decorateClassMethod(attribute: IAttribute): MethodDecorator {
+ return (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor): void => {
+ if (CanDecorate(attribute, target, propertyKey, descriptor)) {
+ Reflection.addAttribute(attribute, target, propertyKey, descriptor)
+ }
+ };
+}
+
+/**
+ * Decorate class field
+ * @param attribute
+ * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+ */
+export function decorateClassProperty(attribute: IAttribute): PropertyDecorator {
+ return (target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void => {
+ // TypeScript is not smart enough to identify the PropertyDescriptor on method
+ if (descriptor) {
+ throw new TypeError(`${Reflect.getPrototypeOf(attribute).constructor.name} can only decorate on class property`);
+ }
+ if (CanDecorate(attribute, target, propertyKey)) {
+ Reflection.addAttribute(attribute, target, propertyKey)
+ }
+ };
+}
+
+export function getDecoratingClass(type: any): any {
+ return type[ORIGIN_CONSTRUCTOR] || type;
+}
diff --git a/packages/vfs/ref/di/core/index.ts b/packages/vfs/ref/di/core/index.ts
new file mode 100644
index 00000000..7c98afe7
--- /dev/null
+++ b/packages/vfs/ref/di/core/index.ts
@@ -0,0 +1,6 @@
+export { IAttribute, IBeforeDecorateAttribute } from './attribute'
+export { IInterceptor } from './interceptor'
+export { IInvocation } from './invocation'
+export { Reflection } from './reflection'
+export { decorateClass, decorateClassMember, decorateClassMethod, decorateClassProperty } from './decorator'
+export { Metadata } from './metadata'
diff --git a/packages/vfs/ref/di/core/interceptor.ts b/packages/vfs/ref/di/core/interceptor.ts
new file mode 100644
index 00000000..0aa4d66c
--- /dev/null
+++ b/packages/vfs/ref/di/core/interceptor.ts
@@ -0,0 +1,53 @@
+import { IInvocation, ConstructInvocation, IInvoke, GetterInvocation, SetterInvocation } from './invocation';
+import { IAttribute } from './attribute';
+import { createInvocationChainFromAttribute } from './chain';
+
+const ORIGIN = Symbol('agent.framework.origin.method');
+
+export interface IInterceptor {
+ intercept(invocation: IInvocation, parameters: ArrayLike): any;
+}
+
+// TODO: add cache to improve performance
+// 1. create a hash based CacheMap
+// 2. implement the hash for attributes/prototype/describer
+// 3. replace InterceptorFactory with CachedInterceptorFactory
+export class InterceptorFactory {
+ public static createConstructInterceptor(attributes: Array,
+ target: T,
+ receiver: any): IInvocation {
+
+ const invocation = new ConstructInvocation(target, receiver);
+ return createInvocationChainFromAttribute(invocation, attributes);
+ }
+ public static createGetterInterceptor(attributes: Array,
+ target: any,
+ propertyKey: PropertyKey,
+ receiver: any): IInvocation {
+ const invocation = new GetterInvocation(target, propertyKey, receiver);
+ return createInvocationChainFromAttribute(invocation, attributes);
+ }
+ public static createSetterInterceptor(attributes: Array,
+ target: any,
+ propertyKey: PropertyKey,
+ receiver: any) {
+ const invocation = new SetterInvocation(target, propertyKey, receiver);
+ return createInvocationChainFromAttribute(invocation, attributes);
+ }
+ public static createFunctionInterceptor(attributes: Array, method: IInvoke) {
+ const originMethod = method[ORIGIN] || method;
+ const origin: IInvocation = {
+ invoke: function (parameters: ArrayLike) {
+ return Reflect.apply(originMethod, this.target, parameters);
+ },
+ method: originMethod
+ };
+ const chain = createInvocationChainFromAttribute(origin, attributes);
+ const upgradedMethod = function () {
+ origin.target = this;
+ return chain.invoke(arguments);
+ };
+ upgradedMethod[ORIGIN] = originMethod;
+ return upgradedMethod;
+ }
+}
diff --git a/packages/vfs/ref/di/core/interceptors/construct.ts b/packages/vfs/ref/di/core/interceptors/construct.ts
new file mode 100644
index 00000000..6faa0c34
--- /dev/null
+++ b/packages/vfs/ref/di/core/interceptors/construct.ts
@@ -0,0 +1,55 @@
+import { Reflection } from '../reflection';
+import { InterceptorFactory } from '../interceptor';
+import { Domain, LocalDomain } from '../../domain';
+import { InjectAttribute } from '../../extra/inject';
+import { AgentAttribute } from '../../agent';
+import { AGENT_DOMAIN } from '../utils';
+import { Metadata } from '../metadata';
+
+export function AddConstructProxyInterceptor(target: Constructor) {
+ const typeProxyHandler = {
+ construct: ConstructInterceptor
+ };
+ return new Proxy(target, typeProxyHandler);
+}
+
+export function ConstructInterceptor(target: T, parameters: ArrayLike, receiver: any): any {
+
+ const customAttributes = Reflection.getAttributes(target);
+ let domain: Domain;
+
+ if (parameters.length && parameters[0] instanceof Domain) {
+ domain = parameters[0] as Domain;
+ }
+ else {
+ domain = LocalDomain;
+ }
+
+ // if (customAttributes.length > 1) {
+ // throw new TypeError('Not Support Multiple Agent Decoration');
+ // }
+
+ const agentTypeConstructor = InterceptorFactory.createConstructInterceptor(customAttributes, target, receiver);
+ const rawAgent = agentTypeConstructor.invoke(parameters);
+
+ // find metadata
+ Metadata.getAll(Reflect.getPrototypeOf(rawAgent)).forEach((reflection: Reflection, key: string) => {
+ reflection.getAttributes(InjectAttribute).forEach((injector: InjectAttribute) => {
+ let injected = domain.getAgent(injector.typeOrIdentifier);
+ Reflect.set(rawAgent, key, injected);
+ });
+ });
+
+ // do not register to domain if no identifier found
+ customAttributes.forEach(attribute => {
+ if (attribute instanceof AgentAttribute) {
+ domain.registerAgent(attribute, rawAgent);
+ }
+ });
+
+ Reflect.set(rawAgent, AGENT_DOMAIN, domain);
+
+ // return the new class constructor
+ return rawAgent;
+
+}
diff --git a/packages/vfs/ref/di/core/interceptors/prototype.ts b/packages/vfs/ref/di/core/interceptors/prototype.ts
new file mode 100644
index 00000000..c9bc6bab
--- /dev/null
+++ b/packages/vfs/ref/di/core/interceptors/prototype.ts
@@ -0,0 +1,45 @@
+import { IsString, IsUndefined } from '../utils';
+import { Reflection } from '../reflection';
+import { InterceptorFactory } from '../interceptor';
+
+/**
+ * Add prototype interceptor (es5)
+ * @param target
+ * @returns {Constructor}
+ * @constructor
+ */
+export function AddPrototypeInterceptor(target: Constructor): void {
+
+ // get the prototype of function
+ const keys = Reflect.ownKeys(target.prototype)
+ .filter(key => key !== 'constructor')
+ .filter(key => IsString(key))
+ .filter(key => Reflection.hasAttributes(target.prototype, key));
+
+ // console.log('hooking', target.name, keys);
+
+ const propertyDescriptors = keys
+ .map(key => {
+ const descriptor = Object.getOwnPropertyDescriptor(target.prototype, key);
+ const attributes = Reflection.getAttributes(target.prototype, key);
+
+ if (!IsUndefined(descriptor.value)) {
+ descriptor.value = InterceptorFactory.createFunctionInterceptor(attributes, descriptor.value);
+ }
+ if (!IsUndefined(descriptor.get)) {
+ descriptor.get = InterceptorFactory.createFunctionInterceptor(attributes, descriptor.get);
+ }
+ if (!IsUndefined(descriptor.set)) {
+ descriptor.set = InterceptorFactory.createFunctionInterceptor(attributes, descriptor.set);
+ }
+
+ return { key, descriptor };
+
+ }).reduce((map, item) => {
+ map[item.key] = item.descriptor;
+ return map;
+ }, {});
+
+ Object.defineProperties(target.prototype, propertyDescriptors);
+
+}
diff --git a/packages/vfs/ref/di/core/interceptors/proxy.ts b/packages/vfs/ref/di/core/interceptors/proxy.ts
new file mode 100644
index 00000000..918dc173
--- /dev/null
+++ b/packages/vfs/ref/di/core/interceptors/proxy.ts
@@ -0,0 +1,90 @@
+import { Reflection } from '../reflection';
+import { InterceptorFactory } from '../interceptor';
+import { ToPropertyKey, IsUndefined } from '../utils';
+
+/**
+ * Add proxy interceptor
+ * @param target
+ * @returns {T}
+ * @constructor
+ */
+export function AddProxyInterceptor(target: T) {
+ const instanceProxyHandler: ProxyHandler = {
+ get: ProxyGetInterceptor,
+ set: ProxySetInterceptor
+ };
+ // console.log('create proxy for ', target);
+ return new Proxy(target, instanceProxyHandler);
+}
+
+/**
+ * The **get** interceptor (es6)
+ * @param target
+ * @param p
+ * @param receiver
+ * @returns {any}
+ * @constructor
+ */
+export function ProxyGetInterceptor(target: T, p: PropertyKey, receiver: any): any {
+
+ const propertyKey = ToPropertyKey(p);
+ const reflection = Reflection.getInstance(target, propertyKey);
+
+ // ignore property without attributes
+ if (!reflection) {
+ return Reflect.get(target, p, receiver);
+ }
+
+ // ignore prototype interceptors and getter/setter
+ // intercept by overloading ES5 prototype (static intercept)
+ // if (!IsUndefined(reflection.descriptor)) {
+ // return Reflect.get(target, p, receiver);
+ // }
+
+ // intercept by implement ES6 proxy (dynamic intercept)
+ if (!IsUndefined(reflection.descriptor) && reflection.descriptor.value) {
+ return InterceptorFactory.createFunctionInterceptor(reflection.getAttributes(), reflection.descriptor.value);
+ }
+
+ // create field getter interceptor on the fly
+ // TODO: get invocation from cache
+ const invocation = InterceptorFactory.createGetterInterceptor(reflection.getAttributes(), target, propertyKey, receiver);
+
+ // call getter
+ return invocation.invoke([]);
+
+}
+
+/**
+ * The **set** interceptor
+ * @param target
+ * @param p
+ * @param value
+ * @param receiver
+ * @returns {boolean}
+ * @constructor
+ */
+export function ProxySetInterceptor(target: T, p: PropertyKey, value: any, receiver: any): boolean {
+
+ const propertyKey = ToPropertyKey(p);
+ const reflection = Reflection.getInstance(target, propertyKey);
+
+ // ignore property without attributes
+ if (!reflection) {
+ return Reflect.set(target, p, value, receiver);
+ }
+
+ // ignore prototype interceptors and getter/setter
+ // if (!IsUndefined(reflection.descriptor)) {
+ // return Reflect.set(target, p, value, receiver);
+ // }
+ if (!IsUndefined(reflection.descriptor) && !reflection.descriptor.set) {
+ return Reflect.set(target, p, value, receiver);
+ }
+
+ // create field setter interceptor on the fly
+ const invocation = InterceptorFactory.createSetterInterceptor(reflection.getAttributes(), target, propertyKey, receiver);
+
+ // call the interceptors
+ return invocation.invoke([value]);
+}
diff --git a/packages/vfs/ref/di/core/invocation.ts b/packages/vfs/ref/di/core/invocation.ts
new file mode 100644
index 00000000..18be10d8
--- /dev/null
+++ b/packages/vfs/ref/di/core/invocation.ts
@@ -0,0 +1,35 @@
+export interface IInvoke {
+ (parameters: ArrayLike): any;
+}
+export interface IInvocation {
+ target?: any;
+ method?: IInvoke;
+ invoke(parameters: ArrayLike): any;
+}
+export class ConstructInvocation implements IInvocation {
+ constructor(private _target: any, private _receiver: any) {}
+ get target(): any {
+ return this._target;
+ }
+ invoke(parameters: ArrayLike): any {
+ return Reflect.construct(this._target, parameters, this._receiver);
+ }
+}
+export class GetterInvocation implements IInvocation {
+ constructor(private _target: any, private _propertyKey: PropertyKey, private _receiver: any) {}
+ get target(): any {
+ return this._target;
+ }
+ invoke(parameters: ArrayLike): any {
+ return Reflect.get(this._target, this._propertyKey, this._receiver);
+ }
+}
+export class SetterInvocation implements IInvocation {
+ constructor(private _target: any, private _propertyKey: PropertyKey, private _receiver: any) {}
+ get target(): any {
+ return this._target;
+ }
+ invoke(parameters: ArrayLike): any {
+ return Reflect.set(this._target, this._propertyKey, parameters[0], this._receiver);
+ }
+}
diff --git a/packages/vfs/ref/di/core/metadata.ts b/packages/vfs/ref/di/core/metadata.ts
new file mode 100644
index 00000000..97eb5bea
--- /dev/null
+++ b/packages/vfs/ref/di/core/metadata.ts
@@ -0,0 +1,63 @@
+import { Reflection } from './reflection';
+import { IsUndefined } from './utils';
+import * as global from '../../global';
+// createGetterInterceptor a unique, global symbol name
+// -----------------------------------
+const key = Symbol.for('agent.framework.metadata');
+// check if the global object has this symbol
+// add it if it does not have the symbol, yet
+// ------------------------------------------
+const globalSymbols = Object.getOwnPropertySymbols(global);
+
+// ensure all version using the same instance
+if (globalSymbols.indexOf(key) === -1) {
+ Reflect.set(global, key, new Map>()); // Object.freeze(kernel); - this will break istanbul test
+ // console.log('metadata store not found, create new metadata store')
+}
+const globalSymbols2 = Object.getOwnPropertySymbols(global);
+
+// ensure all version using the same instance
+if (globalSymbols2.indexOf(key) === -1) {
+ console.log('second');
+}
+
+export class Metadata {
+ private static _metadata: Map> = Reflect.get(global, key);
+ private static _empty: Map = new Map();
+ public static getAll(target: Object | Function): Map {
+ if (this._metadata.has(target)) {
+ return this._metadata.get(target);
+ }
+ else {
+ return this._empty;
+ }
+ }
+ public static get(target: Object | Function, method?: string | symbol): Reflection | null {
+ if (this._metadata.has(target)) {
+ return this._metadata.get(target).get(IsUndefined(method) ? '' : method);
+ }
+ else {
+ const proto = Object.getPrototypeOf(target);
+ if (proto && this._metadata.has(proto)) {
+ return this._metadata.get(proto).get(IsUndefined(method) ? '' : method);
+ }
+ else {
+ return null;
+ }
+ }
+ }
+ public static getOwn(target: Object | Function, method?: string | symbol): Reflection | null {
+ if (this._metadata.has(target)) {
+ return this._metadata.get(target).get(IsUndefined(method) ? '' : method);
+ }
+ else {
+ return null;
+ }
+ }
+ public static saveOwn(reflection: Reflection, target: Object | Function, method?: string | symbol): void {
+ if (!this._metadata.has(target)) {
+ this._metadata.set(target, new Map());
+ }
+ this._metadata.get(target).set(IsUndefined(method) ? '' : method, reflection);
+ }
+}
diff --git a/packages/vfs/ref/di/core/reflection.spec.ts b/packages/vfs/ref/di/core/reflection.spec.ts
new file mode 100644
index 00000000..bd366e6e
--- /dev/null
+++ b/packages/vfs/ref/di/core/reflection.spec.ts
@@ -0,0 +1,55 @@
+import { Reflection } from './reflection';
+import { IAttribute } from './attribute';
+import { IInterceptor } from './interceptor';
+
+class Test {
+}
+
+class TestAttribute implements IAttribute {
+ public beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+ public getInterceptor(): IInterceptor {
+ throw new TypeError('Not Implemented TestAttribute')
+ }
+}
+
+describe('Reflection', () => {
+ describe('# should not able to', () => {
+
+ it('get reflection on non-object', () => {
+ expect(() => {
+ const instance = Reflection.getInstance('Class');
+ console.log('[SHOULD_NEVER_SEEM_THIS]', instance);
+ }).toThrowError();
+ });
+
+ it('get own reflection on non-object', () => {
+ expect(() => {
+ const instance = Reflection.getOwnInstance('Class');
+ console.log('[SHOULD_NEVER_SEEM_THIS]', instance);
+ }).toThrowError();
+ });
+ });
+
+ describe('# should able to', () => {
+
+ it('get empty array if non-attribute found', () => {
+ expect(Reflection.getAttributes(Test)).toEqual([]);
+ });
+
+ it('add attribute multiple times', () => {
+ Reflection.addAttribute(new TestAttribute(), Test);
+ Reflection.addAttribute(new TestAttribute(), Test);
+ const attributes = Reflection.getAttributes(Test);
+ expect(attributes.length).toEqual(2);
+ });
+
+ it('add get target', () => {
+ const reflection = Reflection.getOwnInstance(Test);
+ expect(reflection.target).toEqual(Test.prototype);
+ expect(reflection.targetKey).toBeUndefined();
+ });
+
+ });
+});
diff --git a/packages/vfs/ref/di/core/reflection.ts b/packages/vfs/ref/di/core/reflection.ts
new file mode 100644
index 00000000..9d9859c5
--- /dev/null
+++ b/packages/vfs/ref/di/core/reflection.ts
@@ -0,0 +1,113 @@
+import { IAttribute } from './attribute';
+import { IsObjectOrFunction, IsUndefined, ToPropertyKey, IsFunction } from './utils';
+import { getDecoratingClass } from './decorator';
+import { Metadata } from './metadata';
+export class Reflection {
+ private _attributes: Array;
+ private _metadata: Map;
+ private constructor(private _target: Object, private _targetKey?: string | symbol, private _descriptor?: PropertyDescriptor) {
+ if (IsUndefined(_descriptor) && !IsUndefined(_targetKey)) {
+ this._descriptor = Object.getOwnPropertyDescriptor(_target, _targetKey);
+ }
+ this._attributes = [];
+ this._metadata = new Map();
+ }
+ public static getInstance(target: Object | Function, targetKey?: string | symbol): Reflection | null {
+ if (!IsObjectOrFunction(target)) {
+ throw new TypeError();
+ }
+ if (!IsUndefined(targetKey)) {
+ const instance = IsFunction(target) ? target['prototype'] : target;
+ targetKey = ToPropertyKey(targetKey);
+ return Metadata.get(instance, targetKey);
+ }
+ else {
+ const originTarget = getDecoratingClass(target);
+ const instance = IsFunction(originTarget) ? originTarget['prototype'] : originTarget;
+ return Metadata.get(instance);
+ }
+ }
+ public static getOwnInstance(target: Object | Function, targetKey?: string | symbol): Reflection | null {
+ if (!IsObjectOrFunction(target)) {
+ throw new TypeError();
+ }
+ if (!IsUndefined(targetKey)) {
+ const instance = IsFunction(target) ? target['prototype'] : target;
+ targetKey = ToPropertyKey(targetKey);
+ return Metadata.getOwn(instance, targetKey);
+ }
+ else {
+ const originTarget = getDecoratingClass(target);
+ const instance = IsFunction(originTarget) ? originTarget['prototype'] : originTarget;
+ return Metadata.getOwn(instance);
+ }
+ }
+ public static getAttributes(target: Object | Function, targetKey?: any): Array {
+ const reflection = Reflection.getInstance(target, targetKey);
+ return reflection ? reflection.getAttributes() : [];
+ }
+ public static hasAttributes(target: Object | Function, targetKey?: any): boolean {
+ const reflection = Reflection.getInstance(target, targetKey);
+ return reflection ? reflection.hasAttributes() : false;
+ }
+ public static addAttribute(attribute: IAttribute, target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor) {
+ const reflection = Reflection.getOrCreateOwnInstance(target, targetKey, descriptor);
+ reflection.addAttribute(attribute);
+ }
+ public static addMetadata(key: string, value: any, target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor) {
+ const reflection = Reflection.getOrCreateOwnInstance(target, targetKey, descriptor);
+ reflection.addMetadata(key, value);
+ }
+ private static getOrCreateOwnInstance(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): Reflection {
+ const instance = IsFunction(target) ? target['prototype'] : target;
+ let reflection = Reflection.getOwnInstance(instance, targetKey);
+ if (!reflection) {
+ reflection = new Reflection(instance, targetKey, descriptor);
+ Metadata.saveOwn(reflection, instance, targetKey);
+ }
+ return reflection;
+ }
+ getAttributes(type?): Array {
+ if (type) {
+ return this._attributes.filter(a => a instanceof type) as Array ;
+ }
+ else {
+ return this._attributes.slice(0) as Array ;
+ }
+ }
+ hasAttributes(): boolean {
+ return this._attributes.length > 0
+ }
+ addAttribute(attr: IAttribute): void {
+ this._attributes.push(attr);
+ }
+ getMetadata(key: string): any | null {
+ let metadata;
+ if (typeof Reflect['getMetadata'] === 'function') {
+ metadata = Reflect['getMetadata'](key, this.target, this.targetKey);
+ }
+ return metadata || this._metadata.get(key);
+ }
+ addMetadata(key: string, value: any) {
+ // console.log('added design for ', this._target, '.', this._targetKey, '->', key, '=', value);
+ this._metadata.set(key, value);
+ }
+ get target(): Object | Function {
+ return this._target;
+ }
+ get type(): any {
+ return this.getMetadata('design:type');
+ }
+ get paramtypes(): Array {
+ return this.getMetadata('design:paramtypes');
+ }
+ get returntype(): any {
+ return this.getMetadata('design:returntype');
+ }
+ get targetKey(): string | symbol {
+ return this._targetKey;
+ }
+ get descriptor(): PropertyDescriptor | null {
+ return this._descriptor;
+ }
+}
diff --git a/packages/vfs/ref/di/core/utils.ts b/packages/vfs/ref/di/core/utils.ts
new file mode 100644
index 00000000..2a7d64b6
--- /dev/null
+++ b/packages/vfs/ref/di/core/utils.ts
@@ -0,0 +1,60 @@
+export const ORIGIN_INSTANCE = Symbol('agent.framework.origin.instance');
+
+export const ORIGIN_CONSTRUCTOR = Symbol('agent.framework.origin.constructor');
+
+export const AGENT_DOMAIN = Symbol('agent.framework.domain');
+
+export function IsFunction(x: any): boolean {
+ return typeof x === 'function';
+}
+
+export function IsUndefined(x: any): boolean {
+ return x === undefined
+}
+
+export function IsObjectOrFunction(x: any): boolean {
+ return typeof x === 'object' ? x !== null : typeof x === 'function'
+}
+
+export function IsSymbol(x: any): boolean {
+ return typeof x === 'symbol'
+}
+
+export function IsString(x: any): boolean {
+ return typeof x === 'string';
+}
+
+export function ToPropertyKey(value: any): string | symbol {
+ return IsSymbol(value) ? value as symbol : String(value)
+}
+
+export function IsEqual(x: any, y: any): boolean {
+
+ // remember that NaN === NaN returns false
+ // and isNaN(undefined) returns true
+ if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
+ return true;
+ }
+
+ // Compare primitives and functions.
+ // Check if both arguments link to the same object.
+ // Especially useful on the step where we compare prototypes
+ if (x === y) {
+ return true;
+ }
+
+ if (!x === !y) {
+ return true;
+ }
+ // Works in case when functions are created in constructor.
+ // Comparing dates is a common scenario. Another built-ins?
+ // We can even handle functions passed across iframes
+ if ((typeof x === 'function' && typeof y === 'function') ||
+ (x instanceof Date && y instanceof Date) ||
+ (x instanceof RegExp && y instanceof RegExp) ||
+ (x instanceof String && y instanceof String) ||
+ (x instanceof Number && y instanceof Number)) {
+ return x.toString() === y.toString();
+ }
+ return false;
+}
diff --git a/packages/vfs/ref/di/domain.spec.ts b/packages/vfs/ref/di/domain.spec.ts
new file mode 100644
index 00000000..0b85a769
--- /dev/null
+++ b/packages/vfs/ref/di/domain.spec.ts
@@ -0,0 +1,95 @@
+import { agent } from './agent'
+import { success } from './extra/success';
+import { Domain } from './domain';
+
+class Base {
+
+}
+
+@agent('TestAgent')
+@agent('TestAgent2')
+class Agent extends Base {
+
+ constructor(private _domain: Domain, private _name?: string) {
+ super();
+ }
+
+ @success('tested', true)
+ test(): string {
+ return `Hello, ${this._name}`;
+ }
+
+}
+
+describe('@domain', () => {
+
+ describe('# should able to', () => {
+
+ it('create new instance', () => {
+ const domain1 = new Domain();
+ const agent1 = domain1.createAgent(Agent, 'Domain');
+ expect(Reflect.getPrototypeOf(agent1)).toBe(Agent.prototype);
+ expect(agent1 instanceof Agent).toBe(true);
+ expect(agent1.test()).toEqual('Hello, Domain');
+ expect(agent1['tested']).toBe(true);
+ });
+
+ it('add agent', () => {
+ const domain1 = new Domain();
+ domain1.addAgent(Agent);
+ const a1 = domain1.getAgent('TestAgent');
+ const a2 = domain1.getAgent('TestAgent2');
+ expect(a1).toEqual(a2);
+ });
+
+ });
+
+ describe('# should not able to', () => {
+
+ it('create same agent again', () => {
+ const domain2 = new Domain();
+ domain2.createAgent(Agent, 'Domain');
+ expect(() => {
+ domain2.createAgent(Agent, 'Domain');
+ }).toThrowError()
+ });
+
+ it('add agent twice', () => {
+ const domain1 = new Domain();
+ domain1.addAgent(Agent);
+ expect(() => {
+ domain1.addAgent(Agent);
+ }).toThrowError('Duplicated agent type identifier TestAgent2 is not allowed');
+
+ });
+
+ it('create same agent again', () => {
+ const domain1 = new Domain();
+ domain1.addAgent(Agent);
+ const a1 = domain1.getAgent('TestAgent');
+ const a2 = domain1.getAgent('TestAgent2');
+ expect(a1).toEqual(a2);
+ expect(() => {
+ domain1.createAgent(Agent);
+ }).toThrowError('Can not create agent. Duplicated agent identifier TestAgent2 is not allowed');
+ });
+
+ it('add same agent again', () => {
+ const domain1 = new Domain();
+ domain1.createAgent(Agent);
+ expect(() => {
+ domain1.addAgent(Agent);
+ }).toThrowError('Can not add agent type. Duplicated agent type identifier TestAgent2 is not allowed');
+ });
+
+ it('add same agent and new again', () => {
+ const domain1 = new Domain();
+ domain1.createAgent(Agent);
+ expect(() => {
+ const a1 = new Agent(domain1);
+ }).toThrowError('Duplicated agent identifier TestAgent2 is not allowed');
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/domain.ts b/packages/vfs/ref/di/domain.ts
new file mode 100644
index 00000000..c774044d
--- /dev/null
+++ b/packages/vfs/ref/di/domain.ts
@@ -0,0 +1,100 @@
+import { Agent, AgentAttribute } from './agent';
+import { EventEmitter } from 'events';
+import { Reflection } from './core/reflection';
+
+/**
+ * Domain interface
+ */
+export interface IDomain {
+ /**
+ * Add an agent to domain
+ * @param agentType
+ */
+ addAgent(agentType: Agent): void;
+ /**
+ * Create an agent and added to domain
+ * @param agentType
+ * @param parameters
+ */
+ createAgent(agentType: Agent, ...parameters: Array): Object;
+ /**
+ * Get the agent from domain or create previous added agent. Throw error if identifier not found.
+ * @param typeOrIdentifier
+ */
+ getAgent(typeOrIdentifier: Agent | string): Object;
+}
+
+export class Domain extends EventEmitter implements IDomain {
+ protected types: Map = new Map();
+ protected agents: Map = new Map();
+ registerAgentType(agentAttribute: AgentAttribute, agentType: Agent) {
+ if (!agentAttribute.identifier) {
+ return;
+ }
+ else if (this.types.has(agentAttribute.identifier)) {
+ throw new TypeError(`Duplicated agent type identifier ${agentAttribute.identifier} is not allowed`);
+ }
+ else {
+ this.types.set(agentAttribute.identifier, agentType);
+ }
+ }
+ registerAgent(agentAttribute: AgentAttribute, agent: Object) {
+ if (!agentAttribute.identifier) {
+ return;
+ }
+ else if (this.agents.has(agentAttribute.identifier)) {
+ throw new TypeError(`Duplicated agent identifier ${agentAttribute.identifier} is not allowed`);
+ }
+ else {
+ this.agents.set(agentAttribute.identifier, agent);
+ }
+ }
+ public addAgent(agentType: Agent): void {
+ const attributes = this.extractAgentAttributes(agentType);
+ attributes.forEach(attribute => {
+ if (this.agents.has(attribute.identifier)) {
+ throw new TypeError(`Can not add agent type. Duplicated agent type identifier ${attribute.identifier} is not allowed`);
+ }
+ });
+ attributes.forEach(attribute => {
+ this.registerAgentType(attribute, agentType);
+ });
+ }
+ public createAgent(agentType: Agent, ...parameters: Array): any {
+ const identifiers = this.extractIdentifiers(agentType);
+ identifiers.forEach(identifier => {
+ if (this.agents.has(identifier)) {
+ throw new TypeError(`Can not create agent. Duplicated agent identifier ${identifier} is not allowed`);
+ }
+ });
+ return Reflect.construct(agentType, [this, ...parameters]);
+ }
+ public getAgent(typeOrIdentifier: Agent | string): Object {
+ if (typeof typeOrIdentifier === 'string') {
+ if (this.agents.has(typeOrIdentifier)) {
+ return this.agents.get(typeOrIdentifier);
+ }
+ else if (this.types.has(typeOrIdentifier)) {
+ const agentType = this.types.get(typeOrIdentifier);
+ return this.createAgent(agentType);
+ }
+ else {
+ throw new TypeError(`Agent ${typeOrIdentifier} not found`);
+ }
+ }
+ else {
+ return this.createAgent(typeOrIdentifier);
+ }
+ }
+ private extractAgentAttributes(agentType: Agent): Array {
+ return Reflection.getAttributes(agentType)
+ .filter(a => a instanceof AgentAttribute) as Array;
+ }
+ private extractIdentifiers(agentType: Agent) {
+ return this.extractAgentAttributes(agentType)
+ .map(a => (a as AgentAttribute).identifier)
+ .filter(a => a != null);
+ }
+}
+
+export let LocalDomain = new Domain();
diff --git a/packages/vfs/ref/di/extra/cache.spec.ts b/packages/vfs/ref/di/extra/cache.spec.ts
new file mode 100644
index 00000000..407a4e52
--- /dev/null
+++ b/packages/vfs/ref/di/extra/cache.spec.ts
@@ -0,0 +1,56 @@
+import { agent } from '../agent'
+import { cache } from './cache';
+
+@agent()
+class TestAgentClass {
+
+ numberOfCalls: number = 0;
+
+ @cache()
+ heavyOperation(): any {
+ let x = 2;
+ while (x < 100000000000) {
+ x = x * x;
+ }
+ this.numberOfCalls++;
+ return x;
+ }
+
+ @cache()
+ heavyOperationWithArguments(name: string, score: number): any {
+ let x = 2 + score + name.toString().length;
+ while (x < 100000) {
+ x = x * x;
+ }
+ this.numberOfCalls++;
+ return x;
+ }
+
+}
+
+describe('@cache', () => {
+ describe('# should able to', () => {
+
+ it('cache the result for heavyOperation', () => {
+ const tester = new TestAgentClass();
+ const first = tester.heavyOperation();
+ for (let n = 0; n < 10000; n++) {
+ const val = tester.heavyOperation();
+ expect(val).toEqual(first);
+ }
+ expect(tester.numberOfCalls).toEqual(1);
+ });
+
+ it('cache the result for heavyOperationWithArguments', () => {
+ const tester = new TestAgentClass();
+ const first = tester.heavyOperationWithArguments('ling', 55);
+ for (let n = 0; n < 10000; n++) {
+ const val = tester.heavyOperationWithArguments('ling', 55);
+ expect(val).toEqual(first);
+ }
+ expect(tester.numberOfCalls).toEqual(1);
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/cache.ts b/packages/vfs/ref/di/extra/cache.ts
new file mode 100644
index 00000000..1303fa16
--- /dev/null
+++ b/packages/vfs/ref/di/extra/cache.ts
@@ -0,0 +1,61 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMethod } from '../core';
+
+/**
+ * Define a prerequisite
+ * @returns {(target:any, propertyKey:string, descriptor:PropertyDescriptor)=>undefined}
+ */
+export function cache() {
+ return decorateClassMethod(new CacheAttribute());
+}
+
+/**
+ * PrerequisiteAttribute
+ */
+export class CacheAttribute implements IAttribute, IInterceptor {
+
+ cache = new MemoryCache();
+
+ static normalizeParameters(parameters: ArrayLike): string {
+ return Array.from(parameters).map(value => value.toString()).join('|');
+ }
+
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ const normalized = CacheAttribute.normalizeParameters(parameters);
+ const hit = this.cache.get(normalized);
+ if (hit != null) {
+ return hit;
+ }
+ const result = invocation.invoke(parameters);
+ this.cache.set(normalized, result);
+ return result;
+ }
+}
+
+export class MemoryCache {
+ expires: number = 60000;
+ store: Map = new Map();
+ set(key: string, value: any) {
+ this.store.set(key, { expires: Date.now() + this.expires, value });
+ }
+ get(key: string): any | null {
+ if (this.store.has(key)) {
+ const cached = this.store.get(key);
+ if (cached.expires > Date.now()) {
+ return cached.value;
+ }
+ else {
+ this.store.delete(key);
+ }
+ }
+ return null;
+ }
+}
+
+export interface ICached {
+ expires: number,
+ value: any;
+}
diff --git a/packages/vfs/ref/di/extra/conditional.spec.ts b/packages/vfs/ref/di/extra/conditional.spec.ts
new file mode 100644
index 00000000..3b681de7
--- /dev/null
+++ b/packages/vfs/ref/di/extra/conditional.spec.ts
@@ -0,0 +1,45 @@
+import { agent } from '../agent'
+import { conditional } from './conditional';
+import { Reflection } from '../core/reflection';
+
+@agent()
+class TestAgentClass {
+
+ bool: boolean = true;
+ value: number = 0;
+
+ @conditional('bool', false)
+ notMet(): void {
+ this.value = 100;
+ }
+
+ @conditional('bool', true)
+ met(): void {
+ this.value = 200;
+ }
+
+}
+
+describe('@conditional', () => {
+
+ describe('# should not able to', () => {
+ it('change value', () => {
+ const conditionalAgent = new TestAgentClass();
+ conditionalAgent.notMet();
+ const ref = Reflection.getOwnInstance(TestAgentClass, 'notMet');
+ expect(ref.type).toEqual(Function);
+ expect(ref.paramtypes).toEqual([]);
+ expect(ref.returntype).toEqual(undefined);
+ expect(conditionalAgent.value).toEqual(0);
+ });
+ });
+
+ describe('# should able to', () => {
+ it('change value', () => {
+ const conditionalAgent = new TestAgentClass();
+ conditionalAgent.met();
+ expect(conditionalAgent.value).toEqual(200);
+ });
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/conditional.ts b/packages/vfs/ref/di/extra/conditional.ts
new file mode 100644
index 00000000..5840a24e
--- /dev/null
+++ b/packages/vfs/ref/di/extra/conditional.ts
@@ -0,0 +1,46 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+import { IsEqual } from '../core/utils';
+
+/**
+ * Define a conditional
+ * @param field
+ * @param expect
+ * @returns {(target:any, propertyKey:string, descriptor:PropertyDescriptor)=>undefined}
+ */
+export function conditional(field: string, expect: any) {
+ return decorateClassMember(new ConditionalAttribute(field, expect));
+}
+
+/**
+ * PrerequisiteAttribute
+ */
+export class ConditionalAttribute implements IAttribute, IInterceptor {
+
+ constructor(private _field: string, private _expect: any) {
+ }
+
+ get field(): string {
+ return this._field
+ }
+
+ get expect(): boolean {
+ return this._expect
+ }
+
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ const actualValue = Reflect.get(invocation.target, this.field);
+ if (IsEqual(actualValue, this.expect)) {
+ return invocation.invoke(parameters);
+ }
+ return undefined;
+ }
+
+}
diff --git a/packages/vfs/ref/di/extra/failure.spec.ts b/packages/vfs/ref/di/extra/failure.spec.ts
new file mode 100644
index 00000000..3b83ddae
--- /dev/null
+++ b/packages/vfs/ref/di/extra/failure.spec.ts
@@ -0,0 +1,45 @@
+import { agent } from '../agent'
+import { failure } from './failure'
+
+@agent()
+class TestFailureAgentClass {
+
+ @failure(null)
+ testNull() {
+ throw new Error()
+ }
+
+ @failure(0)
+ testZero() {
+ throw new Error()
+ }
+
+ @failure('')
+ testEmptyString() {
+ throw new Error()
+ }
+
+}
+
+describe('@failure', () => {
+
+ describe('# should able to', () => {
+
+ it('get null when throw', () => {
+ const failureAgent = new TestFailureAgentClass();
+ expect(failureAgent.testNull()).toBe(null);
+ });
+
+ it('get 0 when throw', () => {
+ const failureAgent = new TestFailureAgentClass();
+ expect(failureAgent.testZero()).toBe(0);
+ });
+
+ it('get empty string when throw', () => {
+ const failureAgent = new TestFailureAgentClass();
+ expect(failureAgent.testEmptyString()).toBe('');
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/failure.ts b/packages/vfs/ref/di/extra/failure.ts
new file mode 100644
index 00000000..85c3a856
--- /dev/null
+++ b/packages/vfs/ref/di/extra/failure.ts
@@ -0,0 +1,34 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+
+/**
+ * Return pre-defined value when catch an exception
+ * @param replaced
+ * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+ */
+export function failure(replaced: any) {
+ return decorateClassMember(new FailureAttribute(replaced));
+}
+
+/**
+ * PrerequisiteAttribute
+ */
+export class FailureAttribute implements IAttribute, IInterceptor {
+ constructor(private _value: any) {}
+ get value(): boolean {
+ return this._value;
+ }
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ try {
+ return invocation.invoke(parameters);
+ }
+ catch (err) {
+ return this.value;
+ }
+ }
+}
diff --git a/packages/vfs/ref/di/extra/index.ts b/packages/vfs/ref/di/extra/index.ts
new file mode 100644
index 00000000..a528fa0f
--- /dev/null
+++ b/packages/vfs/ref/di/extra/index.ts
@@ -0,0 +1,9 @@
+export { prerequisite } from './prerequisite'
+export { success } from './success'
+export { failure } from './failure'
+export { normalize } from './normalize'
+export { timestamp } from './timestamp'
+export { cache } from './cache'
+export { conditional } from './conditional'
+export { inject } from './inject'
+export { ready } from './ready'
diff --git a/packages/vfs/ref/di/extra/inject.spec.ts b/packages/vfs/ref/di/extra/inject.spec.ts
new file mode 100644
index 00000000..2e237669
--- /dev/null
+++ b/packages/vfs/ref/di/extra/inject.spec.ts
@@ -0,0 +1,81 @@
+import { agent } from '../agent'
+import { inject } from './inject';
+
+@agent('Util')
+class UtilAgent {
+
+ constructor() {
+ // console.log('calling UtilAgent ctor');
+ }
+
+ format(str: string, name: string) {
+ return str + name;
+ }
+
+}
+
+
+@agent('TestService')
+class TestServiceAgent {
+
+ @inject('Util')
+ util: UtilAgent;
+
+
+ constructor() {
+ // console.log('calling TestServiceAgent ctor');
+ }
+
+ hello() {
+ return 'Hello' + this.util.format(',', 'Name');
+ }
+
+}
+
+@agent('Test')
+class TestAgent {
+
+ @inject(TestServiceAgent)
+ serviceAgent: TestServiceAgent;
+
+ @inject('TestService')
+ serviceAgentById: TestServiceAgent;
+
+ constructor() {
+ // console.log('calling Test ctor', this.serviceAgent);
+ }
+
+}
+
+@agent('Test2')
+class TestAgent2 {
+
+ @inject('Util2')
+ util2: UtilAgent;
+
+}
+
+describe('@inject', () => {
+
+ describe('# should able to', () => {
+
+ it('without domain', () => {
+ const test = new TestAgent();
+ // console.log('test', Object.getPrototypeOf(test), test);
+ expect(test.serviceAgent).toBeDefined();
+ expect(test.serviceAgent).toEqual(test.serviceAgentById);
+ expect(test.serviceAgent.hello()).toEqual('Hello,Name');
+ });
+
+ });
+
+ describe('# should not able to', () => {
+
+ it('non-exist agent', () => {
+ expect(() => {
+ const test = new TestAgent2();
+ }).toThrowError('Agent Util2 not found');
+ });
+
+ });
+});
diff --git a/packages/vfs/ref/di/extra/inject.ts b/packages/vfs/ref/di/extra/inject.ts
new file mode 100644
index 00000000..0a749017
--- /dev/null
+++ b/packages/vfs/ref/di/extra/inject.ts
@@ -0,0 +1,17 @@
+import { IAttribute, IInterceptor } from '../core';
+import { decorateClassProperty } from '../core/decorator';
+import { Agent } from '../agent';
+
+export function inject(typeOrIdentifier: Agent | string) {
+ return decorateClassProperty(new InjectAttribute(typeOrIdentifier));
+}
+
+export class InjectAttribute implements IAttribute {
+ constructor(private _typeOrIdentifier: Agent | string) {}
+ get typeOrIdentifier() {
+ return this._typeOrIdentifier;
+ }
+ getInterceptor(): IInterceptor {
+ return null;
+ }
+}
diff --git a/packages/vfs/ref/di/extra/normalize.spec.ts b/packages/vfs/ref/di/extra/normalize.spec.ts
new file mode 100644
index 00000000..d1b5c592
--- /dev/null
+++ b/packages/vfs/ref/di/extra/normalize.spec.ts
@@ -0,0 +1,73 @@
+import { agent } from '../agent'
+import { normalize } from './normalize';
+
+@agent()
+class TestNormalizeAgentClass {
+
+ private _testField: any;
+
+ @normalize()
+ testFieldWithValue: any = 1102;
+
+ constructor() {
+ this._testField = 1000;
+ this.testFieldWithValue = 2000;
+ }
+
+ @normalize()
+ get test(): any {
+ return this._testField;
+ }
+
+ @normalize()
+ testReturnValue(): any {
+ return 1102
+ }
+
+ @normalize()
+ testReturnArray(): any {
+ return [1101, 1102, 1103]
+ }
+
+ @normalize()
+ testThrowError(): any {
+ throw new Error('october')
+ }
+
+}
+
+describe('@normalize', () => {
+
+ describe('# should able to', () => {
+
+ it('get result', () => {
+ const outputAgent = new TestNormalizeAgentClass();
+ expect(outputAgent.testReturnValue()).toBeDefined();
+ expect(outputAgent.testReturnValue()).toEqual({ ok: 1, result: 1102 });
+ });
+
+ it('get results', () => {
+ const outputAgent = new TestNormalizeAgentClass();
+ expect(outputAgent.testReturnArray()).toBeDefined();
+ expect(outputAgent.testReturnArray()).toEqual({ ok: 1, results: [1101, 1102, 1103] });
+ });
+
+ it('get result from field', () => {
+ const outputAgent = new TestNormalizeAgentClass();
+ expect(outputAgent.test).toEqual({ ok: 1, result: 1000 });
+ });
+
+ it('get result from initialized field', () => {
+ const outputAgent = new TestNormalizeAgentClass();
+ expect(outputAgent.testFieldWithValue).toEqual({ ok: 1, result: 2000 });
+ });
+
+ it('get error', () => {
+ const outputAgent = new TestNormalizeAgentClass();
+ expect(outputAgent.testThrowError()).toBeDefined();
+ expect(outputAgent.testThrowError()).toEqual({ ok: 0, message: 'october' });
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/normalize.ts b/packages/vfs/ref/di/extra/normalize.ts
new file mode 100644
index 00000000..00d2a93c
--- /dev/null
+++ b/packages/vfs/ref/di/extra/normalize.ts
@@ -0,0 +1,33 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+
+/**
+ * Normalize the result { ok: 1, result: '', message: '' }
+ * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+ */
+export function normalize() {
+ return decorateClassMember(new NormalizeAttribute());
+}
+
+export class NormalizeAttribute implements IAttribute, IInterceptor {
+ constructor() {}
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ try {
+ const value = invocation.invoke(parameters);
+ if (Array.isArray(value)) {
+ return { ok: 1, results: value };
+ }
+ else {
+ return { ok: 1, result: value };
+ }
+ }
+ catch (err) {
+ return { ok: 0, message: err.message };
+ }
+ }
+}
diff --git a/packages/vfs/ref/di/extra/prerequisite.spec.ts b/packages/vfs/ref/di/extra/prerequisite.spec.ts
new file mode 100644
index 00000000..a16e7c41
--- /dev/null
+++ b/packages/vfs/ref/di/extra/prerequisite.spec.ts
@@ -0,0 +1,52 @@
+import { agent } from '../agent'
+import { prerequisite } from './prerequisite';
+
+@agent()
+class TestPrerequisiteAgentClass {
+
+ bool: boolean = true;
+
+ @prerequisite('bool', true, 'require bool == true')
+ testBool(): any {
+ return 1102
+ }
+
+ @prerequisite('bool', false, 'require bool == false')
+ testBoolNotSatisfy(): any {
+ return 2201
+ }
+
+ @prerequisite('bool', false, new Error('november'))
+ testBoolNotSatisfyAndCustomError(): any {
+ return 2222
+ }
+
+}
+
+describe('@prerequisite', () => {
+
+ describe('# should able to', () => {
+
+ it('get result', () => {
+ const prerequisiteAgent = new TestPrerequisiteAgentClass();
+ expect(prerequisiteAgent.testBool()).toBeDefined();
+ expect(prerequisiteAgent.testBool()).toEqual(1102);
+ });
+
+ it('get error', () => {
+ const prerequisiteAgent = new TestPrerequisiteAgentClass();
+ expect(() => {
+ prerequisiteAgent.testBoolNotSatisfy()
+ }).toThrow(new Error('require bool == false'));
+ });
+
+ it('get custom error', () => {
+ const prerequisiteAgent = new TestPrerequisiteAgentClass();
+ expect(() => {
+ prerequisiteAgent.testBoolNotSatisfyAndCustomError()
+ }).toThrowError('november')
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/prerequisite.ts b/packages/vfs/ref/di/extra/prerequisite.ts
new file mode 100644
index 00000000..8461fc62
--- /dev/null
+++ b/packages/vfs/ref/di/extra/prerequisite.ts
@@ -0,0 +1,47 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+import { IsEqual, IsString } from '../core/utils';
+
+/**
+ * Define a prerequisite
+ * @param key
+ * @param value
+ * @param message
+ * @returns {(target:any, propertyKey:string, descriptor:PropertyDescriptor)=>undefined}
+ */
+export function prerequisite(key: string, value: any, message: string | Error) {
+ return decorateClassMember(new PrerequisiteAttribute(key, value, message));
+}
+
+/**
+ * PrerequisiteAttribute
+ */
+export class PrerequisiteAttribute implements IAttribute, IInterceptor {
+ constructor(private _key: string, private _value: any, private _message: string | Error) {}
+ get key(): string {
+ return this._key;
+ }
+ get value(): boolean {
+ return this._value;
+ }
+ get message(): string | Error {
+ return this._message;
+ }
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ const actualValue = Reflect.get(invocation.target, this.key);
+ if (!IsEqual(actualValue, this.value)) {
+ if (IsString(this.message)) {
+ throw new TypeError(this.message as string)
+ }
+ else {
+ throw this.message;
+ }
+ }
+ return invocation.invoke(parameters);
+ }
+}
diff --git a/packages/vfs/ref/di/extra/ready.spec.ts b/packages/vfs/ref/di/extra/ready.spec.ts
new file mode 100644
index 00000000..814c1e7c
--- /dev/null
+++ b/packages/vfs/ref/di/extra/ready.spec.ts
@@ -0,0 +1,55 @@
+import { agent } from '../agent'
+import { inject } from './inject';
+import { ready } from './ready';
+import { success } from './success';
+
+@agent('ReadyUtil')
+class ReadyUtilAgent {
+
+ constructor() {
+ // console.log('calling UtilAgent ctor');
+ }
+
+ format(str: string, name: string) {
+ return str + name;
+ }
+
+}
+
+@agent('TestReadyService')
+class TestReadyServiceAgent {
+
+ @inject('ReadyUtil')
+ util: ReadyUtilAgent;
+
+ constructor() {
+ // console.log('calling TestServiceAgent ctor');
+ }
+
+ hello() {
+ return 'Hello' + this.util.format(',', 'Name');
+ }
+
+ @ready()
+ @success('_ready', true)
+ ready() {
+
+ }
+
+}
+
+
+describe('@ready', () => {
+
+ describe('# should able to', () => {
+
+ it('without domain', () => {
+ const test = new TestReadyServiceAgent();
+ // console.log('test', Object.getPrototypeOf(test), test);
+ expect(test.util).toBeDefined();
+ expect(test['_ready']).toEqual(true);
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/ready.ts b/packages/vfs/ref/di/extra/ready.ts
new file mode 100644
index 00000000..011eb1d8
--- /dev/null
+++ b/packages/vfs/ref/di/extra/ready.ts
@@ -0,0 +1,13 @@
+import { IAttribute, IInterceptor } from '../core';
+import { decorateClassMethod } from '../core/decorator';
+
+export function ready() {
+ return decorateClassMethod(new ReadyAttribute());
+}
+
+export class ReadyAttribute implements IAttribute {
+ constructor() {}
+ getInterceptor(): IInterceptor {
+ return null;
+ }
+}
diff --git a/packages/vfs/ref/di/extra/stream.spec.ts b/packages/vfs/ref/di/extra/stream.spec.ts
new file mode 100644
index 00000000..fe81d8c0
--- /dev/null
+++ b/packages/vfs/ref/di/extra/stream.spec.ts
@@ -0,0 +1,28 @@
+// import { agent } from '../agent'
+// import { stream } from './stream';
+//
+// @agent()
+// class TestAgentClass {
+//
+// @stream()
+// *getList(): any {
+// yield 123;
+// }
+//
+//
+// }
+//
+// describe('@stream', () => {
+//
+// describe('# should able to', () => {
+//
+// it('get result', () => {
+// const agent = new TestAgentClass();
+// const iterator = agent.getList();
+// console.log(iterator.next())
+// expect(iterator).toBeDefined();
+// });
+//
+// });
+//
+// });
diff --git a/packages/vfs/ref/di/extra/stream.ts b/packages/vfs/ref/di/extra/stream.ts
new file mode 100644
index 00000000..a6a2084d
--- /dev/null
+++ b/packages/vfs/ref/di/extra/stream.ts
@@ -0,0 +1,30 @@
+// import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+//
+// /**
+// * Normalize the result { ok: 1, result: '', message: '' }
+// * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+// */
+// export function stream() {
+// return decorateClassMember(new InjectAttribute());
+// }
+//
+// export class InjectAttribute implements IAttribute, IInterceptor {
+//
+// constructor() {
+// }
+//
+// beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+// return true;
+// }
+//
+// getInterceptor(): IInterceptor {
+// return this;
+// }
+//
+// intercept(invocation: IInvocation, parameters: ArrayLike): any {
+// console.log('generator')
+// const value = invocation.invoke(parameters);
+// return value;
+// }
+//
+// }
diff --git a/packages/vfs/ref/di/extra/success.spec.ts b/packages/vfs/ref/di/extra/success.spec.ts
new file mode 100644
index 00000000..c5a79d28
--- /dev/null
+++ b/packages/vfs/ref/di/extra/success.spec.ts
@@ -0,0 +1,47 @@
+import { agent } from '../agent'
+import { success } from './success';
+
+@agent()
+class TestSuccessAgentClass {
+
+ bool: boolean = false;
+
+ @success('bool', true)
+ testBool(): any {
+ return 1102
+ }
+
+ @success('bool', true)
+ testBoolNotSatisfy(): any {
+ throw new Error('december')
+ }
+
+}
+
+describe('@success', () => {
+
+ describe('# should not', () => {
+
+ it('change bool value when throw', () => {
+ const successAgent = new TestSuccessAgentClass();
+ expect(successAgent.bool).toEqual(false);
+ expect(() => {
+ successAgent.testBoolNotSatisfy()
+ }).toThrowError('december');
+ expect(successAgent.bool).toEqual(false);
+ });
+
+ });
+
+ describe('# should able to', () => {
+
+ it('change bool value after success called', () => {
+ const successAgent = new TestSuccessAgentClass();
+ expect(successAgent.bool).toEqual(false);
+ expect(successAgent.testBool()).toBeDefined();
+ expect(successAgent.bool).toEqual(true);
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/success.ts b/packages/vfs/ref/di/extra/success.ts
new file mode 100644
index 00000000..b93415b4
--- /dev/null
+++ b/packages/vfs/ref/di/extra/success.ts
@@ -0,0 +1,36 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+
+/**
+ * Define a prerequisite
+ * @param key
+ * @param value
+ * @returns {(target:any, propertyKey:string, descriptor:PropertyDescriptor)=>undefined}
+ */
+export function success(key: string, value: any) {
+ return decorateClassMember(new SuccessAttribute(key, value));
+}
+
+/**
+ * PrerequisiteAttribute
+ */
+export class SuccessAttribute implements IAttribute, IInterceptor {
+ constructor(private _key: string, private _value: any) {}
+ get key(): string {
+ return this._key;
+ }
+ get value(): boolean {
+ return this._value;
+ }
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ const result = invocation.invoke(parameters);
+ // debug(`SuccessAttribute updating target value ${this.key}='${this.value}'`);
+ Reflect.set(invocation.target, this.key, this.value);
+ return result;
+ }
+}
diff --git a/packages/vfs/ref/di/extra/timestamp.spec.ts b/packages/vfs/ref/di/extra/timestamp.spec.ts
new file mode 100644
index 00000000..4fe080f3
--- /dev/null
+++ b/packages/vfs/ref/di/extra/timestamp.spec.ts
@@ -0,0 +1,81 @@
+import { agent } from '../agent'
+import { timestamp } from './timestamp';
+
+@agent()
+class TestTimestampAgentClass {
+
+ @timestamp()
+ name: string;
+
+ homepage: string;
+
+ @timestamp()
+ get activated(): boolean {
+ return this._activated;
+ }
+
+ set activated(value) {
+ this._activated = value
+ }
+
+ get untimestamp(): boolean {
+ return this._activated;
+ }
+
+ set untimestamp(value) {
+ this._activated = value
+ }
+
+ timestamp: number;
+
+ private _activated: boolean = true;
+ private _status: boolean = this._activated;
+
+}
+
+describe('@timestamp', () => {
+
+ describe('# should not', () => {
+
+ it('read timestamp of changing non-timestamp field', () => {
+ const timestampAgent = new TestTimestampAgentClass();
+ timestampAgent.homepage = 'https://github.com/agentframework/agentframework';
+ expect(timestampAgent.timestamp).toBeUndefined();
+ expect(timestampAgent.homepage).toEqual('https://github.com/agentframework/agentframework');
+ });
+
+ it('read timestamp of changing non-timestamp getter/setter', () => {
+ const timestampAgent = new TestTimestampAgentClass();
+ timestampAgent.untimestamp = true;
+ expect(timestampAgent.timestamp).toBeUndefined();
+ expect(timestampAgent.untimestamp).toEqual(true);
+ });
+
+ it('read timestamp of changing index field', () => {
+ const timestampAgent = new TestTimestampAgentClass();
+ timestampAgent[0] = 'agentframework';
+ expect(timestampAgent.timestamp).toBeUndefined();
+ expect(timestampAgent[0]).toEqual('agentframework');
+ });
+
+ });
+
+ describe('# should able to', () => {
+
+ it('read timestamp of last value changes', () => {
+ const timestampAgent = new TestTimestampAgentClass();
+ timestampAgent.name = 'Ling Zhang';
+ expect(timestampAgent.timestamp).toBeDefined();
+ expect(timestampAgent.name).toEqual('Ling Zhang');
+ });
+
+ it('read timestamp of changing getter/setter', () => {
+ const timestampAgent = new TestTimestampAgentClass();
+ timestampAgent.activated = true;
+ expect(timestampAgent.timestamp).toBeDefined();
+ expect(timestampAgent.activated).toEqual(true);
+ });
+
+ });
+
+});
diff --git a/packages/vfs/ref/di/extra/timestamp.ts b/packages/vfs/ref/di/extra/timestamp.ts
new file mode 100644
index 00000000..be850d1f
--- /dev/null
+++ b/packages/vfs/ref/di/extra/timestamp.ts
@@ -0,0 +1,25 @@
+import { IAttribute, IInterceptor, IInvocation, decorateClassMember } from '../core';
+
+/**
+ * Normalize the result { ok: 1, result: '', message: '' }
+ * @returns {(target:Object, propertyKey:(string|symbol), descriptor?:PropertyDescriptor)=>void}
+ */
+export function timestamp() {
+ return decorateClassMember(new TimestampAttribute());
+}
+
+export class TimestampAttribute implements IAttribute, IInterceptor {
+ constructor() {}
+ beforeDecorate(target: Object | Function, targetKey?: string | symbol, descriptor?: PropertyDescriptor): boolean {
+ return true;
+ }
+ getInterceptor(): IInterceptor {
+ return this;
+ }
+ intercept(invocation: IInvocation, parameters: ArrayLike): any {
+ const value = invocation.invoke(parameters);
+ // update timestamp field with current datetime
+ Reflect.set(invocation.target, 'timestamp', Date.now());
+ return value;
+ }
+}
diff --git a/packages/vfs/ref/di/index.ts b/packages/vfs/ref/di/index.ts
new file mode 100644
index 00000000..d3e6edf6
--- /dev/null
+++ b/packages/vfs/ref/di/index.ts
@@ -0,0 +1,16 @@
+export {
+ IAttribute,
+ IBeforeDecorateAttribute,
+ IInterceptor,
+ IInvocation,
+ Reflection,
+ decorateClass,
+ decorateClassMember,
+ decorateClassMethod,
+ decorateClassProperty,
+ Metadata
+} from './core'
+
+export { agent, Agent, AgentAttribute } from './agent'
+export { prerequisite, success, failure, normalize, timestamp, cache, conditional, inject, ready } from './extra'
+export { Domain, IDomain } from './domain'
diff --git a/packages/vfs/ref/fs/append.ts b/packages/vfs/ref/fs/append.ts
new file mode 100644
index 00000000..f81acfb6
--- /dev/null
+++ b/packages/vfs/ref/fs/append.ts
@@ -0,0 +1,53 @@
+import * as fs from 'fs';
+const Q = require('q');
+import { sync as writeSync, async as writeASync } from './write';
+import { validateArgument, validateOptions } from './utils/validate';
+export interface Options {
+ mode: string;
+ encoding?: string;
+ flag?: string;
+}
+export function validateInput(methodName: string, path: string, data: any, options?: Options) {
+ const methodSignature = methodName + '(path, data, [options])';
+ validateArgument(methodSignature, 'path', path, ['string']);
+ validateArgument(methodSignature, 'data', data, ['string', 'buffer']);
+ validateOptions(methodSignature, 'options', options, {
+ mode: ['string', 'number']
+ });
+}
+// ---------------------------------------------------------
+// SYNC
+// ---------------------------------------------------------
+export function sync(path: string, data: any, options: Options): void {
+ try {
+ fs.appendFileSync(path, data, options ? { encoding: options.encoding, mode: options.mode as string } : {});
+ } catch (err) {
+ if (err.code === 'ENOENT') {
+ // Parent directory doesn't exist, so just pass the task to `write`,
+ // which will create the folder and file.
+ writeSync(path, data, options);
+ } else {
+ throw err;
+ }
+ }
+}
+
+// ---------------------------------------------------------
+// ASYNC
+// ---------------------------------------------------------
+const promisedAppendFile = Q.denodeify(fs.appendFile);
+export function async(path: string, data: string | Buffer | Object, options?: Options): Promise {
+ return new Promise((resolve, reject) => {
+ promisedAppendFile(path, data, options)
+ .then(resolve)
+ .catch((err: any) => {
+ if (err.code === 'ENOENT') {
+ // Parent directory doesn't exist, so just pass the task to `write`,
+ // which will create the folder and file.
+ writeASync(path, data, options).then(resolve, reject);
+ } else {
+ reject(err);
+ }
+ });
+ });
+}
diff --git a/packages/vfs/ref/fs/copy.ts b/packages/vfs/ref/fs/copy.ts
new file mode 100644
index 00000000..117a6770
--- /dev/null
+++ b/packages/vfs/ref/fs/copy.ts
@@ -0,0 +1,619 @@
+import * as pathUtil from "path";
+import * as fs from 'fs';
+import { symlinkSync, readFileSync, createReadStream, createWriteStream } from 'fs';
+import * as mkdirp from 'mkdirp';
+
+import { sync as existsSync, async as existsASync } from './exists';
+import { create as matcher } from './utils/matcher';
+import { normalizeFileMode as fileMode } from './utils/mode';
+import { sync as treeWalkerSync } from './utils/tree_walker';
+import { validateArgument, validateOptions } from './utils/validate';
+import { sync as writeSync } from './write';
+import { ErrDestinationExists, ErrDoesntExists } from './errors';
+import { INode, ENodeType, IWriteOptions, ECopyFlags, ENodeOperationStatus, EError, ErrnoException, EInspectFlags, IProcessingNode, ICopyOptions, EResolveMode, IConflictSettings, EResolve, TCopyResult, INodeReport } from './interfaces';
+import { createItem } from './inspect';
+import { sync as rmSync } from './remove';
+import { promisify } from './promisify';
+import { async as iteratorAsync } from './iterator';
+import { ArrayIterator } from '@xblox/core/iterator';
+
+const promisedSymlink = promisify(fs.symlink);
+const promisedReadlink = promisify(fs.readlink);
+const promisedUnlink = promisify(fs.unlink);
+const promisedMkdirp = promisify(mkdirp);
+
+const progress = require('progress-stream');
+const throttle = require('throttle');
+
+const CPROGRESS_THRESHOLD = 1048576 * 5; // minimum file size threshold to use write progress = 5MB
+
+export function validateInput(methodName: string, from: string, to: string, options?: ICopyOptions): void {
+ const methodSignature = methodName + '(from, to, [options])';
+ validateArgument(methodSignature, 'from', from, ['string']);
+ validateArgument(methodSignature, 'to', to, ['string']);
+ validateOptions(methodSignature, 'options', options, {
+ overwrite: ['boolean'],
+ matching: ['string', 'array of string'],
+ progress: ['function'],
+ writeProgress: ['function'],
+ conflictCallback: ['function'],
+ conflictSettings: ['object'],
+ throttel: ['number'],
+ debug: ['boolean'],
+ flags: ['number']
+ });
+};
+const parseOptions = (options: any | null, from: string): ICopyOptions => {
+ const opts: ICopyOptions = options || {} as ICopyOptions;
+ const parsedOptions: ICopyOptions = {};
+ parsedOptions.overwrite = opts.overwrite;
+ parsedOptions.progress = opts.progress;
+ parsedOptions.writeProgress = opts.writeProgress;
+ parsedOptions.conflictCallback = opts.conflictCallback;
+ parsedOptions.conflictSettings = opts.conflictSettings;
+ parsedOptions.debug = opts.debug;
+ parsedOptions.throttel = opts.throttel;
+ parsedOptions.flags = opts.flags || 0;
+ if (!opts.filter) {
+ if (opts.matching) {
+ parsedOptions.filter = matcher(from, opts.matching);
+ } else {
+ parsedOptions.filter = () => { return true; };
+ }
+ }
+ return parsedOptions;
+};
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+const checksBeforeCopyingSync = (from: string, to: string, options?: ICopyOptions) => {
+ if (!existsSync(from)) {
+ throw ErrDoesntExists(from);
+ }
+
+ if (existsSync(to) && !options.overwrite) {
+ throw ErrDestinationExists(to);
+ }
+};
+
+async function copyFileSyncWithProgress(from: string, to: string, options?: ICopyOptions) {
+ return new Promise((resolve, reject) => {
+ const started = Date.now();
+ let cbCalled = false;
+ let elapsed = Date.now();
+ let speed = 0;
+ let done = (err?: any) => {
+ if (!cbCalled) {
+ cbCalled = true;
+ resolve();
+ }
+ };
+ const rd = createReadStream(from).
+ on("error", (err: Error) => done(err));
+
+ const str = progress({
+ length: fs.statSync(from).size,
+ time: 100
+ }).on('progress', (e: any) => {
+ elapsed = (Date.now() - started) / 1000;
+ speed = e.transferred / elapsed;
+ options.writeProgress(from, e.transferred, e.length);
+ });
+
+ const wr = createWriteStream(to);
+ wr.on("error", (err: Error) => done(err));
+ wr.on("close", done);
+
+ rd.pipe(str).pipe(wr);
+ });
+};
+
+async function copyFileSync(from: string, to: string, mode: string, options?: ICopyOptions) {
+ const data = readFileSync(from);
+ const writeOptions: IWriteOptions = {
+ mode: mode
+ };
+ if (options && options.writeProgress) {
+ await copyFileSyncWithProgress(from, to, options);
+ } else {
+ writeSync(to, data, writeOptions);
+ }
+};
+const copySymlinkSync = (from: string, to: string) => {
+ const symlinkPointsAt = fs.readlinkSync(from);
+ try {
+ symlinkSync(symlinkPointsAt, to);
+ } catch (err) {
+ // There is already file/symlink with this name on destination location.
+ // Must erase it manually, otherwise system won't allow us to place symlink there.
+ if (err.code === 'EEXIST') {
+ fs.unlinkSync(to);
+ // Retry...
+ fs.symlinkSync(symlinkPointsAt, to);
+ } else {
+ throw err;
+ }
+ }
+};
+
+async function copyItemSync(from: string, inspectData: INode, to: string, options: ICopyOptions) {
+ const mode: string = fileMode(inspectData.mode);
+ if (inspectData.type === ENodeType.DIR) {
+ mkdirp.sync(to, { mode: parseInt(mode, 8), fs: null });
+ } else if (inspectData.type === ENodeType.FILE) {
+ await copyFileSync(from, to, mode, options);
+ } else if (inspectData.type === ENodeType.SYMLINK) {
+ copySymlinkSync(from, to);
+ }
+};
+export function sync(from: string, to: string, options?: ICopyOptions): void {
+ const opts = parseOptions(options, from);
+ checksBeforeCopyingSync(from, to, opts);
+ let nodes: IProcessingNode[] = [];
+ let sizeTotal = 0;
+ if (options && options.flags & ECopyFlags.EMPTY) {
+ const dstStat = fs.statSync(to);
+ if (dstStat.isDirectory()) {
+ rmSync(to);
+ }
+ }
+
+ const visitor = (path: string, inspectData: INode) => {
+ if (opts.filter(path)) {
+ nodes.push({
+ path: path,
+ item: inspectData,
+ dst: pathUtil.resolve(to, pathUtil.relative(from, path))
+ });
+ sizeTotal += inspectData.size;
+ }
+ };
+
+ treeWalkerSync(from, {
+ inspectOptions: {
+ mode: true,
+ symlinks: true
+ }
+ }, visitor);
+
+ Promise.all(nodes.map(async (item, current) => {
+ await copyItemSync(item.path, item.item, item.dst, options);
+ if (opts.progress) {
+ opts.progress(item.path, current, nodes.length, item.item);
+ }
+ }));
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+
+/**
+ *
+ *
+ * @param {string} from
+ * @param {string} to
+ * @param {ICopyOptions} opts
+ * @returns {(Promise)}
+ */
+const checkAsync = (from: string, to: string, opts: ICopyOptions): Promise => {
+ return existsASync(from)
+ .then(srcPathExists => {
+ if (!srcPathExists) {
+ throw ErrDoesntExists(from);
+ } else {
+ return existsASync(to);
+ }
+ })
+ .then(destPathExists => {
+ if (destPathExists) {
+ if (opts.conflictSettings) {
+ return Promise.resolve(opts.conflictSettings);
+ }
+ if (opts.conflictCallback) {
+ const promise = opts.conflictCallback(to, createItem(to), EError.EXISTS);
+ promise.then((settings: IConflictSettings) => {
+ settings.error = EError.EXISTS;
+ });
+ return promise;
+ }
+ if (!opts.overwrite) {
+ throw ErrDestinationExists(to);
+ }
+ }
+ });
+};
+
+const copyFileAsync = (from: string, to: string, mode: any, options?: ICopyOptions, retriedAttempt?: boolean) => {
+ return new Promise((resolve, reject) => {
+ const readStream = fs.createReadStream(from);
+ const writeStream = fs.createWriteStream(to, { mode: mode });
+ readStream.on('error', reject);
+ writeStream.on('error', (err: ErrnoException) => {
+ const toDirPath = pathUtil.dirname(to);
+ // Force read stream to close, since write stream errored
+ // read stream serves us no purpose.
+ readStream.resume();
+ if (err.code === EError.NOEXISTS && retriedAttempt === undefined) {
+ // Some parent directory doesn't exits. Create it and retry.
+ promisedMkdirp(toDirPath, null).then(() => {
+ // Make retry attempt only once to prevent vicious infinite loop
+ // (when for some obscure reason I/O will keep returning ENOENT error).
+ // Passing retriedAttempt = true.
+ copyFileAsync(from, to, mode, null, true)
+ .then(resolve)
+ .catch(reject);
+ });
+ } else {
+ reject(err);
+ }
+ });
+
+ writeStream.on('finish', () => {
+ // feature: preserve times
+ if (options && options.flags & ECopyFlags.PRESERVE_TIMES) {
+ const sourceStat = fs.statSync(from);
+ fs.open(to, 'w', (err: ErrnoException, fd: number) => {
+ if (err) { throw err; };
+ fs.futimes(fd, sourceStat.atime, sourceStat.mtime, (err) => {
+ if (err) {
+ throw err;
+ };
+ fs.close(fd);
+ resolve();
+ });
+ });
+ } else {
+ resolve();
+ }
+ });
+
+ const size = fs.statSync(from).size;
+ let progressStream = null;
+ if (options && options.writeProgress && size > CPROGRESS_THRESHOLD) {
+ progressStream = progress({
+ length: fs.statSync(from).size,
+ time: 100 // call progress each 100 ms
+ });
+ let elapsed = Date.now();
+ let speed = 0;
+ const started = Date.now();
+ progressStream.on('progress', (e: any) => {
+ elapsed = (Date.now() - started) / 1000;
+ speed = e.transferred / elapsed;
+ options.writeProgress(from, e.transferred, e.length);
+ if (options.debug) {
+ console.log('write ' + from + ' (' + e.transferred + ' of ' + e.length);
+ }
+ });
+ if (options.throttel) {
+ readStream.pipe(progressStream).pipe(new throttle(options.throttel)).pipe(writeStream);
+ } else {
+ readStream.pipe(progressStream).pipe(writeStream);
+ }
+ } else {
+ if (options && options.debug) {
+ console.log('write ' + from + ' to ' + to);
+ }
+ readStream.pipe(writeStream);
+ }
+ });
+};
+export function copySymlinkAsync(from: string, to: string) {
+ return promisedReadlink(from)
+ .then((symlinkPointsAt: string) => {
+ return new Promise((resolve, reject) => {
+ promisedSymlink(symlinkPointsAt, to, null, null)
+ .then(resolve)
+ .catch((err: ErrnoException) => {
+ if (err.code === EError.EXISTS) {
+ // There is already file/symlink with this name on destination location.
+ // Must erase it manually, otherwise system won't allow us to place symlink there.
+ promisedUnlink(to, null)
+ // Retry...
+ .then(() => { return promisedSymlink(symlinkPointsAt, to, null, null); })
+ .then(resolve, reject);
+ } else {
+ reject(err);
+ }
+ });
+ });
+ });
+};
+
+const copyItemAsync = (from: string, inspectData: INode, to: string, options: ICopyOptions): Promise => {
+ const mode = fileMode(inspectData.mode);
+ if (inspectData.type === ENodeType.DIR) {
+ return promisedMkdirp(to, { mode: mode });
+ } else if (inspectData.type === ENodeType.FILE) {
+ return copyFileAsync(from, to, mode, options);
+ } else if (inspectData.type === ENodeType.SYMLINK) {
+ return copySymlinkAsync(from, to);
+ }
+ // EInspectItemType.OTHER
+ return Promise.resolve();
+};
+// handle user side setting "THROW" and non enum values (null)
+const onConflict = (from: string, to: string, options: ICopyOptions, settings: IConflictSettings): EResolveMode | undefined => {
+ switch (settings.overwrite) {
+ case EResolveMode.THROW: {
+ throw ErrDestinationExists(to);
+ }
+ case EResolveMode.OVERWRITE:
+ case EResolveMode.APPEND:
+ case EResolveMode.IF_NEWER:
+ case EResolveMode.ABORT:
+ case EResolveMode.IF_SIZE_DIFFERS:
+ case EResolveMode.SKIP: {
+ return settings.overwrite;
+ }
+ }
+ return undefined;
+};
+
+export function resolveConflict(from: string, to: string, options: ICopyOptions, resolveMode: EResolveMode): boolean {
+ if (resolveMode === undefined) {
+ return true;
+ }
+ const src = createItem(from);
+ const dst = createItem(to);
+ if (resolveMode === EResolveMode.SKIP) {
+ return false;
+ } else if (resolveMode === EResolveMode.IF_NEWER) {
+ if (src.type === ENodeType.DIR && dst.type === ENodeType.DIR) {
+ return true;
+ }
+ if (dst.modifyTime.getTime() > src.modifyTime.getTime()) {
+ return false;
+ }
+ } else if (resolveMode === EResolveMode.IF_SIZE_DIFFERS) {
+ // @TODO : not implemented: copy EInspectItemType.DIR with ECopyResolveMode.IF_SIZE_DIFFERS
+ if (src.type === ENodeType.DIR && dst.type === ENodeType.DIR) {
+ return true;
+ } else if (src.type === ENodeType.FILE && dst.type === ENodeType.FILE) {
+ if (src.size === dst.size) {
+ return false;
+ }
+ }
+ } else if (resolveMode === EResolveMode.OVERWRITE) {
+ return true;
+ } else if (resolveMode === EResolveMode.ABORT) {
+ return false;
+ }
+};
+
+function isDone(nodes: IProcessingNode[]) {
+ let done = true;
+ nodes.forEach((element: IProcessingNode) => {
+ if (element.status !== ENodeOperationStatus.DONE) {
+ done = false;
+ }
+ });
+ return done;
+}
+/**
+ * A callback for treeWalkerStream. This is called when a node has been found.
+ *
+ * @param {string} from
+ * @param {string} to
+ * @param {*} vars
+ * @param {{ path: string, item: INode }} item
+ * @returns {Promise}
+ */
+async function visitor(from: string, to: string, vars: IVisitorArgs, item: IProcessingNode): Promise {
+ const options = vars.options;
+ let rel: string;
+ let destPath: string;
+ if (!item) {
+ return;
+ }
+ rel = pathUtil.relative(from, item.path);
+ destPath = pathUtil.resolve(to, rel);
+
+ item.status = ENodeOperationStatus.PROCESSING;
+ const done = () => {
+ item.status = ENodeOperationStatus.DONE;
+ if (isDone(vars.nodes)) {
+ return vars.resolve(vars.result);
+ }
+ };
+ if (isDone(vars.nodes)) {
+ return vars.resolve(vars.result);
+ }
+ vars.filesInProgress += 1;
+ // our main function after sanity checks
+ const checked = (subResolveSettings: IConflictSettings) => {
+ item.status = ENodeOperationStatus.CHECKED;
+ // feature : report
+ if (subResolveSettings && options && options.flags && options.flags & ECopyFlags.REPORT) {
+ (vars.result as INodeReport[]).push({
+ error: subResolveSettings.error,
+ node: item,
+ resolved: subResolveSettings
+ } as INodeReport);
+ }
+ if (subResolveSettings) {
+ // if the first resolve callback returned an individual resolve settings "THIS",
+ // ask the user again with the same item
+ let always = subResolveSettings.mode === EResolve.ALWAYS;
+ if (always) {
+ options.conflictSettings = subResolveSettings;
+ }
+ let overwriteMode = subResolveSettings.overwrite;
+ overwriteMode = onConflict(item.path, destPath, options, subResolveSettings);
+
+ if (overwriteMode === EResolveMode.ABORT) {
+ vars.abort = true;
+ }
+ if (vars.abort) {
+ return;
+ }
+
+ if (!resolveConflict(item.path, destPath, options, overwriteMode)) {
+ done();
+ return;
+ }
+
+ }
+ item.status = ENodeOperationStatus.PROCESS;
+ copyItemAsync(item.path, item.item, destPath, options).then(() => {
+ vars.filesInProgress -= 1;
+ if (options.progress) {
+ if (options.progress(item.path, vars.filesInProgress, vars.filesInProgress, item.item) === false) {
+ vars.abort = true;
+ return vars.resolve();
+ }
+ }
+ done();
+ }).catch((err: ErrnoException) => {
+ if (options && options.conflictCallback) {
+ if (err.code === EError.PERMISSION || err.code === EError.NOEXISTS) {
+ options.conflictCallback(item.path, createItem(destPath), err.code).then((errorResolveSettings: IConflictSettings) => {
+ // the user has set the conflict resolver to always, so we use the last one
+ if (vars.onCopyErrorResolveSettings) {
+ errorResolveSettings = vars.onCopyErrorResolveSettings;
+ }
+ // user said use this settings always, we track and use this last setting from now on
+ if (errorResolveSettings.mode === EResolve.ALWAYS && !vars.onCopyErrorResolveSettings) {
+ vars.onCopyErrorResolveSettings = errorResolveSettings;
+ }
+
+ if (errorResolveSettings.overwrite === EResolveMode.ABORT) {
+ vars.abort = true;
+ return vars.resolve();
+ }
+ if (errorResolveSettings.overwrite === EResolveMode.THROW) {
+ vars.abort = true;
+ return vars.reject(err);
+ }
+ if (errorResolveSettings.overwrite === EResolveMode.SKIP) {
+ vars.filesInProgress -= 1;
+ }
+
+ // user error, should never happen, unintended
+ if (errorResolveSettings.overwrite === EResolveMode.IF_NEWER ||
+ errorResolveSettings.overwrite === EResolveMode.IF_SIZE_DIFFERS ||
+ errorResolveSettings.overwrite === EResolveMode.OVERWRITE) {
+ vars.reject(new ErrnoException('settings make no sense : errorResolveSettings.overwrite = ' + errorResolveSettings.overwrite));
+ }
+ });
+ }
+ }
+ vars.reject(err);
+ });
+ };
+ return checkAsync(item.path, destPath, options).then(checked);
+}
+function next(nodes: IProcessingNode[]): IProcessingNode {
+ for (let i = 0; i < nodes.length; i++) {
+ if (nodes[i].status === ENodeOperationStatus.COLLECTED) {
+ return nodes[i];
+ }
+ }
+ return null;
+}
+
+interface IVisitorArgs {
+ resolve: Function;
+ reject: Function;
+ abort: boolean;
+ filesInProgress: number;
+ resolveSettings: IConflictSettings;
+ options: ICopyOptions;
+ result: TCopyResult;
+ nodes: IProcessingNode[];
+ onCopyErrorResolveSettings: IConflictSettings;
+}
+
+/**
+ * Final async copy function.
+ * @export
+ * @param {string} from
+ * @param {string} to
+ * @param {ICopyOptions} [options]
+ * @returns
+ */
+export function async(from: string, to: string, options?: ICopyOptions): Promise {
+ options = parseOptions(options, from);
+ return new Promise((resolve, reject) => {
+ checkAsync(from, to, options).then((resolver: IConflictSettings) => {
+ if (!resolver) {
+ resolver = options.conflictSettings || {
+ mode: EResolve.THIS,
+ overwrite: EResolveMode.OVERWRITE
+ };
+ } else {
+ if (resolver.mode === EResolve.ALWAYS) {
+ options.conflictSettings = resolver;
+ }
+ }
+ let overwriteMode = resolver.overwrite;
+ let result: TCopyResult = void 0;
+
+ if (options && options.flags && options.flags & ECopyFlags.REPORT) {
+ result = [];
+ }
+
+ // call onConflict to eventually throw an error
+ overwriteMode = onConflict(from, to, options, resolver);
+
+ // now evaluate the copy conflict settings and eventually abort
+ if (options && options.conflictSettings && !resolveConflict(from, to, options, overwriteMode)) {
+ return resolve();
+ }
+ // feature: clean before
+ if (options && options.flags & ECopyFlags.EMPTY) {
+ const dstStat = fs.statSync(to);
+ if (dstStat.isDirectory()) {
+ rmSync(to);
+ }
+ }
+ // walker variables
+ const visitorArgs: IVisitorArgs = {
+ resolve: resolve,
+ reject: reject,
+ abort: false,
+ filesInProgress: 0,
+ resolveSettings: resolver,
+ options: options,
+ result: result,
+ nodes: [],
+ onCopyErrorResolveSettings: null
+ };
+ const nodes = visitorArgs.nodes;
+ // a function called when the treeWalkerStream or visitor has been finished
+ const process = function () {
+ visitorArgs.nodes = nodes;
+ if (isDone(nodes)) {
+ return resolve(result);
+ }
+ if (nodes.length) {
+ const item = next(nodes);
+ if (item) {
+ visitor(item.path, item.dst, visitorArgs, item).then(process);
+ }
+ }
+ };
+
+ let flags: EInspectFlags = EInspectFlags.MODE;
+ if (options && options.flags && options.flags & ECopyFlags.FOLLOW_SYMLINKS) {
+ flags |= EInspectFlags.SYMLINKS;
+ }
+ iteratorAsync(from, {
+ filter: options.filter,
+ flags: flags
+ }).then((it: ArrayIterator) => {
+ let node: IProcessingNode = null;
+ while (node = it.next()) {
+ nodes.push({
+ path: node.path,
+ item: node.item,
+ dst: pathUtil.resolve(to, pathUtil.relative(from, node.path)),
+ status: ENodeOperationStatus.COLLECTED
+ });
+ }
+ process();
+ });
+ }).catch(reject);
+ });
+};
diff --git a/packages/vfs/ref/fs/dir.ts b/packages/vfs/ref/fs/dir.ts
new file mode 100644
index 00000000..2ff6f35f
--- /dev/null
+++ b/packages/vfs/ref/fs/dir.ts
@@ -0,0 +1,176 @@
+import * as pathUtil from 'path';
+import { Stats, stat, statSync, chmod, chmodSync, readdirSync, readdir } from 'fs';
+import * as rimraf from 'rimraf';
+import { normalizeFileMode as modeUtil } from './utils/mode';
+import { validateArgument, validateOptions } from './utils/validate';
+import { ErrNoDirectory } from './errors';
+import { EError } from './interfaces';
+import { promisify } from './promisify';
+import * as mkdirp from 'mkdirp';
+
+export interface IOptions {
+ empty?: boolean;
+ mode?: number | string;
+}
+
+export const validateInput = function (methodName: string, path: string, options?: IOptions) {
+ let methodSignature = methodName + '(path, [criteria])';
+ validateArgument(methodSignature, 'path', path, ['string']);
+ validateOptions(methodSignature, 'criteria', options, {
+ empty: ['boolean'],
+ mode: ['string', 'number']
+ });
+};
+
+const defaults = (options?: IOptions): IOptions => {
+ const result = options || {};
+ if (typeof result.empty !== 'boolean') {
+ result.empty = false;
+ }
+ if (result.mode !== undefined) {
+ result.mode = modeUtil(result.mode);
+ }
+ return result;
+};
+
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+const dirStatsSync = (path: string): Stats => {
+ let stat: Stats;
+ try {
+ stat = statSync(path);
+ } catch (err) {
+ // Detection if path already exists
+ if (err.code !== EError.NOEXISTS) {
+ throw err;
+ }
+ }
+
+ if (stat && !stat.isDirectory()) {
+ throw ErrNoDirectory(path);
+ }
+
+ return stat;
+};
+
+function mkdirSync(path: string, criteria: IOptions) {
+ mkdirp.sync(path, { mode: criteria.mode as number, fs: null });
+};
+
+function checkDirSync(path: string, stat: Stats, options: IOptions) {
+ const checkMode = function () {
+ const mode = modeUtil(stat.mode);
+ if (options.mode !== undefined && options.mode !== mode) {
+ chmodSync(path, options.mode as string);
+ }
+ };
+ const checkEmptiness = function () {
+ let list: string[];
+ if (options.empty) {
+ // Delete everything inside this directory
+ list = readdirSync(path);
+ list.forEach(function (filename) {
+ rimraf.sync(pathUtil.resolve(path, filename));
+ });
+ }
+ };
+ checkMode();
+ checkEmptiness();
+};
+
+export function sync(path: string, options?: IOptions) {
+ let criteria = defaults(options);
+ let stat = dirStatsSync(path);
+ if (stat) {
+ checkDirSync(path, stat, criteria);
+ } else {
+ mkdirSync(path, criteria);
+ }
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+
+const promisedStat = promisify(stat);
+const promisedChmod = promisify(chmod);
+const promisedReaddir = promisify(readdir);
+const promisedRimraf = promisify(rimraf);
+const promisedMkdirp = promisify(mkdirp);
+
+async function dirStatAsync(path: string): Promise {
+ return new Promise((resolve, reject) => {
+ promisedStat(path)
+ .then(function (stat: any) {
+ if (stat.isDirectory()) {
+ resolve(stat);
+ } else {
+ reject(ErrNoDirectory(path));
+ }
+ })
+ .catch((err: any) => (err.code === EError.NOEXISTS ? resolve(undefined) : reject(err)));
+
+ });
+};
+
+// Delete all files and directores inside given directory
+function emptyAsync(path: string) {
+ return new Promise((resolve, reject) => {
+ promisedReaddir(path)
+ .then(function (list: any[]) {
+ const doOne = function (index: number) {
+ let subPath: string;
+ if (index === list.length) {
+ resolve();
+ } else {
+ subPath = pathUtil.resolve(path, list[index]);
+ promisedRimraf(subPath).then(function () {
+ doOne(index + 1);
+ });
+ }
+ };
+ doOne(0);
+ })
+ .catch(reject);
+ });
+};
+const checkMode = function (criteria: IOptions, stat: Stats, path: string): Promise {
+ const mode = modeUtil(stat.mode);
+ if (criteria.mode !== undefined && criteria.mode !== mode) {
+ return promisedChmod(path, criteria.mode);
+ }
+ return Promise.resolve(null);
+};
+
+const checkDirAsync = (path: string, stat: Stats, options: IOptions) => {
+ return new Promise((resolve, reject) => {
+ const checkEmptiness = function () {
+ if (options.empty) {
+ return emptyAsync(path);
+ }
+ return Promise.resolve();
+ };
+ checkMode(options, stat, path)
+ .then(checkEmptiness)
+ .then(resolve, reject);
+ });
+};
+
+const mkdirAsync = (path: string, criteria: IOptions): Promise => {
+ return promisedMkdirp(path, { mode: criteria.mode });
+};
+
+export function async(path: string, passedCriteria?: IOptions) {
+ const criteria = defaults(passedCriteria);
+ return new Promise((resolve, reject) => {
+ dirStatAsync(path)
+ .then((stat: Stats) => {
+ if (stat !== undefined) {
+ return checkDirAsync(path, stat, criteria);
+ }
+ return mkdirAsync(path, criteria);
+ })
+ .then(resolve, reject);
+ });
+}
diff --git a/packages/vfs/ref/fs/errors.ts b/packages/vfs/ref/fs/errors.ts
new file mode 100644
index 00000000..1235213e
--- /dev/null
+++ b/packages/vfs/ref/fs/errors.ts
@@ -0,0 +1,46 @@
+import { ErrnoException } from './interfaces';
+const errno = require('errno');
+
+Object.keys(errno.code).forEach(function (code) {
+ const e = errno.code[code];
+ exports[code] = (path: string) => {
+ let err = new Error(code + ', ' + e.description + (path ? ' \'' + path + '\'' : '')) as ErrnoException;
+ err.errno = e.errno;
+ err.code = code;
+ err.path = path;
+ return err;
+ };
+});
+
+export function ErrNoFileOrDir(path: string): Error {
+ return new Error("Can't remove " + path + ' The path is not file nor directory');
+};
+export function ErrCantDelete(path: string): Error {
+ return new Error("Can't remove " + path);
+};
+export function ErrNotFile(path: string): Error {
+ return new Error('Path ' + path + ' exists but is not a file.' +
+ ' Halting jetpack.file() call for safety reasons.');
+};
+export function ErrNoDirectory(path: string): Error {
+ return new Error('Path ' + path + ' exists but is not a directory.' +
+ ' Halting jetpack.dir() call for safety reasons.');
+};
+
+export function ErrDoesntExists(path: string): Error {
+ const err: any = new Error("Path to copy doesn't exist " + path);
+ err.code = 'ENOENT';
+ return err;
+};
+
+export function ErrDestinationExists(path: string): Error {
+ const err: any = new Error('Destination path already exists ' + path);
+ err.code = 'EEXIST';
+ return err;
+};
+
+export function ErrIsNotDirectory(path: string): Error {
+ const err = new ErrnoException('Path you want to find stuff in must be a directory ' + path);
+ err.code = 'ENOTDIR';
+ return err;
+};
diff --git a/packages/vfs/ref/fs/exists.ts b/packages/vfs/ref/fs/exists.ts
new file mode 100644
index 00000000..9a062a4c
--- /dev/null
+++ b/packages/vfs/ref/fs/exists.ts
@@ -0,0 +1,52 @@
+import { Stats, statSync, stat, lstat } from 'fs';
+import { validateArgument } from './utils/validate';
+import { ENodeType, ErrnoException } from './interfaces';
+
+export function validateInput(methodName: string, path: string) {
+ const methodSignature = methodName + '(path)';
+ validateArgument(methodSignature, 'path', path, ['string']);
+};
+
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+export function sync(path: string): boolean | string {
+ let stat: Stats;
+ try {
+ stat = statSync(path);
+ if (stat.isDirectory()) {
+ return 'dir';
+ } else if (stat.isFile()) {
+ return 'file';
+ }
+ return 'other';
+ } catch (err) {
+ if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') {
+ throw err;
+ }
+ }
+ return false;
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+export function async(path: string): Promise {
+ return new Promise ((resolve, reject) => {
+ lstat(path, (err: ErrnoException, stat: Stats) => {
+ if (err) {
+ if (err.code === 'ENOENT' || err.code === 'ENOTDIR') {
+ resolve(false);
+ } else {
+ reject(err);
+ }
+ } else if (stat.isDirectory()) {
+ resolve(ENodeType.DIR);
+ } else if (stat.isFile()) {
+ resolve(ENodeType.FILE);
+ } else {
+ resolve(ENodeType.OTHER);
+ }
+ });
+ });
+};
diff --git a/packages/vfs/ref/fs/file.ts b/packages/vfs/ref/fs/file.ts
new file mode 100644
index 00000000..1f04791b
--- /dev/null
+++ b/packages/vfs/ref/fs/file.ts
@@ -0,0 +1,167 @@
+import * as fs from 'fs';
+import { Stats } from 'fs';
+const Q = require('q');
+import { normalizeFileMode } from './utils/mode';
+import { validateArgument, validateOptions } from './utils/validate';
+import { sync as writeSync, async as writeASync } from './write';
+import { ErrNotFile } from './errors';
+import { EError } from './interfaces';
+
+const promisedStat = Q.denodeify(fs.stat);
+const promisedChmod = Q.denodeify(fs.chmod);
+
+export interface IOptions {
+ content: string | Buffer | Object | Array;
+ jsonIndent: number;
+ mode: string;
+}
+
+export function validateInput(methodName: string, path: string, options?: IOptions) {
+ const methodSignature = methodName + '(path, [criteria])';
+ validateArgument(methodSignature, 'path', path, ['string']);
+ validateOptions(methodSignature, 'criteria', options, {
+ content: ['string', 'buffer', 'object', 'array'],
+ jsonIndent: ['number'],
+ mode: ['string', 'number']
+ });
+};
+
+export function defaults(passedCriteria: IOptions | null): IOptions {
+ const criteria: any = passedCriteria || {};
+ if (criteria.mode !== undefined) {
+ criteria.mode = normalizeFileMode(criteria.mode);
+ }
+ return criteria;
+};
+
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+
+const isFile = (path: string): Stats => {
+ let stat: Stats;
+ try {
+ stat = fs.statSync(path);
+ } catch (err) {
+ // Detection if path exists
+ if (err.code !== EError.NOEXISTS) {
+ throw err;
+ }
+ }
+
+ if (stat && !stat.isFile()) {
+ throw ErrNotFile(path);
+ }
+
+ return stat;
+};
+
+const checkContent = function (path: string, mode: string, options: IOptions): boolean {
+ if (options.content !== undefined) {
+ writeSync(path, options.content, {
+ mode: mode,
+ jsonIndent: options.jsonIndent
+ });
+ return true;
+ }
+ return false;
+};
+
+const checkMode = function (path: string, mode: string, options: IOptions) {
+ if (options.mode !== undefined && options.mode !== mode) {
+ fs.chmodSync(path, options.mode);
+ }
+};
+
+const accept = (path: string, stat: Stats, options?: IOptions): void => {
+ const mode = normalizeFileMode(stat.mode);
+ if (!checkContent(path, mode, options)) {
+ checkMode(path, mode, options);
+ }
+};
+
+const touch = (path: string, options: IOptions): void => {
+ const content: string | Buffer | Object | Array = options.content !== undefined ? options.content : '';
+ writeSync(path, content, {
+ mode: options.mode,
+ jsonIndent: options.jsonIndent
+ });
+};
+
+export function sync(path: string, options: IOptions) {
+ options = defaults(options);
+ const stat: Stats = isFile(path);
+ if (stat !== undefined) {
+ accept(path, stat, options);
+ } else {
+ touch(path, options);
+ }
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+
+function isFileAsync(path: string): Promise {
+ return new Promise((resolve, reject) => {
+ promisedStat(path)
+ .then((stat: Stats) => {
+ if ((stat).isFile()) {
+ resolve(stat);
+ } else {
+ reject(ErrNotFile(path));
+ }
+ })
+ .catch((err: any) => (err.code === EError.NOEXISTS ? resolve(undefined) : reject(err)));
+ });
+};
+const checkModeAsync = (path: string, mode: string, options: IOptions) => {
+ if (options.mode !== undefined && options.mode !== mode) {
+ return promisedChmod(path, options.mode);
+ }
+ return undefined;
+};
+const checkContentAsync = (path: string, mode: string, options: IOptions) => {
+ return new Promise((resolve, reject) => {
+ if (options.content !== undefined) {
+ writeASync(path, options.content, {
+ mode: mode,
+ jsonIndent: options.jsonIndent
+ }).then(() => resolve(true))
+ .catch(reject);
+ } else {
+ resolve(false);
+ }
+ });
+};
+async function writeAsync(path: string, stat: Stats, options: IOptions): Promise {
+ const mode = normalizeFileMode(stat.mode);
+ return checkContentAsync(path, mode, options)
+ .then(contentReplaced => {
+ if (!contentReplaced) {
+ return checkModeAsync(path, mode, options);
+ }
+ return undefined;
+ });
+};
+
+const touchAsync = (path: string, options: IOptions) => {
+ return writeASync(path, options.content !== undefined ? options.content : '', {
+ mode: options.mode,
+ jsonIndent: options.jsonIndent
+ });
+};
+
+export async function async(path: string, options: IOptions) {
+ return new Promise((resolve, reject) => {
+ options = defaults(options);
+ isFileAsync(path)
+ .then((stat: Stats) => {
+ if (stat !== undefined) {
+ return writeAsync(path, stat, options);
+ }
+ return touchAsync(path, options);
+ })
+ .then(resolve, reject);
+ });
+};
diff --git a/packages/vfs/ref/fs/find.ts b/packages/vfs/ref/fs/find.ts
new file mode 100644
index 00000000..484671e7
--- /dev/null
+++ b/packages/vfs/ref/fs/find.ts
@@ -0,0 +1,121 @@
+import * as pathUtil from "path";
+import { sync as treeWalkerSync, stream as treeWalkerStream } from './utils/tree_walker';
+import { sync as inspectSync, async as inspectASync } from './inspect';
+import { create as matcher } from './utils/matcher';
+import { validateArgument, validateOptions } from './utils/validate';
+import { INode, ENodeType } from './interfaces';
+import { ErrDoesntExists, ErrIsNotDirectory } from './errors';
+
+export interface IOptions {
+ matching?: string[];
+ files?: boolean;
+ directories?: boolean;
+ recursive?: boolean;
+ cwd?: string;
+}
+export function validateInput(methodName: string, path: string, options?: IOptions): void {
+ const methodSignature = methodName + '([path], options)';
+ validateArgument(methodSignature, 'path', path, ['string']);
+ validateOptions(methodSignature, 'options', options, {
+ matching: ['string', 'array of string'],
+ files: ['boolean'],
+ directories: ['boolean'],
+ recursive: ['boolean']
+ });
+};
+
+const defaults = (options?: IOptions): IOptions => {
+ let opts = options || {} as IOptions;
+ // defaults:
+ if (opts.files === undefined) {
+ opts.files = true;
+ }
+ if (opts.directories === undefined) {
+ opts.directories = false;
+ }
+ if (opts.recursive === undefined) {
+ opts.recursive = true;
+ }
+ return opts;
+};
+
+const processFoundObjects = (foundObjects: any, cwd: string): string[] => {
+ return foundObjects.map((inspectObj: INode) => {
+ return pathUtil.relative(cwd, inspectObj.absolutePath);
+ });
+};
+
+
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+function findSync(path: string, options: IOptions): string[] {
+ const foundInspectObjects: INode[] = [];
+ const matchesAnyOfGlobs = matcher(path, options.matching);
+ treeWalkerSync(path, {
+ maxLevelsDeep: options.recursive ? Infinity : 1,
+ inspectOptions: {
+ absolutePath: true
+ }
+ }, (itemPath, item) => {
+ if (itemPath !== path && matchesAnyOfGlobs(itemPath)) {
+ if ((item.type === ENodeType.FILE && options.files === true)
+ || (item.type === ENodeType.DIR && options.directories === true)) {
+ foundInspectObjects.push(item);
+ }
+ }
+ });
+ return processFoundObjects(foundInspectObjects, options.cwd);
+};
+
+export function sync(path: string, options: IOptions): string[] {
+ const entryPointInspect = inspectSync(path);
+ if (entryPointInspect === undefined) {
+ throw ErrDoesntExists(path);
+ } else if (entryPointInspect.type !== 'dir') {
+ throw ErrIsNotDirectory(path);
+ }
+ return findSync(path, defaults(options));
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+
+function findAsync(path: string, options: IOptions): Promise {
+ return new Promise((resolve, reject) => {
+ const foundInspectObjects: INode[] = [];
+ const matchesAnyOfGlobs = matcher(path, options.matching);
+ const walker = treeWalkerStream(path, {
+ maxLevelsDeep: options.recursive ? Infinity : 1,
+ inspectOptions: {
+ absolutePath: true
+ }
+ }).on('readable', () => {
+ const data = walker.read();
+ let item: INode;
+ if (data && data.path !== path && matchesAnyOfGlobs(data.path)) {
+ item = data.item;
+ if ((item.type === ENodeType.FILE && options.files === true)
+ || (item.type === ENodeType.DIR && options.directories === true)) {
+ foundInspectObjects.push(item);
+ }
+ }
+ }).on('error', reject)
+ .on('end', () => {
+ resolve(processFoundObjects(foundInspectObjects, options.cwd));
+ });
+ });
+};
+
+export function async(path: string, options: IOptions): Promise {
+ return inspectASync(path)
+ .then(entryPointInspect => {
+ if (entryPointInspect === undefined) {
+ throw ErrDoesntExists(path);
+ } else if ((entryPointInspect as any).type !== ENodeType.DIR) {
+ throw ErrIsNotDirectory(path);
+ }
+ return findAsync(path, defaults(options));
+ });
+};
diff --git a/packages/vfs/ref/fs/imports.ts b/packages/vfs/ref/fs/imports.ts
new file mode 100644
index 00000000..1619985e
--- /dev/null
+++ b/packages/vfs/ref/fs/imports.ts
@@ -0,0 +1,8 @@
+const write_fs = require('write-file-atomic');
+export const file = {
+ write_atomic: write_fs
+};
+export const json = {
+ parse: JSON.parse,
+ serialize: JSON.stringify
+};
diff --git a/packages/vfs/ref/fs/inspect.ts b/packages/vfs/ref/fs/inspect.ts
new file mode 100644
index 00000000..7d6eaa2f
--- /dev/null
+++ b/packages/vfs/ref/fs/inspect.ts
@@ -0,0 +1,246 @@
+import { Stats, readlinkSync, statSync, lstatSync, stat, lstat, readlink, createReadStream, readFileSync, readdir, readdirSync } from 'fs';
+import { lookup as mime } from "mime";
+import * as pathUtil from "path";
+import { validateArgument, validateOptions } from './utils/validate';
+import { createHash } from 'crypto';
+import { ENodeType, INode, IInspectOptions } from './interfaces';
+const Q = require('q');
+import * as denodeify from 'denodeify';
+export const supportedChecksumAlgorithms: string[] = ['md5', 'sha1', 'sha256', 'sha512'];
+const promisedStat = denodeify(stat);
+const promisedLstat = denodeify(lstat);
+const promisedReadlink = denodeify(readlink);
+/*
+const _async = require('async');
+export async function size(item, ignoreRegEx?: boolean, callback?: any) {
+ return new Promise((resolve, reject) => {
+ let cb;
+ let ignoreRegExp;
+ if (!callback) {
+ cb = ignoreRegEx;
+ ignoreRegExp = null;
+ } else {
+ cb = callback;
+ ignoreRegExp = ignoreRegEx;
+ }
+
+ lstat(item, function lstat(e, stats) {
+ let total = !e ? (stats.size || 0) : 0;
+ if (!e && stats.isDirectory()) {
+ readdir(item, function readdir(err, list) {
+ if (err) { reject(err); }
+ _async.forEach(
+ list,
+ function iterate(dirItem, next) {
+ size(
+ pathUtil.join(item, dirItem),
+ ignoreRegExp,
+ function readSize(error, size) {
+ if (!error) { total += size; }
+ next(error);
+ }
+ );
+ },
+ function done(finalErr) {
+ resolve({ error: finalErr, total: total });
+ }
+ );
+ });
+ } else {
+ if (ignoreRegExp && ignoreRegExp.test(item)) {
+ total = 0;
+ }
+ resolve({ error: e, total: total });
+ }
+ });
+ });
+}
+export async function sizea(item, ignoreRegEx?: boolean, callback?: any) {
+ return new Promise((resolve, reject) => {
+ let cb;
+ let ignoreRegExp;
+ if (!callback) {
+ cb = ignoreRegEx;
+ ignoreRegExp = null;
+ } else {
+ cb = callback;
+ ignoreRegExp = ignoreRegEx;
+ }
+
+ const stats = lstatSync(item);
+ let total = (stats.size || 0);
+ if (stats.isDirectory()) {
+ const list = readdirSync(item);
+ _async.forEach(
+ list,
+ function iterate(dirItem, next) {
+ size(
+ pathUtil.join(item, dirItem),
+ ignoreRegExp,
+ function readSize(error, size) {
+ if (!error) { total += size; }
+ next(error);
+ }
+ );
+ },
+ function done(finalErr) {
+ resolve({ error: finalErr, total: total });
+ }
+ );
+ } else {
+ if (ignoreRegExp && ignoreRegExp.test(item)) {
+ total = 0;
+ }
+ return { total: total };
+ }
+ });
+}
+
+*/
+export function DefaultInspectOptions(): IInspectOptions {
+ return {
+ times: true,
+ mode: true
+ };
+}
+export function validateInput(methodName: string, path: string, options?: IInspectOptions): void {
+ const methodSignature: string = methodName + '(path, [options])';
+ validateArgument(methodSignature, 'path', path, ['string']);
+ validateOptions(methodSignature, 'options', options, {
+ checksum: ['string'],
+ mode: ['boolean'],
+ times: ['boolean'],
+ absolutePath: ['boolean'],
+ symlinks: ['boolean'],
+ size: 'number',
+ mime: 'string'
+ });
+
+ if (options && options.checksum !== undefined
+ && supportedChecksumAlgorithms.indexOf(options.checksum) === -1) {
+ throw new Error('Argument "options.checksum" passed to ' + methodSignature
+ + ' must have one of values: ' + supportedChecksumAlgorithms.join(', '));
+ }
+};
+
+const createInspectObj = (path: string, options: IInspectOptions, stat: Stats): INode => {
+ let obj: INode = {} as INode;
+ obj.name = pathUtil.basename(path);
+
+ if (stat.isFile()) {
+ obj.type = ENodeType.FILE;
+ obj.size = stat.size;
+ } else if (stat.isDirectory()) {
+ obj.type = ENodeType.DIR;
+ } else if (stat.isSymbolicLink()) {
+ obj.type = ENodeType.SYMLINK;
+ } else {
+ obj.type = ENodeType.OTHER;
+ }
+
+ if (options.mode) {
+ obj.mode = stat.mode;
+ }
+
+ if (options.mime) {
+ if (stat.isDirectory()) {
+ obj.mime = "inode/directory";
+ } else if (stat.isBlockDevice()) { obj.mime = "inode/blockdevice"; }
+ else if (stat.isCharacterDevice()) { obj.mime = "inode/chardevice"; }
+ else if (stat.isSymbolicLink()) { obj.mime = "inode/symlink"; }
+ else if (stat.isFIFO()) { obj.mime = "inode/fifo"; }
+ else if (stat.isSocket()) { obj.mime = "inode/socket"; }
+ else {
+ obj.mime = mime(path);
+ }
+ }
+
+ if (options.times) {
+ obj.accessTime = stat.atime;
+ obj.modifyTime = stat.mtime;
+ obj.changeTime = stat.ctime;
+ }
+
+ if (options.absolutePath) {
+ obj.absolutePath = path;
+ }
+ return obj;
+};
+export function createItem(path: string, options?: IInspectOptions): INode {
+ options = options || DefaultInspectOptions();
+ const stat = (options.symlinks ? lstatSync : statSync)(path);
+ return createInspectObj(path, options, stat);
+};
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+const fileChecksum = (path: string, algo: string): string => {
+ const hash = createHash(algo);
+ const data = readFileSync(path);
+ hash.update(data);
+ return hash.digest('hex');
+};
+
+const addExtraFieldsSync = (path: string, inspectObj: any, options: IInspectOptions): INode => {
+ if (inspectObj.type === ENodeType.FILE && options.checksum) {
+ inspectObj[options.checksum] = fileChecksum(path, options.checksum);
+ } else if (inspectObj.type === ENodeType.SYMLINK) {
+ inspectObj.pointsAt = readlinkSync(path);
+ }
+ return inspectObj;
+};
+
+export function sync(path: string, options?: IInspectOptions): INode {
+ let stat: Stats;
+ options = options || {} as IInspectOptions;
+ try {
+ stat = (options.symlinks ? lstatSync : statSync)(path);
+ } catch (err) {
+ // Detection if path exists
+ if (err.code === 'ENOENT') {
+ // Doesn't exist. Return undefined instead of throwing.
+ return undefined;
+ }
+ throw err;
+ }
+ return addExtraFieldsSync(path, createInspectObj(path, options, stat), options);
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+async function fileChecksumAsync(path: string, algo: string): Promise {
+ const deferred = Q.defer();
+ const hash = createHash(algo);
+ const s = createReadStream(path);
+ s.on('data', (data: string | Buffer) => hash.update(data));
+ s.on('end', () => deferred.resolve(hash.digest('hex')));
+ s.on('error', (e: Error) => deferred.reject(e));
+ return deferred.promise;
+};
+
+const addExtraFieldsAsync = (path: string, inspectObj: INode, options: IInspectOptions) => {
+ if (inspectObj.type === ENodeType.FILE && options.checksum) {
+ return fileChecksumAsync(path, options.checksum)
+ .then(checksum => {
+ (inspectObj as any)[options['checksum']] = checksum;
+ return inspectObj;
+ });
+ } else if (inspectObj.type === ENodeType.SYMLINK) {
+ return promisedReadlink(path)
+ .then(linkPath => {
+ inspectObj.pointsAt = linkPath;
+ return inspectObj;
+ });
+ }
+ return new Q(inspectObj);
+};
+
+export function async(path: string, options?: IInspectOptions): Promise {
+ return new Promise((resolve, reject) => {
+ options = options || {} as IInspectOptions;
+ (options.symlinks ? promisedLstat : promisedStat)(path)
+ .then((stat: Stats) => { addExtraFieldsAsync(path, createInspectObj(path, options, stat), options).then(resolve, reject); })
+ .catch(err => (err.code === 'ENOENT' ? resolve(undefined) : reject(err)));
+ });
+}
diff --git a/packages/vfs/ref/fs/inspect_tree.ts b/packages/vfs/ref/fs/inspect_tree.ts
new file mode 100644
index 00000000..0a2dd9d5
--- /dev/null
+++ b/packages/vfs/ref/fs/inspect_tree.ts
@@ -0,0 +1,141 @@
+import { createHash } from 'crypto';
+import * as pathUtil from "path";
+import { sync as inspectSync, async as inspectASync, supportedChecksumAlgorithms } from './inspect';
+import { ENodeType, INode, IInspectOptions } from './interfaces';
+import { sync as listSync, async as listASync } from './list';
+import { validateArgument, validateOptions } from './utils/validate';
+const Q = require('q');
+
+export interface Options {
+ checksum: string;
+ relativePath: boolean;
+ symlinks: boolean;
+}
+
+export function validateInput(methodName: string, path: string, options: Options): void {
+ const methodSignature = methodName + '(path, options)';
+ validateArgument(methodSignature, 'path', path, ['string']);
+ validateOptions(methodSignature, 'options', options, {
+ checksum: ['string'],
+ relativePath: ['boolean']
+ });
+
+ if (options && options.checksum !== undefined
+ && supportedChecksumAlgorithms.indexOf(options.checksum) === -1) {
+ throw new Error('Argument "options.checksum" passed to ' + methodSignature
+ + ' must have one of values: ' + supportedChecksumAlgorithms.join(', '));
+ }
+};
+
+function generateTreeNodeRelativePath(parent: any, path: string): string {
+ if (!parent) {
+ return '.';
+ }
+ return parent.relativePath + '/' + pathUtil.basename(path);
+};
+
+// Creates checksum of a directory by using
+// checksums and names of all its children inside.
+const checksumOfDir = (inspectList: any[], algo: string): string => {
+ const hash = createHash(algo);
+ inspectList.forEach(function (inspectObj) {
+ hash.update(inspectObj.name + inspectObj[algo]);
+ });
+ return hash.digest('hex');
+};
+
+// ---------------------------------------------------------
+// Sync
+// ---------------------------------------------------------
+function inspectTreeNodeSync(path: string, options: Options, parent: any): INode {
+ const treeBranch = inspectSync(path, { checksum: options.checksum, symlinks: options.symlinks });
+ if (treeBranch) {
+ if (options.relativePath) {
+ treeBranch.relativePath = generateTreeNodeRelativePath(parent, path);
+ }
+ if (treeBranch.type === ENodeType.DIR /*|| (options.symlinks && treeBranch.type === 'symlink')*/) {
+ treeBranch.size = 0;
+ treeBranch.children = (listSync(path) || []).map(function (filename) {
+ let subBranchPath = pathUtil.join(path, filename);
+ let treeSubBranch = inspectTreeNodeSync(subBranchPath, options, treeBranch);
+ // Add together all childrens' size to get directory combined size.
+ treeBranch.size += treeSubBranch.size || 0;
+ //treeBranch.total += treeSubBranch.total;
+ return treeSubBranch;
+ });
+ if (options.checksum) {
+ (treeBranch as any)[options.checksum] = checksumOfDir(treeBranch.children, options.checksum);
+ }
+ }
+ }
+ return treeBranch;
+};
+
+export function sync(path: string, options?: any): any | undefined {
+ options = options || {
+ };
+ options.symlinks = true;
+ return inspectTreeNodeSync(path, options, undefined);
+};
+
+// ---------------------------------------------------------
+// Async
+// ---------------------------------------------------------
+function inspectTreeNodeAsync(path: string, options: Options, parent?: any): Promise {
+ return new Promise((resolve, reject) => {
+ const inspectAllChildren = (treeBranch: INode) => {
+ return new Promise((resolve, reject) => {
+ listASync(path).then((children: any) => {
+ const doNext = (index: number) => {
+ let subPath: string;
+ if (index === children.length) {
+ if (options.checksum) {
+ // We are done, but still have to calculate checksum of whole directory.
+ (treeBranch as any)[options.checksum] = checksumOfDir(treeBranch.children, options.checksum);
+ }
+ resolve();
+ } else {
+ subPath = pathUtil.join(path, children[index]);
+ inspectTreeNodeAsync(subPath, options, treeBranch)
+ .then((treeSubBranch: INode) => {
+ children[index] = treeSubBranch;
+ treeBranch.size += treeSubBranch.size || 0;
+ doNext(index + 1);
+ })
+ .catch(reject);
+ }
+ };
+ treeBranch.children = children;
+ treeBranch.size = 0;
+ doNext(0);
+ });
+ });
+ };
+
+ inspectASync(path, options)
+ .then((treeBranch: INode) => {
+ if (!treeBranch) {
+ // Given path doesn't exist. We are done.
+ resolve(treeBranch);
+ } else {
+ if (options.relativePath) {
+ treeBranch.relativePath = generateTreeNodeRelativePath(parent, path);
+ }
+ if (treeBranch.type !== ENodeType.DIR) {
+ resolve(treeBranch);
+ } else {
+ inspectAllChildren(treeBranch)
+ .then(() => resolve(treeBranch))
+ .catch(reject);
+ }
+ }
+ })
+ .catch(reject);
+ });
+};
+
+export function async(path: string, options?: Options): Promise {
+ options = options || {} as Options;
+ options.symlinks = true;
+ return inspectTreeNodeAsync(path, options);
+};
diff --git a/packages/vfs/ref/fs/interfaces.ts b/packages/vfs/ref/fs/interfaces.ts
new file mode 100644
index 00000000..7e433c3e
--- /dev/null
+++ b/packages/vfs/ref/fs/interfaces.ts
@@ -0,0 +1,474 @@
+/////////////////////////////////////////////////////////
+//
+// Enums
+//
+export enum ENodeType {
+ FILE = 'file',
+ DIR = 'dir',
+ SYMLINK = 'symlink',
+ OTHER = 'other',
+ BLOCK =