diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f34e31f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# all files +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# Markdown files +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..a3375a2 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,23 @@ +{ + "extends": "@lenne.tech/ts", + "rules": { + "@typescript-eslint/brace-style": ["error", "1tbs", {"allowSingleLine": false}], + "@typescript-eslint/member-delimiter-style": [ + "error", + { + "multiline": { + "delimiter": "semi", + "requireLast": true + }, + "singleline": { + "delimiter": "semi", + "requireLast": false + }, + "multilineDetection": "brackets" + } + ], + "@typescript-eslint/no-require-imports": "off", + "@typescript-eslint/no-var-requires": "off", + "curly": ["error", "all"] + } +} diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 287ef37..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - sourceType: 'module', - }, - plugins: ['@typescript-eslint/eslint-plugin'], - extends: ['plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], - root: true, - env: { - node: true, - jest: true, - }, - rules: { - '@typescript-eslint/no-explicit-any': 'off' - } -}; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b0e143c..74b23c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,10 +13,10 @@ jobs: steps: - name: Git checkout uses: actions/checkout@v4 - - name: Use Node.js 16 + - name: Use Node.js 20 uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 - name: Install dependencies run: npm install - name: Lint diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f1b1fd1..77f2e0e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -11,10 +11,10 @@ jobs: steps: - name: Git checkout uses: actions/checkout@v4 - - name: Node 16 + - name: Node 20 uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 - name: NPM install run: npm install - name: Build diff --git a/.husky/pre-commit b/.husky/pre-commit index 094a11e..e8592c5 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,3 +1,3 @@ #!/bin/sh -ts-node --skip-project extras/sync-version.ts && npm run lint +ts-node --skip-project extras/sync-version.ts && npm run lint --fix diff --git a/.husky/pre-push b/.husky/pre-push index a6d839a..c6a9d04 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,4 +1,4 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" -npm run lint && npm run test +npm run lint --fix && npm run test diff --git a/__tests__/cli-integration.test.ts b/__tests__/cli-integration.test.ts index 5ce3140..4d6801a 100644 --- a/__tests__/cli-integration.test.ts +++ b/__tests__/cli-integration.test.ts @@ -1,20 +1,21 @@ -import * as config from '../package.json' -const { system, filesystem } = require('gluegun') +import * as config from '../package.json'; -const src = filesystem.path(__dirname, '..') +const { system, filesystem } = require('gluegun'); + +const src = filesystem.path(__dirname, '..'); const cli = async cmd => - system.run('node ' + filesystem.path(src, 'bin', 'lt') + ` ${cmd}`) + system.run('node ' + filesystem.path(src, 'bin', 'lt') + ` ${cmd}`); test('outputs version', async () => { - const output = await cli('--version') - expect(output).toContain(config.version) -}) + const output = await cli('--version'); + expect(output).toContain(config.version); +}); test('outputs help', async () => { - const output = await cli('--help') - expect(output).toContain(config.version) -}) + const output = await cli('--help'); + expect(output).toContain(config.version); +}); /* test('generates file', async () => { diff --git a/bin/lt b/bin/lt index ebfab04..36fb878 100755 --- a/bin/lt +++ b/bin/lt @@ -3,19 +3,19 @@ /* tslint:disable */ // check if we're running in dev mode -var devMode = require('fs').existsSync(`${__dirname}/../src`) +var devMode = require('fs').existsSync(`${__dirname}/../src`); // or want to "force" running the compiled version with --compiled-build -var wantsCompiled = process.argv.indexOf('--compiled-build') >= 0 +var wantsCompiled = process.argv.indexOf('--compiled-build') >= 0; if (wantsCompiled || !devMode) { // this runs from the compiled javascript source - require(`${__dirname}/../build/cli`).run(process.argv) + require(`${__dirname}/../build/cli`).run(process.argv); } else { // this runs from the typescript source (for dev only) // hook into ts-node so we can run typescript on the fly - require('ts-node').register({ project: `${__dirname}/../tsconfig.json` }) + require('ts-node').register({ project: `${__dirname}/../tsconfig.json` }); // run the CLI with the current process arguments - require(`${__dirname}/../src/cli`).run(process.argv) + require(`${__dirname}/../src/cli`).run(process.argv); } diff --git a/extras/prettier-imports.js b/extras/prettier-imports.js index f22edd1..2e63603 100644 --- a/extras/prettier-imports.js +++ b/extras/prettier-imports.js @@ -1,5 +1,5 @@ -const { parsers: typescriptParsers } = require('prettier/parser-typescript') -const ts = require('typescript') +const { parsers: typescriptParsers } = require('prettier/parser-typescript'); +const ts = require('typescript'); // ============================================================================= // Prettier plugin to optimize and sort imports @@ -8,56 +8,60 @@ const ts = require('typescript') class SingleLanguageServiceHost { constructor(name, content) { - this.name = name - this.content = content - this.getCompilationSettings = ts.getDefaultCompilerOptions - this.getDefaultLibFileName = ts.getDefaultLibFilePath + this.name = name; + this.content = content; + this.getCompilationSettings = ts.getDefaultCompilerOptions; + this.getDefaultLibFileName = ts.getDefaultLibFilePath; } + getScriptFileNames() { - return [this.name] + return [this.name]; } + getScriptVersion() { - return ts.version + return ts.version; } + getScriptSnapshot() { - return ts.ScriptSnapshot.fromString(this.content) + return ts.ScriptSnapshot.fromString(this.content); } + getCurrentDirectory() { - return '' + return ''; } } function applyChanges(text, changes) { return changes.reduceRight((text, change) => { - const head = text.slice(0, change.span.start) - const tail = text.slice(change.span.start + change.span.length) - return `${head}${change.newText}${tail}` - }, text) + const head = text.slice(0, change.span.start); + const tail = text.slice(change.span.start + change.span.length); + return `${head}${change.newText}${tail}`; + }, text); } function organizeImports(text) { - const fileName = 'file.ts' - const host = new SingleLanguageServiceHost(fileName, text) - const languageService = ts.createLanguageService(host) - const formatOptions = ts.getDefaultFormatCodeSettings() + const fileName = 'file.ts'; + const host = new SingleLanguageServiceHost(fileName, text); + const languageService = ts.createLanguageService(host); + const formatOptions = ts.getDefaultFormatCodeSettings(); const fileChanges = languageService.organizeImports( { type: 'file', fileName }, formatOptions, {} - ) - const textChanges = [...fileChanges.map(change => change.textChanges)] - return applyChanges(text, textChanges) + ); + const textChanges = [...fileChanges.map(change => change.textChanges)]; + return applyChanges(text, textChanges); } const parsers = { typescript: { ...typescriptParsers.typescript, preprocess(text) { - text = organizeImports(text) - return text + text = organizeImports(text); + return text; } } -} +}; // Uses module.export because of 'Unexpected token export' error -module.exports = parsers +module.exports = parsers; diff --git a/package-lock.json b/package-lock.json index 6392069..6215e6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@lenne.tech/cli", - "version": "0.0.107", + "version": "0.0.108", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@lenne.tech/cli", - "version": "0.0.107", + "version": "0.0.108", "license": "MIT", "dependencies": { "@lenne.tech/cli-plugin-helper": "0.0.11", @@ -24,6 +24,7 @@ "lt": "bin/lt" }, "devDependencies": { + "@lenne.tech/eslint-config-ts": "0.0.16", "@lenne.tech/npm-package-helper": "0.0.12", "@types/jest": "29.5.13", "@types/node": "20.16.10", @@ -1432,6 +1433,240 @@ "gluegun": ">=4" } }, + "node_modules/@lenne.tech/eslint-config-ts": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@lenne.tech/eslint-config-ts/-/eslint-config-ts-0.0.16.tgz", + "integrity": "sha512-toMlvzTKfO/Vw9wzdPNAQ2UUIyBYcANrUKwUNYsV4/Hculh3IZSs9lp9/+2ugm10QCLeo3f6WNNz1rj7lb1lXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "6.7.0", + "@typescript-eslint/parser": "6.7.0", + "eslint-config-prettier": "9.0.0", + "eslint-plugin-eslint-comments": "3.2.0", + "eslint-plugin-import": "2.28.1", + "eslint-plugin-jsonc": "2.9.0", + "eslint-plugin-markdown": "3.0.1", + "eslint-plugin-no-only-tests": "3.1.0", + "eslint-plugin-perfectionist": "^2.4.2", + "eslint-plugin-unused-imports": "3.0.0", + "eslint-plugin-yml": "1.9.0", + "functions-have-names": "1.2.3" + }, + "peerDependencies": { + "eslint": ">=7.4.0" + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz", + "integrity": "sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/type-utils": "6.7.0", + "@typescript-eslint/utils": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/parser": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.0.tgz", + "integrity": "sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz", + "integrity": "sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/type-utils": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz", + "integrity": "sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "6.7.0", + "@typescript-eslint/utils": "6.7.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/types": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.0.tgz", + "integrity": "sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz", + "integrity": "sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/visitor-keys": "6.7.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/utils": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.0.tgz", + "integrity": "sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.0", + "@typescript-eslint/types": "6.7.0", + "@typescript-eslint/typescript-estree": "6.7.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz", + "integrity": "sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "6.7.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@lenne.tech/eslint-config-ts/node_modules/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/@lenne.tech/gluegun-menu": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@lenne.tech/gluegun-menu/-/gluegun-menu-0.0.6.tgz", @@ -1724,6 +1959,23 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.15.tgz", + "integrity": "sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2" + } + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -1765,6 +2017,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -2216,12 +2475,50 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "license": "MIT" }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -2232,65 +2529,163 @@ "node": ">=8" } }, - "node_modules/arrify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", - "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, "engines": { - "node": ">=12" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "@babel/core": "^7.8.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", + "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "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==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" @@ -2490,6 +2885,26 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "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", @@ -2572,6 +2987,39 @@ "node": ">=10" } }, + "node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -3773,6 +4221,60 @@ "node": ">=8" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dateformat": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", @@ -3877,6 +4379,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -3886,6 +4406,24 @@ "node": ">=8" } }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -4140,95 +4678,538 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "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.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-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "engines": { + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-eslint-comments/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", + "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.findlastindex": "^1.2.2", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.8.0", + "has": "^1.0.3", + "is-core-module": "^2.13.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.6", + "object.groupby": "^1.0.0", + "object.values": "^1.1.6", + "semver": "^6.3.1", + "tsconfig-paths": "^3.14.2" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsonc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsonc/-/eslint-plugin-jsonc-2.9.0.tgz", + "integrity": "sha512-RK+LeONVukbLwT2+t7/OY54NJRccTXh/QbnXzPuTLpFMVZhPuq1C9E07+qWenGx7rrQl0kAalAWl7EmB+RjpGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "jsonc-eslint-parser": "^2.0.4", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-plugin-markdown": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-3.0.1.tgz", + "integrity": "sha512-8rqoc148DWdGdmYF6WSQFT3uQ6PO7zXYgeBpHAOAakX/zpq+NvFYbDA/H7PYzHajwtmaOzAwfxyl++x0g1/N9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^0.8.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-no-only-tests": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.1.0.tgz", + "integrity": "sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=5.0.0" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/eslint-plugin-perfectionist": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-2.11.0.tgz", + "integrity": "sha512-XrtBtiu5rbQv88gl+1e2RQud9te9luYNvKIgM9emttQ2zutHPzY/AQUucwxscDKV4qlTkvLTxjOFvxqeDpPorw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^6.13.0 || ^7.0.0", + "minimatch": "^9.0.3", + "natural-compare-lite": "^1.4.0" + }, + "peerDependencies": { + "astro-eslint-parser": "^1.0.2", + "eslint": ">=8.0.0", + "svelte": ">=3.0.0", + "svelte-eslint-parser": "^0.37.0", + "vue-eslint-parser": ">=9.0.0" + }, + "peerDependenciesMeta": { + "astro-eslint-parser": { + "optional": true + }, + "svelte": { + "optional": true + }, + "svelte-eslint-parser": { + "optional": true + }, + "vue-eslint-parser": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-unused-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.0.0.tgz", + "integrity": "sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw==", "dev": true, "license": "MIT", + "dependencies": { + "eslint-rule-composer": "^0.3.0" + }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^6.0.0", + "eslint": "^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } } }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "node_modules/eslint-plugin-yml": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-yml/-/eslint-plugin-yml-1.9.0.tgz", + "integrity": "sha512-ayuC57WyVQ5+QZ02y62GiB//5+zsiyzUGxUX/mrhLni+jfsKA4KoITjkbR65iUdjjhWpyTJHPcAIFLKQIOwgsw==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "lodash": "^4.17.21", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" + "yaml-eslint-parser": "^1.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ota-meshi" + }, + "peerDependencies": { + "eslint": ">=6.0.0" } }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "node_modules/eslint-rule-composer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", + "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", "dev": true, "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" + "engines": { + "node": ">=4.0.0" } }, "node_modules/eslint-scope": { @@ -4705,6 +5686,16 @@ } } }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -4847,6 +5838,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gauge": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", @@ -4893,6 +5913,26 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -5028,6 +6068,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/git-raw-commits": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", @@ -5553,6 +6611,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -5648,6 +6723,19 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "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", @@ -5691,6 +6779,26 @@ "node": ">=6" } }, + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.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==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -5700,6 +6808,61 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "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", @@ -5893,12 +7056,113 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "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-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -5914,6 +7178,49 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", @@ -5971,6 +7278,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -5980,6 +7298,19 @@ "node": ">=8" } }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "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", @@ -5990,6 +7321,22 @@ "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", @@ -6018,6 +7365,39 @@ "node": ">=0.10.0" } }, + "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==", + "dev": true, + "license": "MIT", + "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.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "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", @@ -6030,6 +7410,38 @@ "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==", + "dev": true, + "license": "MIT", + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", @@ -6042,6 +7454,35 @@ "node": ">=0.10.0" } }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -6982,6 +8423,25 @@ "node": ">=6" } }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -7401,6 +8861,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/mdast-util-from-markdown": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.5.tgz", + "integrity": "sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^2.0.0", + "micromark": "~2.11.0", + "parse-entities": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/meow": { "version": "12.1.1", "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", @@ -7430,6 +8919,27 @@ "node": ">= 8" } }, + "node_modules/micromark": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.11.4.tgz", + "integrity": "sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "debug": "^4.0.0", + "parse-entities": "^2.0.0" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -7594,6 +9104,13 @@ "dev": true, "license": "MIT" }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -7712,13 +9229,107 @@ "set-blocking": "^2.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==", + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/once": { @@ -8021,6 +9632,25 @@ "node": ">=6" } }, + "node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -8465,6 +10095,16 @@ "node": ">=4" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8821,6 +10461,25 @@ "node": ">=8" } }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -8976,6 +10635,32 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -8996,6 +10681,24 @@ ], "license": "MIT" }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -9014,6 +10717,40 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9035,6 +10772,25 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -9406,6 +11162,58 @@ "node": ">=8" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/stringify-package": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", @@ -9780,6 +11588,42 @@ } } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", @@ -9823,6 +11667,83 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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", @@ -9855,12 +11776,42 @@ "node": ">=0.8.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==", + "dev": true, + "license": "MIT", + "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/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/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", @@ -9989,6 +11940,43 @@ "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==", + "dev": true, + "license": "MIT", + "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-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -10172,6 +12160,37 @@ "node": ">= 6" } }, + "node_modules/yaml-eslint-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/yaml-eslint-parser/-/yaml-eslint-parser-1.2.3.tgz", + "integrity": "sha512-4wZWvE398hCP7O8n3nXKu/vdq1HcH01ixYlCREaJL5NUMwQ0g3MaGFUBNSlmBtKmhbtVG/Cm6lyYmSVTEVil8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.0.0", + "lodash": "^4.17.21", + "yaml": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/yaml-eslint-parser/node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index f114593..a55a7f9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lenne.tech/cli", - "version": "0.0.107", + "version": "0.0.108", "description": "lenne.Tech CLI: lt", "keywords": [ "lenne.Tech", @@ -60,6 +60,7 @@ "typescript": "5.5.4" }, "devDependencies": { + "@lenne.tech/eslint-config-ts": "0.0.16", "@lenne.tech/npm-package-helper": "0.0.12", "@types/jest": "29.5.13", "@types/node": "20.16.10", diff --git a/src/cli.ts b/src/cli.ts index 6a52e03..17b769a 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -13,7 +13,7 @@ async function run(argv) { // .plugins('./node_modules', { matching: 'lt-*', hidden: true }) .plugin(join(__dirname, '..', 'node_modules', '@lenne.tech', 'cli-plugin-helper', 'dist'), { commandFilePattern: ['*.js'], - extensionFilePattern: ['*.js'] + extensionFilePattern: ['*.js'], }) .help() // provides default for help, h, --help, -h .version() // provides default for version, v, --version, -v @@ -27,6 +27,7 @@ async function run(argv) { } catch (e) { // Abort via CTRL-C if (!e) { + // eslint-disable-next-line no-console console.log('Goodbye ✌️'); } else { // Throw error diff --git a/src/commands/angular/angular.ts b/src/commands/angular/angular.ts index 5e0c294..f31b2fc 100644 --- a/src/commands/angular/angular.ts +++ b/src/commands/angular/angular.ts @@ -4,10 +4,10 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Angular commands */ module.exports = { - name: 'angular', alias: ['a'], description: 'Angular commands', hidden: true, + name: 'angular', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('angular'); return 'angular'; diff --git a/src/commands/angular/create.ts b/src/commands/angular/create.ts index cbedfb1..d53449f 100644 --- a/src/commands/angular/create.ts +++ b/src/commands/angular/create.ts @@ -1,15 +1,16 @@ import * as crypto from 'crypto'; import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new server */ const NewCommand: GluegunCommand = { - name: 'create', alias: ['c'], description: 'Creates a new angular (fullstack) workspace', hidden: false, + name: 'create', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -50,20 +51,20 @@ const NewCommand: GluegunCommand = { // Check if directory already exists if (filesystem.exists(projectDir)) { - info(``); + info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } // Localize - const localize = - parameters.second?.toLowerCase().includes('localize') || - (!parameters.second && (await confirm(`Init localize for Angular?`, true))); + const localize + = parameters.second?.toLowerCase().includes('localize') + || (!parameters.second && (await confirm('Init localize for Angular?', true))); // Nest-Server - const nestServer = - parameters.second?.toLowerCase().includes('nest') || - (!parameters.second && (await confirm(`Add API (Nest-Server)?`, true))); + const nestServer + = parameters.second?.toLowerCase().includes('nest') + || (!parameters.second && (await confirm('Add API (Nest-Server)?', true))); const gitLink = ( await helper.getInput(null, { @@ -152,7 +153,7 @@ const NewCommand: GluegunCommand = { // Include files from https://github.com/lenneTech/nest-server-starter if (nestServer) { // Init - const serverSpinner = spin(`Integrate Nest Server Starter`); + const serverSpinner = spin('Integrate Nest Server Starter'); // Clone api await system.run(`cd ${projectDir}/projects && git clone https://github.com/lenneTech/nest-server-starter api`); @@ -172,8 +173,8 @@ const NewCommand: GluegunCommand = { // Prepare meta.json in api filesystem.write(`./${projectDir}/projects/api/src/meta.json`, { - name: `${name}-api-server`, description: `API for ${name} app`, + name: `${name}-api-server`, version: '0.0.0', }); @@ -181,24 +182,24 @@ const NewCommand: GluegunCommand = { for (const env of ['LOCAL', 'DEV', 'TEST', 'PREV', 'PROD']) { await patching.replace( `./${projectDir}/projects/api/src/config.env.ts`, - 'SECRET_OR_PRIVATE_KEY_' + env, - crypto.randomBytes(512).toString('base64') + `SECRET_OR_PRIVATE_KEY_${env}`, + crypto.randomBytes(512).toString('base64'), ); await patching.replace( `./${projectDir}/projects/api/src/config.env.ts`, - 'SECRET_OR_PRIVATE_KEY_' + env + '_REFRESH', - crypto.randomBytes(512).toString('base64') + `SECRET_OR_PRIVATE_KEY_${env}_REFRESH`, + crypto.randomBytes(512).toString('base64'), ); } - await patching.update(`./${projectDir}/projects/api/src/config.env.ts`, (data) => - data.replace(/nest-server-/g, projectDir + '-') + await patching.update(`./${projectDir}/projects/api/src/config.env.ts`, data => + data.replace(/nest-server-/g, `${projectDir}-`), ); // Set readme await template.generate({ - template: 'monorepro/README.md.ejs', + props: { name, nameCamel, nameKebab, namePascal, repository: gitLink || 'REPOSITORY' }, target: `./${projectDir}/README.md`, - props: { repository: gitLink || 'REPOSITORY', name, nameCamel, nameKebab, namePascal }, + template: 'monorepro/README.md.ejs', }); // Commit changes @@ -231,15 +232,15 @@ const NewCommand: GluegunCommand = { installSpinner.succeed('Successfully installed all packages'); // We're done, so show what to do next - info(``); + info(''); success(`Generated workspace ${projectDir} with ${name} app in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); - info(`Next:`); + info(''); + info('Next:'); info(` Test and run ${name}:`); info(` $ cd ${projectDir}`); - info(` $ npm run test`); - info(` $ npm run start`); - info(``); + info(' $ npm run test'); + info(' $ npm run start'); + info(''); if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); diff --git a/src/commands/cli/cli.ts b/src/commands/cli/cli.ts index 2458861..05c698b 100644 --- a/src/commands/cli/cli.ts +++ b/src/commands/cli/cli.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * CLI commands */ module.exports = { - name: 'cli', alias: ['c'], description: 'Commands to create a CLI', hidden: true, + name: 'cli', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('cli', { headline: 'CLI commands' }); return 'cli'; - } + }, }; diff --git a/src/commands/cli/create.ts b/src/commands/cli/create.ts index 77b1242..9e6abc8 100644 --- a/src/commands/cli/create.ts +++ b/src/commands/cli/create.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new CLI */ const NewCommand: GluegunCommand = { - name: 'create', alias: ['c'], description: 'Creates a new CLI', hidden: false, + name: 'create', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -20,7 +21,7 @@ const NewCommand: GluegunCommand = { print: { error, info, spin, success }, prompt: { ask }, strings: { kebabCase }, - system + system, } = toolbox; // Info @@ -34,7 +35,7 @@ const NewCommand: GluegunCommand = { // Get name const name = await helper.getInput(parameters.first, { name: 'CLI name', - showError: true + showError: true, }); if (!name) { return; @@ -43,16 +44,16 @@ const NewCommand: GluegunCommand = { // Get author const author = await helper.getInput(parameters.options.author, { name: 'Author', - showError: true + showError: true, }); // Link let link = parameters.options.link && !parameters.options.nolink; if (!parameters.options.link && !parameters.options.nolink) { link = !!(await ask({ - type: 'confirm', + message: 'Link when finished?', name: 'link', - message: 'Link when finished?' + type: 'confirm', })).link; } @@ -64,7 +65,7 @@ const NewCommand: GluegunCommand = { // Check if directory already exists if (filesystem.exists(projectDir)) { - info(``); + info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } @@ -88,26 +89,26 @@ const NewCommand: GluegunCommand = { // Rename files and data const renameSpinner = spin(`Rename files & data ${link ? ' and link' : ''}`); await system.run( - `cd ${projectDir} && npm run rename -- "${name}" --author "${author}" --${link ? 'link' : 'nolink'}` + `cd ${projectDir} && npm run rename -- "${name}" --author "${author}" --${link ? 'link' : 'nolink'}`, ); renameSpinner.succeed(`Files & data renamed${link ? ' and linked' : ''}`); // Init git const initGitSpinner = spin('Initialize git'); await system.run( - `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"` + `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"`, ); initGitSpinner.succeed('Git initialized'); // We're done, so show what to do next - info(``); + info(''); success( - `Generated ${name} server with lenne.Tech CLI ${meta.version()} in ${helper.msToMinutesAndSeconds(timer())}m.` + `Generated ${name} server with lenne.Tech CLI ${meta.version()} in ${helper.msToMinutesAndSeconds(timer())}m.`, ); // For tests return `new cli ${name}`; - } + }, }; export default NewCommand; diff --git a/src/commands/cli/rename.ts b/src/commands/cli/rename.ts index 5949dc6..f295c59 100644 --- a/src/commands/cli/rename.ts +++ b/src/commands/cli/rename.ts @@ -1,15 +1,16 @@ import { GluegunCommand } from 'gluegun'; import { dirname } from 'path'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Rename current CLI */ const NewCommand: GluegunCommand = { - name: 'rename', alias: ['r'], description: 'Rename current CLI', hidden: false, + name: 'rename', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -35,7 +36,7 @@ const NewCommand: GluegunCommand = { await system.run(`cd ${rootPath} && npm run rename -- ${parameters.string}`); // For tests - return `Rename current CLI`; + return 'Rename current CLI'; }, }; diff --git a/src/commands/components/add.ts b/src/commands/components/add.ts index 1c47404..8f10fa1 100644 --- a/src/commands/components/add.ts +++ b/src/commands/components/add.ts @@ -1,244 +1,245 @@ -import { GluegunCommand } from 'gluegun' -import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox' -import * as fs from 'fs' -import * as glob from 'glob' -import * as path from 'path' -import axios from 'axios' +import axios from 'axios'; +import * as fs from 'fs'; +import * as glob from 'glob'; +import { GluegunCommand } from 'gluegun'; +import * as path from 'path'; + +import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; const AddComponentCommand: GluegunCommand = { + description: 'Adds a specific component to another Nuxt project', name: 'add', - description: 'Füge eine bestimmte Komponente zu einem anderen Nuxt-Projekt hinzu', run: async (toolbox: ExtendedGluegunToolbox) => { - const { parameters } = toolbox - const componentName = parameters.first - await addComponent(toolbox, componentName) - process.exit() - return 'add' - } -} + const { parameters } = toolbox; + const componentName = parameters.first; + await addComponent(toolbox, componentName); + process.exit(); + return 'add'; + }, +}; async function getConfigForComponent(fileName: string) { - const data = await getConfig() - const name = fileName.split('.').slice(0, -1).join('.') + const data = await getConfig(); + const name = fileName.split('.').slice(0, -1).join('.'); return data.config[name] || {}; } async function getConfig() { - const githubApiUrl = `https://raw.githubusercontent.com/lenneTech/nuxt-base-components/main/config.json` + const githubApiUrl = 'https://raw.githubusercontent.com/lenneTech/nuxt-base-components/main/config.json'; const response = await axios.get(githubApiUrl); if (response.status === 200) { return response.data; } else { - throw new Error(`Fehler beim Abrufen der Konfiguration von GitHub: ${response.statusText}`) + throw new Error(`Error when retrieving the configuration from GitHub: ${response.statusText}`); } } async function processConfig(config: any, toolbox: ExtendedGluegunToolbox) { - const {prompt} = toolbox; + const { prompt } = toolbox; if (config?.npm) { - const npmPackages = config.npm + const npmPackages = config.npm; for (const npmPackage of npmPackages) { - const confirm = await prompt.confirm(`Das npm-Paket ${npmPackage} wird benötigt. Möchten Sie es installieren?`) + const confirm = await prompt.confirm(`The npm package ${npmPackage} is required. Would you like to install it?`); if (confirm) { - await installPackage(npmPackage, toolbox) + await installPackage(npmPackage, toolbox); } } } if (config?.composables) { - const composables = config.composables + const composables = config.composables; for (const composable of composables) { - const confirm = await prompt.confirm(`Das composable ${composable} wird benötigt. Möchten Sie es hinzufügen?`) + const confirm = await prompt.confirm(`The composable ${composable} is required. Would you like to add it?`); if (confirm) { - await copyComposable(composable, toolbox) + await copyComposable(composable, toolbox); } } } if (config?.components) { - const components = config.components + const components = config.components; for (const component of components) { - const confirm = await prompt.confirm(`Die component ${component} wird benötigt. Möchten Sie es hinzufügen?`) + const confirm = await prompt.confirm(`The component ${component} is required. Would you like to add it?`); if (confirm) { - await copyComponent({ name: component + '.vue', type: 'file' }, toolbox) + await copyComponent({ name: `${component}.vue`, type: 'file' }, toolbox); } } } } async function installPackage(packageName: string, toolbox: ExtendedGluegunToolbox) { - const { print, system } = toolbox - const installSpinner = print.spin(`Installiere npm-Paket ${packageName}...`) - await system.run(`npm install ${packageName} --save-exact`) - installSpinner.succeed(`npm-Paket ${packageName} erfolgreich installiert`) + const { print, system } = toolbox; + const installSpinner = print.spin(`Install npm package ${packageName}...`); + await system.run(`npm install ${packageName} --save-exact`); + installSpinner.succeed(`npm package ${packageName} successfully installed`); } async function copyComposable(composable: string, toolbox: ExtendedGluegunToolbox) { - const { print } = toolbox - const apiUrl = `https://raw.githubusercontent.com/lenneTech/nuxt-base-components/main/composables/${composable}.ts` - const response = await axios.get(apiUrl) + const { print } = toolbox; + const apiUrl = `https://raw.githubusercontent.com/lenneTech/nuxt-base-components/main/composables/${composable}.ts`; + const response = await axios.get(apiUrl); if (response.status === 200) { - const sourceCode = response.data - const cwd = process.cwd() - let targetDirectory: string + const sourceCode = response.data; + const cwd = process.cwd(); + let targetDirectory: string; if (fs.existsSync(path.resolve(cwd, 'composables'))) { - targetDirectory = path.resolve(cwd, 'composables') + targetDirectory = path.resolve(cwd, 'composables'); } else { - const directories = glob.sync('*/composables', { cwd }) + const directories = glob.sync('*/composables', { cwd }); if (directories.length > 0) { - targetDirectory = path.join(cwd, directories[0]) + targetDirectory = path.join(cwd, directories[0]); } else { - targetDirectory = cwd + targetDirectory = cwd; } } - const targetPath = path.join(targetDirectory, `${composable}.ts`) - const spinner = print.spin(`Kopiere das Composable ${composable} nach ${targetPath}...`) - fs.writeFileSync(targetPath, sourceCode) - spinner.succeed(`Das Composable ${composable} wurde erfolgreich kopiert nach ${targetPath}`) + const targetPath = path.join(targetDirectory, `${composable}.ts`); + const spinner = print.spin(`Copy the composable ${composable} to ${targetPath}...`); + fs.writeFileSync(targetPath, sourceCode); + spinner.succeed(`The composable ${composable} was successfully copied to ${targetPath}`); } else { - print.error(`Fehler beim Abrufen der Datei von GitHub: ${response.statusText}`) + print.error(`Error retrieving the file from GitHub: ${response.statusText}`); } } async function getFileInfo(path?: string): Promise<{ name: string; type: 'dir' | 'file' }[]> { - const githubApiUrl = `https://api.github.com/repos/lenneTech/nuxt-base-components/contents/components${path ? '/' + path : ''}` - const response = await axios.get(githubApiUrl) + const githubApiUrl = `https://api.github.com/repos/lenneTech/nuxt-base-components/contents/components${path ? `/${path}` : ''}`; + const response = await axios.get(githubApiUrl); if (response.status === 200) { return response.data.map((file: any) => { return { name: file.name, - type: file.type - } - }) + type: file.type, + }; + }); } else { - throw new Error(`Fehler beim Abrufen der Dateiliste von GitHub: ${response.statusText}`) + throw new Error(`Error when retrieving the file list from GitHub: ${response.statusText}`); } } async function addComponent(toolbox: ExtendedGluegunToolbox, componentName: string | undefined) { - const { print, prompt } = toolbox + const { print, prompt } = toolbox; try { - const compSpinner = print.spin('Lade Komponenten Auswahl von GitHub...') - const possibleComponents = await getFileInfo() - compSpinner.succeed('Komponenten Auswahl von GitHub erfolgreich geladen') + const compSpinner = print.spin('Load component selection from GitHub...'); + const possibleComponents = await getFileInfo(); + compSpinner.succeed('Components selection successfully loaded from GitHub'); if (possibleComponents.length > 0) { - let selectedComponent: string = '' + let selectedComponent: string = ''; if (!componentName) { const response = await prompt.ask({ - type: 'select', + choices: possibleComponents, + message: 'Which component would you like to add?', name: 'componentType', - message: 'Welche Komponente möchten Sie hinzufügen:', - choices: possibleComponents - }) - selectedComponent = response.componentType + type: 'select', + }); + selectedComponent = response.componentType; } else { - selectedComponent = componentName + '.vue'; + selectedComponent = `${componentName}.vue`; } - const selectedFile = possibleComponents.find((e) => e.name === selectedComponent) + const selectedFile = possibleComponents.find(e => e.name === selectedComponent); if (selectedFile?.type === 'dir') { - print.success(`Das Verzeichnis ${selectedFile.name} wurde ausgewählt.`) - const directoryFiles = await getFileInfo(selectedFile.name) + print.success(`The directory ${selectedFile.name} has been selected.`); + const directoryFiles = await getFileInfo(selectedFile.name); if (directoryFiles.length > 0) { for (const file of directoryFiles) { await copyComponent({ name: `${selectedFile.name}/${file.name}`, - type: 'dir' - }, toolbox) + type: 'dir', + }, toolbox); } - print.success(`Alle Dateien aus dem Verzeichnis ${selectedFile.name} wurden erfolgreich kopiert.`) + print.success(`All files from the directory ${selectedFile.name} have been successfully copied.`); } else { - print.error(`Das Verzeichnis ${selectedFile.name} ist leer.`) + print.error(`The directory ${selectedFile.name} is empty.`); } } else if (selectedFile?.type === 'file') { - print.success(`Die Komponente ${selectedFile.name} wurde ausgewählt.`) - await copyComponent(selectedFile, toolbox) + print.success(`The component ${selectedFile.name} was selected.`); + await copyComponent(selectedFile, toolbox); } } else { - print.error('Keine Komponenten auf GitHub gefunden.') + print.error('No components found on GitHub.'); } } catch (error) { - print.error(`Fehler beim Hinzufügen/Auswählen der Komponente: ${error.message}`) + print.error(`Error when adding/selecting the component: ${error.message}`); } } async function copyComponent(file: { name: string; type: 'dir' | 'file' }, toolbox: ExtendedGluegunToolbox) { - const { print } = toolbox - const apiUrl = `https://raw.githubusercontent.com/lenneTech/nuxt-base-components/main/components/${file.name}` + const { print } = toolbox; + const apiUrl = `https://raw.githubusercontent.com/lenneTech/nuxt-base-components/main/components/${file.name}`; return new Promise(async (resolve, reject) => { try { - const configSpinner = print.spin(`Checken der config für ${file.name}...`) - const config = await getConfigForComponent(file.name) - configSpinner.succeed(`Config für ${file.name} erfolgreich geladen`) + const configSpinner = print.spin(`Checking the config for ${file.name}...`); + const config = await getConfigForComponent(file.name); + configSpinner.succeed(`Config for ${file.name} loaded successfully`); if (config) { - await processConfig(config, toolbox) + await processConfig(config, toolbox); } - const compSpinner = print.spin(`Lade Komponente ${file.name} von GitHub...`) - const response = await axios.get(apiUrl) - compSpinner.succeed(`Komponente ${file.name} erfolgreich von GitHub geladen`) + const compSpinner = print.spin(`Load component ${file.name} from GitHub...`); + const response = await axios.get(apiUrl); + compSpinner.succeed(`Component ${file.name} successfully loaded from GitHub`); if (response.status === 200) { - const sourceCode = response.data - const cwd = process.cwd() - let targetDirectory: string + const sourceCode = response.data; + const cwd = process.cwd(); + let targetDirectory: string; if (fs.existsSync(path.resolve(cwd, 'components'))) { - targetDirectory = path.resolve(cwd, 'components') + targetDirectory = path.resolve(cwd, 'components'); } else { - const directories = glob.sync('*/components', { cwd }) + const directories = glob.sync('*/components', { cwd }); if (directories.length > 0) { - targetDirectory = path.join(cwd, directories[0]) + targetDirectory = path.join(cwd, directories[0]); } else { - targetDirectory = cwd + targetDirectory = cwd; } } - const targetPath = path.join(targetDirectory, `${file.name}`) + const targetPath = path.join(targetDirectory, `${file.name}`); if (!fs.existsSync(targetDirectory)) { - const targetDirSpinner = print.spin(`Erstellen des Zielverzeichnis...`) - fs.mkdirSync(targetDirectory, { recursive: true }) + const targetDirSpinner = print.spin('Creating the target directory...'); + fs.mkdirSync(targetDirectory, { recursive: true }); targetDirSpinner.succeed(); } if (file.type === 'dir') { - const dirName = file.name.split('/')[0] - const dirPath = path.join(targetDirectory, dirName) + const dirName = file.name.split('/')[0]; + const dirPath = path.join(targetDirectory, dirName); if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); } } - const spinner = print.spin(`Kopiere die Komponente ${file.name} nach ${targetPath}...`) - fs.writeFileSync(targetPath, sourceCode) - spinner.succeed(`Die Komponente ${file.name} wurde erfolgreich kopiert nach ${targetPath}`) - resolve(targetPath) + const spinner = print.spin(`Copy the component ${file.name} to ${targetPath}...`); + fs.writeFileSync(targetPath, sourceCode); + spinner.succeed(`The component ${file.name} was successfully copied to ${targetPath}`); + resolve(targetPath); } else { - print.error(`Fehler beim Abrufen der Datei von GitHub: ${response.statusText}`) - reject(response.statusText) + print.error(`Error retrieving the file from GitHub: ${response.statusText}`); + reject(response.statusText); } } catch (error) { - print.error(`Fehler beim Kopieren der Komponente ${file.name}: ${error.message}`) - reject(error) + print.error(`Error when copying the component ${file.name}: ${error.message}`); + reject(error); } - }) + }); } -export default AddComponentCommand +export default AddComponentCommand; diff --git a/src/commands/components/components.ts b/src/commands/components/components.ts index 643d8f4..553629b 100644 --- a/src/commands/components/components.ts +++ b/src/commands/components/components.ts @@ -4,10 +4,10 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Components commands */ module.exports = { - name: 'components', alias: ['n'], description: 'Base components for Nuxt', hidden: true, + name: 'components', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('components'); return 'components'; diff --git a/src/commands/deployment/create.ts b/src/commands/deployment/create.ts index ed6eeef..b8e7d46 100644 --- a/src/commands/deployment/create.ts +++ b/src/commands/deployment/create.ts @@ -1,15 +1,16 @@ import { GluegunCommand } from 'gluegun'; import { join } from 'path'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new server module */ const NewCommand: GluegunCommand = { - name: 'create', alias: ['dc'], description: 'Creates a new deployment for mono repository', hidden: false, + name: 'create', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -18,8 +19,8 @@ const NewCommand: GluegunCommand = { parameters, patching, print: { info, spin, success }, - strings: { kebabCase, pascalCase, camelCase }, prompt: { confirm }, + strings: { camelCase, kebabCase, pascalCase }, system, template, } = toolbox; @@ -34,14 +35,14 @@ const NewCommand: GluegunCommand = { let projectName = ''; const config = await filesystem.exists('lt.json'); if (config) { - await patching.update(`lt.json`, (data: Record) => { + await patching.update('lt.json', (data: Record) => { projectName = data.name; return data; }); } if (!projectName) { - await patching.update(`package.json`, (data: Record) => { + await patching.update('package.json', (data: Record) => { projectName = pascalCase(data.name); return data; }); @@ -50,7 +51,7 @@ const NewCommand: GluegunCommand = { // Get name const name = await helper.getInput(parameters.first, { initial: projectName, - name: 'project name (e.g. ' + (projectName ? projectName : 'My new project') + ')', + name: `project name (e.g. ${projectName ? projectName : 'My new project'})`, }); if (!name) { @@ -59,16 +60,16 @@ const NewCommand: GluegunCommand = { // Get domain const domain = await helper.getInput(parameters.second, { - initial: kebabCase(name) + '.lenne.tech', - name: 'main domain of the project (e.g. ' + kebabCase(name) + '.lenne.tech)', + initial: `${kebabCase(name)}.lenne.tech`, + name: `main domain of the project (e.g. ${kebabCase(name)}.lenne.tech)`, }); if (!name) { return; } - const gitHub = await confirm(`Add GitHub pipeline?`); - const gitLab = await confirm(`Add GitLab pipeline?`); + const gitHub = await confirm('Add GitHub pipeline?'); + const gitLab = await confirm('Add GitLab pipeline?'); // GitLab test runner let testRunner; @@ -101,66 +102,66 @@ const NewCommand: GluegunCommand = { const generateSpinner = spin('Generate files'); await template.generate({ - template: 'deployment/scripts/build-push.sh.ejs', - target: join(cwd, 'scripts', 'build-push.sh'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'scripts', 'build-push.sh'), + template: 'deployment/scripts/build-push.sh.ejs', }); await template.generate({ - template: 'deployment/scripts/deploy.sh.ejs', - target: join(cwd, 'scripts', 'deploy.sh'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'scripts', 'deploy.sh'), + template: 'deployment/scripts/deploy.sh.ejs', }); await template.generate({ - template: 'deployment/Dockerfile.ejs', - target: join(cwd, 'Dockerfile'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'Dockerfile'), + template: 'deployment/Dockerfile.ejs', }); await template.generate({ - template: 'deployment/Dockerfile.app.ejs', - target: join(cwd, 'Dockerfile.app'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'Dockerfile.app'), + template: 'deployment/Dockerfile.app.ejs', }); await template.generate({ - template: 'deployment/docker-compose.dev.yml.ejs', - target: join(cwd, 'docker-compose.dev.yml'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'docker-compose.dev.yml'), + template: 'deployment/docker-compose.dev.yml.ejs', }); await template.generate({ - template: 'deployment/docker-compose.test.yml.ejs', - target: join(cwd, 'docker-compose.test.yml'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'docker-compose.test.yml'), + template: 'deployment/docker-compose.test.yml.ejs', }); await template.generate({ - template: 'deployment/docker-compose.prod.yml.ejs', - target: join(cwd, 'docker-compose.prod.yml'), props: { nameCamel, nameKebab, namePascal }, + target: join(cwd, 'docker-compose.prod.yml'), + template: 'deployment/docker-compose.prod.yml.ejs', }); if (gitHub) { await template.generate({ - template: 'deployment/.github/workflows/pre-release.yml.ejs', - target: join(cwd, '.github', 'workflows', 'pre-release.yml'), props: { nameCamel, nameKebab, namePascal, url: domain }, + target: join(cwd, '.github', 'workflows', 'pre-release.yml'), + template: 'deployment/.github/workflows/pre-release.yml.ejs', }); await template.generate({ - template: 'deployment/.github/workflows/release.yml.ejs', - target: join(cwd, '.github', 'workflows', 'release.yml'), props: { nameCamel, nameKebab, namePascal, url: domain }, + target: join(cwd, '.github', 'workflows', 'release.yml'), + template: 'deployment/.github/workflows/release.yml.ejs', }); } if (gitLab) { await template.generate({ - template: 'deployment/.gitlab-ci.yml.ejs', + props: { nameCamel, nameKebab, namePascal, prodRunner, testRunner, url: domain }, target: join(cwd, '.gitlab-ci.yml'), - props: { nameCamel, nameKebab, namePascal, url: domain, testRunner, prodRunner }, + template: 'deployment/.gitlab-ci.yml.ejs', }); } @@ -170,16 +171,16 @@ const NewCommand: GluegunCommand = { const prodEnv = await filesystem.exists('projects/app/src/environments/environment.prod.ts'); if (prodEnv) { await patching.patch('projects/app/src/environments/environment.prod.ts', { + insert: `https://api.${domain}`, replace: new RegExp('http://127.0.0.1:3000', 'g'), - insert: 'https://api.' + domain, }); await patching.patch('projects/app/src/environments/environment.prod.ts', { + insert: `wss://api.${domain}`, replace: new RegExp('ws://127.0.0.1:3000', 'g'), - insert: 'wss://api.' + domain, }); await patching.patch('projects/app/src/environments/environment.prod.ts', { + insert: `https://${domain}`, replace: new RegExp('http://127.0.0.1:4200', 'g'), - insert: 'https://' + domain, }); } else { info('Missing projects/app/src/environments/environment.prod.ts'); @@ -188,16 +189,16 @@ const NewCommand: GluegunCommand = { const testEnv = await filesystem.exists('projects/app/src/environments/environment.test.ts'); if (testEnv) { await patching.patch('projects/app/src/environments/environment.test.ts', { + insert: `https://api.test.${domain}`, replace: new RegExp('http://127.0.0.1:3000', 'g'), - insert: 'https://api.test.' + domain, }); await patching.patch('projects/app/src/environments/environment.test.ts', { + insert: `wss://api.test.${domain}`, replace: new RegExp('ws://127.0.0.1:3000', 'g'), - insert: 'wss://api.test.' + domain, }); await patching.patch('projects/app/src/environments/environment.test.ts', { + insert: `https://test.${domain}`, replace: new RegExp('http://127.0.0.1:4200', 'g'), - insert: 'https://test.' + domain, }); } else { info('Missing projects/app/src/environments/environment.test.ts'); @@ -206,18 +207,18 @@ const NewCommand: GluegunCommand = { environmentsSpinner.succeed('App environment files updated'); // We're done, so show what to do next - info(``); + info(''); success(`Generated deployment for ${namePascal} in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); + info(''); // Hint for CI/CD const subDomains = ['www', 'api', 'test', 'www.test', 'api.test']; - let urlStr = '\n- ' + domain; + let urlStr = `\n- ${domain}`; for (const sub of subDomains) { - urlStr += '\n- ' + sub + '.' + domain; + urlStr += `\n- ${sub}.${domain}`; } success(`HINT: please initialize following Domains before running the CI/CD pipeline:${urlStr}`); - info(``); + info(''); if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); diff --git a/src/commands/deployment/deployment.ts b/src/commands/deployment/deployment.ts index b8c8aa1..7c2107f 100644 --- a/src/commands/deployment/deployment.ts +++ b/src/commands/deployment/deployment.ts @@ -4,10 +4,10 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Deployment commands */ module.exports = { - name: 'deployment', alias: ['d'], description: 'Server commands', hidden: true, + name: 'deployment', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('deployment'); return 'deployment'; diff --git a/src/commands/docs/docs.ts b/src/commands/docs/docs.ts index 9a570b7..e2d8ec6 100644 --- a/src/commands/docs/docs.ts +++ b/src/commands/docs/docs.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Docs commands */ module.exports = { - name: 'docs', alias: ['d'], description: 'Docs commands', hidden: true, + name: 'docs', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('docs'); return 'docs'; - } + }, }; diff --git a/src/commands/docs/open.ts b/src/commands/docs/open.ts index 66a0210..97a917b 100644 --- a/src/commands/docs/open.ts +++ b/src/commands/docs/open.ts @@ -1,22 +1,23 @@ import { GluegunCommand } from 'gluegun'; import * as open from 'open'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Open documentations */ const NewCommand: GluegunCommand = { - name: 'open', alias: ['o'], description: 'Open documentation', hidden: false, + name: 'open', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { helper, parameters, print: { error }, - prompt: { ask } + prompt: { ask }, } = toolbox; const choices = ['lenne.Tech', 'NestJS', 'GlueGun']; @@ -24,15 +25,15 @@ const NewCommand: GluegunCommand = { // Get input let input = await helper.getInput(parameters.first, { name: 'doc', - showError: true + showError: true, }); if (!input || !choices.includes(input)) { // Select type const { type } = await ask({ - type: 'select', - name: 'type', + choices: choices.slice(0), message: 'Select', - choices: choices.slice(0) + name: 'type', + type: 'select', }); input = type; } @@ -57,8 +58,8 @@ const NewCommand: GluegunCommand = { } // For tests - return `docs open`; - } + return 'docs open'; + }, }; export default NewCommand; diff --git a/src/commands/fullstack/fullstack.ts b/src/commands/fullstack/fullstack.ts index 603d047..d41d90a 100644 --- a/src/commands/fullstack/fullstack.ts +++ b/src/commands/fullstack/fullstack.ts @@ -4,10 +4,10 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Fullstack commands */ module.exports = { - name: 'fullstack', alias: ['full'], description: 'Fullstack commands', hidden: true, + name: 'fullstack', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('fullstack'); return 'fullstack'; diff --git a/src/commands/fullstack/init.ts b/src/commands/fullstack/init.ts index 9be85f9..e68a043 100644 --- a/src/commands/fullstack/init.ts +++ b/src/commands/fullstack/init.ts @@ -1,4 +1,5 @@ import { GluegunCommand, patching } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; @@ -6,10 +7,10 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Create a new server */ const NewCommand: GluegunCommand = { - name: 'init', alias: ['init'], description: 'Creates a new fullstack workspace', hidden: false, + name: 'init', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -18,7 +19,7 @@ const NewCommand: GluegunCommand = { helper, parameters, print: { error, info, spin, success }, - prompt: { confirm, ask }, + prompt: { ask, confirm }, server, strings: { kebabCase }, system, @@ -49,16 +50,16 @@ const NewCommand: GluegunCommand = { // Check if directory already exists if (filesystem.exists(projectDir)) { - info(``); + info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } let frontend = ( await ask({ - type: 'input', - name: 'frontend', message: 'Angular (a) or Nuxt 3 (n)', + name: 'frontend', + type: 'input', }) ).frontend; @@ -73,7 +74,7 @@ const NewCommand: GluegunCommand = { let addToGit = false; let gitLink; if (parameters.third !== 'false') { - addToGit = parameters.third === 'true' || (await confirm(`Add workspace to a new git repository?`)); + addToGit = parameters.third === 'true' || (await confirm('Add workspace to a new git repository?')); // Check if git init is active if (addToGit) { @@ -120,7 +121,7 @@ const NewCommand: GluegunCommand = { // Clone ng-base-starter await system.run(`cd ${projectDir}/projects && git clone https://github.com/lenneTech/ng-base-starter.git app`); } else { - await system.run(`npm i -g create-nuxt-base`); + await system.run('npm i -g create-nuxt-base'); await system.run(`cd ${projectDir}/projects && create-nuxt-base app`); } @@ -136,7 +137,7 @@ const NewCommand: GluegunCommand = { if (addToGit) { // Commit changes await system.run( - `cd ${projectDir} && git add . && git commit -am "feat: ${frontend} example integrated" && git push` + `cd ${projectDir} && git add . && git commit -am "feat: ${frontend} example integrated" && git push`, ); } @@ -146,7 +147,7 @@ const NewCommand: GluegunCommand = { // Include files from https://github.com/lenneTech/nest-server-starter // Init - const serverSpinner = spin(`Integrate Nest Server Starter`); + const serverSpinner = spin('Integrate Nest Server Starter'); // Clone api await system.run(`cd ${projectDir}/projects && git clone https://github.com/lenneTech/nest-server-starter api`); @@ -158,8 +159,8 @@ const NewCommand: GluegunCommand = { // Prepare meta.json in api filesystem.write(`./${projectDir}/projects/api/src/meta.json`, { - name: `${name}-api-server`, description: `API for ${name} app`, + name: `${name}-api-server`, version: '0.0.0', }); @@ -169,7 +170,7 @@ const NewCommand: GluegunCommand = { if (addToGit) { // Commit changes await system.run( - `cd ${projectDir} && git add . && git commit -am "feat: Nest Server Starter integrated" && git push` + `cd ${projectDir} && git add . && git commit -am "feat: Nest Server Starter integrated" && git push`, ); } @@ -185,18 +186,18 @@ const NewCommand: GluegunCommand = { installSpinner.succeed('Successfull installed all packages'); // We're done, so show what to do next - info(``); + info(''); success( `Generated fullstack workspace with ${frontend} in ${projectDir} with ${name} app in ${helper.msToMinutesAndSeconds( - timer() - )}m.` + timer(), + )}m.`, ); - info(``); - info(`Next:`); + info(''); + info('Next:'); info(` Run ${name}`); info(` $ cd ${projectDir}`); - info(` $ npm run start`); - info(``); + info(' $ npm run start'); + info(''); if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); diff --git a/src/commands/git/clean.ts b/src/commands/git/clean.ts index d15f284..52220e7 100644 --- a/src/commands/git/clean.ts +++ b/src/commands/git/clean.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Removed local merged branches */ const NewCommand: GluegunCommand = { - name: 'clean', alias: ['rm'], description: 'Removed local merged branches', hidden: false, + name: 'clean', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -46,14 +47,14 @@ const NewCommand: GluegunCommand = { } await run(`git checkout ${branch}`); - info('Changed Branch to ' + branch); + info(`Changed Branch to ${branch}`); } // Start timer const timer = startTimer(); // Reset soft - const undoSpinner = spin(`Start cleaning`); + const undoSpinner = spin('Start cleaning'); const resultFetch = await run('git fetch -p'); info(resultFetch); @@ -62,7 +63,7 @@ const NewCommand: GluegunCommand = { info(resultpull); const resultDelete = await run( - `git branch --merged | egrep -v "(^\\*|main|dev|develop|beta|intern|release)" | xargs git branch -d` + 'git branch --merged | egrep -v "(^\\*|main|dev|develop|beta|intern|release)" | xargs git branch -d', ); info(resultDelete); @@ -73,7 +74,7 @@ const NewCommand: GluegunCommand = { info(''); // For tests - return `cleaned local`; + return 'cleaned local'; }, }; diff --git a/src/commands/git/clear.ts b/src/commands/git/clear.ts index 92a0066..1401b4f 100644 --- a/src/commands/git/clear.ts +++ b/src/commands/git/clear.ts @@ -1,23 +1,24 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Undo current changes */ const NewCommand: GluegunCommand = { - name: 'clear', alias: ['cl'], description: 'Undo current changes', hidden: false, + name: 'clear', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { git, helper, parameters, - prompt: { confirm }, print: { info, spin, success }, - system: { run, startTimer } + prompt: { confirm }, + system: { run, startTimer }, } = toolbox; // Check git @@ -47,7 +48,7 @@ const NewCommand: GluegunCommand = { // For tests return `clear branch ${branch}`; - } + }, }; export default NewCommand; diff --git a/src/commands/git/create.ts b/src/commands/git/create.ts index e166fce..f784680 100644 --- a/src/commands/git/create.ts +++ b/src/commands/git/create.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new branch */ const NewCommand: GluegunCommand = { - name: 'create', alias: ['c'], description: 'Create a new branch', hidden: false, + name: 'create', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -17,7 +18,7 @@ const NewCommand: GluegunCommand = { npm, parameters, print: { error, info, spin, success }, - system + system, } = toolbox; // Check git @@ -31,7 +32,7 @@ const NewCommand: GluegunCommand = { // Get branch const branch = await helper.getInput(parameters.first, { name: 'branch name', - showError: true + showError: true, }); if (!branch) { return; @@ -52,8 +53,8 @@ const NewCommand: GluegunCommand = { const timer = system.startTimer(); // Checkout - const createSpin = spin('Create ' + branch); - await system.run(`git fetch &&` + `git checkout ${baseBranch} &&` + 'git pull && ' + `git checkout -b ${branch}`); + const createSpin = spin(`Create ${branch}`); + await system.run('git fetch &&' + `git checkout ${baseBranch} &&` + 'git pull && ' + `git checkout -b ${branch}`); createSpin.succeed(); // Install npm packages @@ -65,7 +66,7 @@ const NewCommand: GluegunCommand = { // For tests return `created branch ${branch}`; - } + }, }; export default NewCommand; diff --git a/src/commands/git/force-pull.ts b/src/commands/git/force-pull.ts index 2eee25b..ede4c1b 100644 --- a/src/commands/git/force-pull.ts +++ b/src/commands/git/force-pull.ts @@ -1,22 +1,23 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Pull branch with loosing changes */ const NewCommand: GluegunCommand = { - name: 'force-pull', alias: ['pf', 'pull-force'], description: 'Pull branch with loosing changes', hidden: false, + name: 'force-pull', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { git, helper, parameters, - prompt, print: { info, spin, success }, + prompt, system: { run, startTimer }, } = toolbox; @@ -29,7 +30,7 @@ const NewCommand: GluegunCommand = { const branch = await git.currentBranch(); // Ask for reset - if (!parameters.options.noConfirm && !(await prompt.confirm(`You will lose your changes, are you sure?`))) { + if (!parameters.options.noConfirm && !(await prompt.confirm('You will lose your changes, are you sure?'))) { return; } diff --git a/src/commands/git/get.ts b/src/commands/git/get.ts index b235d97..9649976 100644 --- a/src/commands/git/get.ts +++ b/src/commands/git/get.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Checkout git branch */ const NewCommand: GluegunCommand = { - name: 'get', alias: ['g'], description: 'Checkout git branch', hidden: false, + name: 'get', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -61,15 +62,15 @@ const NewCommand: GluegunCommand = { // Ask for checkout branch if (branchName !== branch) { if ( - !parameters.options.noConfirm && - !(await prompt.confirm('Checkout ' + (remoteBranch ? 'remote' : 'local') + ' branch ' + branch)) + !parameters.options.noConfirm + && !(await prompt.confirm(`Checkout ${remoteBranch ? 'remote' : 'local'} branch ${branch}`)) ) { return; } } // Checkout branch - await system.run('git checkout ' + ((await git.getDefaultBranch()) || 'main')); + await system.run(`git checkout ${(await git.getDefaultBranch()) || 'main'}`); let checkoutSpin; // Handling for remote @@ -86,7 +87,7 @@ const NewCommand: GluegunCommand = { } } if (mode === 'hard') { - const prepareSpin = spin('Refresh ' + branch); + const prepareSpin = spin(`Refresh ${branch}`); await system.run(`git branch -D ${branch}`); removed = true; prepareSpin.succeed(); @@ -96,12 +97,12 @@ const NewCommand: GluegunCommand = { } // Start spin - checkoutSpin = spin('Checkout ' + branch); + checkoutSpin = spin(`Checkout ${branch}`); // Checkout remote if local branch not exists if (removed || !(await git.getBranch(branch, { local: true }))) { await system.run( - `git fetch && git checkout --track origin/${branch} && git reset --hard && git clean -fd && git pull` + `git fetch && git checkout --track origin/${branch} && git reset --hard && git clean -fd && git pull`, ); // Checkout local branch @@ -111,7 +112,7 @@ const NewCommand: GluegunCommand = { // Handling for local only } else if (branch) { - checkoutSpin = spin('Checkout ' + branch); + checkoutSpin = spin(`Checkout ${branch}`); await system.run(`git fetch && git checkout ${branch} && git reset --hard && git clean -fd`); // No branch found @@ -127,15 +128,15 @@ const NewCommand: GluegunCommand = { await npm.install(); // Init lerna projects - if (filesystem.isFile(`./lerna.json`)) { + if (filesystem.isFile('./lerna.json')) { const initProjectsSpin = spin('Init projects'); - await system.run(`npm run init --if-present`); + await system.run('npm run init --if-present'); initProjectsSpin.succeed(); } // Success info success( - `${remoteBranch ? 'Remote' : 'Local'} branch ${branch} checked out in ${helper.msToMinutesAndSeconds(timer())}m.` + `${remoteBranch ? 'Remote' : 'Local'} branch ${branch} checked out in ${helper.msToMinutesAndSeconds(timer())}m.`, ); info(''); if (!toolbox.parameters.options.fromGluegunMenu) { diff --git a/src/commands/git/git.ts b/src/commands/git/git.ts index 1140d07..740bf86 100644 --- a/src/commands/git/git.ts +++ b/src/commands/git/git.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Git commands */ module.exports = { - name: 'git', alias: ['g'], description: 'Git commands', hidden: true, + name: 'git', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('git'); return 'git'; - } + }, }; diff --git a/src/commands/git/rebase.ts b/src/commands/git/rebase.ts index 5366632..c57e7d7 100644 --- a/src/commands/git/rebase.ts +++ b/src/commands/git/rebase.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Rebase branch */ const NewCommand: GluegunCommand = { - name: 'rebase', alias: ['rb'], description: 'Rebase branch', hidden: false, + name: 'rebase', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -51,7 +52,7 @@ const NewCommand: GluegunCommand = { // Rebase const rebaseSpin = spin(`Set ${baseBranch} as base of ${branch}`); await run( - `git fetch && git checkout ${baseBranch} && git pull && git checkout ${branch} && git rebase ${baseBranch}` + `git fetch && git checkout ${baseBranch} && git pull && git checkout ${branch} && git rebase ${baseBranch}`, ); rebaseSpin.succeed(); diff --git a/src/commands/git/rename.ts b/src/commands/git/rename.ts index f2e23f2..6e3d7f6 100644 --- a/src/commands/git/rename.ts +++ b/src/commands/git/rename.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Rename branch */ const NewCommand: GluegunCommand = { - name: 'rename', alias: ['rn'], description: 'Rename branch', hidden: false, + name: 'rename', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -75,9 +76,9 @@ const NewCommand: GluegunCommand = { // Ask to delete remote branch if ( - remote && - (parameters.options.deleteRemote || - (!parameters.options.noConfirm && (await confirm(`Delete remote branch ${branch}?`)))) + remote + && (parameters.options.deleteRemote + || (!parameters.options.noConfirm && (await confirm(`Delete remote branch ${branch}?`)))) ) { timer = startTimer(); const deleteSpin = spin(`Delete remote branch ${branch}`); diff --git a/src/commands/git/reset.ts b/src/commands/git/reset.ts index 270e490..7835111 100644 --- a/src/commands/git/reset.ts +++ b/src/commands/git/reset.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Reset current branch */ const NewCommand: GluegunCommand = { - name: 'reset', alias: ['rs'], description: 'Reset current branch', hidden: false, + name: 'reset', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -32,7 +33,7 @@ const NewCommand: GluegunCommand = { // Current branch const branch = await git.currentBranch(); if (!branch) { - error(`No current branch!`); + error('No current branch!'); return; } @@ -49,20 +50,20 @@ const NewCommand: GluegunCommand = { } // Reset - const resetSpin = spin('Reset ' + branch); + const resetSpin = spin(`Reset ${branch}`); await system.run( - 'git clean -fd && ' + - 'git reset HEAD --hard && ' + - 'git checkout main && ' + - 'git fetch && ' + - 'git pull && ' + - 'git branch -D ' + - branch + - ' && ' + - 'git checkout ' + - branch + - ' && ' + - 'git pull' + 'git clean -fd && ' + + 'git reset HEAD --hard && ' + + 'git checkout main && ' + + 'git fetch && ' + + 'git pull && ' + + `git branch -D ${ + branch + } && ` + + `git checkout ${ + branch + } && ` + + 'git pull', ); resetSpin.succeed(); diff --git a/src/commands/git/squash.ts b/src/commands/git/squash.ts index 445c966..c9a9a1e 100644 --- a/src/commands/git/squash.ts +++ b/src/commands/git/squash.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Squash branch */ const NewCommand: GluegunCommand = { - name: 'squash', alias: ['s'], description: 'Squash branch', hidden: false, + name: 'squash', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -29,7 +30,7 @@ const NewCommand: GluegunCommand = { const branch = await git.currentBranch(); // Check branch - if (['master', 'main', 'release', 'test', 'develop', 'dev'].includes(branch)) { + if (['dev', 'develop', 'main', 'master', 'release', 'test'].includes(branch)) { error(`Squash of branch ${branch} is not allowed!`); return; } @@ -55,7 +56,7 @@ const NewCommand: GluegunCommand = { }); // Merge base - const mergeBaseSpin = spin('Get merge ' + base); + const mergeBaseSpin = spin(`Get merge ${base}`); const mergeBase = await git.getMergeBase(base); if (!mergeBase) { error('No merge base found!'); @@ -89,10 +90,10 @@ const NewCommand: GluegunCommand = { if (!author) { author = ( await ask({ - type: 'input', - name: 'author', initial: `${user.name} <${user.email}>`, message: 'Author: ', + name: 'author', + type: 'input', }) ).author; } @@ -102,10 +103,10 @@ const NewCommand: GluegunCommand = { if (!message) { message = ( await ask({ - type: 'input', - name: 'message', initial: squashMessage, message: 'Message: ', + name: 'message', + type: 'input', }) ).message; } @@ -132,7 +133,7 @@ const NewCommand: GluegunCommand = { const pushForceSpin = spin('Push force'); // Push - await run(`git push -f origin HEAD`); + await run('git push -f origin HEAD'); pushForceSpin.succeed(); // Success diff --git a/src/commands/git/undo.ts b/src/commands/git/undo.ts index afc944a..96f0058 100644 --- a/src/commands/git/undo.ts +++ b/src/commands/git/undo.ts @@ -1,22 +1,23 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Undo last commit (without loosing files) */ const NewCommand: GluegunCommand = { - name: 'undo', alias: ['un'], description: 'Undo last commit (without loosing files)', hidden: false, + name: 'undo', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { git, helper, parameters, - prompt: { confirm }, print: { info, spin, success }, + prompt: { confirm }, system: { run, startTimer }, } = toolbox; diff --git a/src/commands/git/update.ts b/src/commands/git/update.ts index f31b276..0c697e2 100644 --- a/src/commands/git/update.ts +++ b/src/commands/git/update.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Update branch */ const NewCommand: GluegunCommand = { - name: 'update', alias: ['up'], description: 'Update branch', hidden: false, + name: 'update', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -16,7 +17,7 @@ const NewCommand: GluegunCommand = { helper, npm, print: { info, spin, success }, - system: { run, startTimer } + system: { run, startTimer }, } = toolbox; // Check git @@ -44,7 +45,7 @@ const NewCommand: GluegunCommand = { // For tests return `updated ${branch}`; - } + }, }; export default NewCommand; diff --git a/src/commands/lt.ts b/src/commands/lt.ts index 1bb29f7..f03bf74 100644 --- a/src/commands/lt.ts +++ b/src/commands/lt.ts @@ -4,11 +4,11 @@ import { ExtendedGluegunToolbox } from '../interfaces/extended-gluegun-toolbox'; * Welcome to lenne.Tech CLI */ module.exports = { - name: 'lt', description: 'Welcome to lenne.Tech CLI', hidden: true, + name: 'lt', run: async (toolbox: ExtendedGluegunToolbox) => { - await toolbox.helper.showMenu(null, { headline: 'Welcome to lenne.Tech CLI ' + toolbox.meta.version() }); + await toolbox.helper.showMenu(null, { headline: `Welcome to lenne.Tech CLI ${toolbox.meta.version()}` }); return 'lt'; - } + }, }; diff --git a/src/commands/npm/npm.ts b/src/commands/npm/npm.ts index 26636fb..2328807 100644 --- a/src/commands/npm/npm.ts +++ b/src/commands/npm/npm.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Npm commands */ module.exports = { - name: 'npm', alias: ['n'], description: 'Npm commands', hidden: true, + name: 'npm', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('npm'); return 'npm'; - } + }, }; diff --git a/src/commands/npm/reinit.ts b/src/commands/npm/reinit.ts index 8f01729..e333674 100644 --- a/src/commands/npm/reinit.ts +++ b/src/commands/npm/reinit.ts @@ -1,15 +1,16 @@ import { GluegunCommand } from 'gluegun'; import { dirname } from 'path'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Reinitialize npm packages */ const NewCommand: GluegunCommand = { - name: 'reinit', alias: ['r'], description: 'Reinitialize npm packages', hidden: false, + name: 'reinit', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -18,14 +19,14 @@ const NewCommand: GluegunCommand = { parameters, print: { spin, success }, prompt, - system + system, } = toolbox; // Start timer const timer = system.startTimer(); // Check - const { path, data } = await npm.getPackageJson({ showError: true }); + const { data, path } = await npm.getPackageJson({ showError: true }); if (!path) { return; } @@ -42,7 +43,7 @@ const NewCommand: GluegunCommand = { installSpin.succeed(); } const updateSpin = spin('Update package.json'); - await system.run('ncu -u --packageFile ' + path); + await system.run(`ncu -u --packageFile ${path}`); updateSpin.succeed(); } @@ -58,7 +59,7 @@ const NewCommand: GluegunCommand = { await system.run('npm i -g rimraf'); } await system.run( - `cd ${dirname(path)} && rimraf package-lock.json && rimraf node_modules && npm cache clean --force && npm i` + `cd ${dirname(path)} && rimraf package-lock.json && rimraf node_modules && npm cache clean --force && npm i`, ); reinitSpin.succeed(); if (data.scripts && data.scripts['test:e2e']) { @@ -76,8 +77,8 @@ const NewCommand: GluegunCommand = { success(`Reinitialized npm packages in ${helper.msToMinutesAndSeconds(timer())}m.`); // For tests - return `npm reinit`; - } + return 'npm reinit'; + }, }; export default NewCommand; diff --git a/src/commands/npm/update.ts b/src/commands/npm/update.ts index 98ce305..2c211f2 100644 --- a/src/commands/npm/update.ts +++ b/src/commands/npm/update.ts @@ -1,35 +1,36 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Update npm packages */ const NewCommand: GluegunCommand = { - name: 'update', alias: ['u', 'up'], description: 'Update npm packages', hidden: false, + name: 'update', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { helper, npm, print: { success }, - system + system, } = toolbox; // Start timer const timer = system.startTimer(); // Update - await npm.update({ showError: true, install: true }); + await npm.update({ install: true, showError: true }); // Success info success(`Updated npm packages in ${helper.msToMinutesAndSeconds(timer())}m.`); // For tests - return `npm update`; - } + return 'npm update'; + }, }; export default NewCommand; diff --git a/src/commands/server/add-property.ts b/src/commands/server/add-property.ts index c246444..04f2e11 100644 --- a/src/commands/server/add-property.ts +++ b/src/commands/server/add-property.ts @@ -1,118 +1,161 @@ import { GluegunCommand, patching } from 'gluegun'; import { join } from 'path'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; import genModule from './module'; +import genObject from './object'; /** * Create a new server module */ const NewCommand: GluegunCommand = { - name: 'addProp', alias: ['ap'], description: 'Adds a property to a module', hidden: false, + name: 'addProp', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { filesystem, - print: { error, info, success, spin, divider }, + print: { divider, error, info, spin, success }, prompt: { ask }, server, } = toolbox; - - const refArray: string[] = []; - + function getModules() { const cwd = filesystem.cwd(); const path = cwd.substr(0, cwd.lastIndexOf('src')); const moduleDirs = join(path, 'src', 'server', 'modules'); - + return filesystem.subdirectories(moduleDirs, true); } - - - const moduleToEdit = ( + + function getObjects() { + const cwd = filesystem.cwd(); + const path = cwd.substr(0, cwd.lastIndexOf('src')); + const objectDirs = join(path, 'src', 'server', 'common', 'objects'); + + return filesystem.subdirectories(objectDirs, true); + } + + const objectOrModule = ( await ask([ { + choices: ['Module', 'Object'], + message: 'What should be updated', + name: 'input', type: 'select', + }, + ]) + ).input; + + + const elementToEdit = ( + await ask([ + { + choices: objectOrModule === 'Module' ? getModules() : getObjects(), + message: 'Choose one to update', name: 'input', - message: 'Choose one of your Modules to update', - choices: getModules(), + type: 'select', }, ]) ).input; - - + + // Check if directory const cwd = filesystem.cwd(); const path = cwd.substr(0, cwd.lastIndexOf('src')); if (!filesystem.exists(join(path, 'src'))) { - info(``); + info(''); error(`No src directory in "${path}".`); return undefined; } - - const { props, refsSet, schemaSet } = await server.addProperties({ refArray }); - + + const { objectsToAdd, props, referencesToAdd, refsSet, schemaSet } = await server.addProperties(); + const updateSpinner = spin('Updating files...'); - // const inputTemplate = server.propsForInput(props, { modelName: name, nullable: true }); - // const createTemplate = server.propsForInput(props, { modelName: name, nullable: false, create: true }); - // const modelTemplate = server.propsForModel(props, { modelName: name }); - - const moduleModel = join(path, 'src', 'server', 'modules', moduleToEdit, `${moduleToEdit}.model.ts`); - const moduleInput = join(path, 'src', 'server', 'modules', moduleToEdit, 'inputs', `${moduleToEdit}.input.ts`); - const moduleCreateInput = join(path, 'src', 'server', 'modules', moduleToEdit, 'inputs', `${moduleToEdit}-create.input.ts`); - + + const elementClass = objectOrModule === 'Module' + ? join(path, 'src', 'server', 'modules', elementToEdit, `${elementToEdit}.model.ts`) + : join(path, 'src', 'server', 'common', 'objects', elementToEdit, `${elementToEdit}.object.ts`); + const elementInput = objectOrModule === 'Module' + ? join(path, 'src', 'server', 'modules', elementToEdit, 'inputs', `${elementToEdit}.input.ts`) + : join(path, 'src', 'server', 'common', 'objects', elementToEdit, `${elementToEdit}.input.ts`); + const elementCreateInput = objectOrModule === 'Module' + ? join(path, 'src', 'server', 'modules', elementToEdit, 'inputs', `${elementToEdit}-create.input.ts`) + : join(path, 'src', 'server', 'common', 'objects', elementToEdit, `${elementToEdit}-create.input.ts`); + for (const prop in props) { - + const propObj = props[prop]; - - if (await patching.exists(moduleModel, `${propObj.name}`)) { + + // eslint-disable-next-line no-console + console.log('propObj.name'); + if (await patching.exists(elementClass, `${propObj.name}`)) { info(''); info(`Property ${propObj.name} already exists`); + + // Remove the reference for this property from the list + const refIndex = referencesToAdd.findIndex(item => item.property === propObj.name); + if (refIndex !== -1) { + referencesToAdd.splice(refIndex, 1); + } + + // Remove the object for this property from the list + const objIndex = objectsToAdd.findIndex(item => item.property === propObj.name); + if (objIndex !== -1) { + objectsToAdd.splice(objIndex, 1); + } + + // Go on continue; } // Patch the Model - await patching.patch(moduleModel, { - insert: server.constructModelPatchString(propObj, moduleToEdit), - after: new RegExp('@Field[\\s\\S]*?undefined;(?![\\s\\S]*@Field)', 'g') + await patching.patch(elementClass, { + after: new RegExp('@Field[\\s\\S]*?undefined;(?![\\s\\S]*@Field)', 'g'), + insert: server.constructModelPatchString(propObj, elementToEdit), }); // Patch the normal input.ts - await patching.patch(moduleInput, { - insert: server.constructInputPatchString(propObj, moduleToEdit), - after: new RegExp('@Field[\\s\\S]*?undefined;(?![\\s\\S]*@Field)', 'g') + await patching.patch(elementInput, { + after: new RegExp('@Field[\\s\\S]*?undefined;(?![\\s\\S]*@Field)', 'g'), + insert: server.constructInputPatchString(propObj, elementToEdit), }); // Patch the create.input.ts - await patching.patch(moduleCreateInput, { - insert: server.constructCreateInputPatchString(propObj, moduleToEdit), - after: new RegExp('@Field[\\s\\S]*?undefined;(?![\\s\\S]*@Field)', 'g') + await patching.patch(elementCreateInput, { + after: new RegExp('@Field[\\s\\S]*?undefined;(?![\\s\\S]*@Field)', 'g'), + insert: server.constructCreateInputPatchString(propObj, elementToEdit), }); - - } - + updateSpinner.succeed('All files updated successfully.'); - - if (refArray.length > 0) { + + // Add additional references + if (referencesToAdd.length > 0) { divider(); - const nextRef = refArray.shift(); - return genModule.run(toolbox, refArray, nextRef); + const nextRef = referencesToAdd.shift().reference; + await genModule.run(toolbox, { currentItem: nextRef, objectsToAdd, preventExitProcess: true, referencesToAdd }); } - + + // Add additional objects + if (objectsToAdd.length > 0) { + divider(); + const nextObj = objectsToAdd.shift().object; + await genObject.run(toolbox, { currentItem: nextObj, objectsToAdd, preventExitProcess: true, referencesToAdd }); + } + if (refsSet || schemaSet) { - success(`HINT: References / Schemata have been added, so it is necessary to add the corresponding imports!`); + success('HINT: References / Schemata have been added, so it is necessary to add the corresponding imports!'); } - + if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); } - - return `properties updated for ${name}`; - + + return `properties updated for ${elementToEdit}`; }, }; diff --git a/src/commands/server/create-secret.ts b/src/commands/server/create-secret.ts index fca76b2..3a624bb 100644 --- a/src/commands/server/create-secret.ts +++ b/src/commands/server/create-secret.ts @@ -1,15 +1,16 @@ import * as crypto from 'crypto'; import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Open regex tools in browser */ const NewCommand: GluegunCommand = { - name: 'createSecret', alias: ['cs'], description: 'Create a new secret string (for JWT config)', hidden: false, + name: 'createSecret', run: async (toolbox: ExtendedGluegunToolbox) => { const { print: { success }, @@ -17,7 +18,7 @@ const NewCommand: GluegunCommand = { success(crypto.randomBytes(512).toString('base64')); // For tests - return `secret created`; + return 'secret created'; }, }; diff --git a/src/commands/server/create.ts b/src/commands/server/create.ts index 8e1b7d7..5005f97 100644 --- a/src/commands/server/create.ts +++ b/src/commands/server/create.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new server */ const NewCommand: GluegunCommand = { - name: 'create', alias: ['c'], description: 'Creates a new server', hidden: false, + name: 'create', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -50,7 +51,7 @@ const NewCommand: GluegunCommand = { // Check if directory already exists if (filesystem.exists(projectDir)) { - info(``); + info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } @@ -85,14 +86,14 @@ const NewCommand: GluegunCommand = { // Set readme await template.generate({ - template: 'nest-server-starter/README.md.ejs', + props: { description, name }, target: `./${projectDir}/README.md`, - props: { name, description }, + template: 'nest-server-starter/README.md.ejs', }); // Replace secret or private keys and remove `nest-server` - await patching.update(`./${projectDir}/src/config.env.ts`, (content) => server.replaceSecretOrPrivateKeys(content).replace(/nest-server-/g, projectDir - + '-')); + await patching.update(`./${projectDir}/src/config.env.ts`, content => server.replaceSecretOrPrivateKeys(content).replace(/nest-server-/g, `${projectDir + }-`)); // Set package.json await patching.update(`./${projectDir}/package.json`, (config) => { @@ -129,24 +130,24 @@ const NewCommand: GluegunCommand = { if (git) { const initGitSpinner = spin('Initialize git'); await system.run( - `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"` + `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"`, ); initGitSpinner.succeed('Git initialized'); } // We're done, so show what to do next - info(``); + info(''); success( - `Generated ${name} server with lenne.Tech CLI ${meta.version()} in ${helper.msToMinutesAndSeconds(timer())}m.` + `Generated ${name} server with lenne.Tech CLI ${meta.version()} in ${helper.msToMinutesAndSeconds(timer())}m.`, ); - info(``); - info(`Next:`); - info(` Start database server (e.g. MongoDB)`); + info(''); + info('Next:'); + info(' Start database server (e.g. MongoDB)'); info(` Check config: ${projectDir}/src/config.env.ts`); info(` Go to project directory: cd ${projectDir}`); - info(` Run tests: npm run test:e2e`); - info(` Start server: npm start`); - info(``); + info(' Run tests: npm run test:e2e'); + info(' Start server: npm start'); + info(''); if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); diff --git a/src/commands/server/module.ts b/src/commands/server/module.ts index 5a29d74..c4ea324 100644 --- a/src/commands/server/module.ts +++ b/src/commands/server/module.ts @@ -1,25 +1,45 @@ import { join } from 'path'; -import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; + import { ExtendedGluegunCommand } from '../../interfaces/extended-gluegun-command'; +import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; +import genObject from './object'; /** * Create a new server module */ const NewCommand: ExtendedGluegunCommand = { - name: 'module', alias: ['m'], description: 'Creates a new server module', hidden: false, - run: async (toolbox: ExtendedGluegunToolbox, refArray: string[] = [], currentRef: string = "") => { + name: 'module', + run: async ( + toolbox: ExtendedGluegunToolbox, + options?: { + currentItem?: string; + objectsToAdd?: { object: string; property: string }[]; + preventExitProcess?: boolean; + referencesToAdd?: { property: string; reference: string }[]; + }, + ) => { + + // Options: + const { currentItem, objectsToAdd, preventExitProcess, referencesToAdd } = { + currentItem: '', + objectsToAdd: [], + preventExitProcess: false, + referencesToAdd: [], + ...options, + }; + // Retrieve the tools we need const { filesystem, helper, parameters, patching, - print: { error, info, spin, success, divider }, + print: { divider, error, info, spin, success }, server, - strings: { kebabCase, pascalCase, camelCase }, + strings: { camelCase, kebabCase, pascalCase }, system, template, } = toolbox; @@ -28,18 +48,15 @@ const NewCommand: ExtendedGluegunCommand = { const timer = system.startTimer(); // Info - let continueWithRef = false; - - if(currentRef) { - info(`Creating a new server module for ${currentRef}`) - continueWithRef = true; + if (currentItem) { + info(`Creating a new server module for ${currentItem}`); } else { - info('Create a new server module'); + info('Create a new server module'); } - const name = await helper.getInput(parameters.first, { + const name = await helper.getInput(currentItem || parameters.first, { + initial: currentItem || '', name: 'module name', - initial: continueWithRef ? currentRef : '', }); if (!name) { return; @@ -54,78 +71,78 @@ const NewCommand: ExtendedGluegunCommand = { const cwd = filesystem.cwd(); const path = cwd.substr(0, cwd.lastIndexOf('src')); if (!filesystem.exists(join(path, 'src'))) { - info(``); + info(''); error(`No src directory in "${path}".`); return undefined; } - const moduleDir = join(path, 'src', 'server', 'modules', nameKebab); - if (filesystem.exists(moduleDir)) { - info(``); - error(`Module directory "${moduleDir}" already exists.`); + const directory = join(path, 'src', 'server', 'modules', nameKebab); + if (filesystem.exists(directory)) { + info(''); + error(`Module directory "${directory}" already exists.`); return undefined; } - - const {props, refsSet, schemaSet} = await server.addProperties({ refArray }); + + const { props, refsSet, schemaSet } = await server.addProperties({ objectsToAdd, referencesToAdd }); const generateSpinner = spin('Generate files'); const inputTemplate = server.propsForInput(props, { modelName: name, nullable: true }); - const createTemplate = server.propsForInput(props, { modelName: name, nullable: false, create: true }); + const createTemplate = server.propsForInput(props, { create: true, modelName: name, nullable: false }); const modelTemplate = server.propsForModel(props, { modelName: name }); // nest-server-module/inputs/xxx.input.ts await template.generate({ + props: { imports: inputTemplate.imports, nameCamel, nameKebab, namePascal, props: inputTemplate.props }, + target: join(directory, 'inputs', `${nameKebab}.input.ts`), template: 'nest-server-module/inputs/template.input.ts.ejs', - target: join(moduleDir, 'inputs', nameKebab + '.input.ts'), - props: { nameCamel, nameKebab, namePascal, props: inputTemplate.props, imports: inputTemplate.imports }, }); // nest-server-module/inputs/xxx-create.input.ts await template.generate({ + props: { imports: createTemplate.imports, nameCamel, nameKebab, namePascal, props: createTemplate.props }, + target: join(directory, 'inputs', `${nameKebab}-create.input.ts`), template: 'nest-server-module/inputs/template-create.input.ts.ejs', - target: join(moduleDir, 'inputs', nameKebab + '-create.input.ts'), - props: { nameCamel, nameKebab, namePascal, props: createTemplate.props, imports: createTemplate.imports }, }); // nest-server-module/output/find-and-count-xxxs-result.output.ts await template.generate({ - template: 'nest-server-module/outputs/template-fac-result.output.ts.ejs', - target: join(moduleDir, 'outputs', 'find-and-count-' + nameKebab + 's-result.output.ts'), props: { nameCamel, nameKebab, namePascal }, + target: join(directory, 'outputs', `find-and-count-${nameKebab}s-result.output.ts`), + template: 'nest-server-module/outputs/template-fac-result.output.ts.ejs', }); // nest-server-module/xxx.model.ts await template.generate({ - template: 'nest-server-module/template.model.ts.ejs', - target: join(moduleDir, nameKebab + '.model.ts'), props: { + imports: modelTemplate.imports, + mappings: modelTemplate.mappings, nameCamel, nameKebab, namePascal, props: modelTemplate.props, - imports: modelTemplate.imports, - mappings: modelTemplate.mappings, }, + target: join(directory, `${nameKebab}.model.ts`), + template: 'nest-server-module/template.model.ts.ejs', }); // nest-server-module/xxx.module.ts await template.generate({ - template: 'nest-server-module/template.module.ts.ejs', - target: join(moduleDir, nameKebab + '.module.ts'), props: { nameCamel, nameKebab, namePascal }, + target: join(directory, `${nameKebab}.module.ts`), + template: 'nest-server-module/template.module.ts.ejs', }); // nest-server-module/xxx.resolver.ts await template.generate({ - template: 'nest-server-module/template.resolver.ts.ejs', - target: join(moduleDir, nameKebab + '.resolver.ts'), props: { nameCamel, nameKebab, namePascal }, + target: join(directory, `${nameKebab}.resolver.ts`), + template: 'nest-server-module/template.resolver.ts.ejs', }); // nest-server-module/xxx.service.ts await template.generate({ - template: 'nest-server-module/template.service.ts.ejs', - target: join(moduleDir, nameKebab + '.service.ts'), props: { nameCamel, nameKebab, namePascal }, + target: join(directory, `${nameKebab}.service.ts`), + template: 'nest-server-module/template.service.ts.ejs', }); generateSpinner.succeed('Files generated'); @@ -136,25 +153,25 @@ const NewCommand: ExtendedGluegunCommand = { // Import module await patching.patch(serverModule, { - insert: `import { ${namePascal}Module } from './modules/${nameKebab}/${nameKebab}.module';\n`, before: 'import', + insert: `import { ${namePascal}Module } from './modules/${nameKebab}/${nameKebab}.module';\n`, }); // Add Module await patching.patch(serverModule, { - insert: ` ${namePascal}Module,\n `, after: new RegExp('imports:[^\\]]*', 'm'), + insert: ` ${namePascal}Module,\n `, }); // Add comma if necessary await patching.patch(serverModule, { insert: '$1,$2', - replace: new RegExp('([^,\\s])(\\s*' + namePascal + 'Module,\\s*\\])'), + replace: new RegExp(`([^,\\s])(\\s*${namePascal}Module,\\s*\\])`), }); includeSpinner.succeed('Module included'); } else { - info("Don't forget to include the module into your main module."); + info('Don\'t forget to include the module into your main module.'); } // Linting @@ -163,24 +180,35 @@ const NewCommand: ExtendedGluegunCommand = { // } // We're done, so show what to do next - info(``); + info(''); success(`Generated ${namePascal}Module in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); - if (refArray.length > 0) { - divider() - const nextRef = refArray.shift(); - return NewCommand.run(toolbox, refArray, nextRef); - } + info(''); - divider() + // Add additional references + if (referencesToAdd.length > 0) { + divider(); + const nextRef = referencesToAdd.shift().reference; + await NewCommand.run(toolbox, { currentItem: nextRef, objectsToAdd, preventExitProcess: true, referencesToAdd }); + } - // We're done, so show what to do next - if (refsSet || schemaSet) { - success(`HINT: References / Schemata have been added, so it is necessary to add the corresponding imports!`); + // Add additional objects + if (objectsToAdd.length > 0) { + divider(); + const nextObj = objectsToAdd.shift().object; + await genObject.run(toolbox, { currentItem: nextObj, objectsToAdd, preventExitProcess: true, referencesToAdd }); } - if (!toolbox.parameters.options.fromGluegunMenu) { - process.exit(); + divider(); + + // We're done, so show what to do next + if (!preventExitProcess) { + if (refsSet || schemaSet) { + success('HINT: References / Schemata have been added, so it is necessary to add the corresponding imports!'); + } + + if (!toolbox.parameters.options.fromGluegunMenu) { + process.exit(); + } } // For tests diff --git a/src/commands/server/object.ts b/src/commands/server/object.ts index 22fce83..7ec4b7a 100644 --- a/src/commands/server/object.ts +++ b/src/commands/server/object.ts @@ -1,26 +1,44 @@ -import { GluegunCommand } from 'gluegun'; import { join } from 'path'; + +import { ExtendedGluegunCommand } from '../../interfaces/extended-gluegun-command'; import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; -import { ServerProps } from '../../interfaces/ServerProps.interface'; +import genModule from './module'; /** * Create a new server module */ -const NewCommand: GluegunCommand = { - name: 'object', +const NewCommand: ExtendedGluegunCommand = { alias: ['o'], description: 'Creates a new server object (with inputs)', hidden: false, - run: async (toolbox: ExtendedGluegunToolbox) => { + name: 'object', + run: async ( + toolbox: ExtendedGluegunToolbox, + options?: { + currentItem?: string; + objectsToAdd?: { object: string; property: string }[]; + preventExitProcess?: boolean; + referencesToAdd?: { property: string; reference: string }[]; + }, + ) => { + + // Options: + const { currentItem, objectsToAdd, preventExitProcess, referencesToAdd } = { + currentItem: '', + objectsToAdd: [], + preventExitProcess: false, + referencesToAdd: [], + ...options, + }; + // Retrieve the tools we need const { filesystem, helper, parameters, - print: { error, info, spin, success }, - prompt: { ask, confirm }, + print: { divider, error, info, spin, success }, server, - strings: { kebabCase, pascalCase, camelCase }, + strings: { camelCase, kebabCase, pascalCase }, system, template, } = toolbox; @@ -29,10 +47,15 @@ const NewCommand: GluegunCommand = { const timer = system.startTimer(); // Info - info('Create a new server object (with inputs)'); + if (currentItem) { + info(`Create a new server object (with inputs) for ${currentItem}`); + } else { + info('Create a new server object (with inputs)'); + } // Get name - const name = await helper.getInput(parameters.first, { + const name = await helper.getInput(currentItem || parameters.first, { + initial: currentItem || '', name: 'object name', }); if (!name) { @@ -48,134 +71,50 @@ const NewCommand: GluegunCommand = { const cwd = filesystem.cwd(); const path = cwd.substr(0, cwd.lastIndexOf('src')); if (!filesystem.exists(join(path, 'src'))) { - info(``); + info(''); error(`No src directory in "${path}".`); return undefined; } - const objectDir = join(path, 'src', 'server', 'common', 'objects', nameKebab); - if (filesystem.exists(objectDir)) { - info(``); - error(`Module directory "${objectDir}" already exists.`); + const directory = join(path, 'src', 'server', 'common', 'objects', nameKebab); + if (filesystem.exists(directory)) { + info(''); + error(`Module directory "${directory}" already exists.`); return undefined; } - // Set props - const props: Record = {}; - const setProps = true; - let refsSet = false; - let schemaSet = false; - while (setProps) { - const name = ( - await ask({ - type: 'input', - name: 'input', - message: `Enter property name (e.g. myProperty) to create new property or leave empty (ENTER)`, - }) - ).input; - if (!name.trim()) { - break; - } - - let type = ( - await ask([ - { - type: 'select', - name: 'input', - message: 'Choose property type', - choices: ['boolean', 'string', 'number', 'ObjectId / Reference', 'Date', 'enum', 'Subobject', 'Use own', 'JSON / any'], - }, - ]) - ).input; - if (type === 'ObjectId / Reference') { - type = 'ObjectId'; - } else if (type === 'JSON / any') { - type = 'JSON'; - } - - let schema: string; - if (type === 'Subobject') - { - type = ( - await ask({ - type: 'input', - name: 'input', - initial: pascalCase(name), - message: `Enter property type (e.g. MyClass)`, - }) - ).input; - schema = type; - schemaSet = true; - } - - - let reference: string; - let enumRef: string; - if (type === 'ObjectId') { - reference = ( - await ask({ - type: 'input', - name: 'input', - initial: pascalCase(name), - message: `Enter reference for ObjectId`, - }) - ).input; - if (reference) { - refsSet = true; - } - } else if (type === 'enum') { - enumRef = ( - await ask({ - type: 'input', - name: 'input', - initial: pascalCase(name) + 'Enum', - message: `Enter enum type`, - }) - ).input; - if (enumRef) { - refsSet = true; - } - } - - const arrayEnding = type.endsWith('[]'); - type = type.replace('[]', ''); - const isArray = arrayEnding || (await confirm(`Array?`)); - - const nullable = await confirm(`Nullable?`, true); - - props[name] = { name, nullable, isArray, type, reference, enumRef, schema }; - } + const { props, refsSet, schemaSet } = await server.addProperties({ objectsToAdd, referencesToAdd }); const generateSpinner = spin('Generate files'); const inputTemplate = server.propsForInput(props, { modelName: name, nullable: true }); - const createTemplate = server.propsForInput(props, { modelName: name, nullable: false, create: true }); + const createTemplate = server.propsForInput(props, { create: true, modelName: name, nullable: false }); const objectTemplate = server.propsForModel(props, { modelName: name }); // nest-server-module/inputs/xxx.input.ts await template.generate({ + props: { imports: inputTemplate.imports, nameCamel, nameKebab, namePascal, props: inputTemplate.props }, + target: join(directory, `${nameKebab}.input.ts`), template: 'nest-server-object/template.input.ts.ejs', - target: join(objectDir, nameKebab + '.input.ts'), - props: { nameCamel, nameKebab, namePascal, props: inputTemplate.props, imports: inputTemplate.imports }, }); // nest-server-object/inputs/xxx-create.input.ts await template.generate({ + props: { imports: createTemplate.imports, nameCamel, nameKebab, namePascal, props: createTemplate.props }, + target: join(directory, `${nameKebab}-create.input.ts`), template: 'nest-server-object/template-create.input.ts.ejs', - target: join(objectDir, nameKebab + '-create.input.ts'), - props: { nameCamel, nameKebab, namePascal, props: createTemplate.props, imports: createTemplate.imports }, }); // nest-server-module/xxx.model.ts await template.generate({ - template: 'nest-server-object/template.object.ts.ejs', - target: join(objectDir, nameKebab + '.object.ts'), props: { + imports: objectTemplate.imports, + mappings: objectTemplate.mappings, nameCamel, nameKebab, namePascal, props: objectTemplate.props, - imports: objectTemplate.imports, - mappings: objectTemplate.mappings, }, + target: join(directory, `${nameKebab}.object.ts`), + template: 'nest-server-object/template.object.ts.ejs', }); generateSpinner.succeed('Files generated'); @@ -186,17 +125,33 @@ const NewCommand: GluegunCommand = { // } // We're done, so show what to do next - info(``); + info(''); success(`Generated ${namePascal}Object in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); + info(''); - // We're done, so show what to do next - if (refsSet || schemaSet) { - success(`HINT: References / Schemata have been added, so it is necessary to add the corresponding imports!`); + // Add additional objects + if (objectsToAdd.length > 0) { + divider(); + const nextObj = objectsToAdd.shift().object; + await NewCommand.run(toolbox, { currentItem: nextObj, objectsToAdd, preventExitProcess: true, referencesToAdd }); + } + + // Add additional references + if (referencesToAdd.length > 0) { + divider(); + const nextRef = referencesToAdd.shift().reference; + await genModule.run(toolbox, { currentItem: nextRef, objectsToAdd, preventExitProcess: true, referencesToAdd }); } - if (!toolbox.parameters.options.fromGluegunMenu) { - process.exit(); + // We're done, so show what to do next + if (!preventExitProcess) { + if (refsSet || schemaSet) { + success('HINT: References / Schemata have been added, so it is necessary to add the corresponding imports!'); + } + + if (!toolbox.parameters.options.fromGluegunMenu) { + process.exit(); + } } // For tests diff --git a/src/commands/server/server.ts b/src/commands/server/server.ts index 5528f35..e188339 100644 --- a/src/commands/server/server.ts +++ b/src/commands/server/server.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Server commands */ module.exports = { - name: 'server', alias: ['s'], description: 'Server commands', hidden: true, + name: 'server', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('server'); return 'server'; - } + }, }; diff --git a/src/commands/server/test.ts b/src/commands/server/test.ts index acfaab8..938d10b 100644 --- a/src/commands/server/test.ts +++ b/src/commands/server/test.ts @@ -1,15 +1,16 @@ import { GluegunCommand } from 'gluegun'; import { join } from 'path'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new server */ const NewCommand: GluegunCommand = { - name: 'test', alias: ['t'], description: 'Creates a new test file', hidden: false, + name: 'test', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -45,16 +46,16 @@ const NewCommand: GluegunCommand = { const cwd = filesystem.cwd(); const path = cwd.substr(0, cwd.lastIndexOf('src')); if (!filesystem.exists(join(path, 'tests'))) { - info(``); + info(''); error(`No tests directory in "${path}".`); return undefined; } const testsDir = join(path, 'tests'); - const filePath = join(testsDir, nameKebab + '.e2e-spec.ts'); + const filePath = join(testsDir, `${nameKebab}.e2e-spec.ts`); // Check if file already exists if (filesystem.exists(filePath)) { - info(``); + info(''); error(`There's already a file named "${filePath}"`); return undefined; } @@ -63,17 +64,17 @@ const NewCommand: GluegunCommand = { // nest-server-tests/tests.e2e-spec.ts.ejs await template.generate({ - template: 'nest-server-tests/tests.e2e-spec.ts.ejs', - target: filePath, props: { nameCamel, nameKebab, namePascal }, + target: filePath, + template: 'nest-server-tests/tests.e2e-spec.ts.ejs', }); generateSpinner.succeed('Generate test file'); // We're done, so show what to do next - info(``); + info(''); success(`Generated ${namePascal} test file in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); + info(''); if (!toolbox.parameters.options.fromGluegunMenu) { process.exit(); diff --git a/src/commands/starter/chrome-extension.ts b/src/commands/starter/chrome-extension.ts index 8b00a90..eed2642 100644 --- a/src/commands/starter/chrome-extension.ts +++ b/src/commands/starter/chrome-extension.ts @@ -1,14 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new TypeScript project */ const NewCommand: GluegunCommand = { - name: 'chrome-extension', alias: ['ce'], description: 'Creates a new Chrome extension', hidden: false, + name: 'chrome-extension', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -20,7 +21,7 @@ const NewCommand: GluegunCommand = { patching, print: { error, info, spin, success }, strings: { kebabCase }, - system + system, } = toolbox; // Start timer @@ -37,7 +38,7 @@ const NewCommand: GluegunCommand = { // Get name const name = await helper.getInput(parameters.first, { name: 'Project name', - showError: true + showError: true, }); if (!name) { return; @@ -48,7 +49,7 @@ const NewCommand: GluegunCommand = { // Check if directory already exists if (filesystem.exists(projectDir)) { - info(``); + info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } @@ -70,7 +71,7 @@ const NewCommand: GluegunCommand = { // Get author const author = await helper.getInput(parameters.second, { name: 'Author', - showError: false + showError: false, }); const prepareSpinner = spin('Prepare files'); @@ -83,21 +84,21 @@ const NewCommand: GluegunCommand = { await patching.replace( `./${projectDir}/README.md`, 'This is the lenne.Tech starter for new Chrome Extension via Angular.', - '' + '', ); // Set package.json await patching.update(`./${projectDir}/package.json`, (config) => { config.author = author; config.bugs = { - url: '' + url: '', }; config.description = name; config.homepage = ''; config.name = nameKebab; config.repository = { type: 'git', - url: '' + url: '', }; config.version = '0.0.1'; return config; @@ -132,18 +133,18 @@ const NewCommand: GluegunCommand = { // Init git const initGitSpinner = spin('Initialize git'); await system.run( - `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"` + `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"`, ); initGitSpinner.succeed('Git initialized'); // We're done, so show what to do next - info(``); + info(''); success(`Generated ${name} with lenne.Tech CLI ${meta.version()} in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); + info(''); // For tests return `project ${name} created`; - } + }, }; export default NewCommand; diff --git a/src/commands/starter/starter.ts b/src/commands/starter/starter.ts index bdaffbd..18d1a3e 100644 --- a/src/commands/starter/starter.ts +++ b/src/commands/starter/starter.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Starter commands */ module.exports = { - name: 'starter', alias: ['st'], description: 'Starter commands', hidden: true, + name: 'starter', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('starter'); return 'starter'; - } + }, }; diff --git a/src/commands/tools/crypt.ts b/src/commands/tools/crypt.ts index e116cf9..2d9f7b5 100644 --- a/src/commands/tools/crypt.ts +++ b/src/commands/tools/crypt.ts @@ -1,21 +1,23 @@ import { GluegunCommand } from 'gluegun'; import { sha256 } from 'js-sha256'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; + import bcrypt = require('bcrypt'); /** * Open regex tools in browser */ const NewCommand: GluegunCommand = { - name: 'crypt', alias: ['c', 'p', 'bcrypt', 'password'], description: 'Generate a password hash with bcrypt as in nest-server', hidden: false, + name: 'crypt', run: async (toolbox: ExtendedGluegunToolbox) => { const { helper, - print: { info, error }, parameters, + print: { error, info }, } = toolbox; let password = await helper.getInput(parameters.first, { @@ -43,7 +45,7 @@ const NewCommand: GluegunCommand = { } // For tests - return `crypt`; + return 'crypt'; }, }; diff --git a/src/commands/tools/jwt-read.ts b/src/commands/tools/jwt-read.ts index cff0443..5f6511f 100644 --- a/src/commands/tools/jwt-read.ts +++ b/src/commands/tools/jwt-read.ts @@ -1,19 +1,20 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Parse a JWT and show the payload */ const NewCommand: GluegunCommand = { - name: 'jwt-read', alias: ['jr'], description: 'Parse a JWT and show the payload', hidden: false, + name: 'jwt-read', run: async (toolbox: ExtendedGluegunToolbox) => { const { helper, - print: { info, error }, parameters, + print: { error, info }, } = toolbox; const jwt = await helper.getInput(parameters.first, { @@ -27,13 +28,13 @@ const NewCommand: GluegunCommand = { } // Hash password - const data = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64').toString()) + const data = JSON.parse(Buffer.from(jwt.split('.')[1], 'base64').toString()); info(data); if (data.iat) { - info('iat: ' + new Date(data.iat * 1000)); + info(`iat: ${new Date(data.iat * 1000)}`); } if (data.exp) { - info('exp: ' + new Date(data.exp * 1000)); + info(`exp: ${new Date(data.exp * 1000)}`); } if (!toolbox.parameters.options.fromGluegunMenu) { @@ -41,7 +42,7 @@ const NewCommand: GluegunCommand = { } // For tests - return `jwt-read`; + return 'jwt-read'; }, }; diff --git a/src/commands/tools/regex.ts b/src/commands/tools/regex.ts index a39b9ff..0e9118a 100644 --- a/src/commands/tools/regex.ts +++ b/src/commands/tools/regex.ts @@ -5,16 +5,16 @@ import * as open from 'open'; * Open regex tools in browser */ const NewCommand: GluegunCommand = { - name: 'regex', alias: ['r'], description: 'Open regex tools in browser', hidden: false, + name: 'regex', run: async () => { // Open link await open('https://regex101.com'); // For tests - return `open regex`; + return 'open regex'; }, }; diff --git a/src/commands/tools/sha256.ts b/src/commands/tools/sha256.ts index b7da7bd..998d989 100644 --- a/src/commands/tools/sha256.ts +++ b/src/commands/tools/sha256.ts @@ -1,20 +1,21 @@ import { GluegunCommand } from 'gluegun'; -import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; import { sha256 } from 'js-sha256'; +import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; + /** * Open regex tools in browser */ const NewCommand: GluegunCommand = { - name: 'sha256', alias: ['h', 'hash'], description: 'Hash a string with sha256', hidden: false, + name: 'sha256', run: async (toolbox: ExtendedGluegunToolbox) => { const { helper, - print: { info }, parameters, + print: { info }, } = toolbox; const input = await helper.getInput(parameters.first, { @@ -29,7 +30,7 @@ const NewCommand: GluegunCommand = { } // For tests - return `sha256`; + return 'sha256'; }, }; diff --git a/src/commands/tools/tools.ts b/src/commands/tools/tools.ts index 7bba054..30f4dd5 100644 --- a/src/commands/tools/tools.ts +++ b/src/commands/tools/tools.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * Tool commands */ module.exports = { - name: 'tools', alias: ['t'], description: 'Tools commands', hidden: true, + name: 'tools', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('tools'); return 'tools'; - } + }, }; diff --git a/src/commands/typescript/create.ts b/src/commands/typescript/create.ts index cf575b6..7de4e0a 100644 --- a/src/commands/typescript/create.ts +++ b/src/commands/typescript/create.ts @@ -1,15 +1,16 @@ import { GluegunCommand } from 'gluegun'; import { join } from 'path'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new TypeScript project */ const NewCommand: GluegunCommand = { - name: 'create', alias: ['c', 'new', 'n'], description: 'Creates a new Typescript project', hidden: false, + name: 'create', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { @@ -22,9 +23,9 @@ const NewCommand: GluegunCommand = { patching, print: { error, info, spin, success }, prompt: { confirm }, - strings: { kebabCase, pascalCase, camelCase }, + strings: { camelCase, kebabCase, pascalCase }, system, - template + template, } = toolbox; // Start timer @@ -41,7 +42,7 @@ const NewCommand: GluegunCommand = { // Get name const name = await helper.getInput(parameters.first, { name: 'Project name', - showError: true + showError: true, }); if (!name) { return; @@ -52,7 +53,7 @@ const NewCommand: GluegunCommand = { // Check if directory already exists if (filesystem.exists(projectDir)) { - info(``); + info(''); error(`There's already a folder named "${projectDir}" here.`); return undefined; } @@ -74,7 +75,7 @@ const NewCommand: GluegunCommand = { // Get author const author = await helper.getInput(parameters.second, { name: 'Author', - showError: false + showError: false, }); const prepareSpinner = spin('Prepare files'); @@ -86,23 +87,23 @@ const NewCommand: GluegunCommand = { // Set readme await template.generate({ - template: 'typescript-starter/README.md.ejs', + props: { author, name, nameCamel, nameKebab, namePascal }, target: `./${projectDir}/README.md`, - props: { name, nameCamel, nameKebab, namePascal, author } + template: 'typescript-starter/README.md.ejs', }); // Set package.json await patching.update(`./${projectDir}/package.json`, (config) => { config.author = author; config.bugs = { - url: '' + url: '', }; config.description = name; config.homepage = ''; config.name = nameKebab; config.repository = { type: 'git', - url: '' + url: '', }; config.version = '0.0.1'; return config; @@ -121,7 +122,7 @@ const NewCommand: GluegunCommand = { const update = await confirm('Do you want to install the latest versions of the included packages?', true); if (update) { // Update - await npm.update({ cwd: join(filesystem.cwd(), projectDir), showError: true, install: true }); + await npm.update({ cwd: join(filesystem.cwd(), projectDir), install: true, showError: true }); } else { // Init npm const installSpinner = spin('Install npm packages'); @@ -132,18 +133,18 @@ const NewCommand: GluegunCommand = { // Init git const initGitSpinner = spin('Initialize git'); await system.run( - `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"` + `cd ${projectDir} && git init && git add . && git commit -am "Init via lenne.Tech CLI ${meta.version()}"`, ); initGitSpinner.succeed('Git initialized'); // We're done, so show what to do next - info(``); + info(''); success(`Generated ${name} with lenne.Tech CLI ${meta.version()} in ${helper.msToMinutesAndSeconds(timer())}m.`); - info(``); + info(''); // For tests return `project ${name} created`; - } + }, }; export default NewCommand; diff --git a/src/commands/typescript/playground.ts b/src/commands/typescript/playground.ts index 8e073a2..156abae 100644 --- a/src/commands/typescript/playground.ts +++ b/src/commands/typescript/playground.ts @@ -1,30 +1,31 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbox'; /** * Create a new branch */ const NewCommand: GluegunCommand = { - name: 'playground', alias: ['pg'], description: 'Create a new typescript playground', hidden: false, + name: 'playground', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { - typescript, print: { error }, - prompt: { ask } + prompt: { ask }, + typescript, } = toolbox; const choices = ['StackBlitz (online)', 'Web-Maker (download)', 'Simple typescript project']; // Select type const { type } = await ask({ - type: 'select', - name: 'type', + choices: choices.slice(0), message: 'Select', - choices: choices.slice(0) + name: 'type', + type: 'select', }); switch (type) { @@ -41,14 +42,14 @@ const NewCommand: GluegunCommand = { break; } default: { - error('No option selected!' + type); + error(`No option selected!${type}`); return; } } // For tests - return `typescript`; - } + return 'typescript'; + }, }; export default NewCommand; diff --git a/src/commands/typescript/typescript.ts b/src/commands/typescript/typescript.ts index d33a294..95730d3 100644 --- a/src/commands/typescript/typescript.ts +++ b/src/commands/typescript/typescript.ts @@ -4,12 +4,12 @@ import { ExtendedGluegunToolbox } from '../../interfaces/extended-gluegun-toolbo * TypeScript commands */ module.exports = { - name: 'typescript', alias: ['ts'], description: 'Typescript commands', hidden: true, + name: 'typescript', run: async (toolbox: ExtendedGluegunToolbox) => { await toolbox.helper.showMenu('typescript', { headline: 'TypeScript commands' }); return 'typescript'; - } + }, }; diff --git a/src/commands/update.ts b/src/commands/update.ts index c4d7780..d6e82f8 100644 --- a/src/commands/update.ts +++ b/src/commands/update.ts @@ -1,19 +1,20 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from '../interfaces/extended-gluegun-toolbox'; /** * Update @lenne.tech/cli */ const NewCommand: GluegunCommand = { - name: 'update', alias: ['up'], description: 'Update @lenne.tech/cli', hidden: false, + name: 'update', run: async (toolbox: ExtendedGluegunToolbox) => { // Retrieve the tools we need const { helper, - runtime: { brand } + runtime: { brand }, } = toolbox; // Update cli and show process @@ -21,7 +22,7 @@ const NewCommand: GluegunCommand = { // For tests return `updated ${brand}`; - } + }, }; export default NewCommand; diff --git a/src/extensions/git.ts b/src/extensions/git.ts index 3498b0e..b6ede51 100644 --- a/src/extensions/git.ts +++ b/src/extensions/git.ts @@ -20,7 +20,7 @@ export class Git { showError: false, text: 'There are changes, reset?', }, - options + options, ); // Toolbox features @@ -54,10 +54,10 @@ export class Git { // Process options const opts = Object.assign( { - showError: false, errorMessage: 'Please commit or stash changes!', + showError: false, }, - options + options, ); // Toolbox features @@ -95,7 +95,7 @@ export class Git { noDiffResult?: string; otherBranch?: string; showWarning?: boolean; - } + }, ) { // Process options const opts = Object.assign( @@ -104,20 +104,20 @@ export class Git { otherBranch: `origin/${branch}`, showWarning: false, }, - options + options, ); // Toolbox features const { - system, print: { warning }, + system, } = this.toolbox; // Get diff try { const diff = await system.run(`git --no-pager diff --name-only ${branch} ${opts.otherBranch}`); // Return relative file paths as array - return diff.split(/\r?\n/).filter((item) => item); + return diff.split(/\r?\n/).filter(item => item); } catch (error) { if (opts.showWarning) { warning('Branch diff could not be performed!'); @@ -170,7 +170,7 @@ export class Git { baseBranch = (await this.getDefaultBranch()) || 'dev'; } if (!branch) { - throw new Error(`Missing branch`); + throw new Error('Missing branch'); } // Toolbox features @@ -194,7 +194,7 @@ export class Git { system: { run }, } = this.toolbox; - return run(`basename $(git symbolic-ref --short refs/remotes/origin/HEAD)`); + return run('basename $(git symbolic-ref --short refs/remotes/origin/HEAD)'); } /** @@ -249,7 +249,7 @@ export class Git { remote?: boolean; // must the branch exist remotely spin?: boolean; // show spinner spinText?: string; // text of spinner - } = {} + } = {}, ) { // Check branch if (!branch) { @@ -267,7 +267,7 @@ export class Git { spin: false, spinText: 'Search branch', }, - options + options, ); // Toolbox features @@ -284,7 +284,7 @@ export class Git { } // Update infos - await system.run(`git fetch`); + await system.run('git fetch'); // Search branch if (opts.exact) { @@ -390,7 +390,7 @@ export class Git { defaultBranch: 'dev', text: 'Select branch', }, - options + options, ); // Toolbox features @@ -411,15 +411,15 @@ export class Git { // Prepare branches if (branches.includes(opts.defaultBranch)) { - branches = [opts.defaultBranch].concat(branches.filter((item) => item !== opts.defaultBranch)); + branches = [opts.defaultBranch].concat(branches.filter(item => item !== opts.defaultBranch)); } // Select branch const { branch } = await ask({ - type: 'select', - name: 'branch', - message: opts.text, choices: branches, + message: opts.text, + name: 'branch', + type: 'select', }); // Return selected branch diff --git a/src/extensions/server.ts b/src/extensions/server.ts index 35edf40..5859c90 100644 --- a/src/extensions/server.ts +++ b/src/extensions/server.ts @@ -1,13 +1,15 @@ +import * as crypto from 'crypto'; import { GluegunFilesystem } from 'gluegun'; import { PromptOptions } from 'gluegun/build/types/toolbox/prompt-enquirer-types'; import { GluegunAskResponse, GluegunEnquirer } from 'gluegun/build/types/toolbox/prompt-types'; import { join } from 'path'; -import { ExtendedGluegunToolbox } from '../interfaces/extended-gluegun-toolbox'; + import { ServerProps } from '../interfaces/ServerProps.interface'; -import * as crypto from 'crypto'; +import { ExtendedGluegunToolbox } from '../interfaces/extended-gluegun-toolbox'; -type GluegunPromptAsk = (questions: PromptOptions | ((this: GluegunEnquirer) => PromptOptions) | (PromptOptions | ((this: GluegunEnquirer) => PromptOptions))[]) => Promise; +type GluegunPromptAsk = (questions: (((this: GluegunEnquirer) => PromptOptions) | PromptOptions)[] | ((this: GluegunEnquirer) => PromptOptions) | PromptOptions) => Promise; type GluegunPromptConfirm = (message: string, initial?: boolean) => Promise; + /** * Server helper functions */ @@ -16,7 +18,7 @@ export class Server { camelCase: (value: string) => string; kebabCase: (value: string) => string; pascalCase: (value: string) => string; - + // Gluegun functions ask: GluegunPromptAsk; confirm: GluegunPromptConfirm; @@ -24,10 +26,10 @@ export class Server { // Specific imports for default modells imports: Record = { - CoreFileInfo: "import { CoreFileInfo } from '@lenne.tech/nest-server';", - GraphQLUpload: "import * as GraphQLUpload from 'graphql-upload/GraphQLUpload.js';", - FileUpload: "import type { FileUpload } from 'graphql-upload/processRequest.js';", - 'Record' : "import { JSON } from '@lenne.tech/nest-server';", + 'CoreFileInfo': 'import { CoreFileInfo } from \'@lenne.tech/nest-server\';', + 'FileUpload': 'import type { FileUpload } from \'graphql-upload/processRequest.js\';', + 'GraphQLUpload': 'import * as GraphQLUpload from \'graphql-upload/GraphQLUpload.js\';', + 'Record': 'import { JSON } from \'@lenne.tech/nest-server\';', }; // Specific types for properties in input fields @@ -36,10 +38,10 @@ export class Server { Date: 'Date', File: 'GraphQLUpload', FileInfo: 'GraphQLUpload', - Id: 'String', ID: 'String', - Json: 'JSON', + Id: 'String', JSON: 'JSON', + Json: 'JSON', Number: 'Number', ObjectId: 'String', String: 'String', @@ -52,10 +54,10 @@ export class Server { Date: 'Date', File: 'FileUpload', FileInfo: 'FileUpload', - Id: 'string', ID: 'string', - Json: 'Record', + Id: 'string', JSON: 'Record', + Json: 'Record', Number: 'number', ObjectId: 'string', String: 'string', @@ -96,8 +98,8 @@ export class Server { // Additional string for ID properties propertySuffixTypes: Record = { - Id: 'Id', ID: 'Id', + Id: 'Id', ObjectId: 'Id', }; @@ -120,25 +122,25 @@ export class Server { * Construct the addition for the create.input.ts */ constructCreateInputPatchString(propObj: ServerProps, moduleToEdit: string): string { - return ` \n\n - /** + return `\n + /** * ${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)} */ @Restricted(RoleEnum.ADMIN) @Field(() => ${propObj.isArray ? `[${propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}]` : propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}, { + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}]` : propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}, { description: '${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)}', nullable: ${propObj.nullable}, }) - ${propObj.nullable ? '@IsOptional()' : ''}${propObj.nullable ? '\n' : ''}override ${propObj.name}${propObj.nullable ? '?' : ''}: ${propObj.isArray ? `${propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}[]` : propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)} = undefined;` + ${propObj.nullable ? '@IsOptional()' : ''}${propObj.nullable ? '\n' : ''} override ${propObj.name}${propObj.nullable ? '?' : ''}: ${propObj.isArray ? `${propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}[]` : propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)} = undefined;`; } /** - * Construct the Addition for the normal input.ts - */ + * Construct the Addition for the normal input.ts + */ constructInputPatchString(propObj: ServerProps, moduleToEdit: string): string { const fieldType = propObj.isArray @@ -147,51 +149,57 @@ export class Server { ? propObj.reference : this.pascalCase(propObj.type); - - return ` -/** - * ${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)} - */ -@Restricted(RoleEnum.ADMIN) -@Field(() => ${fieldType}, { - description: '${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)}', - nullable: ${propObj.nullable}, -}) - ${propObj.nullable ? '@IsOptional()' : ''}${propObj.nullable ? '\n' : ''}override ${propObj.name}${propObj.nullable ? '?' : ''}: ${propObj.isArray ? `${propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}[]` : propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)} = undefined; -`; - + return `\n + /** + * ${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)} + */ + @Restricted(RoleEnum.ADMIN) + @Field(() => ${fieldType}, { + description: '${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)}', + nullable: ${propObj.nullable}, + }) + ${propObj.nullable ? '@IsOptional()' : ''}${propObj.nullable ? '\n' : ''} override ${propObj.name}${propObj.nullable ? '?' : ''}: ${propObj.isArray ? `${propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}[]` : propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)} = undefined; + `; } /** * Construct the addition for the Model */ constructModelPatchString(propObj: ServerProps, moduleToEdit: string): string { - return `\n\n + return `\n /** * ${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)} */ @Restricted(RoleEnum.ADMIN) @Field(() => ${propObj.isArray ? `[${propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}]` : propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}, { + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}]` : propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}, { description: '${this.pascalCase(propObj.name)} of ${this.pascalCase(moduleToEdit)}', nullable: ${propObj.nullable}, }) - @Prop(${propObj.type == 'ObjectId' ? `{ ref: ${propObj.reference}, type: Schema.Types.ObjectId }` : ''}) + @Prop(${propObj.type === 'ObjectId' ? `{ ref: ${propObj.reference}, type: Schema.Types.ObjectId }` : ''}) ${propObj.name}: ${propObj.isArray ? `${propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}[]` : propObj.type - == 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)} = undefined;` - + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)}[]` : propObj.type + === 'ObjectId' ? propObj.reference : this.pascalCase(propObj.type)} = undefined;`; } /** * Add properties to model */ - async addProperties(options?: {refArray?: string[]}): Promise<{props: Record, refsSet: boolean, schemaSet: boolean}> { - const {refArray} = {refArray: [], ...options}; - + async addProperties(options?: { + objectsToAdd?: { object: string; property: string }[]; + referencesToAdd?: { property: string; reference: string }[]; + }): Promise<{ + objectsToAdd: { object: string; property: string }[]; + props: Record; + referencesToAdd: { property: string; reference: string }[]; + refsSet: boolean; + schemaSet: boolean; + }> { + const { objectsToAdd, referencesToAdd } = { objectsToAdd: [], referencesToAdd: [], ...options }; + // Set props const props: Record = {}; const setProps = true; @@ -200,22 +208,22 @@ export class Server { while (setProps) { const name = ( await this.ask({ - type: 'input', + message: 'Enter property name (e.g. myProperty) of the property or leave empty (ENTER)', name: 'input', - message: `Enter property name (e.g. myProperty) of the property or leave empty (ENTER)`, + type: 'input', }) ).input; if (!name.trim()) { break; } - + let type = ( await this.ask([ { - type: 'select', - name: 'input', + choices: ['boolean', 'string', 'number', 'ObjectId / Reference', 'Date', 'enum', 'SubObject', 'Use own', 'JSON / any'], message: 'Choose property type', - choices: ['boolean', 'string', 'number', 'ObjectId / Reference', 'Date', 'enum', 'Subobject', 'Use own', 'JSON / any'], + name: 'input', + type: 'select', }, ]) ).input; @@ -224,72 +232,89 @@ export class Server { } else if (type === 'JSON / any') { type = 'JSON'; } - + let schema: string; - if (type === 'Subobject') { + if (type === 'SubObject') { type = ( await this.ask({ - type: 'input', - name: 'input', initial: this.pascalCase(name), - message: `Enter property type (e.g. MyClass)`, + message: 'Enter property type (e.g. MyClass)', + name: 'input', + type: 'input', }) ).input; schema = type; schemaSet = true; + if (type) { + refsSet = true; + } + + if (type?.trim()) { + let createObjAfter: boolean = false; + const cwd = this.filesystem.cwd(); + const path = cwd.substr(0, cwd.lastIndexOf('src')); + const objectsDir = join(path, 'src', 'server', 'common', 'objects', this.kebabCase(type)); + if (!this.filesystem.exists(objectsDir)) { + createObjAfter = await this.confirm('Create this Object after all the other Properties?', true); + } + + if (createObjAfter && !objectsToAdd.find(obj => obj.object === this.kebabCase(type))) { + objectsToAdd.push({ object: this.kebabCase(type), property: name }); + } + } } - + let reference: string; let enumRef: string; if (type === 'ObjectId') { reference = ( await this.ask({ - type: 'input', - name: 'input', initial: this.pascalCase(name), - message: `Enter reference for ObjectId`, + message: 'Enter reference for ObjectId', + name: 'input', + type: 'input', }) ).input; if (reference) { refsSet = true; } - - let createRefAfter: boolean = false; - const cwd = this.filesystem.cwd(); - const path = cwd.substr(0, cwd.lastIndexOf('src')); - const moduleDir = join(path, 'src', 'server', 'modules', this.kebabCase(name)); - if (!this.filesystem.exists(moduleDir)) { - createRefAfter = await this.confirm(`Create this Object after all the other Properties?`, true) - } - - if(createRefAfter) { - refArray.push(reference) + + if (reference?.trim()) { + let createRefAfter: boolean = false; + const cwd = this.filesystem.cwd(); + const path = cwd.substr(0, cwd.lastIndexOf('src')); + const moduleDir = join(path, 'src', 'server', 'modules', this.kebabCase(reference)); + if (!this.filesystem.exists(moduleDir)) { + createRefAfter = await this.confirm('Create this Module after all the other Properties?', true); + } + + if (createRefAfter && !referencesToAdd.find(ref => ref.reference === this.kebabCase(reference))) { + referencesToAdd.push({ property: name, reference: this.kebabCase(reference) }); + } } - - } else if (type === 'enum') { enumRef = ( await this.ask({ - type: 'input', + initial: `${this.pascalCase(name)}Enum`, + message: 'Enter enum type', name: 'input', - initial: this.pascalCase(name) + 'Enum', - message: `Enter enum type`, + type: 'input', }) ).input; if (enumRef) { refsSet = true; } } - + const arrayEnding = type.endsWith('[]'); type = type.replace('[]', ''); - const isArray = arrayEnding || (await this.confirm(`Array?`)); - - const nullable = await this.confirm(`Nullable?`, true); - - props[name] = { name, nullable, isArray, type, reference, enumRef, schema }; + const isArray = arrayEnding || (await this.confirm('Array?')); + + const nullable = await this.confirm('Nullable?', true); + + props[name] = { enumRef, isArray, name, nullable, reference, schema, type }; } - return {props, refsSet, schemaSet}; + return { objectsToAdd, props, referencesToAdd, refsSet, schemaSet }; } /** @@ -297,8 +322,8 @@ export class Server { */ propsForModel( props: Record, - options?: { modelName?: string; useDefault?: boolean } - ): { mappings: string; imports: string; props: string } { + options?: { modelName?: string; useDefault?: boolean }, + ): { imports: string; mappings: string; props: string } { // Preparations const config = { useDefault: true, ...options }; const { modelName, useDefault } = config; @@ -307,12 +332,14 @@ export class Server { // Check parameters if (!props || !(typeof props !== 'object') || !Object.keys(props).length) { if (!useDefault) { - return { props: '', imports: '', mappings: 'this;' }; + return { imports: '', mappings: 'this;', props: '' }; } // Use default if (!Object.keys(props).length && useDefault) { return { + imports: '', + mappings: 'mapClasses(input, {user: User}, this);', props: ` /** * Description of properties @@ -332,8 +359,6 @@ export class Server { @Prop({ type: Schema.Types.ObjectId, ref: 'User' }) testedBy: User = undefined; `, - imports: '', - mappings: 'mapClasses(input, {user: User}, this);', }; } } @@ -350,9 +375,9 @@ export class Server { ? 'String' : this.modelFieldTypes[this.pascalCase(item.type)] || this.pascalCase(item.type); const isArray = item.isArray; - const modelClassType = - this.modelClassTypes[this.pascalCase(item.type)] || - (this.standardTypes.includes(item.type) ? item.type : this.pascalCase(item.type)); + const modelClassType + = this.modelClassTypes[this.pascalCase(item.type)] + || (this.standardTypes.includes(item.type) ? item.type : this.pascalCase(item.type)); const type = this.standardTypes.includes(item.type) ? item.type : this.pascalCase(item.type); if (!this.standardTypes.includes(type) && type !== 'ObjectId' && type !== 'Enum' && type !== 'Json') { mappings[propName] = type; @@ -363,26 +388,26 @@ export class Server { if (this.imports[modelClassType]) { imports[modelClassType] = this.imports[modelClassType]; } - result += ` + result += ` /** - * ${this.pascalCase(propName) + (modelName ? ' of ' + this.pascalCase(modelName) : '')} + * ${this.pascalCase(propName) + (modelName ? ` of ${this.pascalCase(modelName)}` : '')} */ @Restricted(RoleEnum.S_EVERYONE) @Field(() => ${(isArray ? '[' : '') + (reference ? reference : modelFieldType) + (isArray ? ']' : '')}, { - description: '${this.pascalCase(propName) + (modelName ? ' of ' + this.pascalCase(modelName) : '')}', + description: '${this.pascalCase(propName) + (modelName ? ` of ${this.pascalCase(modelName)}` : '')}', nullable: ${item.nullable}, }) @Prop(${ - reference - ? (isArray ? '[' : '') + `{ ref: '${reference}', type: Schema.Types.ObjectId }` + (isArray ? ']' : '') - : schema - ? (isArray ? '[' : '') + `{ type: ${schema}Schema }` + (isArray ? ']' : '') - : enumRef - ? (isArray ? '[' : '') + `{ enum: ${item.nullable ? `Object.values(${enumRef}).concat([null])` : enumRef}, type: String }` + (isArray ? ']' : '') - : type === 'Json' - ? (isArray ? '[' : '') + `{ type: Object }` + (isArray ? ']' : '') - : '' - }) + reference + ? `${isArray ? '[' : ''}{ ref: '${reference}', type: Schema.Types.ObjectId }${isArray ? ']' : ''}` + : schema + ? `${isArray ? '[' : ''}{ type: ${schema}Schema }${isArray ? ']' : ''}` + : enumRef + ? `${isArray ? '[' : ''}{ enum: ${item.nullable ? `Object.values(${enumRef}).concat([null])` : enumRef}, type: String }${isArray ? ']' : ''}` + : type === 'Json' + ? `${isArray ? '[' : ''}{ type: Object }${isArray ? ']' : ''}` + : '' + }) ${propName}: ${ (reference ? reference : enumRef || modelClassType) + (isArray ? '[]' : '') // (reference ? ' | ' + reference + (isArray ? '[]' : '') : '') @@ -404,9 +429,9 @@ export class Server { // Return template data return { - props: result, imports: importsResult, mappings: mappingsResult.length ? `mapClasses(input, { ${mappingsResult.join(', ')} }, this);` : 'this;', + props: result, }; } @@ -415,29 +440,30 @@ export class Server { */ propsForInput( props: Record, - options?: { modelName?: string; nullable?: boolean; create?: boolean } - ): { props: string; imports: string } { + options?: { create?: boolean; modelName?: string; nullable?: boolean }, + ): { imports: string; props: string } { // Preparations const config = { useDefault: true, ...options }; - const { modelName, nullable, create, useDefault } = config; + const { create, modelName, nullable, useDefault } = config; let result = ''; // Check parameters if (!props || !(typeof props !== 'object') || !Object.keys(props).length) { if (!useDefault) { - return { props: '', imports: '' }; + return { imports: '', props: '' }; } // Use default if (!Object.keys(props).length && useDefault) { return { + imports: '', props: ` /** * Description of properties */ @Restricted(RoleEnum.ADMIN, RoleEnum.S_CREATOR) @Field(() => [String], { description: 'Properties of ${this.pascalCase(modelName)}', nullable: ${ - config.nullable ? config.nullable : `'items'` + config.nullable ? config.nullable : '\'items\'' }}) properties: string[] = undefined; @@ -450,28 +476,27 @@ export class Server { }) testedBy: User = undefined; `, - imports: '', }; } // Process configuration const imports = {}; for (const [name, item] of Object.entries(props)) { - let inputFieldType = - this.inputFieldTypes[this.pascalCase(item.type)] || - (item.enumRef + let inputFieldType + = this.inputFieldTypes[this.pascalCase(item.type)] + || (item.enumRef ? this.pascalCase(item.enumRef) : this.pascalCase(item.type) + (create ? 'CreateInput' : 'Input')); inputFieldType = this.modelFieldTypes[item.type] ? this.modelFieldTypes[item.type] : inputFieldType; - const inputClassType = - this.inputClassTypes[this.pascalCase(item.type)] || - (this.standardTypes.includes(item.type) + const inputClassType + = this.inputClassTypes[this.pascalCase(item.type)] + || (this.standardTypes.includes(item.type) ? item.type : item.enumRef - ? this.pascalCase(item.enumRef) - : this.pascalCase(item.type) + (create ? 'CreateInput' : 'Input')); + ? this.pascalCase(item.enumRef) + : this.pascalCase(item.type) + (create ? 'CreateInput' : 'Input')); const propertySuffix = this.propertySuffixTypes[this.pascalCase(item.type)] || ''; const overrideFlag = create ? 'override ' : ''; if (this.imports[inputFieldType]) { @@ -480,13 +505,13 @@ export class Server { if (this.imports[inputClassType]) { imports[inputClassType] = this.imports[inputClassType]; } - result += ` + result += ` /** - * ${this.pascalCase(name) + propertySuffix + (modelName ? ' of ' + this.pascalCase(modelName) : '')} + * ${this.pascalCase(name) + propertySuffix + (modelName ? ` of ${this.pascalCase(modelName)}` : '')} */ @Restricted(RoleEnum.S_EVERYONE) @Field(() => ${(item.isArray ? '[' : '') + inputFieldType + (item.isArray ? ']' : '')}, { - description: '${this.pascalCase(name) + propertySuffix + (modelName ? ' of ' + this.pascalCase(modelName) : '')}', + description: '${this.pascalCase(name) + propertySuffix + (modelName ? ` of ${this.pascalCase(modelName)}` : '')}', nullable: ${nullable || item.nullable}, })${nullable || item.nullable ? '\n @IsOptional()' : ''} ${overrideFlag + this.camelCase(name)}${nullable || item.nullable ? '?' : ''}: ${ @@ -503,31 +528,31 @@ export class Server { // Return template data return { - props: result, imports: importsResult, + props: result, }; } } - + /** * Replace secret or private keys in string (e.g. for config files) */ replaceSecretOrPrivateKeys(configContent: string): string { // Matches SECRET_OR_PRIVATE_KEY then any amount of anything until there is a ' const regex = /SECRET_OR_PRIVATE_KEY[^']*/gm; - + // if str aint defined its empty, when const count = (str, pattern) => { - const re = new RegExp(pattern, 'gi') - return ((str || '').match(re) || []).length - } - - const secretArr: string[] = [] - + const re = new RegExp(pattern, 'gi'); + return ((str || '').match(re) || []).length; + }; + + const secretArr: string[] = []; + for (let i = 0; i < count(configContent, regex); i++) { secretArr.push(crypto.randomBytes(512).toString('base64')); } - + // Getting the config content and using native ts to replace the content because patching.update doest accept regex let secretIndex = 0; return configContent.replace(regex, () => { diff --git a/src/extensions/tools.ts b/src/extensions/tools.ts index 57141ad..5f623d5 100644 --- a/src/extensions/tools.ts +++ b/src/extensions/tools.ts @@ -1,4 +1,5 @@ import { readFileSync, writeFileSync } from 'fs'; + import { ExtendedGluegunToolbox } from '../interfaces/extended-gluegun-toolbox'; const singleComment = Symbol('singleComment'); @@ -38,7 +39,7 @@ export class Tools { * Strip JSON comments from a string * Inspired by https://github.com/sindresorhus/strip-json-comments/blob/main/index.js */ - stripJsonComments(jsonString, { whitespace = true, trailingCommas = false } = {}) { + stripJsonComments(jsonString, { trailingCommas = false, whitespace = true } = {}) { if (typeof jsonString !== 'string') { throw new TypeError(`Expected argument \`jsonString\` to be a \`string\`, got \`${typeof jsonString}\``); } @@ -110,10 +111,10 @@ export class Tools { offset = index; commaIndex = -1; } else if ( - currentCharacter !== ' ' && - currentCharacter !== '\t' && - currentCharacter !== '\r' && - currentCharacter !== '\n' + currentCharacter !== ' ' + && currentCharacter !== '\t' + && currentCharacter !== '\r' + && currentCharacter !== '\n' ) { // Hit non-whitespace following a comma; comma is not trailing buffer += jsonString.slice(offset, index); diff --git a/src/extensions/typescript.ts b/src/extensions/typescript.ts index c68b8ff..e6a524b 100644 --- a/src/extensions/typescript.ts +++ b/src/extensions/typescript.ts @@ -1,7 +1,8 @@ import * as fs from 'fs'; +import * as open from 'open'; import { join } from 'path'; + import { ExtendedGluegunToolbox } from '../interfaces/extended-gluegun-toolbox'; -import * as open from 'open'; /** * Common helper functions @@ -22,13 +23,13 @@ export class Typescript { helper, npm, print: { error, info, spin, success }, - system: { run, startTimer, which } + system: { run, startTimer, which }, } = this.toolbox; // Get project name const name = await helper.getInput(null, { name: 'project name', - showError: true + showError: true, }); if (!name) { return; @@ -51,9 +52,9 @@ export class Typescript { await run(`cd ${dir} && npm init -y && npx gts init && npm install -D ts-node`); // Prepare package.json - const { path, data } = await npm.getPackageJson({ + const { data, path } = await npm.getPackageJson({ cwd: dir, - showError: true + showError: true, }); if (!path) { return; @@ -67,11 +68,11 @@ export class Typescript { // Overwrite index.ts const pathOfIndex = join(dir, 'src', 'index.ts'); fs.unlinkSync(pathOfIndex); - fs.writeFileSync(pathOfIndex, "// Write your code here\nconsole.log('hello world!');"); + fs.writeFileSync(pathOfIndex, '// Write your code here\nconsole.log(\'hello world!\');'); // Init git if (which('git')) { - await run(`git init`); + await run('git init'); } cloneSpin.succeed(); @@ -99,7 +100,7 @@ export class Typescript { helper, npm, print: { error, spin }, - system: { run } + system: { run }, } = this.toolbox; // Check git @@ -110,7 +111,7 @@ export class Typescript { // Get project name const name = await helper.getInput(null, { name: 'project name', - showError: true + showError: true, }); if (!name) { return; diff --git a/src/interfaces/ServerProps.interface.ts b/src/interfaces/ServerProps.interface.ts index 5f2c95d..1a49731 100644 --- a/src/interfaces/ServerProps.interface.ts +++ b/src/interfaces/ServerProps.interface.ts @@ -2,11 +2,11 @@ * Server properties for models and inputs */ export interface ServerProps { - name: string; + enumRef: string; isArray: boolean; + name: string; nullable: boolean; reference: string; - enumRef: string; schema: string; type: string; } diff --git a/src/interfaces/extended-gluegun-command.ts b/src/interfaces/extended-gluegun-command.ts index 29e07b0..328dd02 100644 --- a/src/interfaces/extended-gluegun-command.ts +++ b/src/interfaces/extended-gluegun-command.ts @@ -1,6 +1,15 @@ import { GluegunCommand } from 'gluegun'; + import { ExtendedGluegunToolbox } from './extended-gluegun-toolbox'; export interface ExtendedGluegunCommand extends GluegunCommand { - run: (toolbox: ExtendedGluegunToolbox, refArr?: string[], currentRef?: string) => void; + run: ( + toolbox: ExtendedGluegunToolbox, + options?: { + currentItem?: string; + objectsToAdd?: { object: string; property: string }[]; + preventExitProcess?: boolean; + referencesToAdd?: { property: string; reference: string }[]; + } + ) => Promise; } diff --git a/src/interfaces/extended-gluegun-toolbox.ts b/src/interfaces/extended-gluegun-toolbox.ts index c534c82..68b6e8b 100644 --- a/src/interfaces/extended-gluegun-toolbox.ts +++ b/src/interfaces/extended-gluegun-toolbox.ts @@ -1,7 +1,8 @@ import { IHelperExtendedGluegunToolbox } from '@lenne.tech/cli-plugin-helper'; + import { Git } from '../extensions/git'; -import { Tools } from '../extensions/tools'; import { Server } from '../extensions/server'; +import { Tools } from '../extensions/tools'; import { Typescript } from '../extensions/typescript'; /** @@ -10,6 +11,6 @@ import { Typescript } from '../extensions/typescript'; export interface ExtendedGluegunToolbox extends IHelperExtendedGluegunToolbox { git: Git; server: Server; - typescript: Typescript; tools: Tools; + typescript: Typescript; }