From 8499c724ffc46250039a24b224b7042b4fc86357 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 16 Mar 2023 06:44:45 +0000 Subject: [PATCH 01/19] add tsconfig.json; udpate deps --- package-lock.json | 90 ++++++++++++++++++++++++++++++++++++++--------- package.json | 4 ++- tsconfig.json | 52 +++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 18 deletions(-) create mode 100644 tsconfig.json diff --git a/package-lock.json b/package-lock.json index 5b859a8ed..5274c57c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "commit-and-tag-version": "bin/cli.js" }, "devDependencies": { + "@types/node": "^18.15.3", "chai": "^4.2.0", "eslint": "^8.16.0", "eslint-config-standard": "^17.0.0", @@ -40,7 +41,8 @@ "nyc": "^15.1.0", "shelljs": "^0.8.4", "std-mocks": "^1.0.1", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.0", + "typescript": "^4.9.5" }, "engines": { "node": ">=14" @@ -621,6 +623,12 @@ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, + "node_modules/@types/node": { + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "dev": true + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -5478,6 +5486,19 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/uglify-js": { "version": "3.15.5", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.5.tgz", @@ -5687,17 +5708,17 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -5759,10 +5780,23 @@ "node": ">=8" } }, + "node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "engines": { "node": ">=12" } @@ -6233,6 +6267,12 @@ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, + "@types/node": { + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", + "dev": true + }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", @@ -9825,6 +9865,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true + }, "uglify-js": { "version": "3.15.5", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.5.tgz", @@ -9990,23 +10036,33 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.7.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", + "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==" + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" } } }, diff --git a/package.json b/package.json index f9d9207bd..15786bdca 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "yargs": "^17.0.0" }, "devDependencies": { + "@types/node": "^18.15.3", "chai": "^4.2.0", "eslint": "^8.16.0", "eslint-config-standard": "^17.0.0", @@ -68,6 +69,7 @@ "nyc": "^15.1.0", "shelljs": "^0.8.4", "std-mocks": "^1.0.1", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.0", + "typescript": "^4.9.5" } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..8222e12b4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,52 @@ +{ + "compilerOptions": { + "noEmit": true, + "target": "ES2015", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "removeComments": true, + "useUnknownInCatchVariables": true, + "allowJs": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "exactOptionalPropertyTypes": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "module": "CommonJS", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noErrorTruncation": true, + "noUncheckedIndexedAccess": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "baseUrl": ".", + "outDir": "./dist", + "types": [ + "node" + ] + }, + "include": [ + "**/*.js", + "**/*.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] + } + \ No newline at end of file From 6bf24f91e7982cca47ff80cb6cb34d3d676b15c8 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 16 Mar 2023 06:46:09 +0000 Subject: [PATCH 02/19] convert default options to typescript --- defaults.js | 43 --------------------------------- defaults.ts | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 43 deletions(-) delete mode 100644 defaults.js create mode 100644 defaults.ts diff --git a/defaults.js b/defaults.js deleted file mode 100644 index ed9884fd0..000000000 --- a/defaults.js +++ /dev/null @@ -1,43 +0,0 @@ -const spec = require('conventional-changelog-config-spec') - -const defaults = { - infile: 'CHANGELOG.md', - firstRelease: false, - sign: false, - noVerify: false, - commitAll: false, - silent: false, - tagPrefix: 'v', - releaseCount: 1, - scripts: {}, - skip: {}, - dryRun: false, - tagForce: false, - gitTagFallback: true, - preset: require.resolve('conventional-changelog-conventionalcommits'), - npmPublishHint: undefined -} - -/** - * Merge in defaults provided by the spec - */ -Object.keys(spec.properties).forEach((propertyKey) => { - const property = spec.properties[propertyKey] - defaults[propertyKey] = property.default -}) - -/** - * Sets the default for `header` (provided by the spec) for backwards - * compatibility. This should be removed in the next major version. - */ -defaults.header = - '# Changelog\n\nAll notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.\n' - -defaults.packageFiles = ['package.json', 'bower.json', 'manifest.json'] - -defaults.bumpFiles = defaults.packageFiles.concat([ - 'package-lock.json', - 'npm-shrinkwrap.json' -]) - -module.exports = defaults diff --git a/defaults.ts b/defaults.ts new file mode 100644 index 000000000..d6d625c23 --- /dev/null +++ b/defaults.ts @@ -0,0 +1,69 @@ +import spec from 'conventional-changelog-config-spec/versions/2.1.0/schema.json' + +type Defaults = { + infile: "CHANGELOG.md"; + firstRelease: false; + sign: false; + noVerify: false; + commitAll: false; + silent: false; + tagPrefix: "v"; + releaseCount: 1; + scripts: {}; + skip: {}; + dryRun: false; + tagForce: false; + gitTagFallback: true; + preset: any; + npmPublishHint: undefined; +} & { + packageFiles: ['package.json', 'bower.json', 'manifest.json'], + bumpFiles: ['package.json', 'bower.json', 'manifest.json', 'package-lock.json', 'npm-shrinkwrap.json'] +} & { + [key in keyof typeof spec.properties]: typeof spec.properties[key]["default"] +} + +const defaults: Defaults = { + infile: 'CHANGELOG.md', + firstRelease: false, + sign: false, + noVerify: false, + commitAll: false, + silent: false, + tagPrefix: 'v', + releaseCount: 1, + scripts: {}, + skip: {}, + dryRun: false, + tagForce: false, + gitTagFallback: true, + preset: require.resolve('conventional-changelog-conventionalcommits'), + npmPublishHint: undefined +} as any; + +/** + * Merge in defaults provided by the spec + */ +Object.keys(spec.properties).forEach((propertyKey) => { + const k: keyof typeof spec.properties = propertyKey as any; + const property = spec.properties[k] + // @ts-expect-error - we know that the key exists + defaults[k] = property.default +}) + +/** + * Sets the default for `header` (provided by the spec) for backwards + * compatibility. This should be removed in the next major version. + */ +defaults.header = + '# Changelog\n\nAll notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.\n' + +defaults.packageFiles = ['package.json', 'bower.json', 'manifest.json'] + +defaults.bumpFiles = [ + ...defaults.packageFiles, + 'package-lock.json', + 'npm-shrinkwrap.json' +]; + +export default defaults From d29ca8e02a0b5a7af1574dffde7077465fefee9f Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 19:09:34 +0000 Subject: [PATCH 03/19] refactor: add type-helpers, config types chore: update deps / package.json scripts; add `tsup` build tool; feat: new config API (WIP) --- command.js => command.ts | 19 ++- defaults.ts | 112 ++++++++++-------- lib/{configuration.js => configuration.ts} | 19 +-- lib/opts/index.ts | 127 +++++++++++++++++++++ package.json | 27 ++++- type-helpers.ts | 10 ++ 6 files changed, 250 insertions(+), 64 deletions(-) rename command.js => command.ts (83%) rename lib/{configuration.js => configuration.ts} (70%) create mode 100644 lib/opts/index.ts create mode 100644 type-helpers.ts diff --git a/command.js b/command.ts similarity index 83% rename from command.js rename to command.ts index afe65fe8d..00323b041 100755 --- a/command.js +++ b/command.ts @@ -1,6 +1,17 @@ -const spec = require('conventional-changelog-config-spec') -const { getConfiguration } = require('./lib/configuration') -const defaults = require('./defaults') +// @ts-nocheck +/* +I haven't been able to find API docs for yargs that explain the runtime semantics thoroughly enough to describe the types, +and the types give do not appear to agree with the usage below. This leads me to believe the types are either incorrect or incomplete, +and adding types to Yargs is outside of scope. + +As a compromise, `argv` is manually typed, and the type must be updated as changes are made below. There is a +[separate isssue](https://github.com/absolute-version/commit-and-tag-version/issues/31) for refactoring the API to bring the CLI +options to parity with the JSON options, which would likely involve breaking changes. +*/ + +import spec from 'conventional-changelog-config-spec/versions/2.1.0/schema.json' +import { getConfiguration } from './lib/configuration' +import defaults from './defaults' const yargs = require('yargs') .usage('Usage: $0 [options]') @@ -148,7 +159,7 @@ const yargs = require('yargs') .wrap(97) Object.keys(spec.properties).forEach((propertyKey) => { - const property = spec.properties[propertyKey] + const property = spec.properties[propertyKey as keyof typeof spec.properties] yargs.option(propertyKey, { type: property.type, describe: property.description, diff --git a/defaults.ts b/defaults.ts index d6d625c23..8bad42e38 100644 --- a/defaults.ts +++ b/defaults.ts @@ -1,36 +1,52 @@ -import spec from 'conventional-changelog-config-spec/versions/2.1.0/schema.json' +import spec from "conventional-changelog-config-spec/versions/2.1.0/schema.json"; -type Defaults = { - infile: "CHANGELOG.md"; - firstRelease: false; - sign: false; - noVerify: false; - commitAll: false; - silent: false; - tagPrefix: "v"; - releaseCount: 1; - scripts: {}; - skip: {}; - dryRun: false; - tagForce: false; - gitTagFallback: true; - preset: any; - npmPublishHint: undefined; -} & { - packageFiles: ['package.json', 'bower.json', 'manifest.json'], - bumpFiles: ['package.json', 'bower.json', 'manifest.json', 'package-lock.json', 'npm-shrinkwrap.json'] -} & { - [key in keyof typeof spec.properties]: typeof spec.properties[key]["default"] -} +type Defaults = Readonly< + { + infile: string; + firstRelease: boolean; + sign: boolean; + noVerify: boolean; + commitAll: boolean; + silent: boolean; + tagPrefix: string; + releaseCount: number; + scripts: { + prerelease?: string; + prebump?: string; + postbump?: string; + prechangelog?: string; + postchangelog?: string; + precommit?: string; + postcommit?: string; + pretag?: string; + posttag?: string; + }; + skip: { + bump?: boolean; + changelog?: boolean; + commit?: boolean; + tag?: boolean; + }; + dryRun: boolean; + tagForce: boolean; + gitTagFallback: boolean; + preset: string; + npmPublishHint: string | undefined; + packageFiles: readonly string[]; + bumpFiles: readonly string[]; + } & { + [key in keyof typeof spec.properties]: typeof spec.properties[key]["default"]; + } +>; -const defaults: Defaults = { - infile: 'CHANGELOG.md', +const defaults = { + infile: "CHANGELOG.md", firstRelease: false, sign: false, noVerify: false, commitAll: false, silent: false, - tagPrefix: 'v', + tagPrefix: "v", releaseCount: 1, scripts: {}, skip: {}, @@ -38,32 +54,32 @@ const defaults: Defaults = { tagForce: false, gitTagFallback: true, preset: require.resolve('conventional-changelog-conventionalcommits'), - npmPublishHint: undefined -} as any; + npmPublishHint: undefined, + /** + * Sets the default for `header` (provided by the spec) for backwards + * compatibility. This should be removed in the next major version. + */ + header: + "# Changelog\n\nAll notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.\n", + packageFiles: ["package.json", "bower.json", "manifest.json"], + bumpFiles: [ + "package.json", + "bower.json", + "manifest.json", + "package-lock.json", + "npm-shrinkwrap.json", + ], +} as const satisfies Partial>; /** * Merge in defaults provided by the spec */ Object.keys(spec.properties).forEach((propertyKey) => { - const k: keyof typeof spec.properties = propertyKey as any; - const property = spec.properties[k] + const k: keyof typeof spec.properties = + propertyKey as keyof typeof spec.properties; + const property = spec.properties[k]; // @ts-expect-error - we know that the key exists - defaults[k] = property.default -}) + defaults[k] = property.default; +}); -/** - * Sets the default for `header` (provided by the spec) for backwards - * compatibility. This should be removed in the next major version. - */ -defaults.header = - '# Changelog\n\nAll notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.\n' - -defaults.packageFiles = ['package.json', 'bower.json', 'manifest.json'] - -defaults.bumpFiles = [ - ...defaults.packageFiles, - 'package-lock.json', - 'npm-shrinkwrap.json' -]; - -export default defaults +export default defaults as any as Defaults; diff --git a/lib/configuration.js b/lib/configuration.ts similarity index 70% rename from lib/configuration.js rename to lib/configuration.ts index b73e0b1ca..d322d0157 100644 --- a/lib/configuration.js +++ b/lib/configuration.ts @@ -1,30 +1,31 @@ -const path = require('path') -const findUp = require('find-up') -const { readFileSync } = require('fs') +import path from 'path' +import findUp from 'find-up' +import { readFileSync } from 'fs' +import { CatVConfig } from './opts' const CONFIGURATION_FILES = [ '.versionrc', - '.versionrc.cjs', '.versionrc.json', + '.versionrc.cjs', '.versionrc.js' -] +] as const; -module.exports.getConfiguration = function () { - let config = {} +export async function getConfiguration () { + let config = {} as Partial const configPath = findUp.sync(CONFIGURATION_FILES) if (!configPath) { return config } const ext = path.extname(configPath) if (ext === '.js' || ext === '.cjs') { - const jsConfiguration = require(configPath) + const jsConfiguration = await import(configPath) if (typeof jsConfiguration === 'function') { config = jsConfiguration() } else { config = jsConfiguration } } else { - config = JSON.parse(readFileSync(configPath)) + config = JSON.parse(readFileSync(configPath, 'utf-8')) } /** diff --git a/lib/opts/index.ts b/lib/opts/index.ts new file mode 100644 index 000000000..349bda003 --- /dev/null +++ b/lib/opts/index.ts @@ -0,0 +1,127 @@ +import { getConfiguration as getConfigFile } from "lib/configuration"; +import { isin } from "type-helpers"; +import type { PrettyPrint } from "type-helpers"; + +type Release = "minor" | "major" | "patch"; +type Task = "changelog" | "commit" | "tag"; +type Hook = + | "prerelease" + | "prebump" + | "postbump" + | "prechangelog" + | "postchangelog" + | "precommit" + | "postcommit" + | "pretag" + | "posttag"; + +type TypePrefixes = Array< + ( + | { section: string; hidden?: boolean | undefined } + | { hidden: true; section?: string | undefined } + ) & { type: string } +>; + +type ConfigFiles = Array< + | string + | { filename: string; type: "json" | "gradle" | "plain-text" } + | { filename: string; updater: string } +>; + +/** + * __THIS SHOULD NOT CHANGE.__ + * @deprecated + * + * The configuration options for `standard-version` as of version 9.5 (The last version prior to the fork; deprecated). + */ +export type SVConfig = { + packageFiles: ConfigFiles; + bumpFiles: ConfigFiles; + releaseAs: Release; + prerelease: string | boolean; + infile: string; + message: string; + firstRelease: boolean; + sign: boolean; + noVerify: boolean; + commitAll: boolean; + silent: boolean; + tagPrefix: string; + scripts: Record; + skip: Record; + dryRun: boolean; + gitTagFallback: boolean; + path: string; + changelogHeader: string; + preset: string; + lernaPackage: string; + header: string; + types: TypePrefixes; + preMajor: boolean; + commitUrlFormat: string; + compareUrlFormat: string; + issueUrlFormat: string; + userUrlFormat: string; + releaseCommitMessageFormat: string; + issuePrefixes: string[]; +}; + +/** + * The configuration object for commit-and-tag-version, which is a superset of the conventional-changelog-config-spec (as of version 2.1.0) + * This may or may not maintain backwards compatibility with standard-version (as of version 9.5.0). + */ +export type CatVConfig = PrettyPrint< + SVConfig & { + npmPublishHint: string; + releaseCount: number; + tagForce: boolean; + } +>; + +/** The configuration options that are not supported by standard-version (as of version 9.5.0). */ +const catVOnlyFeatures = [ + "npmPublishHint", + "releaseCount", + "tagForce", +] as const satisfies ReadonlyArray>; + +export const getMergedConfig = async ( + cwd?: string +): Promise> => { + const dir = cwd ?? process.cwd(); + const json = (await import("path")).join(dir, "package.json"); + const svConfig: SVConfig = (await import(json))["standard-version"]; + const catvConfig: CatVConfig = (await import(json))["commit-and-tag-version"]; + + const config: Partial = {}; + + if (svConfig) { + for (const key in svConfig) { + // @ts-expect-error - We know this key SHOULD NOT be in svConfig, but we're going to allow it and warn the user + if (catVOnlyFeatures.includes(key)) { + console.warn( + `The "${key}" option is a feature of commit-and-tag-version, and is not supported by standard-version.${"\n"}Please move this option to the 'commit-and-tag-version' key.${"\n"}In a future version, this will throw an error.` + ); + } + if (isin(catvConfig, key)) { + console.warn( + `"standard-version"."${key}" in package.json is being overridden by "commit-and-tag-version"."${key}". in package.json` + ); + } + // @ts-expect-error - We know better than TS here. This is valid. + config[key] = svConfig[key]; + } + } + for (const key in catvConfig) { + // @ts-expect-error - We know better than TS here. This is valid. + config[key] = catvConfig[key]; + } + + return config; +}; + +export const mergeJsonOptions = async (): Promise> => { + const config1 = await getMergedConfig(); + const config2 = await getConfigFile(); + return { ...config1, ...config2 }; +}; diff --git a/package.json b/package.json index 15786bdca..c0aa9133e 100644 --- a/package.json +++ b/package.json @@ -2,14 +2,18 @@ "name": "commit-and-tag-version", "version": "11.2.0", "description": "replacement for `npm version` with automatic CHANGELOG generation", - "bin": "bin/cli.js", + "bin": "dist/bin/cli.js", + "main": "dist/index.js", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", "scripts": { "fix": "eslint . --fix", "posttest": "eslint .", "test": "nyc mocha --timeout=30000", "test:unit": "mocha --exclude test/git.spec.js", "coverage": "nyc report --reporter=lcov", - "release": "bin/cli.js" + "release": "dist/bin/cli.js", + "build": "npx tsc && tsup" }, "nyc": { "exclude": [ @@ -32,7 +36,8 @@ ], "author": "Ben Coe ", "contributors": [ - "Timothy Jones (https://github.com/TimothyJones)" + "Timothy Jones (https://github.com/TimothyJones)", + "Alec Helmturner (https://github.com/helmturner)" ], "license": "ISC", "bugs": { @@ -70,6 +75,22 @@ "shelljs": "^0.8.4", "std-mocks": "^1.0.1", "strip-ansi": "^6.0.0", + "tsup": "^6.6.3", "typescript": "^4.9.5" + }, + "tsup": { + "minify": true, + "minifyIdentifiers": false, + "treeshake": true, + "tsconfig": "tsconfig.json", + "dts": true, + "entry": [ + "./src/index.ts" + ], + "outDir": "./dist", + "format": [ + "esm", + "cjs" + ] } } diff --git a/type-helpers.ts b/type-helpers.ts new file mode 100644 index 000000000..bfaa91cc9 --- /dev/null +++ b/type-helpers.ts @@ -0,0 +1,10 @@ +export type PrettyPrint = T extends infer U extends object + ? { [K in keyof U]: U[K] } + : T extends object + ? never + : T; + +export const isin = ( + obj: T, + key: PropertyKey + ): key is keyof T => key in obj; From f2aa8bda05533a78ca0041ef0622fe1bc4d2b0d5 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 19:17:30 +0000 Subject: [PATCH 04/19] fix: correct imports in index.ts --- lib/opts/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/opts/index.ts b/lib/opts/index.ts index 349bda003..0074ed0d4 100644 --- a/lib/opts/index.ts +++ b/lib/opts/index.ts @@ -1,6 +1,6 @@ -import { getConfiguration as getConfigFile } from "lib/configuration"; -import { isin } from "type-helpers"; -import type { PrettyPrint } from "type-helpers"; +import { getConfiguration as getConfigFile } from "../configuration"; +import { isin } from "../../type-helpers"; +import type { PrettyPrint } from "../../type-helpers"; type Release = "minor" | "major" | "patch"; type Task = "changelog" | "commit" | "tag"; From d6056d0a2c44e74d2d2a6d822968c838a6c2cf77 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 19:23:46 +0000 Subject: [PATCH 05/19] chore: udpate deps, lockfile --- package-lock.json | 1626 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 4 +- 2 files changed, 1617 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 359581cc6..40e9eb734 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "yargs": "^17.0.0" }, "bin": { - "commit-and-tag-version": "bin/cli.js" + "commit-and-tag-version": "dist/bin/cli.js" }, "devDependencies": { "@types/node": "^18.15.3", @@ -41,7 +41,8 @@ "shelljs": "^0.8.4", "std-mocks": "^1.0.1", "strip-ansi": "^6.0.0", - "typescript": "^4.9.5" + "tsup": "^6.7.0", + "typescript": "^5.0.3" }, "engines": { "node": ">=14" @@ -412,6 +413,358 @@ "node": ">=6.9.0" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", + "integrity": "sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz", + "integrity": "sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.15.tgz", + "integrity": "sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz", + "integrity": "sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz", + "integrity": "sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz", + "integrity": "sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz", + "integrity": "sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz", + "integrity": "sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz", + "integrity": "sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz", + "integrity": "sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz", + "integrity": "sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz", + "integrity": "sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz", + "integrity": "sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz", + "integrity": "sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz", + "integrity": "sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz", + "integrity": "sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz", + "integrity": "sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz", + "integrity": "sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz", + "integrity": "sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz", + "integrity": "sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz", + "integrity": "sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz", + "integrity": "sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -611,6 +964,41 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -713,6 +1101,12 @@ "node": ">=4" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -777,6 +1171,15 @@ "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", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -896,6 +1299,30 @@ "semver": "^7.0.0" } }, + "node_modules/bundle-require": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.1.tgz", + "integrity": "sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==", + "dev": true, + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.17" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -1072,6 +1499,15 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -1522,6 +1958,27 @@ "node": ">=0.3.1" } }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dir-glob/node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1701,6 +2158,43 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "node_modules/esbuild": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", + "integrity": "sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.15", + "@esbuild/android-arm64": "0.17.15", + "@esbuild/android-x64": "0.17.15", + "@esbuild/darwin-arm64": "0.17.15", + "@esbuild/darwin-x64": "0.17.15", + "@esbuild/freebsd-arm64": "0.17.15", + "@esbuild/freebsd-x64": "0.17.15", + "@esbuild/linux-arm": "0.17.15", + "@esbuild/linux-arm64": "0.17.15", + "@esbuild/linux-ia32": "0.17.15", + "@esbuild/linux-loong64": "0.17.15", + "@esbuild/linux-mips64el": "0.17.15", + "@esbuild/linux-ppc64": "0.17.15", + "@esbuild/linux-riscv64": "0.17.15", + "@esbuild/linux-s390x": "0.17.15", + "@esbuild/linux-x64": "0.17.15", + "@esbuild/netbsd-x64": "0.17.15", + "@esbuild/openbsd-x64": "0.17.15", + "@esbuild/sunos-x64": "0.17.15", + "@esbuild/win32-arm64": "0.17.15", + "@esbuild/win32-ia32": "0.17.15", + "@esbuild/win32-x64": "0.17.15" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -2303,12 +2797,51 @@ "node": ">=0.10.0" } }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2321,6 +2854,15 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -2624,6 +3166,18 @@ "node": ">=10" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -2739,10 +3293,30 @@ "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2899,6 +3473,15 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, "node_modules/ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -3404,6 +3987,15 @@ "node": ">=8" } }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3517,6 +4109,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -3552,6 +4153,15 @@ "node": ">=4" } }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3588,6 +4198,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3899,6 +4515,43 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -4123,6 +4776,17 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -4187,6 +4851,18 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -4388,6 +5064,15 @@ "node": ">=6" } }, + "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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", @@ -4450,6 +5135,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -4639,6 +5339,15 @@ "node": ">=0.10.0" } }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -4703,6 +5412,35 @@ "node": ">=8" } }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4747,6 +5485,26 @@ "teleport": ">=0.2.0" } }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -5003,6 +5761,16 @@ "node": ">=4" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -5018,6 +5786,45 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.2.tgz", + "integrity": "sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -5110,6 +5917,15 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5285,6 +6101,15 @@ "node": ">=8" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -5308,6 +6133,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.31.0.tgz", + "integrity": "sha512-6QsHnkqyVEzYcaiHsOKkzOtOgdJcb8i54x6AV2hDwyZcY9ZyykGZVw6L/YN98xC0evwTP6utsWWrKRaa8QlfEQ==", + "dev": true, + "dependencies": { + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5358,6 +6224,27 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -5392,6 +6279,24 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -5400,6 +6305,12 @@ "node": ">=8" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -5433,6 +6344,72 @@ "node": ">=4" } }, + "node_modules/tsup": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.7.0.tgz", + "integrity": "sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==", + "dev": true, + "dependencies": { + "bundle-require": "^4.0.0", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.17.6", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^3.0.1", + "resolve-from": "^5.0.0", + "rollup": "^3.2.5", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=14.18" + }, + "peerDependencies": { + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5481,16 +6458,16 @@ } }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=12.20" } }, "node_modules/uglify-js": { @@ -5559,6 +6536,23 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5701,6 +6695,15 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/yargs": { "version": "17.7.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", @@ -6092,6 +7095,160 @@ "to-fast-properties": "^2.0.0" } }, + "@esbuild/android-arm": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", + "integrity": "sha512-sRSOVlLawAktpMvDyJIkdLI/c/kdRTOqo8t6ImVxg8yT7LQDUYV5Rp2FKeEosLr6ZCja9UjYAzyRSxGteSJPYg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.15.tgz", + "integrity": "sha512-0kOB6Y7Br3KDVgHeg8PRcvfLkq+AccreK///B4Z6fNZGr/tNHX0z2VywCc7PTeWp+bPvjA5WMvNXltHw5QjAIA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.15.tgz", + "integrity": "sha512-MzDqnNajQZ63YkaUWVl9uuhcWyEyh69HGpMIrf+acR4otMkfLJ4sUCxqwbCyPGicE9dVlrysI3lMcDBjGiBBcQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.15.tgz", + "integrity": "sha512-7siLjBc88Z4+6qkMDxPT2juf2e8SJxmsbNVKFY2ifWCDT72v5YJz9arlvBw5oB4W/e61H1+HDB/jnu8nNg0rLA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.15.tgz", + "integrity": "sha512-NbImBas2rXwYI52BOKTW342Tm3LTeVlaOQ4QPZ7XuWNKiO226DisFk/RyPk3T0CKZkKMuU69yOvlapJEmax7cg==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.15.tgz", + "integrity": "sha512-Xk9xMDjBVG6CfgoqlVczHAdJnCs0/oeFOspFap5NkYAmRCT2qTn1vJWA2f419iMtsHSLm+O8B6SLV/HlY5cYKg==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.15.tgz", + "integrity": "sha512-3TWAnnEOdclvb2pnfsTWtdwthPfOz7qAfcwDLcfZyGJwm1SRZIMOeB5FODVhnM93mFSPsHB9b/PmxNNbSnd0RQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.15.tgz", + "integrity": "sha512-MLTgiXWEMAMr8nmS9Gigx43zPRmEfeBfGCwxFQEMgJ5MC53QKajaclW6XDPjwJvhbebv+RzK05TQjvH3/aM4Xw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.15.tgz", + "integrity": "sha512-T0MVnYw9KT6b83/SqyznTs/3Jg2ODWrZfNccg11XjDehIved2oQfrX/wVuev9N936BpMRaTR9I1J0tdGgUgpJA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.15.tgz", + "integrity": "sha512-wp02sHs015T23zsQtU4Cj57WiteiuASHlD7rXjKUyAGYzlOKDAjqK6bk5dMi2QEl/KVOcsjwL36kD+WW7vJt8Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.15.tgz", + "integrity": "sha512-k7FsUJjGGSxwnBmMh8d7IbObWu+sF/qbwc+xKZkBe/lTAF16RqxRCnNHA7QTd3oS2AfGBAnHlXL67shV5bBThQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.15.tgz", + "integrity": "sha512-ZLWk6czDdog+Q9kE/Jfbilu24vEe/iW/Sj2d8EVsmiixQ1rM2RKH2n36qfxK4e8tVcaXkvuV3mU5zTZviE+NVQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.15.tgz", + "integrity": "sha512-mY6dPkIRAiFHRsGfOYZC8Q9rmr8vOBZBme0/j15zFUKM99d4ILY4WpOC7i/LqoY+RE7KaMaSfvY8CqjJtuO4xg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.15.tgz", + "integrity": "sha512-EcyUtxffdDtWjjwIH8sKzpDRLcVtqANooMNASO59y+xmqqRYBBM7xVLQhqF7nksIbm2yHABptoioS9RAbVMWVA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.15.tgz", + "integrity": "sha512-BuS6Jx/ezxFuHxgsfvz7T4g4YlVrmCmg7UAwboeyNNg0OzNzKsIZXpr3Sb/ZREDXWgt48RO4UQRDBxJN3B9Rbg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.15.tgz", + "integrity": "sha512-JsdS0EgEViwuKsw5tiJQo9UdQdUJYuB+Mf6HxtJSPN35vez1hlrNb1KajvKWF5Sa35j17+rW1ECEO9iNrIXbNg==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.15.tgz", + "integrity": "sha512-R6fKjtUysYGym6uXf6qyNephVUQAGtf3n2RCsOST/neIwPqRWcnc3ogcielOd6pT+J0RDR1RGcy0ZY7d3uHVLA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.15.tgz", + "integrity": "sha512-mVD4PGc26b8PI60QaPUltYKeSX0wxuy0AltC+WCTFwvKCq2+OgLP4+fFd+hZXzO2xW1HPKcytZBdjqL6FQFa7w==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.15.tgz", + "integrity": "sha512-U6tYPovOkw3459t2CBwGcFYfFRjivcJJc1WC8Q3funIwX8x4fP+R6xL/QuTPNGOblbq/EUDxj9GU+dWKX0oWlQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.15.tgz", + "integrity": "sha512-W+Z5F++wgKAleDABemiyXVnzXgvRFs+GVKThSI+mGgleLWluv0D7Diz4oQpgdpNzh4i2nNDzQtWbjJiqutRp6Q==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.15.tgz", + "integrity": "sha512-Muz/+uGgheShKGqSVS1KsHtCyEzcdOn/W/Xbh6H91Etm+wiIfwZaBn1W58MeGtfI8WA961YMHFYTthBdQs4t+w==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.15.tgz", + "integrity": "sha512-DjDa9ywLUUmjhV2Y9wUTIF+1XsmuFGvZoCmOWkli1XcNAh5t25cc7fgsCx4Zi/Uurep3TTLyDiKATgGEg61pkA==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -6250,6 +7407,32 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -6331,6 +7514,12 @@ "color-convert": "^1.9.0" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -6383,6 +7572,12 @@ "is-string": "^1.0.7" } }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "array.prototype.flat": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", @@ -6468,6 +7663,21 @@ "semver": "^7.0.0" } }, + "bundle-require": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.0.1.tgz", + "integrity": "sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==", + "dev": true, + "requires": { + "load-tsconfig": "^0.2.3" + } + }, + "cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true + }, "caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -6593,6 +7803,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -6936,6 +8152,23 @@ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -7078,6 +8311,36 @@ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true }, + "esbuild": { + "version": "0.17.15", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.15.tgz", + "integrity": "sha512-LBUV2VsUIc/iD9ME75qhT4aJj0r75abCVS0jakhFzOtR7TQsqQA5w0tZ+KTKnwl3kXE0MhskNdHDh/I5aCR1Zw==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.17.15", + "@esbuild/android-arm64": "0.17.15", + "@esbuild/android-x64": "0.17.15", + "@esbuild/darwin-arm64": "0.17.15", + "@esbuild/darwin-x64": "0.17.15", + "@esbuild/freebsd-arm64": "0.17.15", + "@esbuild/freebsd-x64": "0.17.15", + "@esbuild/linux-arm": "0.17.15", + "@esbuild/linux-arm64": "0.17.15", + "@esbuild/linux-ia32": "0.17.15", + "@esbuild/linux-loong64": "0.17.15", + "@esbuild/linux-mips64el": "0.17.15", + "@esbuild/linux-ppc64": "0.17.15", + "@esbuild/linux-riscv64": "0.17.15", + "@esbuild/linux-s390x": "0.17.15", + "@esbuild/linux-x64": "0.17.15", + "@esbuild/netbsd-x64": "0.17.15", + "@esbuild/openbsd-x64": "0.17.15", + "@esbuild/sunos-x64": "0.17.15", + "@esbuild/win32-arm64": "0.17.15", + "@esbuild/win32-ia32": "0.17.15", + "@esbuild/win32-x64": "0.17.15" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -7510,12 +8773,42 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -7528,6 +8821,15 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -7746,6 +9048,12 @@ } } }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -7833,6 +9141,20 @@ "type-fest": "^0.20.2" } }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -7936,6 +9258,12 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, "ignore": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", @@ -8295,6 +9623,12 @@ "istanbul-lib-report": "^3.0.0" } }, + "joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -8378,6 +9712,12 @@ "type-check": "~0.4.0" } }, + "lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -8406,6 +9746,12 @@ } } }, + "load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -8436,6 +9782,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -8661,6 +10013,34 @@ } } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -8831,6 +10211,17 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -8880,6 +10271,15 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, "nyc": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", @@ -9041,6 +10441,12 @@ } } }, + "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==", + "dev": true + }, "object-inspect": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.1.tgz", @@ -9085,6 +10491,15 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -9219,6 +10634,12 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true + }, "pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -9267,6 +10688,16 @@ } } }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -9298,6 +10729,12 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, "quick-lru": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", @@ -9489,6 +10926,12 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -9498,6 +10941,24 @@ "glob": "^7.1.3" } }, + "rollup": { + "version": "3.20.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.2.tgz", + "integrity": "sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -9569,6 +11030,12 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -9708,6 +11175,12 @@ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, "strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -9722,6 +11195,36 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "sucrase": { + "version": "3.31.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.31.0.tgz", + "integrity": "sha512-6QsHnkqyVEzYcaiHsOKkzOtOgdJcb8i54x6AV2hDwyZcY9ZyykGZVw6L/YN98xC0evwTP6utsWWrKRaa8QlfEQ==", + "dev": true, + "requires": { + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -9757,6 +11260,24 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9785,11 +11306,32 @@ "is-number": "^7.0.0" } }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, "trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==" }, + "ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -9819,6 +11361,45 @@ } } }, + "tsup": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.7.0.tgz", + "integrity": "sha512-L3o8hGkaHnu5TdJns+mCqFsDBo83bJ44rlK7e6VdanIvpea4ArPcU3swWGsLVbXak1PqQx/V+SSmFPujBK+zEQ==", + "dev": true, + "requires": { + "bundle-require": "^4.0.0", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.17.6", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^3.0.1", + "resolve-from": "^5.0.0", + "rollup": "^3.2.5", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } + } + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -9855,9 +11436,9 @@ } }, "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", "dev": true }, "uglify-js": { @@ -9913,6 +11494,23 @@ "spdx-expression-parse": "^3.0.0" } }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -10024,6 +11622,12 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, "yargs": { "version": "17.7.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", diff --git a/package.json b/package.json index d69de728b..f7ee98742 100644 --- a/package.json +++ b/package.json @@ -74,8 +74,8 @@ "shelljs": "^0.8.4", "std-mocks": "^1.0.1", "strip-ansi": "^6.0.0", - "tsup": "^6.6.3", - "typescript": "^4.9.5" + "tsup": "^6.7.0", + "typescript": "^5.0.3" }, "tsup": { "minify": true, From 200d78d37bea5ac136b4f387f1164bd160173aa8 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 19:39:13 +0000 Subject: [PATCH 06/19] refactor: config helper fn --- lib/opts/index.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/opts/index.ts b/lib/opts/index.ts index 0074ed0d4..b891de86b 100644 --- a/lib/opts/index.ts +++ b/lib/opts/index.ts @@ -117,11 +117,6 @@ export const getMergedConfig = async ( config[key] = catvConfig[key]; } - return config; -}; - -export const mergeJsonOptions = async (): Promise> => { - const config1 = await getMergedConfig(); const config2 = await getConfigFile(); - return { ...config1, ...config2 }; + return { ...config, ...config2 }; }; From 5e6d029e3cc9cc4e7f39e5ca4834b2c9c7e4c1a2 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 21:00:42 -0500 Subject: [PATCH 07/19] chore: remove ts-nocheck in comand.ts refactor: cleaner types in command.ts --- command.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/command.ts b/command.ts index 00323b041..e5392e34c 100755 --- a/command.ts +++ b/command.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* I haven't been able to find API docs for yargs that explain the runtime semantics thoroughly enough to describe the types, and the types give do not appear to agree with the usage below. This leads me to believe the types are either incorrect or incomplete, @@ -137,7 +136,7 @@ const yargs = require('yargs') default: defaults.npmPublishHint, describe: 'Customized publishing hint' }) - .check((argv) => { + .check((argv: any) => { if (typeof argv.scripts !== 'object' || Array.isArray(argv.scripts)) { throw Error('scripts must be an object') } else if (typeof argv.skip !== 'object' || Array.isArray(argv.skip)) { @@ -159,11 +158,12 @@ const yargs = require('yargs') .wrap(97) Object.keys(spec.properties).forEach((propertyKey) => { - const property = spec.properties[propertyKey as keyof typeof spec.properties] + const propName = propertyKey as keyof typeof spec.properties; + const property = spec.properties[propName] yargs.option(propertyKey, { type: property.type, describe: property.description, - default: defaults[propertyKey] ? defaults[propertyKey] : property.default, + default: defaults[propName] ? defaults[propName] : property.default, group: 'Preset Configuration:' }) }) From 66bfde6b930777f017964093f86b7561114b5dd8 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 21:26:34 -0500 Subject: [PATCH 08/19] refactor: improve types defaults --- defaults.ts | 61 ++++++++++++----------------------------------------- 1 file changed, 14 insertions(+), 47 deletions(-) diff --git a/defaults.ts b/defaults.ts index 8bad42e38..83d7616c3 100644 --- a/defaults.ts +++ b/defaults.ts @@ -1,43 +1,5 @@ import spec from "conventional-changelog-config-spec/versions/2.1.0/schema.json"; - -type Defaults = Readonly< - { - infile: string; - firstRelease: boolean; - sign: boolean; - noVerify: boolean; - commitAll: boolean; - silent: boolean; - tagPrefix: string; - releaseCount: number; - scripts: { - prerelease?: string; - prebump?: string; - postbump?: string; - prechangelog?: string; - postchangelog?: string; - precommit?: string; - postcommit?: string; - pretag?: string; - posttag?: string; - }; - skip: { - bump?: boolean; - changelog?: boolean; - commit?: boolean; - tag?: boolean; - }; - dryRun: boolean; - tagForce: boolean; - gitTagFallback: boolean; - preset: string; - npmPublishHint: string | undefined; - packageFiles: readonly string[]; - bumpFiles: readonly string[]; - } & { - [key in keyof typeof spec.properties]: typeof spec.properties[key]["default"]; - } ->; +import { PrettyPrint } from "type-helpers"; const defaults = { infile: "CHANGELOG.md", @@ -53,7 +15,7 @@ const defaults = { dryRun: false, tagForce: false, gitTagFallback: true, - preset: require.resolve('conventional-changelog-conventionalcommits'), + preset: require.resolve("conventional-changelog-conventionalcommits"), npmPublishHint: undefined, /** * Sets the default for `header` (provided by the spec) for backwards @@ -69,17 +31,22 @@ const defaults = { "package-lock.json", "npm-shrinkwrap.json", ], -} as const satisfies Partial>; +} as const; + +type Defaults = PrettyPrint< + typeof defaults & + Readonly<{ + [key in keyof typeof spec.properties]: typeof spec.properties[key]["default"]; + }> +>; /** * Merge in defaults provided by the spec */ Object.keys(spec.properties).forEach((propertyKey) => { - const k: keyof typeof spec.properties = - propertyKey as keyof typeof spec.properties; - const property = spec.properties[k]; - // @ts-expect-error - we know that the key exists - defaults[k] = property.default; + const property = spec.properties[propertyKey as keyof typeof spec.properties]; + // @ts-expect-error - We used a const assertion to infer literal types for intellisense, so TS thinks defaults is readonly. + defaults[propertyKey] = property.default; }); -export default defaults as any as Defaults; +export default defaults as Defaults; From 111683f350d5186b29b67f9909d62a6e1c91bbfb Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 21:28:01 -0500 Subject: [PATCH 09/19] refactor: fix type in configuration.ts --- lib/configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/configuration.ts b/lib/configuration.ts index d322d0157..a76afe880 100644 --- a/lib/configuration.ts +++ b/lib/configuration.ts @@ -11,7 +11,7 @@ const CONFIGURATION_FILES = [ ] as const; export async function getConfiguration () { - let config = {} as Partial + let config: Partial = {} const configPath = findUp.sync(CONFIGURATION_FILES) if (!configPath) { return config From c8172618f6767c68e7db18a117544973e72a5973 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 22:09:39 -0500 Subject: [PATCH 10/19] refactor: better names, style in lib/opts/index.ts --- lib/configuration.ts | 4 +- lib/opts/index.ts | 133 +++++++++++++++++++++---------------------- 2 files changed, 66 insertions(+), 71 deletions(-) diff --git a/lib/configuration.ts b/lib/configuration.ts index a76afe880..c0e11af48 100644 --- a/lib/configuration.ts +++ b/lib/configuration.ts @@ -1,7 +1,7 @@ import path from 'path' import findUp from 'find-up' import { readFileSync } from 'fs' -import { CatVConfig } from './opts' +import { Config } from './opts' const CONFIGURATION_FILES = [ '.versionrc', @@ -11,7 +11,7 @@ const CONFIGURATION_FILES = [ ] as const; export async function getConfiguration () { - let config: Partial = {} + let config: Partial = {} const configPath = findUp.sync(CONFIGURATION_FILES) if (!configPath) { return config diff --git a/lib/opts/index.ts b/lib/opts/index.ts index b891de86b..1ca736808 100644 --- a/lib/opts/index.ts +++ b/lib/opts/index.ts @@ -1,4 +1,4 @@ -import { getConfiguration as getConfigFile } from "../configuration"; +import { getConfiguration as getConfigFromFile } from "../configuration"; import { isin } from "../../type-helpers"; import type { PrettyPrint } from "../../type-helpers"; @@ -34,89 +34,84 @@ type ConfigFiles = Array< * * The configuration options for `standard-version` as of version 9.5 (The last version prior to the fork; deprecated). */ -export type SVConfig = { - packageFiles: ConfigFiles; - bumpFiles: ConfigFiles; - releaseAs: Release; - prerelease: string | boolean; - infile: string; - message: string; - firstRelease: boolean; - sign: boolean; - noVerify: boolean; - commitAll: boolean; - silent: boolean; - tagPrefix: string; - scripts: Record; - skip: Record; - dryRun: boolean; - gitTagFallback: boolean; - path: string; - changelogHeader: string; - preset: string; - lernaPackage: string; - header: string; - types: TypePrefixes; - preMajor: boolean; - commitUrlFormat: string; - compareUrlFormat: string; - issueUrlFormat: string; - userUrlFormat: string; - releaseCommitMessageFormat: string; - issuePrefixes: string[]; -}; +export type LegacyConfig = + | { + packageFiles: ConfigFiles; + bumpFiles: ConfigFiles; + releaseAs: Release; + prerelease: string | boolean; + infile: string; + message: string; + firstRelease: boolean; + sign: boolean; + noVerify: boolean; + commitAll: boolean; + silent: boolean; + tagPrefix: string; + scripts: Record; + skip: Record; + dryRun: boolean; + gitTagFallback: boolean; + path: string; + changelogHeader: string; + preset: string; + lernaPackage: string; + header: string; + types: TypePrefixes; + preMajor: boolean; + commitUrlFormat: string; + compareUrlFormat: string; + issueUrlFormat: string; + userUrlFormat: string; + releaseCommitMessageFormat: string; + issuePrefixes: string[]; + } + | undefined; /** * The configuration object for commit-and-tag-version, which is a superset of the conventional-changelog-config-spec (as of version 2.1.0) * This may or may not maintain backwards compatibility with standard-version (as of version 9.5.0). */ -export type CatVConfig = PrettyPrint< - SVConfig & { - npmPublishHint: string; - releaseCount: number; - tagForce: boolean; - } ->; +export type Config = + | PrettyPrint< + LegacyConfig & { + npmPublishHint: string; + releaseCount: number; + tagForce: boolean; + } + > + | undefined; /** The configuration options that are not supported by standard-version (as of version 9.5.0). */ const catVOnlyFeatures = [ "npmPublishHint", "releaseCount", "tagForce", -] as const satisfies ReadonlyArray>; +] as const satisfies ReadonlyArray< + Exclude, keyof LegacyConfig> +>; export const getMergedConfig = async ( cwd?: string -): Promise> => { - const dir = cwd ?? process.cwd(); - const json = (await import("path")).join(dir, "package.json"); - const svConfig: SVConfig = (await import(json))["standard-version"]; - const catvConfig: CatVConfig = (await import(json))["commit-and-tag-version"]; +): Promise> => { + const searchDir = cwd ?? process.cwd(); + const pkgJson = (await import("path")).join(searchDir, "package.json"); + const legacyConf: LegacyConfig = (await import(pkgJson))["standard-version"]; + const modernConf: Config = (await import(pkgJson))["commit-and-tag-version"]; - const config: Partial = {}; - - if (svConfig) { - for (const key in svConfig) { - // @ts-expect-error - We know this key SHOULD NOT be in svConfig, but we're going to allow it and warn the user - if (catVOnlyFeatures.includes(key)) { - console.warn( - `The "${key}" option is a feature of commit-and-tag-version, and is not supported by standard-version.${"\n"}Please move this option to the 'commit-and-tag-version' key.${"\n"}In a future version, this will throw an error.` - ); - } - if (isin(catvConfig, key)) { - console.warn( - `"standard-version"."${key}" in package.json is being overridden by "commit-and-tag-version"."${key}". in package.json` - ); - } - // @ts-expect-error - We know better than TS here. This is valid. - config[key] = svConfig[key]; + Object.keys(legacyConf ?? {}).forEach((key) => { + if (catVOnlyFeatures.includes(key as any)) { + console.warn( + `The "${key}" option is a feature of commit-and-tag-version, and is not supported by standard-version.${"\n"}Please move this option to the 'commit-and-tag-version' key.${"\n"}In a future version, this will throw an error.` + ); + } + if (modernConf && isin(modernConf, key as any)) { + console.warn( + `"standard-version"."${key}" in package.json is being overridden by "commit-and-tag-version"."${key}". in package.json` + ); } - } - for (const key in catvConfig) { - // @ts-expect-error - We know better than TS here. This is valid. - config[key] = catvConfig[key]; - } + }); - const config2 = await getConfigFile(); - return { ...config, ...config2 }; + const configFromFile = await getConfigFromFile(); + return { ...(legacyConf ?? {}), ...(modernConf ?? {}), ...(configFromFile ?? {}) }; }; From 0e57e4bb3704e074217ae52c9c25c3b2a047b298 Mon Sep 17 00:00:00 2001 From: Alec Helmturner Date: Thu, 6 Apr 2023 22:20:41 -0500 Subject: [PATCH 11/19] refactor: remoe dom libs from tsconfig --- tsconfig.json | 95 +++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 8222e12b4..cb19c36a9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,52 +1,49 @@ { - "compilerOptions": { - "noEmit": true, - "target": "ES2015", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "removeComments": true, - "useUnknownInCatchVariables": true, - "allowJs": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "exactOptionalPropertyTypes": true, - "forceConsistentCasingInFileNames": true, - "esModuleInterop": true, - "module": "CommonJS", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "noErrorTruncation": true, - "noUncheckedIndexedAccess": true, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noImplicitAny": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "strictNullChecks": true, - "strictFunctionTypes": true, - "strictBindCallApply": true, - "strictPropertyInitialization": true, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "baseUrl": ".", - "outDir": "./dist", - "types": [ - "node" - ] - }, - "include": [ - "**/*.js", - "**/*.ts" + "compilerOptions": { + "noEmit": true, + "target": "ES2015", + "lib": [ + "esnext" ], - "exclude": [ - "node_modules", - "dist" + "removeComments": true, + "useUnknownInCatchVariables": true, + "allowJs": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "exactOptionalPropertyTypes": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "module": "CommonJS", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noErrorTruncation": true, + "noUncheckedIndexedAccess": true, + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noImplicitAny": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "baseUrl": ".", + "outDir": "./dist", + "types": [ + "node" ] - } - \ No newline at end of file + }, + "include": [ + "**/*.js", + "**/*.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] +} From 040beae8eff19f1d2bb767da0da50932e792ef7b Mon Sep 17 00:00:00 2001 From: Timothy Jones Date: Fri, 7 Apr 2023 15:29:25 +1000 Subject: [PATCH 12/19] test: Roughly convert test/config-files.spec.js to typescript --- defaults.ts | 2 +- lib/opts/index.ts | 6 +- package-lock.json | 495 ++++++++++++++++++++++++++++++++++++-- package.json | 11 +- test/config-files.spec.js | 179 -------------- test/config-files.spec.ts | 209 ++++++++++++++++ tsconfig.json | 18 +- 7 files changed, 706 insertions(+), 214 deletions(-) delete mode 100644 test/config-files.spec.js create mode 100644 test/config-files.spec.ts diff --git a/defaults.ts b/defaults.ts index 83d7616c3..1b7aaa336 100644 --- a/defaults.ts +++ b/defaults.ts @@ -1,5 +1,5 @@ import spec from "conventional-changelog-config-spec/versions/2.1.0/schema.json"; -import { PrettyPrint } from "type-helpers"; +import { PrettyPrint } from "./type-helpers"; const defaults = { infile: "CHANGELOG.md", diff --git a/lib/opts/index.ts b/lib/opts/index.ts index 1ca736808..102686bdb 100644 --- a/lib/opts/index.ts +++ b/lib/opts/index.ts @@ -113,5 +113,9 @@ export const getMergedConfig = async ( }); const configFromFile = await getConfigFromFile(); - return { ...(legacyConf ?? {}), ...(modernConf ?? {}), ...(configFromFile ?? {}) }; + return { + ...(legacyConf ?? {}), + ...(modernConf ?? {}), + ...(configFromFile ?? {}), + }; }; diff --git a/package-lock.json b/package-lock.json index 40e9eb734..15d0419ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,13 +21,19 @@ "find-up": "^5.0.0", "git-semver-tags": "^4.0.0", "semver": "^7.1.1", + "ts-node": "^10.9.1", "yargs": "^17.0.0" }, "bin": { "commit-and-tag-version": "dist/bin/cli.js" }, "devDependencies": { + "@types/chai": "^4.3.4", + "@types/mocha": "^10.0.1", + "@types/mockery": "^1.4.30", "@types/node": "^18.15.3", + "@types/shelljs": "^0.8.11", + "@types/std-mocks": "^1.0.1", "chai": "^4.2.0", "eslint": "^8.16.0", "eslint-config-standard": "^17.0.0", @@ -41,6 +47,7 @@ "shelljs": "^0.8.4", "std-mocks": "^1.0.1", "strip-ansi": "^6.0.0", + "ts-mocha": "^10.0.0", "tsup": "^6.7.0", "typescript": "^5.0.3" }, @@ -413,6 +420,26 @@ "node": ">=6.9.0" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", @@ -934,7 +961,6 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -951,8 +977,7 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.13", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", - "dev": true + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.13", @@ -999,28 +1024,97 @@ "node": ">= 8" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "node_modules/@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "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 }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, + "node_modules/@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, + "node_modules/@types/mockery": { + "version": "1.4.30", + "resolved": "https://registry.npmjs.org/@types/mockery/-/mockery-1.4.30.tgz", + "integrity": "sha512-uv53RrNdhbkV/3VmVCtfImfYCWC3GTTRn3R11Whni3EJ+gb178tkZBVNj2edLY5CMrB749dQi+SJkg87jsN8UQ==", + "dev": true + }, "node_modules/@types/node": { "version": "18.15.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", - "dev": true + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, + "node_modules/@types/shelljs": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz", + "integrity": "sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==", + "dev": true, + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "node_modules/@types/std-mocks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/std-mocks/-/std-mocks-1.0.1.tgz", + "integrity": "sha512-pwOrGJ6jnqb1bw9TxrmbbHTI+7ngY8yEEkrTG7lJuwplvFT9XSwOCQC3Zb4E+e6g9yDzrFX+S1ysLZuT/07WYg==", + "dev": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -1031,7 +1125,6 @@ "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1048,6 +1141,14 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", @@ -1138,6 +1239,11 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1812,6 +1918,11 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -4334,6 +4445,11 @@ "semver": "bin/semver.js" } }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -4589,6 +4705,18 @@ "node": ">= 6" } }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/mocha": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", @@ -5934,6 +6062,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -6311,6 +6449,117 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "node_modules/ts-mocha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-10.0.0.tgz", + "integrity": "sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==", + "dev": true, + "dependencies": { + "ts-node": "7.0.1" + }, + "bin": { + "ts-mocha": "bin/ts-mocha" + }, + "engines": { + "node": ">= 6.X.X" + }, + "optionalDependencies": { + "tsconfig-paths": "^3.5.0" + }, + "peerDependencies": { + "mocha": "^3.X.X || ^4.X.X || ^5.X.X || ^6.X.X || ^7.X.X || ^8.X.X || ^9.X.X || ^10.X.X" + } + }, + "node_modules/ts-mocha/node_modules/diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/ts-mocha/node_modules/ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "dependencies": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + }, + "bin": { + "ts-node": "dist/bin.js" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ts-mocha/node_modules/yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -6461,7 +6710,6 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6527,6 +6775,11 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -6798,6 +7051,14 @@ "node": ">=12" } }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -7095,6 +7356,25 @@ "to-fast-properties": "^2.0.0" } }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, "@esbuild/android-arm": { "version": "0.17.15", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.15.tgz", @@ -7382,8 +7662,7 @@ "@jridgewell/resolve-uri": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", - "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", - "dev": true + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==" }, "@jridgewell/set-array": { "version": "1.1.1", @@ -7394,8 +7673,7 @@ "@jridgewell/sourcemap-codec": { "version": "1.4.13", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", - "dev": true + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==" }, "@jridgewell/trace-mapping": { "version": "0.3.13", @@ -7433,28 +7711,97 @@ "fastq": "^1.6.0" } }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "requires": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "@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 }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==" }, + "@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, + "@types/mockery": { + "version": "1.4.30", + "resolved": "https://registry.npmjs.org/@types/mockery/-/mockery-1.4.30.tgz", + "integrity": "sha512-uv53RrNdhbkV/3VmVCtfImfYCWC3GTTRn3R11Whni3EJ+gb178tkZBVNj2edLY5CMrB749dQi+SJkg87jsN8UQ==", + "dev": true + }, "@types/node": { "version": "18.15.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", - "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", - "dev": true + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==" }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, + "@types/shelljs": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz", + "integrity": "sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==", + "dev": true, + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, + "@types/std-mocks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/std-mocks/-/std-mocks-1.0.1.tgz", + "integrity": "sha512-pwOrGJ6jnqb1bw9TxrmbbHTI+7ngY8yEEkrTG7lJuwplvFT9XSwOCQC3Zb4E+e6g9yDzrFX+S1ysLZuT/07WYg==", + "dev": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -7464,8 +7811,7 @@ "acorn": { "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", - "dev": true + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" }, "acorn-jsx": { "version": "5.3.2", @@ -7474,6 +7820,11 @@ "dev": true, "requires": {} }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, "add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", @@ -7545,6 +7896,11 @@ "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", "dev": true }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -8051,6 +8407,11 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -9883,6 +10244,11 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -10069,6 +10435,15 @@ "kind-of": "^6.0.3" } }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, "mocha": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz", @@ -11041,6 +11416,16 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -11332,6 +11717,73 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "ts-mocha": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-mocha/-/ts-mocha-10.0.0.tgz", + "integrity": "sha512-VRfgDO+iiuJFlNB18tzOfypJ21xn2xbuZyDvJvqpTbWgkAgD17ONGr8t+Tl8rcBtOBdjXp5e/Rk+d39f7XBHRw==", + "dev": true, + "requires": { + "ts-node": "7.0.1", + "tsconfig-paths": "^3.5.0" + }, + "dependencies": { + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "ts-node": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", + "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "buffer-from": "^1.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.6", + "yn": "^2.0.0" + } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha512-uTv8J/wiWTgUTg+9vLTi//leUl5vDQS6uii/emeTb2ssY7vl6QWf2fFbIIGjnhjvbdKlU0ed7QPgY1htTC86jQ==", + "dev": true + } + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + } + } + }, "tsconfig-paths": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", @@ -11438,8 +11890,7 @@ "typescript": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.3.tgz", - "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==", - "dev": true + "integrity": "sha512-xv8mOEDnigb/tN9PSMTwSEqAnUvkoXMQlicOb0IUVDBSQCgBSaAAROUZYy2IcUy5qU6XajK5jjjO7TMWqBTKZA==" }, "uglify-js": { "version": "3.15.5", @@ -11485,6 +11936,11 @@ "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -11696,6 +12152,11 @@ } } }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index f7ee98742..b666aa8af 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "scripts": { "fix": "eslint . --fix", "posttest": "eslint .", - "test": "nyc mocha --timeout=30000", - "test:unit": "mocha --exclude test/git.spec.js", + "test": "nyc ts-mocha --type-check --timeout=30000", + "test:unit": "ts-mocha --exclude test/git.spec.js", "coverage": "nyc report --reporter=lcov", "release": "dist/bin/cli.js", "build": "npx tsc && tsup" @@ -57,10 +57,16 @@ "find-up": "^5.0.0", "git-semver-tags": "^4.0.0", "semver": "^7.1.1", + "ts-node": "^10.9.1", "yargs": "^17.0.0" }, "devDependencies": { + "@types/chai": "^4.3.4", + "@types/mocha": "^10.0.1", + "@types/mockery": "^1.4.30", "@types/node": "^18.15.3", + "@types/shelljs": "^0.8.11", + "@types/std-mocks": "^1.0.1", "chai": "^4.2.0", "eslint": "^8.16.0", "eslint-config-standard": "^17.0.0", @@ -74,6 +80,7 @@ "shelljs": "^0.8.4", "std-mocks": "^1.0.1", "strip-ansi": "^6.0.0", + "ts-mocha": "^10.0.0", "tsup": "^6.7.0", "typescript": "^5.0.3" }, diff --git a/test/config-files.spec.js b/test/config-files.spec.js deleted file mode 100644 index 9e04877c1..000000000 --- a/test/config-files.spec.js +++ /dev/null @@ -1,179 +0,0 @@ -/* global describe it beforeEach afterEach */ - -'use strict' - -const shell = require('shelljs') -const fs = require('fs') -const { Readable } = require('stream') -const mockery = require('mockery') -const stdMocks = require('std-mocks') - -require('chai').should() - -function exec () { - const cli = require('../command') - const opt = cli.parse('commit-and-tag-version') - opt.skip = { commit: true, tag: true } - return require('../index')(opt) -} - -/** - * Mock external conventional-changelog modules - * - * Mocks should be unregistered in test cleanup by calling unmock() - * - * bump?: 'major' | 'minor' | 'patch' | Error | (opt, cb) => { cb(err) | cb(null, { releaseType }) } - * changelog?: string | Error | Array string | null> - * tags?: string[] | Error - */ -function mock ({ bump, changelog, tags } = {}) { - mockery.enable({ warnOnUnregistered: false, useCleanCache: true }) - - mockery.registerMock('conventional-recommended-bump', function (opt, cb) { - if (typeof bump === 'function') bump(opt, cb) - else if (bump instanceof Error) cb(bump) - else cb(null, bump ? { releaseType: bump } : {}) - }) - - if (!Array.isArray(changelog)) changelog = [changelog] - mockery.registerMock( - 'conventional-changelog', - (opt) => - new Readable({ - read (_size) { - const next = changelog.shift() - if (next instanceof Error) { - this.destroy(next) - } else if (typeof next === 'function') { - this.push(next(opt)) - } else { - this.push(next ? Buffer.from(next, 'utf8') : null) - } - } - }) - ) - - mockery.registerMock('git-semver-tags', function (cb) { - if (tags instanceof Error) cb(tags) - else cb(null, tags | []) - }) - - stdMocks.use() - return () => stdMocks.flush() -} - -describe('config files', () => { - beforeEach(function () { - shell.rm('-rf', 'tmp') - shell.config.silent = true - shell.mkdir('tmp') - shell.cd('tmp') - fs.writeFileSync( - 'package.json', - JSON.stringify({ version: '1.0.0' }), - 'utf-8' - ) - }) - - afterEach(function () { - shell.cd('../') - shell.rm('-rf', 'tmp') - - mockery.deregisterAll() - mockery.disable() - stdMocks.restore() - - // push out prints from the Mocha reporter - const { stdout } = stdMocks.flush() - for (const str of stdout) { - if (str.startsWith(' ')) process.stdout.write(str) - } - }) - - const configKeys = ['commit-and-tag-version', 'standard-version'] - - configKeys.forEach((configKey) => { - it(`reads config from package.json key '${configKey}'`, async function () { - const issueUrlFormat = - 'https://commit-and-tag-version.company.net/browse/{{id}}' - mock({ - bump: 'minor', - changelog: ({ preset }) => preset.issueUrlFormat - }) - const pkg = { - version: '1.0.0', - repository: { url: 'git+https://company@scm.org/office/app.git' }, - [configKey]: { issueUrlFormat } - } - fs.writeFileSync('package.json', JSON.stringify(pkg), 'utf-8') - - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.include(issueUrlFormat) - }) - }) - - it('reads config from .versionrc', async function () { - const issueUrlFormat = 'http://www.foo.com/{{id}}' - const changelog = ({ preset }) => preset.issueUrlFormat - mock({ bump: 'minor', changelog }) - fs.writeFileSync('.versionrc', JSON.stringify({ issueUrlFormat }), 'utf-8') - - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.include(issueUrlFormat) - }) - - it('reads config from .versionrc.json', async function () { - const issueUrlFormat = 'http://www.foo.com/{{id}}' - const changelog = ({ preset }) => preset.issueUrlFormat - mock({ bump: 'minor', changelog }) - fs.writeFileSync( - '.versionrc.json', - JSON.stringify({ issueUrlFormat }), - 'utf-8' - ) - - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.include(issueUrlFormat) - }) - - it('evaluates a config-function from .versionrc.js', async function () { - const issueUrlFormat = 'http://www.foo.com/{{id}}' - const src = `module.exports = function() { return ${JSON.stringify({ - issueUrlFormat - })} }` - const changelog = ({ preset }) => preset.issueUrlFormat - mock({ bump: 'minor', changelog }) - fs.writeFileSync('.versionrc.js', src, 'utf-8') - - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.include(issueUrlFormat) - }) - - it('evaluates a config-object from .versionrc.js', async function () { - const issueUrlFormat = 'http://www.foo.com/{{id}}' - const src = `module.exports = ${JSON.stringify({ issueUrlFormat })}` - const changelog = ({ preset }) => preset.issueUrlFormat - mock({ bump: 'minor', changelog }) - fs.writeFileSync('.versionrc.js', src, 'utf-8') - - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.include(issueUrlFormat) - }) - - it('throws an error when a non-object is returned from .versionrc.js', async function () { - mock({ bump: 'minor' }) - fs.writeFileSync('.versionrc.js', 'module.exports = 3', 'utf-8') - try { - await exec() - /* istanbul ignore next */ - throw new Error('Unexpected success') - } catch (error) { - error.message.should.match(/Invalid configuration/) - } - }) -}) diff --git a/test/config-files.spec.ts b/test/config-files.spec.ts new file mode 100644 index 000000000..aceff6184 --- /dev/null +++ b/test/config-files.spec.ts @@ -0,0 +1,209 @@ +/* global describe it beforeEach afterEach */ + +import shell from "shelljs"; +import * as fs from "node:fs"; +import { Readable } from "stream"; +import mockery from "mockery"; +import stdMocks from "std-mocks"; +import { expect } from "chai"; + +require("chai").should(); + +function exec() { + const cli = require("../command"); + const opt = cli.parse("commit-and-tag-version"); + opt.skip = { commit: true, tag: true }; + return require("../index")(opt); +} + +// These types are all guesses to get mocha working +// TODO: Fix these types and remove the start and end comments +type Preset = { + issueUrlFormat: string; +}; + +type HasPreset = { + preset: Preset; +}; + +type ChangelogFn = (props: HasPreset) => string; + +type MockArg = { + bump?: string | Function | Error; + changelog?: ChangelogFn | ChangelogFn[]; + tags?: string[] | Error; +}; + +type BumpCallback = (n: Error | null, s?: { releaseType?: string }) => void; + +type TagsCallback = (n: Error | null, s?: string[]) => void; + +type Options = unknown; +// END GUESSES + +/** + * Mock external conventional-changelog modules + * + * Mocks should be unregistered in test cleanup by calling unmock() + * + * bump?: 'major' | 'minor' | 'patch' | Error | (opt, cb) => { cb(err) | cb(null, { releaseType }) } + * changelog?: string | Error | Array string | null> + * tags?: string[] | Error + */ +function mock({ bump, changelog, tags }: MockArg = {}) { + mockery.enable({ warnOnUnregistered: false, useCleanCache: true }); + + mockery.registerMock( + "conventional-recommended-bump", + function (opt: Options, cb: BumpCallback) { + if (typeof bump === "function") bump(opt, cb); + else if (bump instanceof Error) cb(bump); + else cb(null, bump ? { releaseType: bump } : {}); + } + ); + + if (!Array.isArray(changelog)) changelog = changelog ? [changelog] : []; + + mockery.registerMock( + "conventional-changelog", + (opt: HasPreset) => + new Readable({ + read(_size) { + const next = (changelog as ChangelogFn[]).shift(); + if (next instanceof Error) { + this.destroy(next); + } else if (typeof next === "function") { + this.push(next(opt)); + } else { + this.push(next ? Buffer.from(next, "utf8") : null); + } + }, + }) + ); + + mockery.registerMock("git-semver-tags", function (cb: TagsCallback) { + if (tags instanceof Error) cb(tags); + // I don't think this is right, but I didn't want to change the behaviour + // @ts-ignore + else cb(null, tags | []); + }); + + stdMocks.use(); + return () => stdMocks.flush(); +} + +describe("config files", () => { + beforeEach(function () { + shell.rm("-rf", "tmp"); + shell.config.silent = true; + shell.mkdir("tmp"); + shell.cd("tmp"); + fs.writeFileSync( + "package.json", + JSON.stringify({ version: "1.0.0" }), + "utf-8" + ); + }); + + afterEach(function () { + shell.cd("../"); + shell.rm("-rf", "tmp"); + + mockery.deregisterAll(); + mockery.disable(); + stdMocks.restore(); + + // push out prints from the Mocha reporter + const { stdout } = stdMocks.flush(); + for (const str of stdout) { + if (str.startsWith(" ")) process.stdout.write(str); + } + }); + + const configKeys = ["commit-and-tag-version", "standard-version"]; + + configKeys.forEach((configKey) => { + it(`reads config from package.json key '${configKey}'`, async function () { + const issueUrlFormat = + "https://commit-and-tag-version.company.net/browse/{{id}}"; + mock({ + bump: "minor", + changelog: ({ preset }) => preset.issueUrlFormat, + }); + const pkg = { + version: "1.0.0", + repository: { url: "git+https://company@scm.org/office/app.git" }, + [configKey]: { issueUrlFormat }, + }; + fs.writeFileSync("package.json", JSON.stringify(pkg), "utf-8"); + + await exec(); + const content = fs.readFileSync("CHANGELOG.md", "utf-8"); + expect(content).should.include(issueUrlFormat); + }); + }); + + it("reads config from .versionrc", async function () { + const issueUrlFormat = "http://www.foo.com/{{id}}"; + const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; + mock({ bump: "minor", changelog }); + fs.writeFileSync(".versionrc", JSON.stringify({ issueUrlFormat }), "utf-8"); + + await exec(); + const content = fs.readFileSync("CHANGELOG.md", "utf-8"); + content.should.include(issueUrlFormat); + }); + + it("reads config from .versionrc.json", async function () { + const issueUrlFormat = "http://www.foo.com/{{id}}"; + const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; + mock({ bump: "minor", changelog }); + fs.writeFileSync( + ".versionrc.json", + JSON.stringify({ issueUrlFormat }), + "utf-8" + ); + + await exec(); + const content = fs.readFileSync("CHANGELOG.md", "utf-8"); + content.should.include(issueUrlFormat); + }); + + it("evaluates a config-function from .versionrc.js", async function () { + const issueUrlFormat = "http://www.foo.com/{{id}}"; + const src = `module.exports = function() { return ${JSON.stringify({ + issueUrlFormat, + })} }`; + const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; + mock({ bump: "minor", changelog }); + fs.writeFileSync(".versionrc.js", src, "utf-8"); + + await exec(); + const content = fs.readFileSync("CHANGELOG.md", "utf-8"); + content.should.include(issueUrlFormat); + }); + + it("evaluates a config-object from .versionrc.js", async function () { + const issueUrlFormat = "http://www.foo.com/{{id}}"; + const src = `module.exports = ${JSON.stringify({ issueUrlFormat })}`; + const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; + mock({ bump: "minor", changelog }); + fs.writeFileSync(".versionrc.js", src, "utf-8"); + + await exec(); + const content = fs.readFileSync("CHANGELOG.md", "utf-8"); + content.should.include(issueUrlFormat); + }); + + it("throws an error when a non-object is returned from .versionrc.js", async function () { + mock({ bump: "minor" }); + fs.writeFileSync(".versionrc.js", "module.exports = 3", "utf-8"); + try { + await exec(); + /* istanbul ignore next */ + throw new Error("Unexpected success"); + } catch (error) { + expect((error as Error).message).should.match(/Invalid configuration/); + } + }); +}); diff --git a/tsconfig.json b/tsconfig.json index cb19c36a9..8b79b87d6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,9 +2,7 @@ "compilerOptions": { "noEmit": true, "target": "ES2015", - "lib": [ - "esnext" - ], + "lib": ["esnext"], "removeComments": true, "useUnknownInCatchVariables": true, "allowJs": true, @@ -34,16 +32,8 @@ "noPropertyAccessFromIndexSignature": true, "baseUrl": ".", "outDir": "./dist", - "types": [ - "node" - ] + "types": ["node", "mocha"] }, - "include": [ - "**/*.js", - "**/*.ts" - ], - "exclude": [ - "node_modules", - "dist" - ] + "include": ["**/*.js", "**/*.ts"], + "exclude": ["node_modules", "dist"] } From 127744cd9bd603288b15d53c47ee62b1441c8968 Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Fri, 7 Apr 2023 09:41:27 -0600 Subject: [PATCH 13/19] chore: add @types dependencies and eslint configuration --- .eslintrc | 15 +- package-lock.json | 609 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 + 3 files changed, 626 insertions(+), 3 deletions(-) diff --git a/.eslintrc b/.eslintrc index 42a52a6bc..55407f173 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,15 @@ { - "extends": "standard", + "extends": [ + "standard", + "plugin:@typescript-eslint/recommended", + "plugin:@typescript-eslint/recommended-requiring-type-checking" + ], + "settings": { + "import/resolver": "typescript" + }, + "parser": "@typescript-eslint/parser", "rules": { "no-var": "error" - } -} \ No newline at end of file + }, + "root": true +} diff --git a/package-lock.json b/package-lock.json index 15d0419ac..0a0501036 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,11 +29,16 @@ }, "devDependencies": { "@types/chai": "^4.3.4", + "@types/conventional-changelog-config-spec": "^2.1.2", + "@types/conventional-recommended-bump": "^6.1.0", "@types/mocha": "^10.0.1", "@types/mockery": "^1.4.30", "@types/node": "^18.15.3", "@types/shelljs": "^0.8.11", "@types/std-mocks": "^1.0.1", + "@types/yargs": "^17.0.24", + "@typescript-eslint/eslint-plugin": "^5.57.0", + "@typescript-eslint/parser": "^5.57.0", "chai": "^4.2.0", "eslint": "^8.16.0", "eslint-config-standard": "^17.0.0", @@ -792,6 +797,30 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "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-community/regexpp": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -1050,6 +1079,68 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "node_modules/@types/conventional-changelog-config-spec": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.2.tgz", + "integrity": "sha512-Mahx5cJCf5XKmUsLFfCjDzNaa28aNjCkf4L7eyUZXF+d7Yux0vGbcYPPOUIYx/qrCacjB5s7gztMbAyaONVZEA==", + "dev": true, + "dependencies": { + "@types/json-schema": "*" + } + }, + "node_modules/@types/conventional-changelog-core": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog-core/-/conventional-changelog-core-4.2.1.tgz", + "integrity": "sha512-XdQKXrWvHYvnhuXal4JcvIh3sn9LpcER/WjWDDQHh0yz3/yt0r8TvE5AyJwX6xL9BwJRpE1Ce+A0Hj16nsfI6w==", + "dev": true, + "dependencies": { + "@types/conventional-changelog-writer": "*", + "@types/conventional-commits-parser": "*", + "@types/conventional-recommended-bump": "*", + "@types/git-raw-commits": "*", + "@types/node": "*", + "@types/normalize-package-data": "*" + } + }, + "node_modules/@types/conventional-changelog-writer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog-writer/-/conventional-changelog-writer-4.0.2.tgz", + "integrity": "sha512-3WZjXOh1k2FYDZlmR/lFCaTJlOGTfqOW0PWd4A1hwIVVSk5fWP8fRR9228DiEbcq9ZrQl07ACbPpxGCCEJ6cQQ==", + "dev": true, + "dependencies": { + "@types/conventional-commits-parser": "*", + "@types/node": "*" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-3.0.3.tgz", + "integrity": "sha512-aoUKfRQYvGMH+spFpOTX9jO4nZoz9/BKp4hlHPxL3Cj2r2Xj+jEcwlXtFIyZr5uL8bh1nbWynDEYaAota+XqPg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-AlhJsbzY2W+9xkn44qvEgeJGY6FbQIluPRZawwU2JgJw+o7PYB/yjeuRsJhNZRKto3j71hDj+hQik10w/7bI4Q==", + "dev": true, + "dependencies": { + "@types/conventional-changelog-core": "*", + "@types/conventional-changelog-writer": "*", + "@types/conventional-commits-parser": "*" + } + }, + "node_modules/@types/git-raw-commits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/git-raw-commits/-/git-raw-commits-2.0.1.tgz", + "integrity": "sha512-vE2lbXxqJ0AqMDoP4N6d+WVfbcBla9+z8IL6e+37JNQIwYZCYY0z3J7hdpY8D/VGwFZ0yIYQLcqk8eCnfXsaEg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", @@ -1060,6 +1151,12 @@ "@types/node": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1099,6 +1196,12 @@ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "node_modules/@types/shelljs": { "version": "0.8.11", "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz", @@ -1115,6 +1218,231 @@ "integrity": "sha512-pwOrGJ6jnqb1bw9TxrmbbHTI+7ngY8yEEkrTG7lJuwplvFT9XSwOCQC3Zb4E+e6g9yDzrFX+S1ysLZuT/07WYg==", "dev": true }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", + "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/type-utils": "5.57.1", + "@typescript-eslint/utils": "5.57.1", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz", + "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", + "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", + "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/utils": "5.57.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", + "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", + "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", + "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", + "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.57.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -3438,6 +3766,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -4933,6 +5267,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "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 + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -6593,6 +6933,12 @@ "node": ">=4" } }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/tsup": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.7.0.tgz", @@ -6659,6 +7005,21 @@ "node": ">= 8" } }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7529,6 +7890,21 @@ "dev": true, "optional": true }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "dev": true + }, "@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -7737,6 +8113,68 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "@types/conventional-changelog-config-spec": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.2.tgz", + "integrity": "sha512-Mahx5cJCf5XKmUsLFfCjDzNaa28aNjCkf4L7eyUZXF+d7Yux0vGbcYPPOUIYx/qrCacjB5s7gztMbAyaONVZEA==", + "dev": true, + "requires": { + "@types/json-schema": "*" + } + }, + "@types/conventional-changelog-core": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog-core/-/conventional-changelog-core-4.2.1.tgz", + "integrity": "sha512-XdQKXrWvHYvnhuXal4JcvIh3sn9LpcER/WjWDDQHh0yz3/yt0r8TvE5AyJwX6xL9BwJRpE1Ce+A0Hj16nsfI6w==", + "dev": true, + "requires": { + "@types/conventional-changelog-writer": "*", + "@types/conventional-commits-parser": "*", + "@types/conventional-recommended-bump": "*", + "@types/git-raw-commits": "*", + "@types/node": "*", + "@types/normalize-package-data": "*" + } + }, + "@types/conventional-changelog-writer": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog-writer/-/conventional-changelog-writer-4.0.2.tgz", + "integrity": "sha512-3WZjXOh1k2FYDZlmR/lFCaTJlOGTfqOW0PWd4A1hwIVVSk5fWP8fRR9228DiEbcq9ZrQl07ACbPpxGCCEJ6cQQ==", + "dev": true, + "requires": { + "@types/conventional-commits-parser": "*", + "@types/node": "*" + } + }, + "@types/conventional-commits-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-3.0.3.tgz", + "integrity": "sha512-aoUKfRQYvGMH+spFpOTX9jO4nZoz9/BKp4hlHPxL3Cj2r2Xj+jEcwlXtFIyZr5uL8bh1nbWynDEYaAota+XqPg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-AlhJsbzY2W+9xkn44qvEgeJGY6FbQIluPRZawwU2JgJw+o7PYB/yjeuRsJhNZRKto3j71hDj+hQik10w/7bI4Q==", + "dev": true, + "requires": { + "@types/conventional-changelog-core": "*", + "@types/conventional-changelog-writer": "*", + "@types/conventional-commits-parser": "*" + } + }, + "@types/git-raw-commits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/git-raw-commits/-/git-raw-commits-2.0.1.tgz", + "integrity": "sha512-vE2lbXxqJ0AqMDoP4N6d+WVfbcBla9+z8IL6e+37JNQIwYZCYY0z3J7hdpY8D/VGwFZ0yIYQLcqk8eCnfXsaEg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", @@ -7747,6 +8185,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -7786,6 +8230,12 @@ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "@types/shelljs": { "version": "0.8.11", "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz", @@ -7802,6 +8252,138 @@ "integrity": "sha512-pwOrGJ6jnqb1bw9TxrmbbHTI+7ngY8yEEkrTG7lJuwplvFT9XSwOCQC3Zb4E+e6g9yDzrFX+S1ysLZuT/07WYg==", "dev": true }, + "@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.57.1.tgz", + "integrity": "sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/type-utils": "5.57.1", + "@typescript-eslint/utils": "5.57.1", + "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.57.1.tgz", + "integrity": "sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.57.1.tgz", + "integrity": "sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.57.1.tgz", + "integrity": "sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.57.1", + "@typescript-eslint/utils": "5.57.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.57.1.tgz", + "integrity": "sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.1.tgz", + "integrity": "sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/visitor-keys": "5.57.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.57.1.tgz", + "integrity": "sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.57.1", + "@typescript-eslint/types": "5.57.1", + "@typescript-eslint/typescript-estree": "5.57.1", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.1.tgz", + "integrity": "sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.57.1", + "eslint-visitor-keys": "^3.3.0" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -9521,6 +10103,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -10609,6 +11197,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "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 + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -11813,6 +12407,12 @@ } } }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "tsup": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.7.0.tgz", @@ -11852,6 +12452,15 @@ } } }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index b666aa8af..a894fee0a 100644 --- a/package.json +++ b/package.json @@ -62,11 +62,16 @@ }, "devDependencies": { "@types/chai": "^4.3.4", + "@types/conventional-changelog-config-spec": "^2.1.2", + "@types/conventional-recommended-bump": "^6.1.0", "@types/mocha": "^10.0.1", "@types/mockery": "^1.4.30", "@types/node": "^18.15.3", "@types/shelljs": "^0.8.11", "@types/std-mocks": "^1.0.1", + "@types/yargs": "^17.0.24", + "@typescript-eslint/eslint-plugin": "^5.57.0", + "@typescript-eslint/parser": "^5.57.0", "chai": "^4.2.0", "eslint": "^8.16.0", "eslint-config-standard": "^17.0.0", From 737d00b6eaa905d37c6bbdfd54f72e54fb44a214 Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Fri, 7 Apr 2023 09:41:40 -0600 Subject: [PATCH 14/19] chore: add dotgitignore declaration file --- @types/dotgitignore.d.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 @types/dotgitignore.d.ts diff --git a/@types/dotgitignore.d.ts b/@types/dotgitignore.d.ts new file mode 100644 index 000000000..68edff06d --- /dev/null +++ b/@types/dotgitignore.d.ts @@ -0,0 +1,12 @@ +declare module 'dotgitignore' { + interface Options { + readonly cwd?: URL | string; + readonly type?: 'file' | 'directory'; + readonly allowSymlinks?: boolean; + } + interface DotGitIgnoreInstance { + ignore(name: string): boolean; + } + function DotGitIgnore(opts?: Options): DotGitIgnoreInstance; + export default DotGitIgnore; +} From 9afa9f2090e545d23425477a260efc7eadee82f1 Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Tue, 11 Apr 2023 16:53:24 -0600 Subject: [PATCH 15/19] chore: convert everything to typescript --- argstest.ts | 7 + command.ts | 363 ++++++++++-------- defaults.ts | 41 +- index.js | 92 ----- index.ts | 74 ++++ lib/checkpoint.js | 12 - lib/checkpoint.ts | 12 + lib/configuration.ts | 30 +- ...e-manager.js => detect-package-manager.ts} | 12 +- ...it-message.js => format-commit-message.ts} | 2 +- lib/latest-semver-tag.js | 17 - lib/latest-semver-tag.ts | 24 ++ lib/lifecycles/bump.js | 176 --------- lib/lifecycles/bump.ts | 199 ++++++++++ lib/lifecycles/changelog.js | 67 ---- lib/lifecycles/changelog.ts | 80 ++++ lib/lifecycles/commit.js | 69 ---- lib/lifecycles/commit.ts | 71 ++++ lib/lifecycles/{tag.js => tag.ts} | 18 +- lib/opts/index.ts | 202 +++++----- lib/opts/spec.ts | 25 ++ lib/opts/types.ts | 201 ++++++++++ lib/preset-loader.js | 17 - lib/preset-loader.ts | 17 + lib/print-error.js | 12 - lib/print-error.ts | 31 ++ lib/run-exec.js | 18 - lib/run-exec.ts | 20 + lib/run-execFile.js | 18 - lib/run-execFile.ts | 21 + lib/run-lifecycle-script.js | 13 - lib/run-lifecycle-script.ts | 17 + ...ingify-package.js => stringify-package.ts} | 8 +- lib/updaters/index.js | 93 ----- lib/updaters/index.ts | 114 ++++++ lib/updaters/types/gradle.js | 16 - lib/updaters/types/gradle.ts | 15 + lib/updaters/types/json.js | 25 -- lib/updaters/types/json.ts | 25 ++ lib/updaters/types/plain-text.js | 7 - lib/updaters/types/plain-text.ts | 9 + lib/write-file.js | 6 - lib/write-file.ts | 7 + package-lock.json | 52 +++ package.json | 4 + tsconfig.json | 21 +- 46 files changed, 1408 insertions(+), 972 deletions(-) create mode 100644 argstest.ts delete mode 100755 index.js create mode 100755 index.ts delete mode 100644 lib/checkpoint.js create mode 100644 lib/checkpoint.ts rename lib/{detect-package-manager.js => detect-package-manager.ts} (81%) rename lib/{format-commit-message.js => format-commit-message.ts} (52%) delete mode 100644 lib/latest-semver-tag.js create mode 100644 lib/latest-semver-tag.ts delete mode 100644 lib/lifecycles/bump.js create mode 100644 lib/lifecycles/bump.ts delete mode 100644 lib/lifecycles/changelog.js create mode 100644 lib/lifecycles/changelog.ts delete mode 100644 lib/lifecycles/commit.js create mode 100644 lib/lifecycles/commit.ts rename lib/lifecycles/{tag.js => tag.ts} (75%) create mode 100644 lib/opts/spec.ts create mode 100644 lib/opts/types.ts delete mode 100644 lib/preset-loader.js create mode 100644 lib/preset-loader.ts delete mode 100644 lib/print-error.js create mode 100644 lib/print-error.ts delete mode 100644 lib/run-exec.js create mode 100644 lib/run-exec.ts delete mode 100644 lib/run-execFile.js create mode 100644 lib/run-execFile.ts delete mode 100644 lib/run-lifecycle-script.js create mode 100644 lib/run-lifecycle-script.ts rename lib/{stringify-package.js => stringify-package.ts} (81%) delete mode 100644 lib/updaters/index.js create mode 100644 lib/updaters/index.ts delete mode 100644 lib/updaters/types/gradle.js create mode 100644 lib/updaters/types/gradle.ts delete mode 100644 lib/updaters/types/json.js create mode 100644 lib/updaters/types/json.ts delete mode 100644 lib/updaters/types/plain-text.js create mode 100644 lib/updaters/types/plain-text.ts delete mode 100644 lib/write-file.js create mode 100644 lib/write-file.ts diff --git a/argstest.ts b/argstest.ts new file mode 100644 index 000000000..b226db6a8 --- /dev/null +++ b/argstest.ts @@ -0,0 +1,7 @@ +import argv from './command'; +function main() { + console.log((argv as any).bumpFiles); +} + +console.dir(argv); +main(); diff --git a/command.ts b/command.ts index e5392e34c..532a90e45 100755 --- a/command.ts +++ b/command.ts @@ -8,164 +8,225 @@ As a compromise, `argv` is manually typed, and the type must be updated as chang options to parity with the JSON options, which would likely involve breaking changes. */ -import spec from 'conventional-changelog-config-spec/versions/2.1.0/schema.json' -import { getConfiguration } from './lib/configuration' -import defaults from './defaults' +import yargs from 'yargs/yargs'; +import { Task } from './lib/opts/types'; +import spec from './lib/opts/spec'; -const yargs = require('yargs') +const cmdParser = yargs(process.argv.slice(2)) + .scriptName('commit-and-tag-version') .usage('Usage: $0 [options]') - .option('packageFiles', { - default: defaults.packageFiles, - array: true - }) - .option('bumpFiles', { - default: defaults.bumpFiles, - array: true - }) - .option('release-as', { - alias: 'r', - describe: - 'Specify the release type manually (like npm version )', - requiresArg: true, - string: true - }) - .option('prerelease', { - alias: 'p', - describe: - 'make a pre-release with optional option value to specify a tag id', - string: true - }) - .option('infile', { - alias: 'i', - describe: 'Read the CHANGELOG from this file', - default: defaults.infile - }) - .option('message', { - alias: ['m'], - describe: - '[DEPRECATED] Commit message, replaces %s with new version.\nThis option will be removed in the next major version, please use --releaseCommitMessageFormat.', - type: 'string' - }) - .option('first-release', { - alias: 'f', - describe: 'Is this the first release?', - type: 'boolean', - default: defaults.firstRelease - }) - .option('sign', { - alias: 's', - describe: 'Should the git commit and tag be signed?', - type: 'boolean', - default: defaults.sign - }) - .option('no-verify', { - alias: 'n', - describe: - 'Bypass pre-commit or commit-msg git hooks during the commit phase', - type: 'boolean', - default: defaults.noVerify - }) - .option('commit-all', { - alias: 'a', - describe: - 'Commit all staged changes, not just files affected by commit-and-tag-version', - type: 'boolean', - default: defaults.commitAll - }) - .option('silent', { - describe: "Don't print logs and errors", - type: 'boolean', - default: defaults.silent - }) - .option('tag-prefix', { - alias: 't', - describe: 'Set a custom prefix for the git tag to be created', - type: 'string', - default: defaults.tagPrefix - }) - .option('release-count', { - describe: 'How many releases of changelog you want to generate. It counts from the upcoming release. Useful when you forgot to generate any previous changelog. Set to 0 to regenerate all.', - type: 'number', - default: defaults.releaseCount - }) - .option('tag-force', { - describe: 'Allow tag replacement', - type: 'boolean', - default: defaults.tagForce - }) - .option('scripts', { - describe: - 'Provide scripts to execute for lifecycle events (prebump, precommit, etc.,)', - default: defaults.scripts - }) - .option('skip', { - describe: 'Map of steps in the release process that should be skipped', - default: defaults.skip - }) - .option('dry-run', { - type: 'boolean', - default: defaults.dryRun, - describe: 'See the commands that running commit-and-tag-version would run' - }) - .option('git-tag-fallback', { - type: 'boolean', - default: defaults.gitTagFallback, - describe: - 'fallback to git tags for version, if no meta-information file is found (e.g., package.json)' - }) - .option('path', { - type: 'string', - describe: 'Only populate commits made under this path' - }) - .option('changelogHeader', { - type: 'string', - describe: - '[DEPRECATED] Use a custom header when generating and updating changelog.\nThis option will be removed in the next major version, please use --header.' - }) - .option('preset', { - type: 'string', - default: defaults.preset, - describe: 'Commit message guideline preset' - }) - .option('lerna-package', { - type: 'string', - describe: 'Name of the package from which the tags will be extracted' - }) - .option('npmPublishHint', { - type: 'string', - default: defaults.npmPublishHint, - describe: 'Customized publishing hint' - }) - .check((argv: any) => { - if (typeof argv.scripts !== 'object' || Array.isArray(argv.scripts)) { - throw Error('scripts must be an object') - } else if (typeof argv.skip !== 'object' || Array.isArray(argv.skip)) { - throw Error('skip must be an object') - } else { - return true - } - }) + .help('help').alias('help', 'h') .alias('version', 'v') - .alias('help', 'h') + .options({ + verbose: { + boolean: true, + }, + packageFiles: { + // default: defaults.packageFiles, + array: true, + string: true, + requiresArg: true, + }, + bumpFiles: { + array: true, + string: true, + requiresArg: true, + }, + releaseAs: { + alias: 'r', + describe: 'Specify the release type manually (like npm version )', + requiresArg: true, + string: true, + }, + prerelease: { + alias: 'p', + string: true, + describe: 'Make a pre-release with optional option value to specify a tag id', + }, + infile: { + alias: 'i', + describe: 'Read the CHANGELOG from this file', + // default: defaults.infile, + }, + releaseCommitMessageFormat: { + alias: 'm', + describe: 'Commit message, replaces %s with new version', + string: true, + // default: spec.releaseCommitMessageFormat.default, + }, + message: { + describe: 'This option will be removed in the next major version', + string: true, + deprecated: 'Use --releaseCommitMessageFormat', + }, + firstRelease: { + alias: 'f', + describe: 'Is this the first release?', + boolean: true, + // default: defaults.firstRelease + }, + sign: { + alias: 's', + describe: 'Should the git commit and tag be signed?', + boolean: true, + // default: defaults.sign + }, + noVerify: { + alias: 'n', + describe: + 'Bypass pre-commit or commit-msg git hooks during the commit phase', + boolean: true, + // default: defaults.noVerify + }, + commitAll: { + alias: 'a', + describe: + 'Commit all staged changes, not just files affected by commit-and-tag-version', + boolean: true, + // default: defaults.commitAll + }, + silent: { + alias: ['s', 'q', 'quiet'], + describe: "Don't print logs and errors", + boolean: true, + // default: defaults.silent + }, + tagPrefix: { + alias: 't', + describe: 'Set a custom prefix for the git tag to be created', + string: true, + // default: defaults.tagPrefix + }, + releaseCount: { + describe: 'How many releases of changelog you want to generate. It counts from the upcoming release. Useful when you forgot to generate any previous changelog. Set to 0 to regenerate all.', + number: true, + // default: defaults.releaseCount + }, + tagForce: { + describe: 'Allow tag replacement', + boolean: true, + // default: defaults.tagForce + }, + scripts: { + describe: 'Provide scripts to execute for lifecycle events (prebump, precommit, etc.,)', + // default: defaults.scripts + }, + skip: { + array: true, + string: true, + describe: 'Map of steps in the release process that should be skipped', + choices: Object.values(Task), + + // default: defaults.skip + }, + dryRun: { + boolean: true, + // default: defaults.dryRun, + describe: 'See the commands that running commit-and-tag-version would run' + }, + gitTagFallback: { + boolean: true, + // default: defaults.gitTagFallback, + describe: 'Fallback to git tags for version, if no meta-information file is found (e.g., package.json)' + }, + path: { + string: true, + describe: 'Only populate commits made under this path' + }, + changelogHeader: { + string: true, + describe: 'This option will be removed in the next major version', + deprecated: 'Use --header' + }, + preset: { + string: true, + // default: defaults.preset, + describe: 'Commit message guideline preset' + }, + lernaPackage: { + alias: 'lerna-package', + string: true, + describe: 'Name of the package from which the tags will be extracted' + }, + npmPublishHint: { + string: true, + // default: defaults.npmPublishHint, + describe: 'Customized publishing hint' + }, + header: { + alias: 'h', + string: true, + // default: defaults.header, + describe: 'Use a custom header when generating and updating changelog', + }, + types: { + alias: 'type', + array: true, + // default: defaults.types, + describe: spec.types.description + }, + preMajor: { + boolean: true, + // default: defaults.dryRun, + describe: spec.preMajor.description, + }, + commitUrlFormat: { + string: true, + describe: spec.commitUrlFormat.description, + }, + issueUrlFormat: { + string: true, + describe: spec.issueUrlFormat.description, + }, + userUrlFormat: { + string: true, + describe: spec.userUrlFormat.description, + }, + issuePrefixes: { + array: true, + string: true, + describe: spec.issuePrefixes.description, + }, + }) + // .check((argv) => { + // if (argv.scripts && (typeof argv.scripts !== 'object' || Array.isArray(argv.scripts))) { + // throw Error('scripts must be an object') + // } else if (argv.skip && (typeof argv.skip !== 'object' || Array.isArray(argv.skip))) { + // throw Error('skip must be an object') + // } else { + // return true + // } + // }) .example('$0', 'Update changelog and tag release') .example( '$0 -m "%s: see changelog for details"', 'Update changelog and tag release with custom commit message' ) - .pkgConf('standard-version') - .pkgConf('commit-and-tag-version') - .config(getConfiguration()) - .wrap(97) + // .pkgConf('standard-version') + // .pkgConf('commit-and-tag-version') + // .config(getConfiguration()) + .wrap(97); -Object.keys(spec.properties).forEach((propertyKey) => { - const propName = propertyKey as keyof typeof spec.properties; - const property = spec.properties[propName] - yargs.option(propertyKey, { - type: property.type, - describe: property.description, - default: defaults[propName] ? defaults[propName] : property.default, - group: 'Preset Configuration:' - }) -}) +// type YargsOptionsType = 'array' | 'count' | 'boolean' | 'number' | 'string' | undefined; + +// function convertSpecPropertyType(type: JSONSchema7TypeName): YargsOptionsType { +// if (type === 'integer') return 'number'; +// if (type === 'null') return undefined; +// if (type === 'object') return 'array'; +// return type; +// } + +// Object.keys(spec).forEach((propertyKey) => { +// const propName = propertyKey as keyof typeof spec; +// const property = spec[propName]; +// console.log('propertyKey:', propertyKey); -module.exports = yargs +// cmdParser.option(propertyKey, { +// type: convertSpecPropertyType(property.type), +// describe: property.description, +// // default: defaults[propName] ? defaults[propName] : property.default, +// // group: 'Preset Configuration:', +// }); +// }); +const argv = cmdParser.parseSync(); +export default argv; diff --git a/defaults.ts b/defaults.ts index 1b7aaa336..daa8632b1 100644 --- a/defaults.ts +++ b/defaults.ts @@ -1,7 +1,8 @@ -import spec from "conventional-changelog-config-spec/versions/2.1.0/schema.json"; import { PrettyPrint } from "./type-helpers"; +import { Config } from './lib/opts/types'; +import spec from './lib/opts/spec'; -const defaults = { +const defaults: Config = { infile: "CHANGELOG.md", firstRelease: false, sign: false, @@ -16,7 +17,7 @@ const defaults = { tagForce: false, gitTagFallback: true, preset: require.resolve("conventional-changelog-conventionalcommits"), - npmPublishHint: undefined, + // npmPublishHint: undefined, /** * Sets the default for `header` (provided by the spec) for backwards * compatibility. This should be removed in the next major version. @@ -31,22 +32,22 @@ const defaults = { "package-lock.json", "npm-shrinkwrap.json", ], -} as const; + types: spec.types.default, + preMajor: spec.preMajor.default, + commitUrlFormat: spec.commitUrlFormat.default, + compareUrlFormat: spec.compareUrlFormat.default, + issueUrlFormat: spec.issueUrlFormat.default, + userUrlFormat: spec.userUrlFormat.default, + releaseCommitMessageFormat: spec.releaseCommitMessageFormat.default, + issuePrefixes: spec.issuePrefixes.default, + verbose: false, +}; -type Defaults = PrettyPrint< - typeof defaults & - Readonly<{ - [key in keyof typeof spec.properties]: typeof spec.properties[key]["default"]; - }> ->; +// type Defaults = PrettyPrint< +// typeof defaults & +// Readonly<{ +// [key in keyof typeof specSchema.properties]: typeof specSchema.properties[key]["default"]; +// }> +// >; -/** - * Merge in defaults provided by the spec - */ -Object.keys(spec.properties).forEach((propertyKey) => { - const property = spec.properties[propertyKey as keyof typeof spec.properties]; - // @ts-expect-error - We used a const assertion to infer literal types for intellisense, so TS thinks defaults is readonly. - defaults[propertyKey] = property.default; -}); - -export default defaults as Defaults; +export default defaults; diff --git a/index.js b/index.js deleted file mode 100755 index 8941e654a..000000000 --- a/index.js +++ /dev/null @@ -1,92 +0,0 @@ -const bump = require('./lib/lifecycles/bump') -const changelog = require('./lib/lifecycles/changelog') -const commit = require('./lib/lifecycles/commit') -const fs = require('fs') -const latestSemverTag = require('./lib/latest-semver-tag') -const path = require('path') -const printError = require('./lib/print-error') -const tag = require('./lib/lifecycles/tag') -const { resolveUpdaterObjectFromArgument } = require('./lib/updaters') - -module.exports = async function standardVersion (argv) { - const defaults = require('./defaults') - /** - * `--message` (`-m`) support will be removed in the next major version. - */ - const message = argv.m || argv.message - if (message) { - /** - * The `--message` flag uses `%s` for version substitutions, we swap this - * for the substitution defined in the config-spec for future-proofing upstream - * handling. - */ - argv.releaseCommitMessageFormat = message.replace(/%s/g, '{{currentTag}}') - if (!argv.silent) { - console.warn( - '[commit-and-tag-version]: --message (-m) will be removed in the next major release. Use --releaseCommitMessageFormat.' - ) - } - } - - if (argv.changelogHeader) { - argv.header = argv.changelogHeader - if (!argv.silent) { - console.warn( - '[commit-and-tag-version]: --changelogHeader will be removed in the next major release. Use --header.' - ) - } - } - - if ( - argv.header && - argv.header.search(changelog.START_OF_LAST_RELEASE_PATTERN) !== -1 - ) { - throw Error( - `custom changelog header must not match ${changelog.START_OF_LAST_RELEASE_PATTERN}` - ) - } - - /** - * If an argument for `packageFiles` provided, we include it as a "default" `bumpFile`. - */ - if (argv.packageFiles) { - defaults.bumpFiles = defaults.bumpFiles.concat(argv.packageFiles) - } - - const args = Object.assign({}, defaults, argv) - let pkg - for (const packageFile of args.packageFiles) { - const updater = resolveUpdaterObjectFromArgument(packageFile) - if (!updater) return - const pkgPath = path.resolve(process.cwd(), updater.filename) - try { - const contents = fs.readFileSync(pkgPath, 'utf8') - pkg = { - version: updater.updater.readVersion(contents), - private: - typeof updater.updater.isPrivate === 'function' - ? updater.updater.isPrivate(contents) - : false - } - break - } catch (err) {} - } - try { - let version - if (pkg && pkg.version) { - version = pkg.version - } else if (args.gitTagFallback) { - version = await latestSemverTag(args.tagPrefix) - } else { - throw new Error('no package file found') - } - - const newVersion = await bump(args, version) - await changelog(args, newVersion) - await commit(args, newVersion) - await tag(newVersion, pkg ? pkg.private : false, args) - } catch (err) { - printError(args, err.message) - throw err - } -} diff --git a/index.ts b/index.ts new file mode 100755 index 000000000..9e18d0828 --- /dev/null +++ b/index.ts @@ -0,0 +1,74 @@ +import fs from 'fs'; +import path from 'path'; + +import Bump from './lib/lifecycles/bump'; +import changelog from './lib/lifecycles/changelog'; +import commit from './lib/lifecycles/commit'; +import latestSemverTag from './lib/latest-semver-tag'; +import printError from './lib/print-error'; +import tag from './lib/lifecycles/tag'; +import { resolveUpdaterObjectFromArgument } from './lib/updaters'; +import { getMergedConfig } from './lib/opts'; +import { BumpFile, Config } from 'lib/opts/types'; + +interface PackageInfo { + version: string; + private: boolean; +} + +export default async function standardVersion() { + const config = await getMergedConfig(); + + if ( + config.header && + config.header.search(changelog.START_OF_LAST_RELEASE_PATTERN) !== -1 + ) { + throw Error( + `custom changelog header must not match ${changelog.START_OF_LAST_RELEASE_PATTERN}` + ); + } + + try { + const info = await getPackageInfo(config); + const newVersion = await Bump(config, info.version); + + await changelog(config, newVersion); + await commit(config, newVersion); + await tag(newVersion, info.private, config); + } catch (err: any) { + printError(config, err.message) + throw err; + } +} + +async function getPackageInfo(config: Config): Promise { + const pkg = getPackage(config.packageFiles); + + if (pkg) return pkg; + + if (config.gitTagFallback) { + const version = await latestSemverTag(config.tagPrefix); + return { + version, + private: false, + } + } + + throw new Error('no package file found') +} + +function getPackage(packageFiles: BumpFile[]) { + for (const packageFile of packageFiles) { + const updater = resolveUpdaterObjectFromArgument(packageFile) + if (!updater) continue; + const pkgPath = path.resolve(process.cwd(), updater.filename) + try { + const contents = fs.readFileSync(pkgPath, 'utf8') + return { + version: updater.updater.readVersion(contents), + private: updater.updater.isPrivate(contents), + }; + } catch (err) {} + } + return undefined; +} diff --git a/lib/checkpoint.js b/lib/checkpoint.js deleted file mode 100644 index c37275b78..000000000 --- a/lib/checkpoint.js +++ /dev/null @@ -1,12 +0,0 @@ -const chalk = require('chalk') -const figures = require('figures') -const util = require('util') - -module.exports = function (argv, msg, args, figure) { - const defaultFigure = argv.dryRun ? chalk.yellow(figures.tick) : chalk.green(figures.tick) - if (!argv.silent) { - console.info((figure || defaultFigure) + ' ' + util.format.apply(util, [msg].concat(args.map(function (arg) { - return chalk.bold(arg) - })))) - } -} diff --git a/lib/checkpoint.ts b/lib/checkpoint.ts new file mode 100644 index 000000000..548f13857 --- /dev/null +++ b/lib/checkpoint.ts @@ -0,0 +1,12 @@ +import chalk from 'chalk'; +import figures from 'figures'; +import util from 'util'; +import { Config } from './opts/types'; + +export default function checkpoint(config: Config, msg: string, args: string[], figure?: string) { + const defaultFigure = config.dryRun ? chalk.yellow(figures.tick) : chalk.green(figures.tick) + if (!config.silent) { + const message = util.format.apply(util, [msg].concat(args.map((arg) => chalk.bold(arg)))); + console.info(`${figure || defaultFigure} ${message}`); + } +} diff --git a/lib/configuration.ts b/lib/configuration.ts index c0e11af48..99f0989d4 100644 --- a/lib/configuration.ts +++ b/lib/configuration.ts @@ -1,7 +1,7 @@ import path from 'path' import findUp from 'find-up' import { readFileSync } from 'fs' -import { Config } from './opts' +import { FileConfig } from './opts/types' const CONFIGURATION_FILES = [ '.versionrc', @@ -10,23 +10,12 @@ const CONFIGURATION_FILES = [ '.versionrc.js' ] as const; -export async function getConfiguration () { - let config: Partial = {} +export async function getConfiguration(): Promise { const configPath = findUp.sync(CONFIGURATION_FILES) if (!configPath) { - return config - } - const ext = path.extname(configPath) - if (ext === '.js' || ext === '.cjs') { - const jsConfiguration = await import(configPath) - if (typeof jsConfiguration === 'function') { - config = jsConfiguration() - } else { - config = jsConfiguration - } - } else { - config = JSON.parse(readFileSync(configPath, 'utf-8')) + return {} } + const config = await readConfigFile(configPath); /** * @todo we could eventually have deeper validation of the configuration (using `ajv`) and @@ -40,3 +29,14 @@ export async function getConfiguration () { return config } +async function readConfigFile(configPath: string): Promise { + const ext = path.extname(configPath); + if (ext === '.js' || ext === '.cjs') { + const jsConfiguration = require(configPath); + if (typeof jsConfiguration === 'function') { + return jsConfiguration(); + } + return jsConfiguration; + } + return JSON.parse(readFileSync(configPath, 'utf-8')); +} diff --git a/lib/detect-package-manager.js b/lib/detect-package-manager.ts similarity index 81% rename from lib/detect-package-manager.js rename to lib/detect-package-manager.ts index 99680bc2b..4fb30608e 100644 --- a/lib/detect-package-manager.js +++ b/lib/detect-package-manager.ts @@ -4,13 +4,13 @@ * modified to support only detecting lock file and not detecting global package manager */ -const { promises: fs } = require('fs') -const { resolve } = require('path') +import { promises as fs } from 'fs'; +import { resolve } from 'path'; /** * Check if a path exists */ -async function pathExists (p) { +async function pathExists (p: string) { try { await fs.access(p) return true @@ -39,7 +39,7 @@ function getTypeofLockFile (cwd = '.') { }) } -const detectPMByLockFile = async (cwd) => { +const detectPMByLockFile = async (cwd: string) => { const type = await getTypeofLockFile(cwd) if (type) { return type @@ -48,6 +48,4 @@ const detectPMByLockFile = async (cwd) => { return 'npm' } -module.exports = { - detectPMByLockFile -} +export default detectPMByLockFile; diff --git a/lib/format-commit-message.js b/lib/format-commit-message.ts similarity index 52% rename from lib/format-commit-message.js rename to lib/format-commit-message.ts index a597b5198..bd019d1b6 100644 --- a/lib/format-commit-message.js +++ b/lib/format-commit-message.ts @@ -1,4 +1,4 @@ -module.exports = function (rawMsg, newVersion) { +export default function formatCommitMessage(rawMsg: string, newVersion: string) { const message = String(rawMsg) return message.replace(/{{currentTag}}/g, newVersion) } diff --git a/lib/latest-semver-tag.js b/lib/latest-semver-tag.js deleted file mode 100644 index eec93af2b..000000000 --- a/lib/latest-semver-tag.js +++ /dev/null @@ -1,17 +0,0 @@ -const gitSemverTags = require('git-semver-tags') -const semver = require('semver') - -module.exports = function (tagPrefix = undefined) { - return new Promise((resolve, reject) => { - gitSemverTags({ tagPrefix }, function (err, tags) { - if (err) return reject(err) - else if (!tags.length) return resolve('1.0.0') - // Respect tagPrefix - tags = tags.map(tag => tag.replace(new RegExp('^' + tagPrefix), '')) - // ensure that the largest semver tag is at the head. - tags = tags.map(tag => { return semver.clean(tag) }) - tags.sort(semver.rcompare) - return resolve(tags[0]) - }) - }) -} diff --git a/lib/latest-semver-tag.ts b/lib/latest-semver-tag.ts new file mode 100644 index 000000000..e1c238798 --- /dev/null +++ b/lib/latest-semver-tag.ts @@ -0,0 +1,24 @@ +import gitSemverTags from 'git-semver-tags'; +import semver from 'semver'; + +export default async function latestSemverTags(tagPrefix?: string) { + return new Promise((resolve, reject) => { + gitSemverTags({ tagPrefix }, (err, tags) => { + if (err) { + reject(err); + } else if (tags.length) { + const mapped = tags + // Respect tagPrefix + .map(tag => tag.replace(new RegExp('^' + tagPrefix), '')) + // ensure that the largest semver tag is at the head. + .map(tag => semver.clean(tag) || ''); + + mapped.sort(semver.rcompare) + const version = mapped[0]; + if (version) resolve(version); + } + + resolve('1.0.0'); + }) + }) +} diff --git a/lib/lifecycles/bump.js b/lib/lifecycles/bump.js deleted file mode 100644 index 7758dc6e6..000000000 --- a/lib/lifecycles/bump.js +++ /dev/null @@ -1,176 +0,0 @@ -'use strict' - -const chalk = require('chalk') -const checkpoint = require('../checkpoint') -const conventionalRecommendedBump = require('conventional-recommended-bump') -const figures = require('figures') -const fs = require('fs') -const DotGitignore = require('dotgitignore') -const path = require('path') -const presetLoader = require('../preset-loader') -const runLifecycleScript = require('../run-lifecycle-script') -const semver = require('semver') -const writeFile = require('../write-file') -const { resolveUpdaterObjectFromArgument } = require('../updaters') -let configsToUpdate = {} - -async function Bump (args, version) { - // reset the cache of updated config files each - // time we perform the version bump step. - configsToUpdate = {} - - if (args.skip.bump) return version - let newVersion = version - await runLifecycleScript(args, 'prerelease') - const stdout = await runLifecycleScript(args, 'prebump') - if (stdout && stdout.trim().length) args.releaseAs = stdout.trim() - const release = await bumpVersion(args.releaseAs, version, args) - if (!args.firstRelease) { - const releaseType = getReleaseType(args.prerelease, release.releaseType, version) - const releaseTypeAsVersion = releaseType === 'pre' + release.releaseType ? semver.valid(release.releaseType + '-' + args.prerelease + '.0') : semver.valid(releaseType) - - newVersion = releaseTypeAsVersion || semver.inc(version, releaseType, args.prerelease) - updateConfigs(args, newVersion) - } else { - checkpoint(args, 'skip version bump on first release', [], chalk.red(figures.cross)) - } - await runLifecycleScript(args, 'postbump') - return newVersion -} - -Bump.getUpdatedConfigs = function () { - return configsToUpdate -} - -function getReleaseType (prerelease, expectedReleaseType, currentVersion) { - if (isString(prerelease)) { - if (isInPrerelease(currentVersion)) { - if (shouldContinuePrerelease(currentVersion, expectedReleaseType) || - getTypePriority(getCurrentActiveType(currentVersion)) > getTypePriority(expectedReleaseType) - ) { - return 'prerelease' - } - } - - return 'pre' + expectedReleaseType - } else { - return expectedReleaseType - } -} - -function isString (val) { - return typeof val === 'string' -} - -/** - * if a version is currently in pre-release state, - * and if it current in-pre-release type is same as expect type, - * it should continue the pre-release with the same type - * - * @param version - * @param expectType - * @return {boolean} - */ -function shouldContinuePrerelease (version, expectType) { - return getCurrentActiveType(version) === expectType -} - -function isInPrerelease (version) { - return Array.isArray(semver.prerelease(version)) -} - -const TypeList = ['major', 'minor', 'patch'].reverse() - -/** - * extract the in-pre-release type in target version - * - * @param version - * @return {string} - */ -function getCurrentActiveType (version) { - const typelist = TypeList - for (let i = 0; i < typelist.length; i++) { - if (semver[typelist[i]](version)) { - return typelist[i] - } - } -} - -/** - * calculate the priority of release type, - * major - 2, minor - 1, patch - 0 - * - * @param type - * @return {number} - */ -function getTypePriority (type) { - return TypeList.indexOf(type) -} - -function bumpVersion (releaseAs, currentVersion, args) { - return new Promise((resolve, reject) => { - if (releaseAs) { - return resolve({ - releaseType: releaseAs - }) - } else { - const presetOptions = presetLoader(args) - if (typeof presetOptions === 'object') { - if (semver.lt(currentVersion, '1.0.0')) presetOptions.preMajor = true - } - conventionalRecommendedBump({ - debug: args.verbose && console.info.bind(console, 'conventional-recommended-bump'), - preset: presetOptions, - path: args.path, - tagPrefix: args.tagPrefix, - lernaPackage: args.lernaPackage - }, function (err, release) { - if (err) return reject(err) - else return resolve(release) - }) - } - }) -} - -/** - * attempt to update the version number in provided `bumpFiles` - * @param args config object - * @param newVersion version number to update to. - * @return void - */ -function updateConfigs (args, newVersion) { - const dotgit = DotGitignore() - args.bumpFiles.forEach(function (bumpFile) { - const updater = resolveUpdaterObjectFromArgument(bumpFile) - if (!updater) { - return - } - const configPath = path.resolve(process.cwd(), updater.filename) - try { - if (dotgit.ignore(updater.filename)) return - const stat = fs.lstatSync(configPath) - - if (!stat.isFile()) return - const contents = fs.readFileSync(configPath, 'utf8') - const newContents = updater.updater.writeVersion(contents, newVersion) - const realNewVersion = updater.updater.readVersion(newContents) - checkpoint( - args, - 'bumping version in ' + updater.filename + ' from %s to %s', - [updater.updater.readVersion(contents), realNewVersion] - ) - writeFile( - args, - configPath, - newContents - ) - // flag any config files that we modify the version # for - // as having been updated. - configsToUpdate[updater.filename] = true - } catch (err) { - if (err.code !== 'ENOENT') console.warn(err.message) - } - }) -} - -module.exports = Bump diff --git a/lib/lifecycles/bump.ts b/lib/lifecycles/bump.ts new file mode 100644 index 000000000..ed88b7041 --- /dev/null +++ b/lib/lifecycles/bump.ts @@ -0,0 +1,199 @@ +import chalk from 'chalk' +import checkpoint from '../checkpoint' +import conventionalRecommendedBump, { Callback } from 'conventional-recommended-bump' +import figures from 'figures' +import fs from 'fs' +import DotGitignore from 'dotgitignore' +import path from 'path' +import presetLoader from '../preset-loader' +import runLifecycleScript from '../run-lifecycle-script' +import semver from 'semver' +import writeFile from '../write-file' +import { resolveUpdaterObjectFromArgument } from '../updaters' +import { Config, Hook, Release } from 'lib/opts/types' +import { ReleaseType } from 'semver' + +let configsToUpdate: Record = {}; + +interface BumpResults { + version: string; + newVersion: string; + releaseAs: Release; +} + +async function Bump(config: Config, version: string) { + // reset the cache of updated config files each + // time we perform the version bump step. + configsToUpdate = {} + + if (config.skip.bump) return version; + + const results: BumpResults = { + version, + newVersion: version, + releaseAs: config.releaseAs || 'minor', + }; + + await runLifecycleScript(config, Hook.prerelease); + + const stdout = await runLifecycleScript(config, Hook.prebump); + if (stdout && stdout.trim().length) results.releaseAs = stdout.trim() as Release; + + const expectedReleaseType = await bumpVersion(config.releaseAs, version, config); + + if (!config.firstRelease) { + const releaseType = getReleaseType( + config.prerelease, + expectedReleaseType, + version + ) + const releaseTypeAsVersion = + releaseType === 'pre' + expectedReleaseType + ? semver.valid(expectedReleaseType + '-' + config.prerelease + '.0') + : semver.valid(releaseType); + + // TODO: semver.inc() possibly returns null. + results.newVersion = + releaseTypeAsVersion || semver.inc(version, releaseType, !!config.prerelease) || version; + + updateConfigs(config, results.newVersion); + } else { + checkpoint( + config, + 'skip version bump on first release', + [], + chalk.red(figures.cross) + ) + } + await runLifecycleScript(config, Hook.postbump); + return results.newVersion +} + +Bump.getUpdatedConfigs = function () { + return configsToUpdate +} + +function getReleaseType (prerelease: string | boolean | undefined, expectedReleaseType: Release, currentVersion: string): ReleaseType { + if (typeof prerelease === 'string') { + if (isInPrerelease(currentVersion)) { + const currentActiveType = getCurrentActiveType(currentVersion); + if ( + shouldContinuePrerelease(currentVersion, expectedReleaseType) || + (currentActiveType && getTypePriority(currentActiveType) > + getTypePriority(expectedReleaseType)) + ) { + return 'prerelease' + } + } + + return `pre${expectedReleaseType}`; + } else { + return expectedReleaseType + } +} + +/** + * if a version is currently in pre-release state, + * and if it current in-pre-release type is same as expect type, + * it should continue the pre-release with the same type + * + * @param version + * @param expectType + * @return {boolean} + */ +function shouldContinuePrerelease (version: string, expectType: ReleaseType) { + return getCurrentActiveType(version) === expectType; +} + +function isInPrerelease (version: string) { + return Array.isArray(semver.prerelease(version)) +} + +const TypeList: Release[] = ['patch', 'minor', 'major']; + +/** + * extract the in-pre-release type in target version + */ +function getCurrentActiveType(version: string) { + return TypeList.find((type) => semver[type](version)); +} + +/** + * calculate the priority of release type, + * major - 2, minor - 1, patch - 0 + */ +function getTypePriority(type: Release) { + return TypeList.indexOf(type); +} + +async function bumpVersion(releaseAs: Release | undefined, currentVersion: string, config: Config) { + return await new Promise((resolve, reject) => { + if (releaseAs) { + resolve(releaseAs); + } else { + const presetOptions = presetLoader(config) + if (typeof presetOptions === 'object') { + if (semver.lt(currentVersion, '1.0.0')) presetOptions['preMajor'] = true + } + // TODO: conventionalRecommendedBump options preset type is string | undefined, not an object + // TODO: conventionalRecommendedBump options does not include a debug property + conventionalRecommendedBump( + { + // debug: + // config.verbose && + // console.info.bind(console, 'conventional-recommended-bump'), + preset: config.preset, // presetOptions, + path: config.path, + tagPrefix: config.tagPrefix, + lernaPackage: config.lernaPackage + }, + function (err, release) { + if (err) { + reject(err); + } else { + resolve(release.releaseType! as Release); + } + } + ) + } + }) +} + +/** + * attempt to update the version number in provided `bumpFiles` + * @param config config object + * @param newVersion version number to update to. + * @return void + */ +function updateConfigs(config: Config, newVersion: string) { + const dotgit = DotGitignore() + config.bumpFiles.forEach(function (bumpFile) { + const updater = resolveUpdaterObjectFromArgument(bumpFile) + if (!updater) { + return + } + const configPath = path.resolve(process.cwd(), updater.filename) + try { + if (dotgit.ignore(updater.filename)) return + const stat = fs.lstatSync(configPath) + + if (!stat.isFile()) return + const contents = fs.readFileSync(configPath, 'utf8') + const newContents = updater.updater.writeVersion(contents, newVersion) + const realNewVersion = updater.updater.readVersion(newContents) + checkpoint( + config, + 'bumping version in ' + updater.filename + ' from %s to %s', + [updater.updater.readVersion(contents), realNewVersion] + ) + writeFile(config, configPath, newContents) + // flag any config files that we modify the version # for + // as having been updated. + configsToUpdate[updater.filename] = true + } catch (err: any) { + if (err.code !== 'ENOENT') console.warn(err.message); + } + }) +} + +export default Bump; diff --git a/lib/lifecycles/changelog.js b/lib/lifecycles/changelog.js deleted file mode 100644 index 6d4ba990a..000000000 --- a/lib/lifecycles/changelog.js +++ /dev/null @@ -1,67 +0,0 @@ -const chalk = require('chalk') -const checkpoint = require('../checkpoint') -const conventionalChangelog = require('conventional-changelog') -const fs = require('fs') -const presetLoader = require('../preset-loader') -const runLifecycleScript = require('../run-lifecycle-script') -const writeFile = require('../write-file') -const START_OF_LAST_RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+| { - createIfMissing(args) - const header = args.header - - let oldContent = args.dryRun || args.releaseCount === 0 ? '' : fs.readFileSync(args.infile, 'utf-8') - const oldContentStart = oldContent.search(START_OF_LAST_RELEASE_PATTERN) - // find the position of the last release and remove header: - if (oldContentStart !== -1) { - oldContent = oldContent.substring(oldContentStart) - } - let content = '' - const context = { version: newVersion } - const changelogStream = conventionalChangelog({ - debug: args.verbose && console.info.bind(console, 'conventional-changelog'), - preset: presetLoader(args), - tagPrefix: args.tagPrefix, - releaseCount: args.releaseCount - }, context, { merges: null, path: args.path, showSignature: false }, args.parserOpts, args.writerOpts) - .on('error', function (err) { - return reject(err) - }) - - changelogStream.on('data', function (buffer) { - content += buffer.toString() - }) - - changelogStream.on('end', function () { - checkpoint(args, 'outputting changes to %s', [args.infile]) - if (args.dryRun) console.info(`\n---\n${chalk.gray(content.trim())}\n---\n`) - else writeFile(args, args.infile, header + '\n' + (content + oldContent).replace(/\n+$/, '\n')) - return resolve() - }) - }) -} - -function createIfMissing (args) { - try { - fs.accessSync(args.infile, fs.F_OK) - } catch (err) { - if (err.code === 'ENOENT') { - checkpoint(args, 'created %s', [args.infile]) - args.outputUnreleased = true - writeFile(args, args.infile, '\n') - } - } -} diff --git a/lib/lifecycles/changelog.ts b/lib/lifecycles/changelog.ts new file mode 100644 index 000000000..ec95dd614 --- /dev/null +++ b/lib/lifecycles/changelog.ts @@ -0,0 +1,80 @@ +import chalk from 'chalk'; +import checkpoint from '../checkpoint'; +import conventionalChangelog from 'conventional-changelog'; +import fs from 'fs'; +import presetLoader from '../preset-loader'; +import runLifecycleScript from '../run-lifecycle-script'; +import writeFile from '../write-file'; +import { Config, Hook } from 'lib/opts/types'; + +const START_OF_LAST_RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+|((resolve, reject) => { + createIfMissing(config) + const header = config.header + + let oldContent = config.dryRun || config.releaseCount === 0 ? '' : fs.readFileSync(config.infile, 'utf-8') + const oldContentStart = oldContent.search(START_OF_LAST_RELEASE_PATTERN) + // find the position of the last release and remove header: + if (oldContentStart !== -1) { + oldContent = oldContent.substring(oldContentStart) + } + let content = '' + const context = { version: newVersion } + const changelogStream = conventionalChangelog( + { + // debug: config.verbose && console.info.bind(console, 'conventional-changelog'), + // TODO: Same issue here with debug and preset + preset: config.preset, // presetLoader(config), + tagPrefix: config.tagPrefix, + releaseCount: config.releaseCount + }, + context, + { + merges: null, + path: config.path, + showSignature: false, + }, + // TODO: Where did parserOpts and writerOpts come from? + // config.parserOpts, + // config.writerOpts + ).on('error', function (err) { + return reject(err) + }); + + changelogStream.on('data', function (buffer) { + content += buffer.toString() + }) + + changelogStream.on('end', function () { + checkpoint(config, 'outputting changes to %s', [config.infile]) + if (config.dryRun) console.info(`\n---\n${chalk.gray(content.trim())}\n---\n`) + else writeFile(config, config.infile, header + '\n' + (content + oldContent).replace(/\n+$/, '\n')) + return resolve() + }) + }) +} + +function createIfMissing(config: Config) { + try { + fs.accessSync(config.infile, fs.constants.F_OK) + } catch (err: any) { + if (err.code === 'ENOENT') { + checkpoint(config, 'created %s', [config.infile]) + // TODO: what is outputUnreleased used for? + // config.outputUnreleased = true + writeFile(config, config.infile, '\n'); + } + } +} diff --git a/lib/lifecycles/commit.js b/lib/lifecycles/commit.js deleted file mode 100644 index 1f56ec632..000000000 --- a/lib/lifecycles/commit.js +++ /dev/null @@ -1,69 +0,0 @@ -const bump = require('../lifecycles/bump') -const checkpoint = require('../checkpoint') -const formatCommitMessage = require('../format-commit-message') -const path = require('path') -const runExecFile = require('../run-execFile') -const runLifecycleScript = require('../run-lifecycle-script') - -module.exports = async function (args, newVersion) { - if (args.skip.commit) return - const message = await runLifecycleScript(args, 'precommit') - if (message && message.length) args.releaseCommitMessageFormat = message - await execCommit(args, newVersion) - await runLifecycleScript(args, 'postcommit') -} - -async function execCommit (args, newVersion) { - let msg = 'committing %s' - let paths = [] - const verify = args.verify === false || args.n ? ['--no-verify'] : [] - const sign = args.sign ? ['-S'] : [] - const toAdd = [] - - // only start with a pre-populated paths list when CHANGELOG processing is not skipped - if (!args.skip.changelog) { - paths = [args.infile] - toAdd.push(args.infile) - } - - // commit any of the config files that we've updated - // the version # for. - Object.keys(bump.getUpdatedConfigs()).forEach(function (p) { - paths.unshift(p) - toAdd.push(path.relative(process.cwd(), p)) - - // account for multiple files in the output message - if (paths.length > 1) { - msg += ' and %s' - } - }) - - if (args.commitAll) { - msg += ' and %s' - paths.push('all staged files') - } - - checkpoint(args, msg, paths) - - // nothing to do, exit without commit anything - if (!args.commitAll && args.skip.changelog && args.skip.bump && toAdd.length === 0) { - return - } - - await runExecFile(args, 'git', ['add'].concat(toAdd)) - await runExecFile( - args, - 'git', - [ - 'commit' - ].concat( - verify, - sign, - args.commitAll ? [] : toAdd, - [ - '-m', - `${formatCommitMessage(args.releaseCommitMessageFormat, newVersion)}` - ] - ) - ) -} diff --git a/lib/lifecycles/commit.ts b/lib/lifecycles/commit.ts new file mode 100644 index 000000000..98409fea9 --- /dev/null +++ b/lib/lifecycles/commit.ts @@ -0,0 +1,71 @@ +import bump from '../lifecycles/bump'; +import checkpoint from '../checkpoint'; +import formatCommitMessage from '../format-commit-message'; +import path from 'path'; +import runExecFile from '../run-execFile'; +import runLifecycleScript from '../run-lifecycle-script'; +import { Config, Hook } from 'lib/opts/types'; + +export default async function (config: Config, newVersion: string) { + if (config.skip.commit) return; + + const message = await runLifecycleScript(config, Hook.precommit) + if (message && message.length) config.releaseCommitMessageFormat = message; + await execCommit(config, newVersion) + await runLifecycleScript(config, Hook.postcommit); +} + +async function execCommit (config: Config, newVersion: string) { + let msg = 'committing %s' + let paths: string[] = [] + const verify: string[] = !config.noVerify ? ['--no-verify'] : []; + const sign: string[] = config.sign ? ['-S'] : [] + const toAdd: string[] = []; + + // only start with a pre-populated paths list when CHANGELOG processing is not skipped + if (!config.skip.changelog) { + paths = [config.infile] + toAdd.push(config.infile) + } + + // commit any of the config files that we've updated + // the version # for. + Object.keys(bump.getUpdatedConfigs()).forEach(function (p) { + paths.unshift(p) + toAdd.push(path.relative(process.cwd(), p)) + + // account for multiple files in the output message + if (paths.length > 1) { + msg += ' and %s' + } + }) + + if (config.commitAll) { + msg += ' and %s' + paths.push('all staged files') + } + + checkpoint(config, msg, paths) + + // nothing to do, exit without commit anything + if (!config.commitAll && config.skip.changelog && config.skip.bump && toAdd.length === 0) { + return + } + + await runExecFile(config, 'git', ['add'].concat(toAdd)) + await runExecFile( + config, + 'git', + [ + 'commit' + ].concat( + verify, + sign, + config.commitAll ? [] : toAdd, + [ + '-m', + `${formatCommitMessage(config.releaseCommitMessageFormat, newVersion)}` + ] + ) + ) +} diff --git a/lib/lifecycles/tag.js b/lib/lifecycles/tag.ts similarity index 75% rename from lib/lifecycles/tag.js rename to lib/lifecycles/tag.ts index 5093990b8..926f225db 100644 --- a/lib/lifecycles/tag.js +++ b/lib/lifecycles/tag.ts @@ -1,13 +1,13 @@ -const bump = require('../lifecycles/bump') -const chalk = require('chalk') -const checkpoint = require('../checkpoint') -const figures = require('figures') -const formatCommitMessage = require('../format-commit-message') -const runExecFile = require('../run-execFile') -const runLifecycleScript = require('../run-lifecycle-script') +import Bump from '../lifecycles/bump'; +import chalk from 'chalk'; +import checkpoint from '../checkpoint'; +import figures from 'figures'; +import formatCommitMessage from '../format-commit-message'; +import runExecFile from '../run-execFile'; +import runLifecycleScript from '../run-lifecycle-script'; const { detectPMByLockFile } = require('../detect-package-manager') -module.exports = async function (newVersion, pkgPrivate, args) { +export default async function tag(newVersion, pkgPrivate, args) { if (args.skip.tag) return await runLifecycleScript(args, 'pretag') await execTag(newVersion, pkgPrivate, args) @@ -34,7 +34,7 @@ async function execTag (newVersion, pkgPrivate, args) { await runExecFile(args, 'git', ['tag', ...tagOption, args.tagPrefix + newVersion, '-m', `${formatCommitMessage(args.releaseCommitMessageFormat, newVersion)}`]) const currentBranch = await runExecFile('', 'git', ['rev-parse', '--abbrev-ref', 'HEAD']) let message = 'git push --follow-tags origin ' + currentBranch.trim() - if (pkgPrivate !== true && bump.getUpdatedConfigs()['package.json']) { + if (pkgPrivate !== true && Bump.getUpdatedConfigs()['package.json']) { const npmPublishHint = args.npmPublishHint || await detectPublishHint() message += ` && ${npmPublishHint}` if (args.prerelease !== undefined) { diff --git a/lib/opts/index.ts b/lib/opts/index.ts index 102686bdb..8d9f0e030 100644 --- a/lib/opts/index.ts +++ b/lib/opts/index.ts @@ -1,121 +1,121 @@ +import path from "path"; import { getConfiguration as getConfigFromFile } from "../configuration"; import { isin } from "../../type-helpers"; -import type { PrettyPrint } from "../../type-helpers"; - -type Release = "minor" | "major" | "patch"; -type Task = "changelog" | "commit" | "tag"; -type Hook = - | "prerelease" - | "prebump" - | "postbump" - | "prechangelog" - | "postchangelog" - | "precommit" - | "postcommit" - | "pretag" - | "posttag"; - -type TypePrefixes = Array< - ( - | { section: string; hidden?: boolean | undefined } - | { hidden: true; section?: string | undefined } - ) & { type: string } ->; - -type ConfigFiles = Array< - | string - | { filename: string; type: "json" | "gradle" | "plain-text" } - | { filename: string; updater: string } ->; - -/** - * __THIS SHOULD NOT CHANGE.__ - * @deprecated - * - * The configuration options for `standard-version` as of version 9.5 (The last version prior to the fork; deprecated). - */ -export type LegacyConfig = - | { - packageFiles: ConfigFiles; - bumpFiles: ConfigFiles; - releaseAs: Release; - prerelease: string | boolean; - infile: string; - message: string; - firstRelease: boolean; - sign: boolean; - noVerify: boolean; - commitAll: boolean; - silent: boolean; - tagPrefix: string; - scripts: Record; - skip: Record; - dryRun: boolean; - gitTagFallback: boolean; - path: string; - changelogHeader: string; - preset: string; - lernaPackage: string; - header: string; - types: TypePrefixes; - preMajor: boolean; - commitUrlFormat: string; - compareUrlFormat: string; - issueUrlFormat: string; - userUrlFormat: string; - releaseCommitMessageFormat: string; - issuePrefixes: string[]; - } - | undefined; - -/** - * The configuration object for commit-and-tag-version, which is a superset of the conventional-changelog-config-spec (as of version 2.1.0) - * This may or may not maintain backwards compatibility with standard-version (as of version 9.5.0). - */ -export type Config = - | PrettyPrint< - LegacyConfig & { - npmPublishHint: string; - releaseCount: number; - tagForce: boolean; - } - > - | undefined; +import { Config, FileConfig, LegacyConfig, SkipLifecycleSteps, Task } from './types'; +import defaults from 'defaults'; +import argv from 'command'; /** The configuration options that are not supported by standard-version (as of version 9.5.0). */ const catVOnlyFeatures = [ "npmPublishHint", "releaseCount", "tagForce", -] as const satisfies ReadonlyArray< - Exclude, keyof LegacyConfig> ->; +]; -export const getMergedConfig = async ( - cwd?: string -): Promise> => { +export async function getMergedConfig(cwd?: string): Promise { const searchDir = cwd ?? process.cwd(); - const pkgJson = (await import("path")).join(searchDir, "package.json"); - const legacyConf: LegacyConfig = (await import(pkgJson))["standard-version"]; - const modernConf: Config = (await import(pkgJson))["commit-and-tag-version"]; + const pkgJson = await import(path.join(searchDir, "package.json")); + const legacyConf = convertLegacy(pkgJson["standard-version"] ?? {}); + const modernConf: FileConfig = pkgJson["commit-and-tag-version"] ?? {}; + const cliConf = convertCliConfig(); + const configFromFile = await getConfigFromFile(); - Object.keys(legacyConf ?? {}).forEach((key) => { - if (catVOnlyFeatures.includes(key as any)) { - console.warn( - `The "${key}" option is a feature of commit-and-tag-version, and is not supported by standard-version.${"\n"}Please move this option to the 'commit-and-tag-version' key.${"\n"}In a future version, this will throw an error.` - ); - } - if (modernConf && isin(modernConf, key as any)) { + // Check for legacy config properties that will be overwritten + Object.keys(legacyConf).forEach((key) => { + if (isin(modernConf, key as any)) { console.warn( `"standard-version"."${key}" in package.json is being overridden by "commit-and-tag-version"."${key}". in package.json` ); } }); - const configFromFile = await getConfigFromFile(); + const merged: FileConfig = { + ...legacyConf, + ...modernConf, + ...configFromFile, + ...cliConf, + }; + + const defaultConfig = { ...defaults }; + + /** + * If an argument for `packageFiles` provided, + * we include it as a "default" `bumpFile`. + */ + if (merged.packageFiles) { + defaultConfig.bumpFiles = Array.from(new Set([ + ...(merged.bumpFiles || []), + ...merged.packageFiles, + ])); + } + + const config: Config = { + ...defaults, + + }; + return { - ...(legacyConf ?? {}), - ...(modernConf ?? {}), - ...(configFromFile ?? {}), + ...defaultConfig, + ...merged, }; +} + +const deprecatedOptions: Record = { + message: 'releaseCommitMessageFormat', + changelogHeader: 'header', }; + +function resolveKey(key: string): keyof FileConfig { + const deprecatedKey = deprecatedOptions[key]; + if (deprecatedKey) { + console.warn(`The ${key} option is deprecated and will be removed in the next major version. Use ${deprecatedKey} instead.`); + return deprecatedKey; + } + return key as keyof FileConfig; +} + +/** + * Converts LegacyConfig to modern FileConfig by changing deprecated keys + * in LegacyConfig to the modern equivalent + */ +function convertLegacy(legacyConf: LegacyConfig): FileConfig { + const config: FileConfig = {}; + Object.keys(legacyConf).forEach((k) => { + if (catVOnlyFeatures.includes(k)) { + console.warn( + `The "${k}" option is a feature of commit-and-tag-version, and is not supported by standard-version.${"\n"}Please move this option to the 'commit-and-tag-version' key.${"\n"}In a future version, this will throw an error.` + ); + } + const legacyKey = k as keyof LegacyConfig; + const legacyValue = legacyConf[legacyKey] as any; + const modernKey = resolveKey(legacyKey); + config[modernKey] = legacyValue; + }); + + return config; +} + +function resolveCliValue(key: string): any { + if (key === 'skip') { + return convertCliSkip(argv.skip || []); + } +} + +function convertCliConfig(): FileConfig { + const config: FileConfig = {}; + Object.keys(argv).forEach((key) => { + const value = resolveCliValue(key); + const modernKey = resolveKey(key); + config[modernKey] = value; + }); + + return config; +} + +function convertCliSkip(arg: Task[]) { + const skipOptions: SkipLifecycleSteps = {}; + arg.forEach((a) => { + skipOptions[a] = true; + }); + return skipOptions; +} diff --git a/lib/opts/spec.ts b/lib/opts/spec.ts new file mode 100644 index 000000000..8cc3c4ddb --- /dev/null +++ b/lib/opts/spec.ts @@ -0,0 +1,25 @@ +import { JSONSchema7TypeName } from 'json-schema'; +import { Config } from "conventional-changelog-config-spec"; +import specSchema from "conventional-changelog-config-spec/versions/2.1.0/schema.json"; + +interface SpecProperty { + type: JSONSchema7TypeName; + default: T; + description: string; +} + +interface SpecProperties { + header: SpecProperty; + types: SpecProperty + preMajor: SpecProperty; + commitUrlFormat: SpecProperty; + compareUrlFormat: SpecProperty; + issueUrlFormat: SpecProperty; + userUrlFormat: SpecProperty; + releaseCommitMessageFormat: SpecProperty; + issuePrefixes: SpecProperty; +} + +const spec = specSchema.properties as any as SpecProperties; + +export default spec; diff --git a/lib/opts/types.ts b/lib/opts/types.ts new file mode 100644 index 000000000..83b3613d7 --- /dev/null +++ b/lib/opts/types.ts @@ -0,0 +1,201 @@ +import { Config as SpecConfig } from "conventional-changelog-config-spec"; +import type { PrettyPrint } from "../../type-helpers"; + +export type Release = "minor" | "major" | "patch"; + +export enum Task { + bump = 'bump', + changelog = 'changelog', + commit = 'commit', + tag = 'tag', +} + +export enum Hook { + prerelease = 'prerelease', + prebump = 'prebump', + postbump = 'postbump', + prechangelog = 'prechangelog', + postchangelog = 'postchangelog', + precommit = 'precommit', + postcommit = 'postcommit', + pretag = 'pretag', + posttag = 'posttag', +} + +export type LifecycleHookScripts = { + [key in Hook]?: string; +} + +export type SkipLifecycleSteps = { + [key in Task]?: boolean; +} + + +type TypePrefixes = SpecConfig.Type[]; + +export type BumpFile = + | string + | { filename: string; type: "json" | "gradle" | "plain-text" } + | { filename: string; updater: string }; + +/** + * __THIS SHOULD NOT CHANGE.__ + * @deprecated + * + * The configuration options for `standard-version` as of version 9.5 + * (The last version prior to the fork; deprecated). + * All properties are optional as none are required to br provided by the user. + */ +export interface LegacyConfig { + packageFiles?: BumpFile[]; + bumpFiles?: BumpFile[]; + releaseAs?: Release; + prerelease?: string | boolean; + infile?: string; + message?: string; + firstRelease?: boolean; + sign?: boolean; + noVerify?: boolean; + commitAll?: boolean; + silent?: boolean; + tagPrefix?: string; + scripts?: LifecycleHookScripts; + skip?: SkipLifecycleSteps; + dryRun?: boolean; + gitTagFallback?: boolean; + path?: string; + changelogHeader?: string; + preset?: string; + lernaPackage?: string; + header?: string; + types?: TypePrefixes; + preMajor?: boolean; + commitUrlFormat?: string; + compareUrlFormat?: string; + issueUrlFormat?: string; + userUrlFormat?: string; + releaseCommitMessageFormat?: string; + issuePrefixes?: string[]; + verbose?: boolean; +}; + +/** + * Configuration object read from files + * All properties are optional as none are required to br provided by the user. + * This does not inherit from or extend {@link LegacyConfig} to provide + * a distinct delineation between the old and new + */ +export interface FileConfig { + packageFiles?: BumpFile[]; + bumpFiles?: BumpFile[]; + releaseAs?: Release; + prerelease?: string | boolean; + infile?: string; + firstRelease?: boolean; + sign?: boolean; + noVerify?: boolean; + commitAll?: boolean; + silent?: boolean; + tagPrefix?: string; + releaseCount?: number; + tagForce?: boolean; + scripts?: LifecycleHookScripts; + skip?: SkipLifecycleSteps; + dryRun?: boolean; + gitTagFallback?: boolean; + path?: string; + preset?: string; + lernaPackage?: string; + header?: string; + types?: TypePrefixes; + preMajor?: boolean; + commitUrlFormat?: string; + compareUrlFormat?: string; + issueUrlFormat?: string; + userUrlFormat?: string; + releaseCommitMessageFormat?: string; + issuePrefixes?: string[]; + npmPublishHint?: string; + verbose?: boolean; +}; + +export interface CliConfig { + packageFiles?: BumpFile[]; + bumpFiles?: BumpFile[]; + releaseAs?: Release; + prerelease?: string | boolean; + infile?: string; + message?: string; + firstRelease?: boolean; + sign?: boolean; + noVerify?: boolean; + commitAll?: boolean; + silent?: boolean; + tagPrefix?: string; + releaseCount?: number; + tagForce?: boolean; + scripts?: LifecycleHookScripts; + skip?: SkipLifecycleSteps; + dryRun?: boolean; + gitTagFallback?: boolean; + path?: string; + preset?: string; + lernaPackage?: string; + header?: string; + types?: TypePrefixes; + preMajor?: boolean; + commitUrlFormat?: string; + compareUrlFormat?: string; + issueUrlFormat?: string; + userUrlFormat?: string; + releaseCommitMessageFormat?: string; + issuePrefixes?: string[]; + npmPublishHint?: string; + verbose?: boolean; +} + +/** + * The configuration object for commit-and-tag-version, + * which is a superset of the conventional-changelog-config-spec + * (as of version 2.1.0) + * This may or may not maintain backwards compatibility with + * standard-version (as of version 9.5.0). + * + * This overrides properties in {@link FileConfig} that are required + * for the code to run properly, eliminating some checks to see + * if an option was specified. + * + * All options read from package.json or a config file are merged + * with the default config options. + */ +interface Configuration extends FileConfig { + packageFiles: BumpFile[]; + bumpFiles: BumpFile[]; + infile: string; + firstRelease: boolean; + sign: boolean; + noVerify: boolean; + commitAll: boolean; + silent: boolean; + tagPrefix: string; + releaseCount: number; + tagForce: boolean; + scripts: LifecycleHookScripts; + skip: SkipLifecycleSteps; + dryRun: boolean; + gitTagFallback: boolean; + preset: string; + header: string; + types: TypePrefixes; + preMajor: boolean; + commitUrlFormat: string; + compareUrlFormat: string; + issueUrlFormat: string; + userUrlFormat: string; + releaseCommitMessageFormat: string; + issuePrefixes: string[]; + verbose: boolean; +} + +/** The primary config type to use throughout the code base */ +export type Config = PrettyPrint; diff --git a/lib/preset-loader.js b/lib/preset-loader.js deleted file mode 100644 index a7c077281..000000000 --- a/lib/preset-loader.js +++ /dev/null @@ -1,17 +0,0 @@ -// TODO: this should be replaced with an object we maintain and -// describe in: https://github.com/conventional-changelog/conventional-changelog-config-spec -const spec = require('conventional-changelog-config-spec') - -module.exports = (args) => { - const defaultPreset = require.resolve('conventional-changelog-conventionalcommits') - let preset = args.preset || defaultPreset - if (preset === defaultPreset) { - preset = { - name: defaultPreset - } - Object.keys(spec.properties).forEach(key => { - if (args[key] !== undefined) preset[key] = args[key] - }) - } - return preset -} diff --git a/lib/preset-loader.ts b/lib/preset-loader.ts new file mode 100644 index 000000000..c4db70e1a --- /dev/null +++ b/lib/preset-loader.ts @@ -0,0 +1,17 @@ +// TODO: this should be replaced with an object we maintain and +// describe in: https://github.com/conventional-changelog/conventional-changelog-config-spec +import spec from './opts/spec'; +import { Config } from './opts/types'; + +export default function presetLoader(config: Config) { + if (config.preset) return config.preset; + const defaultPreset = require.resolve('conventional-changelog-conventionalcommits') + const preset: Record = { + name: defaultPreset, + }; + Object.keys(spec).forEach(key => { + const value = config[key as keyof Config]; + if (value !== undefined) preset[key] = value; + }) + return preset; +} diff --git a/lib/print-error.js b/lib/print-error.js deleted file mode 100644 index 84aaa8257..000000000 --- a/lib/print-error.js +++ /dev/null @@ -1,12 +0,0 @@ -const chalk = require('chalk') - -module.exports = function (args, msg, opts) { - if (!args.silent) { - opts = Object.assign({ - level: 'error', - color: 'red' - }, opts) - - console[opts.level](chalk[opts.color](msg)) - } -} diff --git a/lib/print-error.ts b/lib/print-error.ts new file mode 100644 index 000000000..8daf31403 --- /dev/null +++ b/lib/print-error.ts @@ -0,0 +1,31 @@ +import chalk from 'chalk'; +import { Config } from './opts/types'; + +interface PrintErrorOptions { + level?: ('error' | 'warn' | 'info' | 'debug' | 'log'); + color?: + | 'black' + | 'red' + | 'green' + | 'yellow' + | 'blue' + | 'magenta' + | 'cyan' + | 'white' + | 'gray' + | 'grey' + | 'blackBright' + | 'redBright' + | 'greenBright' + | 'yellowBright' + | 'blueBright' + | 'magentaBright' + | 'cyanBright' + | 'whiteBright'; +} + +export default function printError(config: Config, msg: string, opts?: PrintErrorOptions) { + if (!config.silent) { + console[opts?.level || 'error'](chalk[opts?.color || 'red'](msg)); + } +} diff --git a/lib/run-exec.js b/lib/run-exec.js deleted file mode 100644 index eec2feb3d..000000000 --- a/lib/run-exec.js +++ /dev/null @@ -1,18 +0,0 @@ -const { promisify } = require('util') -const printError = require('./print-error') - -const exec = promisify(require('child_process').exec) - -module.exports = async function (args, cmd) { - if (args.dryRun) return - try { - const { stderr, stdout } = await exec(cmd) - // If exec returns content in stderr, but no error, print it as a warning - if (stderr) printError(args, stderr, { level: 'warn', color: 'yellow' }) - return stdout - } catch (error) { - // If exec returns an error, print it and exit with return code 1 - printError(args, error.stderr || error.message) - throw error - } -} diff --git a/lib/run-exec.ts b/lib/run-exec.ts new file mode 100644 index 000000000..e19d6707f --- /dev/null +++ b/lib/run-exec.ts @@ -0,0 +1,20 @@ +import { exec as processExec } from 'child_process'; +import { promisify } from 'util'; +import printError from './print-error'; +import { Config } from './opts/types'; + +const exec = promisify(processExec); + +export default async function runExec(config: Config, cmd: string) { + if (config.dryRun) return + try { + const { stderr, stdout } = await exec(cmd) + // If exec returns content in stderr, but no error, print it as a warning + if (stderr) printError(config, stderr, { level: 'warn', color: 'yellow' }) + return stdout + } catch (error: any) { + // If exec returns an error, print it and exit with return code 1 + printError(config, error.stderr || error.message); + throw error; + } +} diff --git a/lib/run-execFile.js b/lib/run-execFile.js deleted file mode 100644 index c0c814d45..000000000 --- a/lib/run-execFile.js +++ /dev/null @@ -1,18 +0,0 @@ -const { promisify } = require('util') -const printError = require('./print-error') - -const execFile = promisify(require('child_process').execFile) - -module.exports = async function (args, cmd, cmdArgs) { - if (args.dryRun) return - try { - const { stderr, stdout } = await execFile(cmd, cmdArgs) - // If execFile returns content in stderr, but no error, print it as a warning - if (stderr) printError(args, stderr, { level: 'warn', color: 'yellow' }) - return stdout - } catch (error) { - // If execFile returns an error, print it and exit with return code 1 - printError(args, error.stderr || error.message) - throw error - } -} diff --git a/lib/run-execFile.ts b/lib/run-execFile.ts new file mode 100644 index 000000000..de8e9708d --- /dev/null +++ b/lib/run-execFile.ts @@ -0,0 +1,21 @@ +import { execFile as processExecFile } from 'child_process'; +import { Config } from './opts/types'; + +import { promisify } from 'util'; +import printError from './print-error'; + +const execFile = promisify(processExecFile); + +export default async function runExecFile(config: Config, file: string, cmdArgs?: string[]) { + if (config.dryRun) return + try { + const { stderr, stdout } = await execFile(file, cmdArgs); + // If execFile returns content in stderr, but no error, print it as a warning + if (stderr) printError(config, stderr, { level: 'warn', color: 'yellow' }); + return stdout; + } catch (error: any) { + // If execFile returns an error, print it and exit with return code 1 + printError(config, error.stderr || error.message); + throw error; + } +} diff --git a/lib/run-lifecycle-script.js b/lib/run-lifecycle-script.js deleted file mode 100644 index a4c88c2e9..000000000 --- a/lib/run-lifecycle-script.js +++ /dev/null @@ -1,13 +0,0 @@ -const chalk = require('chalk') -const checkpoint = require('./checkpoint') -const figures = require('figures') -const runExec = require('./run-exec') - -module.exports = function (args, hookName) { - const scripts = args.scripts - if (!scripts || !scripts[hookName]) return Promise.resolve() - const command = scripts[hookName] - checkpoint(args, 'Running lifecycle script "%s"', [hookName]) - checkpoint(args, '- execute command: "%s"', [command], chalk.blue(figures.info)) - return runExec(args, command) -} diff --git a/lib/run-lifecycle-script.ts b/lib/run-lifecycle-script.ts new file mode 100644 index 000000000..5eaa3b522 --- /dev/null +++ b/lib/run-lifecycle-script.ts @@ -0,0 +1,17 @@ +import chalk from 'chalk'; +import checkpoint from './checkpoint'; +import figures from 'figures'; +import runExec from './run-exec'; +import { Config, Hook } from './opts/types'; + +export default async function runLifecycleScript(config: Config, hookName: Hook) { + const scripts = config.scripts + if (!scripts || !scripts[hookName]) return Promise.resolve() + const command = scripts[hookName]; + if (command) { + checkpoint(config, 'Running lifecycle script "%s"', [hookName]) + checkpoint(config, '- execute command: "%s"', [command], chalk.blue(figures.info)) + return runExec(config, command) + } + return undefined; +} diff --git a/lib/stringify-package.js b/lib/stringify-package.ts similarity index 81% rename from lib/stringify-package.js rename to lib/stringify-package.ts index 46594cf78..6ac18b002 100644 --- a/lib/stringify-package.js +++ b/lib/stringify-package.ts @@ -16,17 +16,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. https://github.com/npm/stringify-package/blob/main/LICENSE */ -'use strict' - module.exports = stringifyPackage const DEFAULT_INDENT = 2 const CRLF = '\r\n' const LF = '\n' -function stringifyPackage (data, indent, newline) { - indent = indent || (indent === 0 ? 0 : DEFAULT_INDENT) - const json = JSON.stringify(data, null, indent) +export default function stringifyPackage(data: any, indent?: string | number, newline?: string) { + const resolvedIndent = indent || (indent === 0 ? 0 : DEFAULT_INDENT) + const json = JSON.stringify(data, null, resolvedIndent) if (newline === CRLF) { return json.replace(/\n/g, CRLF) + CRLF diff --git a/lib/updaters/index.js b/lib/updaters/index.js deleted file mode 100644 index 819733010..000000000 --- a/lib/updaters/index.js +++ /dev/null @@ -1,93 +0,0 @@ -const path = require('path') -const JSON_BUMP_FILES = require('../../defaults').bumpFiles -const updatersByType = { - json: require('./types/json'), - 'plain-text': require('./types/plain-text'), - gradle: require('./types/gradle') -} -const PLAIN_TEXT_BUMP_FILES = ['VERSION.txt', 'version.txt'] - -function getUpdaterByType (type) { - const updater = updatersByType[type] - if (!updater) { - throw Error(`Unable to locate updater for provided type (${type}).`) - } - return updater -} - -function getUpdaterByFilename (filename) { - if (JSON_BUMP_FILES.includes(path.basename(filename))) { - return getUpdaterByType('json') - } - if (PLAIN_TEXT_BUMP_FILES.includes(filename)) { - return getUpdaterByType('plain-text') - } - if (/build.gradle/.test(filename)) { - return getUpdaterByType('gradle') - } - throw Error( - `Unsupported file (${filename}) provided for bumping.\n Please specify the updater \`type\` or use a custom \`updater\`.` - ) -} - -function getCustomUpdaterFromPath (updater) { - if (typeof updater === 'string') { - return require(path.resolve(process.cwd(), updater)) - } - if ( - typeof updater.readVersion === 'function' && - typeof updater.writeVersion === 'function' - ) { - return updater - } - throw new Error('Updater must be a string path or an object with readVersion and writeVersion methods') -} - -/** - * Simple check to determine if the object provided is a compatible updater. - */ -function isValidUpdater (obj) { - return ( - obj && - typeof obj.readVersion === 'function' && - typeof obj.writeVersion === 'function' - ) -} - -module.exports.resolveUpdaterObjectFromArgument = function (arg) { - /** - * If an Object was not provided, we assume it's the path/filename - * of the updater. - */ - let updater = arg - if (isValidUpdater(updater)) { - return updater - } - if (typeof updater !== 'object') { - updater = { - filename: arg - } - } - - if (!isValidUpdater(updater.updater)) { - try { - if (typeof updater.updater === 'string') { - updater.updater = getCustomUpdaterFromPath(updater.updater) - } else if (updater.type) { - updater.updater = getUpdaterByType(updater.type) - } else { - updater.updater = getUpdaterByFilename(updater.filename) - } - } catch (err) { - if (err.code !== 'ENOENT') console.warn(`Unable to obtain updater for: ${JSON.stringify(arg)}\n - Error: ${err.message}\n - Skipping...`) - } - } - /** - * We weren't able to resolve an updater for the argument. - */ - if (!isValidUpdater(updater.updater)) { - return false - } - - return updater -} diff --git a/lib/updaters/index.ts b/lib/updaters/index.ts new file mode 100644 index 000000000..bcc1ab836 --- /dev/null +++ b/lib/updaters/index.ts @@ -0,0 +1,114 @@ +import path from 'path'; +import defaults from '../../defaults'; +import jsonUpdater from './types/json'; +import plainTextUpdater from './types/plain-text'; +import gradleUpdater from './types/gradle'; +import { BumpFile } from 'lib/opts/types'; + +interface Updater { + readVersion(contents: string): string; + writeVersion(contents: string, version: string): any; + isPrivate?: (contents: string) => boolean; +} + +interface VersionUpdater { + filename: string; + updater: Required; +} + +type UpdaterType = 'json' | 'plain-text' | 'gradle'; + +const JSON_BUMP_FILES = defaults.bumpFiles; +const PLAIN_TEXT_BUMP_FILES = ['VERSION.txt', 'version.txt'] + +const updatersByType: Record = { + json: jsonUpdater, + 'plain-text': plainTextUpdater, + gradle: gradleUpdater, +}; + +function getUpdaterByType(type: UpdaterType, filename: string): VersionUpdater { + const updater = updatersByType[type]; + if (!updater) { + throw Error(`Unable to locate updater for provided type (${type}).`) + } + return { + filename, + updater: { + isPrivate: () => false, + ...updater, + }, + }; +} + +function getUpdaterTypeFromFilename(filename: string) { + if (JSON_BUMP_FILES.includes(path.basename(filename))) { + return 'json'; + } + if (PLAIN_TEXT_BUMP_FILES.includes(filename)) { + return 'plain-text'; + } + if (/build.gradle/.test(filename)) { + return 'gradle'; + } + throw Error( + `Unsupported file (${filename}) provided for bumping.\n Please specify the updater \`type\` or use a custom \`updater\`.` + ) +} + +function getUpdaterFromFile(updater: string, filename: string): VersionUpdater { + const type = getUpdaterTypeFromFilename(updater); + return getUpdaterByType(type, filename); +} + +function getCustomUpdaterFromPath(filename: string): VersionUpdater { + const updater = require(path.resolve(process.cwd(), filename)); + /** + * TODO: This doesn't seem right. If just a string is provided, we use + * that as the loader, but don't know what file to read/write to! + */ + if (isValidUpdater(updater)) { + return { + filename, + updater: { + isPrivate: () => false, + ...updater, + }, + }; + } + + throw new Error('Updater must be a string path or an object with readVersion and writeVersion methods') +} + +/** + * Simple check to determine if the object provided is a compatible updater. + */ +function isValidUpdater(obj: any): obj is Updater { + return ( + obj && + typeof obj.readVersion === 'function' && + typeof obj.writeVersion === 'function' + ) +} + +export function resolveUpdaterObjectFromArgument(arg: BumpFile): VersionUpdater | undefined { + /** + * If an Object was not provided, we assume it's the path/filename + * of the updater. + */ + try { + if (typeof arg === 'string') { + return getCustomUpdaterFromPath(arg); + } else if ('type' in arg) { + return getUpdaterByType(arg.type, arg.filename); + } else { + return getUpdaterFromFile(arg.filename, arg.updater); + } + } catch (err: any) { + if (err.code !== 'ENOENT') console.warn(`Unable to obtain updater for: ${JSON.stringify(arg)}\n - Error: ${err.message}\n - Skipping...`) + } + /** + * We weren't able to resolve an updater for the argument. + */ + return undefined; +} diff --git a/lib/updaters/types/gradle.js b/lib/updaters/types/gradle.js deleted file mode 100644 index 818922e3f..000000000 --- a/lib/updaters/types/gradle.js +++ /dev/null @@ -1,16 +0,0 @@ -const versionRegex = /^version\s+=\s+['"]([\d.]+)['"]/m - -module.exports.readVersion = function (contents) { - const matches = versionRegex.exec(contents) - if (matches === null) { - throw new Error('Failed to read the version field in your gradle file - is it present?') - } - - return matches[1] -} - -module.exports.writeVersion = function (contents, version) { - return contents.replace(versionRegex, () => { - return `version = "${version}"` - }) -} diff --git a/lib/updaters/types/gradle.ts b/lib/updaters/types/gradle.ts new file mode 100644 index 000000000..0d8d1f6dd --- /dev/null +++ b/lib/updaters/types/gradle.ts @@ -0,0 +1,15 @@ +const versionRegex = /^version\s+=\s+['"]([\d.]+)['"]/m + +export default { + readVersion(contents: string) { + const matches = versionRegex.exec(contents) + if (matches === null || !matches[1]) { + throw new Error('Failed to read the version field in your gradle file - is it present?') + } + + return matches[1]; + }, + writeVersion(contents: string, version: string) { + return contents.replace(versionRegex, () => `version = "${version}"`); + }, +}; diff --git a/lib/updaters/types/json.js b/lib/updaters/types/json.js deleted file mode 100644 index e0cba511c..000000000 --- a/lib/updaters/types/json.js +++ /dev/null @@ -1,25 +0,0 @@ -const stringifyPackage = require('../../stringify-package') -const detectIndent = require('detect-indent') -const detectNewline = require('detect-newline') - -module.exports.readVersion = function (contents) { - return JSON.parse(contents).version -} - -module.exports.writeVersion = function (contents, version) { - const json = JSON.parse(contents) - const indent = detectIndent(contents).indent - const newline = detectNewline(contents) - json.version = version - - if (json.packages && json.packages['']) { - // package-lock v2 stores version there too - json.packages[''].version = version - } - - return stringifyPackage(json, indent, newline) -} - -module.exports.isPrivate = function (contents) { - return JSON.parse(contents).private -} diff --git a/lib/updaters/types/json.ts b/lib/updaters/types/json.ts new file mode 100644 index 000000000..f7e78ccc9 --- /dev/null +++ b/lib/updaters/types/json.ts @@ -0,0 +1,25 @@ +import stringifyPackage from '../../stringify-package'; +import detectIndent from 'detect-indent'; +import detectNewline from 'detect-newline'; + +export default { + readVersion(contents: string) { + return JSON.parse(contents).version + }, + writeVersion(contents: string, version: string) { + const json = JSON.parse(contents) + const indent = detectIndent(contents).indent + const newline = detectNewline(contents) + json.version = version + + if (json.packages && json.packages['']) { + // package-lock v2 stores version there too + json.packages[''].version = version + } + + return stringifyPackage(json, indent, newline) + }, + isPrivate(contents: string) { + return JSON.parse(contents).private +}, +}; diff --git a/lib/updaters/types/plain-text.js b/lib/updaters/types/plain-text.js deleted file mode 100644 index 18bcabed2..000000000 --- a/lib/updaters/types/plain-text.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports.readVersion = function (contents) { - return contents -} - -module.exports.writeVersion = function (_contents, version) { - return version -} diff --git a/lib/updaters/types/plain-text.ts b/lib/updaters/types/plain-text.ts new file mode 100644 index 000000000..60cd33e22 --- /dev/null +++ b/lib/updaters/types/plain-text.ts @@ -0,0 +1,9 @@ +export default { + readVersion(contents: string) { + return contents; + }, + + writeVersion(_contents: string, version: string) { + return version; + }, +}; diff --git a/lib/write-file.js b/lib/write-file.js deleted file mode 100644 index b6aaa19f7..000000000 --- a/lib/write-file.js +++ /dev/null @@ -1,6 +0,0 @@ -const fs = require('fs') - -module.exports = function (args, filePath, content) { - if (args.dryRun) return - fs.writeFileSync(filePath, content, 'utf8') -} diff --git a/lib/write-file.ts b/lib/write-file.ts new file mode 100644 index 000000000..1ab2ea93e --- /dev/null +++ b/lib/write-file.ts @@ -0,0 +1,7 @@ +import fs from 'fs'; +import { Config } from './opts/types' + +export default function writeFile(config: Config, filePath: string, content: string | NodeJS.ArrayBufferView) { + if (config.dryRun) return; + fs.writeFileSync(filePath, content, 'utf8'); +} diff --git a/package-lock.json b/package-lock.json index 0a0501036..e65a2d5a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,8 +29,11 @@ }, "devDependencies": { "@types/chai": "^4.3.4", + "@types/conventional-changelog": "^3.1.1", "@types/conventional-changelog-config-spec": "^2.1.2", + "@types/conventional-changelog-core": "^4.2.1", "@types/conventional-recommended-bump": "^6.1.0", + "@types/git-semver-tags": "^4.1.1", "@types/mocha": "^10.0.1", "@types/mockery": "^1.4.30", "@types/node": "^18.15.3", @@ -45,6 +48,7 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-n": "^15.2.0", "eslint-plugin-promise": "^6.0.0", + "json-schema": "^0.4.0", "mocha": "^10.0.0", "mock-fs": "^5.0.0", "mockery": "^2.1.0", @@ -1079,6 +1083,18 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "node_modules/@types/conventional-changelog": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog/-/conventional-changelog-3.1.1.tgz", + "integrity": "sha512-+Ei7ZUTHnWseUthn22+MVLQjcQZ0AitqOk/UMl3/3aX5FMPofGeKVn/0HZYabsLN+kCioP3FpBrucrWdcCoMJw==", + "dev": true, + "dependencies": { + "@types/conventional-changelog-core": "*", + "@types/conventional-changelog-writer": "*", + "@types/conventional-commits-parser": "*", + "@types/node": "*" + } + }, "node_modules/@types/conventional-changelog-config-spec": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@types/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.2.tgz", @@ -1141,6 +1157,12 @@ "@types/node": "*" } }, + "node_modules/@types/git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-6RrosMDOX0rU233ldLAuF4WbF61S44GeQV56D+sV7SG4ZGEXd43LjIgr87NFsD9cE1Kr+n5NMHFRTFpk4MeNxw==", + "dev": true + }, "node_modules/@types/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", @@ -4481,6 +4503,12 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -8113,6 +8141,18 @@ "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, + "@types/conventional-changelog": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/conventional-changelog/-/conventional-changelog-3.1.1.tgz", + "integrity": "sha512-+Ei7ZUTHnWseUthn22+MVLQjcQZ0AitqOk/UMl3/3aX5FMPofGeKVn/0HZYabsLN+kCioP3FpBrucrWdcCoMJw==", + "dev": true, + "requires": { + "@types/conventional-changelog-core": "*", + "@types/conventional-changelog-writer": "*", + "@types/conventional-commits-parser": "*", + "@types/node": "*" + } + }, "@types/conventional-changelog-config-spec": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@types/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.2.tgz", @@ -8175,6 +8215,12 @@ "@types/node": "*" } }, + "@types/git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-6RrosMDOX0rU233ldLAuF4WbF61S44GeQV56D+sV7SG4ZGEXd43LjIgr87NFsD9cE1Kr+n5NMHFRTFpk4MeNxw==", + "dev": true + }, "@types/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", @@ -10609,6 +10655,12 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", diff --git a/package.json b/package.json index a894fee0a..1984654de 100644 --- a/package.json +++ b/package.json @@ -62,8 +62,11 @@ }, "devDependencies": { "@types/chai": "^4.3.4", + "@types/conventional-changelog": "^3.1.1", "@types/conventional-changelog-config-spec": "^2.1.2", + "@types/conventional-changelog-core": "^4.2.1", "@types/conventional-recommended-bump": "^6.1.0", + "@types/git-semver-tags": "^4.1.1", "@types/mocha": "^10.0.1", "@types/mockery": "^1.4.30", "@types/node": "^18.15.3", @@ -78,6 +81,7 @@ "eslint-plugin-import": "^2.26.0", "eslint-plugin-n": "^15.2.0", "eslint-plugin-promise": "^6.0.0", + "json-schema": "^0.4.0", "mocha": "^10.0.0", "mock-fs": "^5.0.0", "mockery": "^2.1.0", diff --git a/tsconfig.json b/tsconfig.json index 8b79b87d6..52b6c3825 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,9 @@ "compilerOptions": { "noEmit": true, "target": "ES2015", - "lib": ["esnext"], + "lib": [ + "esnext" + ], "removeComments": true, "useUnknownInCatchVariables": true, "allowJs": true, @@ -22,7 +24,7 @@ "noImplicitReturns": true, "noImplicitThis": true, "noImplicitAny": true, - "noUnusedLocals": true, + "noUnusedLocals": false, "noUnusedParameters": true, "strictNullChecks": true, "strictFunctionTypes": true, @@ -32,8 +34,17 @@ "noPropertyAccessFromIndexSignature": true, "baseUrl": ".", "outDir": "./dist", - "types": ["node", "mocha"] + "types": [ + "node", + "mocha" + ] }, - "include": ["**/*.js", "**/*.ts"], - "exclude": ["node_modules", "dist"] + "include": [ + "**/*.js", + "**/*.ts" + ], + "exclude": [ + "node_modules", + "dist" + ] } From a779fc3c6bdfd8eb93d1affa2d4080796ee714d9 Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Wed, 12 Apr 2023 08:34:00 -0600 Subject: [PATCH 16/19] chore: rename test files to .ts --- test/{core.spec.js => core.spec.ts} | 0 test/{git.spec.js => git.spec.ts} | 0 test/mocks/updater/{customer-updater.js => customer-updater.ts} | 0 test/mocks/updater/{increment-updater.js => increment-updater.ts} | 0 test/{preset.spec.js => preset.spec.ts} | 0 test/{stringify-package.spec.js => stringify-package.spec.ts} | 0 test/{utils.spec.js => utils.spec.ts} | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename test/{core.spec.js => core.spec.ts} (100%) rename test/{git.spec.js => git.spec.ts} (100%) rename test/mocks/updater/{customer-updater.js => customer-updater.ts} (100%) rename test/mocks/updater/{increment-updater.js => increment-updater.ts} (100%) rename test/{preset.spec.js => preset.spec.ts} (100%) rename test/{stringify-package.spec.js => stringify-package.spec.ts} (100%) rename test/{utils.spec.js => utils.spec.ts} (100%) diff --git a/test/core.spec.js b/test/core.spec.ts similarity index 100% rename from test/core.spec.js rename to test/core.spec.ts diff --git a/test/git.spec.js b/test/git.spec.ts similarity index 100% rename from test/git.spec.js rename to test/git.spec.ts diff --git a/test/mocks/updater/customer-updater.js b/test/mocks/updater/customer-updater.ts similarity index 100% rename from test/mocks/updater/customer-updater.js rename to test/mocks/updater/customer-updater.ts diff --git a/test/mocks/updater/increment-updater.js b/test/mocks/updater/increment-updater.ts similarity index 100% rename from test/mocks/updater/increment-updater.js rename to test/mocks/updater/increment-updater.ts diff --git a/test/preset.spec.js b/test/preset.spec.ts similarity index 100% rename from test/preset.spec.js rename to test/preset.spec.ts diff --git a/test/stringify-package.spec.js b/test/stringify-package.spec.ts similarity index 100% rename from test/stringify-package.spec.js rename to test/stringify-package.spec.ts diff --git a/test/utils.spec.js b/test/utils.spec.ts similarity index 100% rename from test/utils.spec.js rename to test/utils.spec.ts From 03aeb0c5ffb4fb4f740520a2936e6fc3019a02bd Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Wed, 12 Apr 2023 17:24:06 -0600 Subject: [PATCH 17/19] chore: wip on converting tests --- .mocharc.json | 3 + TEST_CHANGELOG.md | 23 +++ command.ts | 3 +- index.ts | 6 +- lib/configuration.ts | 31 +++- lib/detect-package-manager.ts | 38 ++--- lib/lifecycles/bump.ts | 8 +- lib/lifecycles/changelog.ts | 2 +- lib/lifecycles/commit.ts | 2 +- lib/lifecycles/tag.ts | 37 ++-- lib/opts/index.ts | 42 +++-- lib/updaters/index.ts | 14 +- package-lock.json | 170 ++++++++++++++----- package.json | 4 +- test/config-files.spec.ts | 214 +++++++----------------- test/core.spec.ts | 19 +-- test/git.spec.ts | 33 ++-- test/mocks/npm/package-lock.json | 0 test/mocks/pnpm/pnpm-lock.yaml | 0 test/mocks/updater/customer-updater.ts | 11 +- test/mocks/updater/increment-updater.ts | 4 +- test/mocks/yarn/yarn.lock | 0 test/preset.spec.ts | 19 ++- test/stringify-package.spec.ts | 5 +- test/utils.spec.ts | 51 ++---- tsconfig.json | 7 +- vitest.config.ts | 24 +++ 27 files changed, 401 insertions(+), 369 deletions(-) create mode 100644 .mocharc.json create mode 100644 TEST_CHANGELOG.md create mode 100644 test/mocks/npm/package-lock.json create mode 100644 test/mocks/pnpm/pnpm-lock.yaml create mode 100644 test/mocks/yarn/yarn.lock create mode 100644 vitest.config.ts diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 000000000..1e696bc50 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,3 @@ +{ + "jobs": 1 +} diff --git a/TEST_CHANGELOG.md b/TEST_CHANGELOG.md new file mode 100644 index 000000000..e19bb8180 --- /dev/null +++ b/TEST_CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) + +## [1.0.2](https://github.com/SharpSeeEr/commit-and-tag-version/compare/v11.2.1...v1.0.2) (2023-04-12) diff --git a/command.ts b/command.ts index 532a90e45..7b7043955 100755 --- a/command.ts +++ b/command.ts @@ -12,7 +12,7 @@ import yargs from 'yargs/yargs'; import { Task } from './lib/opts/types'; import spec from './lib/opts/spec'; -const cmdParser = yargs(process.argv.slice(2)) +export const cmdParser = yargs(process.argv.slice(2)) .scriptName('commit-and-tag-version') .usage('Usage: $0 [options]') .help('help').alias('help', 'h') @@ -229,4 +229,5 @@ const cmdParser = yargs(process.argv.slice(2)) // }); // }); const argv = cmdParser.parseSync(); + export default argv; diff --git a/index.ts b/index.ts index 9e18d0828..e26b82500 100755 --- a/index.ts +++ b/index.ts @@ -9,15 +9,15 @@ import printError from './lib/print-error'; import tag from './lib/lifecycles/tag'; import { resolveUpdaterObjectFromArgument } from './lib/updaters'; import { getMergedConfig } from './lib/opts'; -import { BumpFile, Config } from 'lib/opts/types'; +import { BumpFile, Config } from './lib/opts/types'; interface PackageInfo { version: string; private: boolean; } -export default async function standardVersion() { - const config = await getMergedConfig(); +export default async function standardVersion(argv: any) { + const config = await getMergedConfig(argv); if ( config.header && diff --git a/lib/configuration.ts b/lib/configuration.ts index 99f0989d4..c8e1a7c2c 100644 --- a/lib/configuration.ts +++ b/lib/configuration.ts @@ -1,3 +1,4 @@ +import fs from 'fs'; import path from 'path' import findUp from 'find-up' import { readFileSync } from 'fs' @@ -10,32 +11,46 @@ const CONFIGURATION_FILES = [ '.versionrc.js' ] as const; -export async function getConfiguration(): Promise { - const configPath = findUp.sync(CONFIGURATION_FILES) - if (!configPath) { +export async function getConfiguration(cwd?: string): Promise { + const currentDir = cwd || process.cwd(); + const configFile = getConfigFile(cwd || process.cwd()); // findUp.sync(CONFIGURATION_FILES) + if (!configFile) { return {} } - const config = await readConfigFile(configPath); + const config = await readConfigFile(configFile, currentDir); + console.log(currentDir, configFile, typeof config, config); + const contents = fs.readFileSync(configFile, 'utf-8'); + // console.log(contents); /** * @todo we could eventually have deeper validation of the configuration (using `ajv`) and * provide a more helpful error. */ if (typeof config !== 'object') { - throw Error( - `[commit-and-tag-version] Invalid configuration in ${configPath} provided. Expected an object but found ${typeof config}.` + throw new Error( + `[commit-and-tag-version] Invalid configuration in ${configFile} provided. Expected an object but found ${typeof config}.` ) } return config } -async function readConfigFile(configPath: string): Promise { - const ext = path.extname(configPath); + +function getConfigFile(cwd: string) { + return CONFIGURATION_FILES.find((file) => fs.existsSync(path.join(cwd, file))); +} + +async function readConfigFile(configFile: string, cwd: string): Promise { + const configPath = path.resolve(cwd, configFile); + console.log('configPath', configPath) + + const ext = path.extname(configFile); if (ext === '.js' || ext === '.cjs') { const jsConfiguration = require(configPath); if (typeof jsConfiguration === 'function') { + console.log(jsConfiguration()); return jsConfiguration(); } + console.log(jsConfiguration); return jsConfiguration; } return JSON.parse(readFileSync(configPath, 'utf-8')); diff --git a/lib/detect-package-manager.ts b/lib/detect-package-manager.ts index 4fb30608e..ae5984bec 100644 --- a/lib/detect-package-manager.ts +++ b/lib/detect-package-manager.ts @@ -4,48 +4,40 @@ * modified to support only detecting lock file and not detecting global package manager */ -import { promises as fs } from 'fs'; +import { access } from 'fs/promises'; import { resolve } from 'path'; /** * Check if a path exists */ -async function pathExists (p: string) { +async function pathExists(p: string) { try { - await fs.access(p) + await access(p) return true } catch { return false } } -function getTypeofLockFile (cwd = '.') { - return Promise.all([ - pathExists(resolve(cwd, 'yarn.lock')), - pathExists(resolve(cwd, 'package-lock.json')), - pathExists(resolve(cwd, 'pnpm-lock.yaml')) - ]).then(([isYarn, isNpm, isPnpm]) => { - let value = null +async function getTypeofLockFile(cwd: string) { + const yarnCheck = pathExists(resolve(cwd, 'yarn.lock')); + const npmCheck = pathExists(resolve(cwd, 'package-lock.json')); + const pnpmCheck = pathExists(resolve(cwd, 'pnpm-lock.yaml')); - if (isYarn) { - value = 'yarn' - } else if (isPnpm) { - value = 'pnpm' - } else if (isNpm) { - value = 'npm' - } + const isYarn = await yarnCheck; + const isNpm = await npmCheck; + const isPnpm = await pnpmCheck; + if (isYarn) return 'yarn'; + if (isNpm) return 'npm'; + if (isPnpm) return 'pnpm'; - return value - }) + return ''; } -const detectPMByLockFile = async (cwd: string) => { +export default async function detectPMByLockFile(cwd = '.') { const type = await getTypeofLockFile(cwd) if (type) { return type } - return 'npm' } - -export default detectPMByLockFile; diff --git a/lib/lifecycles/bump.ts b/lib/lifecycles/bump.ts index ed88b7041..e579dfabb 100644 --- a/lib/lifecycles/bump.ts +++ b/lib/lifecycles/bump.ts @@ -1,17 +1,17 @@ import chalk from 'chalk' import checkpoint from '../checkpoint' -import conventionalRecommendedBump, { Callback } from 'conventional-recommended-bump' +import semver, { ReleaseType } from 'semver' +import conventionalRecommendedBump from 'conventional-recommended-bump' import figures from 'figures' import fs from 'fs' import DotGitignore from 'dotgitignore' import path from 'path' + import presetLoader from '../preset-loader' import runLifecycleScript from '../run-lifecycle-script' -import semver from 'semver' import writeFile from '../write-file' import { resolveUpdaterObjectFromArgument } from '../updaters' -import { Config, Hook, Release } from 'lib/opts/types' -import { ReleaseType } from 'semver' +import { Config, Hook, Release } from '../opts/types' let configsToUpdate: Record = {}; diff --git a/lib/lifecycles/changelog.ts b/lib/lifecycles/changelog.ts index ec95dd614..4c89f1328 100644 --- a/lib/lifecycles/changelog.ts +++ b/lib/lifecycles/changelog.ts @@ -5,7 +5,7 @@ import fs from 'fs'; import presetLoader from '../preset-loader'; import runLifecycleScript from '../run-lifecycle-script'; import writeFile from '../write-file'; -import { Config, Hook } from 'lib/opts/types'; +import { Config, Hook } from '../opts/types'; const START_OF_LAST_RELEASE_PATTERN = /(^#+ \[?[0-9]+\.[0-9]+\.[0-9]+| { +async function loadPackageJson(cwd?: string): Promise { const searchDir = cwd ?? process.cwd(); - const pkgJson = await import(path.join(searchDir, "package.json")); + const pkgPath = path.join(searchDir, 'package.json'); + if (fs.existsSync(pkgPath)) { + return await import(pkgPath); + } + return {}; +} + +export async function getMergedConfig(argv: any, cwd?: string): Promise { + // const searchDir = cwd ?? process.cwd(); + const pkgJson = await loadPackageJson(cwd); // await import(path.join(searchDir, "package.json")); + console.log(pkgJson['commit-and-tag-version']); const legacyConf = convertLegacy(pkgJson["standard-version"] ?? {}); const modernConf: FileConfig = pkgJson["commit-and-tag-version"] ?? {}; - const cliConf = convertCliConfig(); - const configFromFile = await getConfigFromFile(); + const cliConf = convertCliConfig(argv); + const configFromFile = await getConfiguration(); + + // console.log('legacyConf', legacyConf); + // console.log('modernConf', modernConf); + // console.log('cliConf', cliConf); + // console.log('configFromFile', configFromFile); // Check for legacy config properties that will be overwritten Object.keys(legacyConf).forEach((key) => { @@ -35,7 +50,6 @@ export async function getMergedConfig(cwd?: string): Promise { ...configFromFile, ...cliConf, }; - const defaultConfig = { ...defaults }; /** @@ -49,11 +63,6 @@ export async function getMergedConfig(cwd?: string): Promise { ])); } - const config: Config = { - ...defaults, - - }; - return { ...defaultConfig, ...merged, @@ -95,16 +104,17 @@ function convertLegacy(legacyConf: LegacyConfig): FileConfig { return config; } -function resolveCliValue(key: string): any { +function resolveCliValue(argv: any, key: string): any { if (key === 'skip') { return convertCliSkip(argv.skip || []); } + return argv[key]; } -function convertCliConfig(): FileConfig { +function convertCliConfig(argv: any): FileConfig { const config: FileConfig = {}; Object.keys(argv).forEach((key) => { - const value = resolveCliValue(key); + const value = resolveCliValue(argv, key); const modernKey = resolveKey(key); config[modernKey] = value; }); diff --git a/lib/updaters/index.ts b/lib/updaters/index.ts index bcc1ab836..8b5172cbd 100644 --- a/lib/updaters/index.ts +++ b/lib/updaters/index.ts @@ -3,7 +3,7 @@ import defaults from '../../defaults'; import jsonUpdater from './types/json'; import plainTextUpdater from './types/plain-text'; import gradleUpdater from './types/gradle'; -import { BumpFile } from 'lib/opts/types'; +import { BumpFile } from '../opts/types'; interface Updater { readVersion(contents: string): string; @@ -56,13 +56,13 @@ function getUpdaterTypeFromFilename(filename: string) { ) } -function getUpdaterFromFile(updater: string, filename: string): VersionUpdater { - const type = getUpdaterTypeFromFilename(updater); +function getUpdaterFromFilename(filename: string): VersionUpdater { + const type = getUpdaterTypeFromFilename(filename); return getUpdaterByType(type, filename); } -function getCustomUpdaterFromPath(filename: string): VersionUpdater { - const updater = require(path.resolve(process.cwd(), filename)); +function getCustomUpdaterFromPath(updaterFilename: string, filename: string): VersionUpdater { + const updater = require(path.resolve(process.cwd(), updaterFilename)); /** * TODO: This doesn't seem right. If just a string is provided, we use * that as the loader, but don't know what file to read/write to! @@ -98,11 +98,11 @@ export function resolveUpdaterObjectFromArgument(arg: BumpFile): VersionUpdater */ try { if (typeof arg === 'string') { - return getCustomUpdaterFromPath(arg); + return getUpdaterFromFilename(arg); } else if ('type' in arg) { return getUpdaterByType(arg.type, arg.filename); } else { - return getUpdaterFromFile(arg.filename, arg.updater); + return getCustomUpdaterFromPath(arg.updater, arg.filename); } } catch (err: any) { if (err.code !== 'ENOENT') console.warn(`Unable to obtain updater for: ${JSON.stringify(arg)}\n - Error: ${err.message}\n - Skipping...`) diff --git a/package-lock.json b/package-lock.json index e65a2d5a6..903613472 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1472,9 +1472,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "bin": { "acorn": "bin/acorn" }, @@ -1857,14 +1857,14 @@ ] }, "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -2349,15 +2349,15 @@ } }, "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=6" } }, "node_modules/deep-is": { @@ -4092,9 +4092,9 @@ } }, "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "dependencies": { "has": "^1.0.3" }, @@ -4764,9 +4764,9 @@ } }, "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "dependencies": { "get-func-name": "^2.0.0" @@ -5908,6 +5908,32 @@ "node": ">=8" } }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "optional": true, + "peer": true, + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/postcss-load-config": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", @@ -5937,6 +5963,26 @@ } } }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "optional": true, + "peer": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -6233,11 +6279,11 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dependencies": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -6430,6 +6476,17 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -8437,9 +8494,9 @@ "dev": true }, "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" }, "acorn-jsx": { "version": "5.3.2", @@ -8712,14 +8769,14 @@ "dev": true }, "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -9092,9 +9149,9 @@ } }, "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -10363,9 +10420,9 @@ "dev": true }, "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "requires": { "has": "^1.0.3" } @@ -10851,9 +10908,9 @@ } }, "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "requires": { "get-func-name": "^2.0.0" @@ -11709,6 +11766,29 @@ } } }, + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "dependencies": { + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "optional": true, + "peer": true + } + } + }, "postcss-load-config": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", @@ -11932,11 +12012,11 @@ "dev": true }, "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "requires": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -12062,6 +12142,14 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "optional": true, + "peer": true + }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", diff --git a/package.json b/package.json index 1984654de..e4e1db614 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ "scripts": { "fix": "eslint . --fix", "posttest": "eslint .", - "test": "nyc ts-mocha --type-check --timeout=30000", - "test:unit": "ts-mocha --exclude test/git.spec.js", + "test": "nyc ts-mocha --type-check --timeout=30000 test/", + "test:unit": "mocha -r ts-node/register -j 1 test/**/config-files.spec.ts", "coverage": "nyc report --reporter=lcov", "release": "dist/bin/cli.js", "build": "npx tsc && tsup" diff --git a/test/config-files.spec.ts b/test/config-files.spec.ts index aceff6184..af1d8091c 100644 --- a/test/config-files.spec.ts +++ b/test/config-files.spec.ts @@ -1,209 +1,111 @@ /* global describe it beforeEach afterEach */ - import shell from "shelljs"; import * as fs from "node:fs"; import { Readable } from "stream"; import mockery from "mockery"; -import stdMocks from "std-mocks"; +// import { use as stdMocksUse, flush as stdMocksFlush, restore } from "std-mocks"; import { expect } from "chai"; - -require("chai").should(); +import { cmdParser } from '../command'; +import { Release, Task } from '../lib/opts/types'; +import cli from '../index'; +import { getMergedConfig } from '../lib/opts'; +import { getConfiguration } from '../lib/configuration'; function exec() { - const cli = require("../command"); - const opt = cli.parse("commit-and-tag-version"); - opt.skip = { commit: true, tag: true }; - return require("../index")(opt); + const argv = cmdParser.parseSync("commit-and-tag-version"); + argv.skip = [Task.commit, Task.tag]; + return getMergedConfig(argv); } -// These types are all guesses to get mocha working -// TODO: Fix these types and remove the start and end comments -type Preset = { - issueUrlFormat: string; -}; - -type HasPreset = { - preset: Preset; -}; - -type ChangelogFn = (props: HasPreset) => string; - -type MockArg = { - bump?: string | Function | Error; - changelog?: ChangelogFn | ChangelogFn[]; - tags?: string[] | Error; -}; - -type BumpCallback = (n: Error | null, s?: { releaseType?: string }) => void; - -type TagsCallback = (n: Error | null, s?: string[]) => void; - -type Options = unknown; -// END GUESSES - -/** - * Mock external conventional-changelog modules - * - * Mocks should be unregistered in test cleanup by calling unmock() - * - * bump?: 'major' | 'minor' | 'patch' | Error | (opt, cb) => { cb(err) | cb(null, { releaseType }) } - * changelog?: string | Error | Array string | null> - * tags?: string[] | Error - */ -function mock({ bump, changelog, tags }: MockArg = {}) { - mockery.enable({ warnOnUnregistered: false, useCleanCache: true }); - - mockery.registerMock( - "conventional-recommended-bump", - function (opt: Options, cb: BumpCallback) { - if (typeof bump === "function") bump(opt, cb); - else if (bump instanceof Error) cb(bump); - else cb(null, bump ? { releaseType: bump } : {}); - } - ); - - if (!Array.isArray(changelog)) changelog = changelog ? [changelog] : []; - - mockery.registerMock( - "conventional-changelog", - (opt: HasPreset) => - new Readable({ - read(_size) { - const next = (changelog as ChangelogFn[]).shift(); - if (next instanceof Error) { - this.destroy(next); - } else if (typeof next === "function") { - this.push(next(opt)); - } else { - this.push(next ? Buffer.from(next, "utf8") : null); - } - }, - }) - ); - - mockery.registerMock("git-semver-tags", function (cb: TagsCallback) { - if (tags instanceof Error) cb(tags); - // I don't think this is right, but I didn't want to change the behaviour - // @ts-ignore - else cb(null, tags | []); - }); - - stdMocks.use(); - return () => stdMocks.flush(); +function writePackageJson(configKey: string, issueUrlFormat: string) { + const pkg = { + version: "1.0.0", + repository: { url: "git+https://company@scm.org/office/app.git" }, + [configKey]: { issueUrlFormat }, + }; + fs.writeFileSync("package.json", JSON.stringify(pkg), "utf-8"); } describe("config files", () => { - beforeEach(function () { + before(() => { shell.rm("-rf", "tmp"); shell.config.silent = true; shell.mkdir("tmp"); shell.cd("tmp"); - fs.writeFileSync( - "package.json", - JSON.stringify({ version: "1.0.0" }), - "utf-8" - ); }); - afterEach(function () { + after(() => { shell.cd("../"); shell.rm("-rf", "tmp"); + shell.config.silent = false; + }); - mockery.deregisterAll(); - mockery.disable(); - stdMocks.restore(); + beforeEach(function () { + shell.mkdir(this.currentTest!.id); + shell.cd(this.currentTest!.id); + }); - // push out prints from the Mocha reporter - const { stdout } = stdMocks.flush(); - for (const str of stdout) { - if (str.startsWith(" ")) process.stdout.write(str); - } + afterEach(function () { + shell.cd("../"); + shell.rm("-rf", this.currentTest!.id); }); - const configKeys = ["commit-and-tag-version", "standard-version"]; - - configKeys.forEach((configKey) => { - it(`reads config from package.json key '${configKey}'`, async function () { - const issueUrlFormat = - "https://commit-and-tag-version.company.net/browse/{{id}}"; - mock({ - bump: "minor", - changelog: ({ preset }) => preset.issueUrlFormat, - }); - const pkg = { - version: "1.0.0", - repository: { url: "git+https://company@scm.org/office/app.git" }, - [configKey]: { issueUrlFormat }, - }; - fs.writeFileSync("package.json", JSON.stringify(pkg), "utf-8"); - - await exec(); - const content = fs.readFileSync("CHANGELOG.md", "utf-8"); - expect(content).should.include(issueUrlFormat); - }); + const issueUrlFormat = "http://www.foo.com/{{id}}"; + const configObjString = `{ issueUrlFormat: "${issueUrlFormat}" }`; + + it(`reads config from package.json key 'commit-and-tag-version'`, async function () { + writePackageJson('commit-and-tag-version', issueUrlFormat); + + const config = await exec(); + expect(config.issueUrlFormat).eq(issueUrlFormat); + }); + + it(`reads config from package.json key 'standard-version'`, async function () { + writePackageJson('standard-version', issueUrlFormat); + + const config = await exec(); + expect(config.issueUrlFormat).eq(issueUrlFormat); }); it("reads config from .versionrc", async function () { - const issueUrlFormat = "http://www.foo.com/{{id}}"; - const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; - mock({ bump: "minor", changelog }); fs.writeFileSync(".versionrc", JSON.stringify({ issueUrlFormat }), "utf-8"); - await exec(); - const content = fs.readFileSync("CHANGELOG.md", "utf-8"); - content.should.include(issueUrlFormat); + const config = await exec(); + expect(config.issueUrlFormat).eq(issueUrlFormat); }); it("reads config from .versionrc.json", async function () { - const issueUrlFormat = "http://www.foo.com/{{id}}"; - const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; - mock({ bump: "minor", changelog }); - fs.writeFileSync( - ".versionrc.json", - JSON.stringify({ issueUrlFormat }), - "utf-8" - ); - - await exec(); - const content = fs.readFileSync("CHANGELOG.md", "utf-8"); - content.should.include(issueUrlFormat); + fs.writeFileSync(".versionrc.json", JSON.stringify({ issueUrlFormat }), "utf-8"); + + const config = await exec(); + expect(config.issueUrlFormat).eq(issueUrlFormat); }); it("evaluates a config-function from .versionrc.js", async function () { - const issueUrlFormat = "http://www.foo.com/{{id}}"; - const src = `module.exports = function() { return ${JSON.stringify({ - issueUrlFormat, - })} }`; - const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; - mock({ bump: "minor", changelog }); + const src = `module.exports = function() { return ${configObjString}; }`; fs.writeFileSync(".versionrc.js", src, "utf-8"); - await exec(); - const content = fs.readFileSync("CHANGELOG.md", "utf-8"); - content.should.include(issueUrlFormat); + const config = await exec(); + expect(config.issueUrlFormat).eq(issueUrlFormat); }); it("evaluates a config-object from .versionrc.js", async function () { - const issueUrlFormat = "http://www.foo.com/{{id}}"; - const src = `module.exports = ${JSON.stringify({ issueUrlFormat })}`; - const changelog: ChangelogFn = ({ preset }) => preset.issueUrlFormat; - mock({ bump: "minor", changelog }); + const src = `module.exports = ${configObjString}`; fs.writeFileSync(".versionrc.js", src, "utf-8"); - await exec(); - const content = fs.readFileSync("CHANGELOG.md", "utf-8"); - content.should.include(issueUrlFormat); + const config = await exec(); + expect(config.issueUrlFormat).eq(issueUrlFormat); }); it("throws an error when a non-object is returned from .versionrc.js", async function () { - mock({ bump: "minor" }); fs.writeFileSync(".versionrc.js", "module.exports = 3", "utf-8"); try { - await exec(); + await getConfiguration(); /* istanbul ignore next */ throw new Error("Unexpected success"); - } catch (error) { - expect((error as Error).message).should.match(/Invalid configuration/); + } catch (error: any) { + console.log(error.message) + expect(error.message).match(/Invalid configuration/); } }); }); diff --git a/test/core.spec.ts b/test/core.spec.ts index a94ac5035..096e1f2a8 100644 --- a/test/core.spec.ts +++ b/test/core.spec.ts @@ -1,15 +1,12 @@ /* global describe it afterEach */ - -'use strict' - -const shell = require('shelljs') -const fs = require('fs') -const { resolve } = require('path') -const { Readable } = require('stream') -const mockFS = require('mock-fs') -const mockery = require('mockery') -const stdMocks = require('std-mocks') -const stripAnsi = require('strip-ansi') +import shell from 'shelljs' +import fs from 'fs' +import { resolve } from 'path' +import { Readable } from 'stream' +import mockFS from 'mock-fs' +import mockery from 'mockery' +import stdMocks from 'std-mocks' +import stripAnsi from 'strip-ansi' const cli = require('../command') const formatCommitMessage = require('../lib/format-commit-message') diff --git a/test/git.spec.ts b/test/git.spec.ts index 74ee6313e..a908562dd 100644 --- a/test/git.spec.ts +++ b/test/git.spec.ts @@ -1,12 +1,10 @@ /* global describe it beforeEach afterEach */ - -'use strict' - -const shell = require('shelljs') -const fs = require('fs') -const { Readable } = require('stream') -const mockery = require('mockery') -const stdMocks = require('std-mocks') +import shell from 'shelljs' +import fs from 'fs' +import { Readable } from 'stream' +import mockery from 'mockery' +import stdMocks from 'std-mocks' +import { Hook, Release } from 'lib/opts/types' require('chai').should() @@ -18,12 +16,12 @@ function exec (opt = '') { return require('../index')(opt) } -function writePackageJson (version, option) { +function writePackageJson(version: string, option: any) { const pkg = Object.assign({}, option, { version }) fs.writeFileSync('package.json', JSON.stringify(pkg), 'utf-8') } -function writeHook (hookName, causeError, script) { +function writeHook (hookName: Hook, causeError: boolean, script: string) { shell.mkdir('-p', 'scripts') let content = script || 'console.error("' + hookName + ' ran")' content += causeError ? '\nthrow new Error("' + hookName + '-failure")' : '' @@ -35,6 +33,11 @@ function getPackageVersion () { return JSON.parse(fs.readFileSync('package.json', 'utf-8')).version } +interface MockArgs { + bump: Release | Error; + changelog: string | Error | (string | Error)[]; + tags: string[]; +} /** * Mock external conventional-changelog modules * @@ -42,13 +45,13 @@ function getPackageVersion () { * changelog?: string | Error | Array string | null> * tags?: string[] | Error */ -function mock ({ bump, changelog, tags }) { +function mock ({ bump, changelog, tags }: MockArgs) { if (bump === undefined) throw new Error('bump must be defined for mock()') mockery.enable({ warnOnUnregistered: false, useCleanCache: true }) - mockery.registerMock('conventional-recommended-bump', function (opt, cb) { - if (typeof bump === 'function') bump(opt, cb) - else if (bump instanceof Error) cb(bump) + mockery.registerMock('conventional-recommended-bump', function (opt: string, cb: ()) { + // if (typeof bump === 'function') bump(opt, cb) + if (bump instanceof Error) cb(bump) else cb(null, { releaseType: bump }) }) @@ -70,7 +73,7 @@ function mock ({ bump, changelog, tags }) { }) ) - mockery.registerMock('git-semver-tags', function (_, cb) { + mockery.registerMock('git-semver-tags', function (_: any, cb: ) { if (tags instanceof Error) cb(tags) else cb(null, tags || []) }) diff --git a/test/mocks/npm/package-lock.json b/test/mocks/npm/package-lock.json new file mode 100644 index 000000000..e69de29bb diff --git a/test/mocks/pnpm/pnpm-lock.yaml b/test/mocks/pnpm/pnpm-lock.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/test/mocks/updater/customer-updater.ts b/test/mocks/updater/customer-updater.ts index 989aba3c0..56a8b53f9 100644 --- a/test/mocks/updater/customer-updater.ts +++ b/test/mocks/updater/customer-updater.ts @@ -1,12 +1,13 @@ const REPLACER = /version: "(.*)"/ -module.exports.readVersion = function (contents) { - return REPLACER.exec(contents)[1] +module.exports.readVersion = function (contents: string) { + const version = REPLACER.exec(contents); + return version ? version[1] : ''; } -module.exports.writeVersion = function (contents, version) { +module.exports.writeVersion = function (contents: string, version: string) { return contents.replace( - REPLACER.exec(contents)[0], - `version: "${version}"` + REPLACER, + `version: "${version}"`, ) } diff --git a/test/mocks/updater/increment-updater.ts b/test/mocks/updater/increment-updater.ts index 823fa0195..5f8f311ed 100644 --- a/test/mocks/updater/increment-updater.ts +++ b/test/mocks/updater/increment-updater.ts @@ -1,7 +1,7 @@ -module.exports.readVersion = function (contents) { +module.exports.readVersion = function (contents: string) { return Number.parseInt(contents) } -module.exports.writeVersion = function (contents, version) { +module.exports.writeVersion = function (contents: string, _version: string) { return this.readVersion(contents) + 1 } diff --git a/test/mocks/yarn/yarn.lock b/test/mocks/yarn/yarn.lock new file mode 100644 index 000000000..e69de29bb diff --git a/test/preset.spec.ts b/test/preset.spec.ts index 7bee33299..facd34557 100644 --- a/test/preset.spec.ts +++ b/test/preset.spec.ts @@ -1,15 +1,17 @@ /* global describe it beforeEach, afterEach */ -const shell = require('shelljs') -const fs = require('fs') +import shell from 'shelljs' +import fs from 'fs' +import { cmdParser } from '../command' +import cli from '../index'; +import { Task } from '../lib/opts/types'; require('chai').should() -function exec (opt) { - const cli = require('../command') - opt = cli.parse(`commit-and-tag-version ${opt} --silent`) - opt.skip = { commit: true, tag: true } - return require('../index')(opt) +function exec (opt?: string) { + const argv = cmdParser.parseSync(`commit-and-tag-version ${opt} --silent`) + argv.skip = [Task.commit, Task.tag]; + return cli(argv) } describe('presets', () => { @@ -17,7 +19,7 @@ describe('presets', () => { shell.rm('-rf', 'tmp') shell.config.silent = true shell.mkdir('tmp') - shell.cd('tmp') + shell.cd('./tmp') shell.exec('git init') shell.exec('git config commit.gpgSign false') shell.exec('git config core.autocrlf false') @@ -37,6 +39,7 @@ describe('presets', () => { it('Conventional Commits (default)', async function () { await exec() const content = fs.readFileSync('CHANGELOG.md', 'utf-8') + console.log(content); content.should.contain('### Features') content.should.not.contain('### Performance Improvements') content.should.not.contain('### Custom') diff --git a/test/stringify-package.spec.ts b/test/stringify-package.spec.ts index 08a2dd908..dc640eb1b 100644 --- a/test/stringify-package.spec.ts +++ b/test/stringify-package.spec.ts @@ -1,8 +1,5 @@ /* global describe it */ - -'use strict' - -const stringifyPackage = require('../lib/stringify-package') +import stringifyPackage from '../lib/stringify-package' require('chai').should() diff --git a/test/utils.spec.ts b/test/utils.spec.ts index 14f8a3216..c48313c4c 100644 --- a/test/utils.spec.ts +++ b/test/utils.spec.ts @@ -1,52 +1,21 @@ /* global describe it */ +import detectPMByLockFile from '../lib/detect-package-manager' -const mockery = require('mockery') -const { promises: fsp } = require('fs') require('chai').should() -function mockNpm () { - mockery.enable({ warnOnUnregistered: false, useCleanCache: true }) - let lockFile = '' - - const fsMock = { - promises: { - access: async function (path) { - if (lockFile && path.endsWith(lockFile)) { - return true - } - await fsp.access(path) - } - } - } - mockery.registerMock('fs', fsMock) - return { - setLockFile (file) { - lockFile = file - } - } -} - describe('utils', () => { - it('detectPMByLockFile should work', async function () { - const { setLockFile } = mockNpm() - const { detectPMByLockFile } = require('../lib/detect-package-manager') - - let pm = await detectPMByLockFile() + it('detectPMByLockFile should detect npm', async function () { + const pm = await detectPMByLockFile('./test/mocks/npm') pm.should.equal('npm') + }); - setLockFile('yarn.lock') - pm = await detectPMByLockFile() + it('detectPMByLockFile should detect yarn', async function () { + const pm = await detectPMByLockFile('./test/mocks/yarn') pm.should.equal('yarn') + }); - setLockFile('package-lock.json') - pm = await detectPMByLockFile() - pm.should.equal('npm') - - setLockFile('pnpm-lock.yaml') - pm = await detectPMByLockFile() + it('detectPMByLockFile should detect pnpm', async function () { + const pm = await detectPMByLockFile('./test/mocks/pnpm') pm.should.equal('pnpm') - - mockery.deregisterAll() - mockery.disable() - }) + }); }) diff --git a/tsconfig.json b/tsconfig.json index 52b6c3825..4fe3751cd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,7 +37,7 @@ "types": [ "node", "mocha" - ] + ], }, "include": [ "**/*.js", @@ -46,5 +46,8 @@ "exclude": [ "node_modules", "dist" - ] + ], + "ts-node": { + "files": true + } } diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 000000000..ac4596b7f --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,24 @@ +import { defineConfig } from 'vitest/config' +import { resolve, dirname } from 'path' +import { fileURLToPath } from 'url' + +const dir = dirname(fileURLToPath(import.meta.url)) + +export default defineConfig({ + test: { + // Alias transformations to match the ones on tsconfig.json paths + alias: { + '@': resolve(dir, 'src'), + '@typings': resolve(dir, 'src/typings'), + '@bin': resolve(dir, 'src/bin'), + '@lib': resolve(dir, 'src/lib'), + '@test': resolve(dir, 'test'), + '@mocks': resolve(dir, 'test/mocks') + }, + coverage: { + provider: 'istanbul', + reporter: ['text', 'html', 'lcov', 'json'] + }, + globals: true, + } +}) From 1a9a1e6f59b002e720db19d698e73a99e5902d8f Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Thu, 13 Apr 2023 17:06:27 -0600 Subject: [PATCH 18/19] chore(release): 11.2.2 --- tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md | 10 ++++++++++ tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md create mode 100644 tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md diff --git a/tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md b/tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md new file mode 100644 index 000000000..b778d431c --- /dev/null +++ b/tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. + +## [11.2.2](https://github.com/absolute-version/commit-and-tag-version/compare/v11.2.1...v11.2.2) (2023-04-13) + + +### Bug Fixes + +* correct imports in index.ts ([f2aa8bd](https://github.com/absolute-version/commit-and-tag-version/commit/f2aa8bda05533a78ca0041ef0622fe1bc4d2b0d5)) diff --git a/tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md b/tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md new file mode 100644 index 000000000..b778d431c --- /dev/null +++ b/tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. + +## [11.2.2](https://github.com/absolute-version/commit-and-tag-version/compare/v11.2.1...v11.2.2) (2023-04-13) + + +### Bug Fixes + +* correct imports in index.ts ([f2aa8bd](https://github.com/absolute-version/commit-and-tag-version/commit/f2aa8bda05533a78ca0041ef0622fe1bc4d2b0d5)) From 8f57c8983155e8774fdba9c80f3bd665fe4e5936 Mon Sep 17 00:00:00 2001 From: Aaron Throckmorton Date: Thu, 13 Apr 2023 17:13:54 -0600 Subject: [PATCH 19/19] chore: wip updating tests --- command.ts | 2 +- lib/configuration.ts | 6 - lib/lifecycles/bump.ts | 104 ++++--- lib/lifecycles/changelog.ts | 16 +- lib/lifecycles/commit.ts | 62 ++-- lib/opts/index.ts | 7 +- lib/opts/types.ts | 1 + package.json | 2 +- test/cli.spec.ts | 366 ++++++++++++++++++++++++ test/core.spec.ts | 373 +------------------------ test/format-commit-message.spec.ts | 24 ++ test/preset.spec.ts | 1 - test/test-utils.ts | 100 +++++++ tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md | 10 - tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md | 10 - 15 files changed, 602 insertions(+), 482 deletions(-) create mode 100644 test/cli.spec.ts create mode 100644 test/format-commit-message.spec.ts create mode 100644 test/test-utils.ts delete mode 100644 tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md delete mode 100644 tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md diff --git a/command.ts b/command.ts index 7b7043955..8c78aebdf 100755 --- a/command.ts +++ b/command.ts @@ -86,7 +86,7 @@ export const cmdParser = yargs(process.argv.slice(2)) // default: defaults.commitAll }, silent: { - alias: ['s', 'q', 'quiet'], + alias: ['q', 'quiet'], describe: "Don't print logs and errors", boolean: true, // default: defaults.silent diff --git a/lib/configuration.ts b/lib/configuration.ts index c8e1a7c2c..4b596c557 100644 --- a/lib/configuration.ts +++ b/lib/configuration.ts @@ -19,9 +19,6 @@ export async function getConfiguration(cwd?: string): Promise { } const config = await readConfigFile(configFile, currentDir); - console.log(currentDir, configFile, typeof config, config); - const contents = fs.readFileSync(configFile, 'utf-8'); - // console.log(contents); /** * @todo we could eventually have deeper validation of the configuration (using `ajv`) and * provide a more helpful error. @@ -41,16 +38,13 @@ function getConfigFile(cwd: string) { async function readConfigFile(configFile: string, cwd: string): Promise { const configPath = path.resolve(cwd, configFile); - console.log('configPath', configPath) const ext = path.extname(configFile); if (ext === '.js' || ext === '.cjs') { const jsConfiguration = require(configPath); if (typeof jsConfiguration === 'function') { - console.log(jsConfiguration()); return jsConfiguration(); } - console.log(jsConfiguration); return jsConfiguration; } return JSON.parse(readFileSync(configPath, 'utf-8')); diff --git a/lib/lifecycles/bump.ts b/lib/lifecycles/bump.ts index e579dfabb..99afc57de 100644 --- a/lib/lifecycles/bump.ts +++ b/lib/lifecycles/bump.ts @@ -1,13 +1,12 @@ import chalk from 'chalk' import checkpoint from '../checkpoint' -import semver, { ReleaseType } from 'semver' +import semver from 'semver' import conventionalRecommendedBump from 'conventional-recommended-bump' import figures from 'figures' import fs from 'fs' import DotGitignore from 'dotgitignore' import path from 'path' -import presetLoader from '../preset-loader' import runLifecycleScript from '../run-lifecycle-script' import writeFile from '../write-file' import { resolveUpdaterObjectFromArgument } from '../updaters' @@ -39,22 +38,25 @@ async function Bump(config: Config, version: string) { const stdout = await runLifecycleScript(config, Hook.prebump); if (stdout && stdout.trim().length) results.releaseAs = stdout.trim() as Release; - const expectedReleaseType = await bumpVersion(config.releaseAs, version, config); + const expectedReleaseType = await getExpectedReleaseType(config); + + if (!expectedReleaseType) { + throw new Error('Unable to determine expected release type') + } if (!config.firstRelease) { const releaseType = getReleaseType( config.prerelease, expectedReleaseType, version - ) - const releaseTypeAsVersion = - releaseType === 'pre' + expectedReleaseType - ? semver.valid(expectedReleaseType + '-' + config.prerelease + '.0') - : semver.valid(releaseType); + ); + // Removed this as semver.valid() as used will always return null + // const releaseTypeAsVersion = + // releaseType.startsWith('pre') + // ? semver.valid(expectedReleaseType + '-' + config.prerelease + '.0') + // : semver.valid(releaseType); - // TODO: semver.inc() possibly returns null. - results.newVersion = - releaseTypeAsVersion || semver.inc(version, releaseType, !!config.prerelease) || version; + results.newVersion = semver.inc(version, releaseType, !!config.prerelease) || version; updateConfigs(config, results.newVersion); } else { @@ -73,8 +75,12 @@ Bump.getUpdatedConfigs = function () { return configsToUpdate } -function getReleaseType (prerelease: string | boolean | undefined, expectedReleaseType: Release, currentVersion: string): ReleaseType { - if (typeof prerelease === 'string') { +function getReleaseType( + prerelease: string | boolean | undefined, + expectedReleaseType: Release, + currentVersion: string, +): semver.ReleaseType { + if (prerelease) { if (isInPrerelease(currentVersion)) { const currentActiveType = getCurrentActiveType(currentVersion); if ( @@ -101,7 +107,7 @@ function getReleaseType (prerelease: string | boolean | undefined, expectedRelea * @param expectType * @return {boolean} */ -function shouldContinuePrerelease (version: string, expectType: ReleaseType) { +function shouldContinuePrerelease (version: string, expectType: semver.ReleaseType) { return getCurrentActiveType(version) === expectType; } @@ -114,8 +120,13 @@ const TypeList: Release[] = ['patch', 'minor', 'major']; /** * extract the in-pre-release type in target version */ -function getCurrentActiveType(version: string) { - return TypeList.find((type) => semver[type](version)); +function getCurrentActiveType(version: string): Release | undefined { + const parsed = semver.parse(version); + if ((parsed?.patch ?? 0) > 0) return 'patch'; + if ((parsed?.minor ?? 0) > 0) return 'minor'; + if ((parsed?.patch ?? 0) > 0) return 'patch'; + + return undefined; } /** @@ -126,32 +137,37 @@ function getTypePriority(type: Release) { return TypeList.indexOf(type); } -async function bumpVersion(releaseAs: Release | undefined, currentVersion: string, config: Config) { - return await new Promise((resolve, reject) => { - if (releaseAs) { - resolve(releaseAs); +async function getExpectedReleaseType(config: Config): Promise { + return await new Promise((resolve, reject) => { + if (config.releaseAs) { + resolve(config.releaseAs); } else { - const presetOptions = presetLoader(config) - if (typeof presetOptions === 'object') { - if (semver.lt(currentVersion, '1.0.0')) presetOptions['preMajor'] = true - } - // TODO: conventionalRecommendedBump options preset type is string | undefined, not an object - // TODO: conventionalRecommendedBump options does not include a debug property + // const presetOptions = presetLoader(config) + // if (typeof presetOptions === 'object') { + // if (semver.lt(currentVersion, '1.0.0')) presetOptions['preMajor'] = true + // } + const bumpOptions: conventionalRecommendedBump.Options = { + preset: config.preset, + path: config.path, + tagPrefix: config.tagPrefix, + lernaPackage: config.lernaPackage, + }; + + // Is this needed? + // if (config.issuePrefixes) { + // bumpOptions.config = { + // parserOpts: { + // issuePrefixes: config.issuePrefixes, + // }, + // }; + // } conventionalRecommendedBump( - { - // debug: - // config.verbose && - // console.info.bind(console, 'conventional-recommended-bump'), - preset: config.preset, // presetOptions, - path: config.path, - tagPrefix: config.tagPrefix, - lernaPackage: config.lernaPackage - }, + bumpOptions, function (err, release) { if (err) { reject(err); } else { - resolve(release.releaseType! as Release); + resolve(release.releaseType); } } ) @@ -169,24 +185,28 @@ function updateConfigs(config: Config, newVersion: string) { const dotgit = DotGitignore() config.bumpFiles.forEach(function (bumpFile) { const updater = resolveUpdaterObjectFromArgument(bumpFile) - if (!updater) { - return - } - const configPath = path.resolve(process.cwd(), updater.filename) + + if (!updater) return; + if (dotgit.ignore(updater.filename)) return; + try { - if (dotgit.ignore(updater.filename)) return + const configPath = path.resolve(process.cwd(), updater.filename) const stat = fs.lstatSync(configPath) - if (!stat.isFile()) return + if (!stat.isFile()) return; + const contents = fs.readFileSync(configPath, 'utf8') const newContents = updater.updater.writeVersion(contents, newVersion) const realNewVersion = updater.updater.readVersion(newContents) + checkpoint( config, 'bumping version in ' + updater.filename + ' from %s to %s', [updater.updater.readVersion(contents), realNewVersion] ) + writeFile(config, configPath, newContents) + // flag any config files that we modify the version # for // as having been updated. configsToUpdate[updater.filename] = true diff --git a/lib/lifecycles/changelog.ts b/lib/lifecycles/changelog.ts index 4c89f1328..27a6087b7 100644 --- a/lib/lifecycles/changelog.ts +++ b/lib/lifecycles/changelog.ts @@ -2,7 +2,6 @@ import chalk from 'chalk'; import checkpoint from '../checkpoint'; import conventionalChangelog from 'conventional-changelog'; import fs from 'fs'; -import presetLoader from '../preset-loader'; import runLifecycleScript from '../run-lifecycle-script'; import writeFile from '../write-file'; import { Config, Hook } from '../opts/types'; @@ -34,21 +33,24 @@ function outputChangelog(config: Config, newVersion: string) { const context = { version: newVersion } const changelogStream = conventionalChangelog( { - // debug: config.verbose && console.info.bind(console, 'conventional-changelog'), - // TODO: Same issue here with debug and preset + debug: config.verbose ? console.info.bind(console, 'conventional-changelog') : undefined, preset: config.preset, // presetLoader(config), tagPrefix: config.tagPrefix, - releaseCount: config.releaseCount + + releaseCount: config.releaseCount, + config: { + parserOpts: { + issuePrefixes: config.issuePrefixes, + }, + }, }, context, { merges: null, path: config.path, showSignature: false, + }, - // TODO: Where did parserOpts and writerOpts come from? - // config.parserOpts, - // config.writerOpts ).on('error', function (err) { return reject(err) }); diff --git a/lib/lifecycles/commit.ts b/lib/lifecycles/commit.ts index 1becf94a9..112ceebe9 100644 --- a/lib/lifecycles/commit.ts +++ b/lib/lifecycles/commit.ts @@ -16,56 +16,64 @@ export default async function (config: Config, newVersion: string) { } async function execCommit (config: Config, newVersion: string) { - let msg = 'committing %s' - let paths: string[] = [] + const paths: string[] = [] const verify: string[] = !config.noVerify ? ['--no-verify'] : []; const sign: string[] = config.sign ? ['-S'] : [] - const toAdd: string[] = []; + const addFiles: string[] = []; - // only start with a pre-populated paths list when CHANGELOG processing is not skipped + // only start with a pre-populated paths list + // when CHANGELOG processing is not skipped if (!config.skip.changelog) { - paths = [config.infile] - toAdd.push(config.infile) + // paths.push(config.infile); + addFiles.push(config.infile); } // commit any of the config files that we've updated // the version # for. Object.keys(bump.getUpdatedConfigs()).forEach(function (p) { - paths.unshift(p) - toAdd.push(path.relative(process.cwd(), p)) + // paths.unshift(p) + // addFiles.push(path.relative(process.cwd(), p)) + addFiles.push(p) // account for multiple files in the output message - if (paths.length > 1) { - msg += ' and %s' - } + // if (paths.length > 1) { + // msg += ' and %s' + // } }) if (config.commitAll) { - msg += ' and %s' + // msg += ' and %s' paths.push('all staged files') } - checkpoint(config, msg, paths) + const msg = `committing ${addFiles.join(', ')}`; + checkpoint(config, msg, []); // nothing to do, exit without commit anything - if (!config.commitAll && config.skip.changelog && config.skip.bump && toAdd.length === 0) { - return + if (!config.commitAll && config.skip.changelog && config.skip.bump && addFiles.length === 0) { + return; } - await runExecFile(config, 'git', ['add'].concat(toAdd)) + const cwd = process.cwd(); + const addFilePaths = addFiles.map((f) => path.relative(cwd, f)); + + await runExecFile(config, 'git', ['add'].concat(addFilePaths)); + + const commitMsg = [ + '-m', + `${formatCommitMessage(config.releaseCommitMessageFormat, newVersion)}` + ]; + + const cmdArgs = ['commit'].concat( + verify, + sign, + config.commitAll ? [] : addFilePaths, + commitMsg, + ); + await runExecFile( config, 'git', - [ - 'commit' - ].concat( - verify, - sign, - config.commitAll ? [] : toAdd, - [ - '-m', - `${formatCommitMessage(config.releaseCommitMessageFormat, newVersion)}` - ] - ) + cmdArgs, ) } diff --git a/lib/opts/index.ts b/lib/opts/index.ts index 0a0f99da6..63fef183b 100644 --- a/lib/opts/index.ts +++ b/lib/opts/index.ts @@ -24,17 +24,11 @@ async function loadPackageJson(cwd?: string): Promise { export async function getMergedConfig(argv: any, cwd?: string): Promise { // const searchDir = cwd ?? process.cwd(); const pkgJson = await loadPackageJson(cwd); // await import(path.join(searchDir, "package.json")); - console.log(pkgJson['commit-and-tag-version']); const legacyConf = convertLegacy(pkgJson["standard-version"] ?? {}); const modernConf: FileConfig = pkgJson["commit-and-tag-version"] ?? {}; const cliConf = convertCliConfig(argv); const configFromFile = await getConfiguration(); - // console.log('legacyConf', legacyConf); - // console.log('modernConf', modernConf); - // console.log('cliConf', cliConf); - // console.log('configFromFile', configFromFile); - // Check for legacy config properties that will be overwritten Object.keys(legacyConf).forEach((key) => { if (isin(modernConf, key as any)) { @@ -61,6 +55,7 @@ export async function getMergedConfig(argv: any, cwd?: string): Promise ...(merged.bumpFiles || []), ...merged.packageFiles, ])); + } return { diff --git a/lib/opts/types.ts b/lib/opts/types.ts index 83b3613d7..bc07fa169 100644 --- a/lib/opts/types.ts +++ b/lib/opts/types.ts @@ -1,5 +1,6 @@ import { Config as SpecConfig } from "conventional-changelog-config-spec"; import type { PrettyPrint } from "../../type-helpers"; +import { ParserOptions, WriterOptions } from 'conventional-changelog-core'; export type Release = "minor" | "major" | "patch"; diff --git a/package.json b/package.json index e4e1db614..38d662f40 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "fix": "eslint . --fix", "posttest": "eslint .", "test": "nyc ts-mocha --type-check --timeout=30000 test/", - "test:unit": "mocha -r ts-node/register -j 1 test/**/config-files.spec.ts", + "test:unit": "mocha -r ts-node/register -j 1 test/**/cli.spec.ts", "coverage": "nyc report --reporter=lcov", "release": "dist/bin/cli.js", "build": "npx tsc && tsup" diff --git a/test/cli.spec.ts b/test/cli.spec.ts new file mode 100644 index 000000000..f7dfaf7f8 --- /dev/null +++ b/test/cli.spec.ts @@ -0,0 +1,366 @@ +/* global describe it afterEach */ +import fs from 'fs' +import { afterEachTestIdDir, beforeEachTestIdDir, exec, git, removeTmpDir, useTmpDir, writePackageJson } from './test-utils' + +const should = require('chai').should(); + +describe('cli', function () { + before(() => { + useTmpDir(); + }); + + after(() => { + removeTmpDir(); + }); + + beforeEach(function () { + beforeEachTestIdDir(this.currentTest!.id); + }); + afterEach(function (done) { + afterEachTestIdDir(this.currentTest!.id); + done(); + }); + + describe('CHANGELOG.md does not exist', function () { + it('populates changelog with commits since last tag by default', async function () { + git.init(); + git.commitMsg('fix: A superb fix'); + await exec(); + const content = fs.readFileSync('CHANGELOG.md', 'utf-8') + content.should.match(/A superb fix/) + }) + + it('includes all commits if --first-release is true', async function () { + git.init(); + git.commitType('initial'); + git.commitType('fix') + git.commitType('feat') + + await exec({ cliArgs: '--first-release' }); + const content = fs.readFileSync('CHANGELOG.md', 'utf-8') + content.should.match(/A superb bug fix/); + content.should.match(/A feature commit/); + }) + + it('skipping changelog will not create a changelog file', async function () { + writePackageJson('1.1.0'); + git.init(); + git.commitType('feat'); + git.tag('1.1.0'); + git.commitMsg('fix: A superb fix'); + await exec({ cliArgs: '--skip changelog' }); + try { + fs.readFileSync('CHANGELOG.md', 'utf-8') + throw new Error('File should not exist') + } catch (err: any) { + err.code.should.equal('ENOENT') + } + }) + }) + + // describe('CHANGELOG.md exists', function () { + // it('appends the new release above the last release, removing the old header (legacy format)', async function () { + // mock({ + // bump: 'patch', + // changelog: 'release 1.0.1\n', + // fs: { 'CHANGELOG.md': 'legacy header format\n' }, + // tags: ['v1.0.0'] + // }) + // await exec() + // const content = fs.readFileSync('CHANGELOG.md', 'utf-8') + // content.should.match(/1\.0\.1/) + // content.should.not.match(/legacy header format/) + // }) + + // it('appends the new release above the last release, removing the old header (new format)', async function () { + // const { header } = require('../defaults') + // const changelog1 = + // '### [1.0.1](/compare/v1.0.0...v1.0.1) (YYYY-MM-DD)\n\n\n### Bug Fixes\n\n* patch release ABCDEFXY\n' + // mock({ bump: 'patch', changelog: changelog1, tags: ['v1.0.0'] }) + // await exec() + // let content = fs.readFileSync('CHANGELOG.md', 'utf-8') + // content.should.equal(header + '\n' + changelog1) + + // const changelog2 = + // '### [1.0.2](/compare/v1.0.1...v1.0.2) (YYYY-MM-DD)\n\n\n### Bug Fixes\n\n* another patch release ABCDEFXY\n' + // unmock() + // mock({ + // bump: 'patch', + // changelog: changelog2, + // fs: { 'CHANGELOG.md': content }, + // tags: ['v1.0.0', 'v1.0.1'] + // }) + // await exec() + // content = fs.readFileSync('CHANGELOG.md', 'utf-8') + // content.should.equal(header + '\n' + changelog2 + changelog1) + // }) + + // it('[DEPRECATED] (--changelogHeader) allows for a custom changelog header', async function () { + // const header = '# Pork Chop Log' + // mock({ + // bump: 'minor', + // changelog: header + '\n', + // fs: { 'CHANGELOG.md': '' } + // }) + // await exec(`--changelogHeader="${header}"`) + // const content = fs.readFileSync('CHANGELOG.md', 'utf-8') + // content.should.match(new RegExp(header)) + // }) + + // it('[DEPRECATED] (--changelogHeader) exits with error if changelog header matches last version search regex', async function () { + // mock({ bump: 'minor', fs: { 'CHANGELOG.md': '' } }) + // try { + // await exec('--changelogHeader="## 3.0.2"') + // throw new Error('That should not have worked') + // } catch (error) { + // error.message.should.match(/custom changelog header must not match/) + // } + // }) + // }) + + // describe('lifecycle scripts', () => { + // describe('prerelease hook', function () { + // it('should run the prerelease hook when provided', async function () { + // const flush = mock({ + // bump: 'minor', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + + // await exec({ + // scripts: { + // prerelease: "node -e \"console.error('prerelease' + ' ran')\"" + // } + // }) + // const { stderr } = flush() + // stderr.join('\n').should.match(/prerelease ran/) + // }) + + // it('should abort if the hook returns a non-zero exit code', async function () { + // mock({ + // bump: 'minor', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + + // try { + // await exec({ + // scripts: { + // prerelease: "node -e \"throw new Error('prerelease' + ' fail')\"" + // } + // }) + // /* istanbul ignore next */ + // throw new Error('Unexpected success') + // } catch (error) { + // error.message.should.match(/prerelease fail/) + // } + // }) + // }) + + // describe('prebump hook', function () { + // it('should allow prebump hook to return an alternate version #', async function () { + // const flush = mock({ + // bump: 'minor', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + + // await exec({ + // scripts: { + // prebump: "node -e \"console.log(Array.of(9, 9, 9).join('.'))\"" + // } + // }) + // const { stdout } = flush() + // stdout.join('').should.match(/9\.9\.9/) + // }) + // }) + + // describe('postbump hook', function () { + // it('should run the postbump hook when provided', async function () { + // const flush = mock({ + // bump: 'minor', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + + // await exec({ + // scripts: { + // postbump: "node -e \"console.error('postbump' + ' ran')\"" + // } + // }) + // const { stderr } = flush() + // stderr.join('\n').should.match(/postbump ran/) + // }) + + // it('should run the postbump and exit with error when postbump fails', async function () { + // mock({ + // bump: 'minor', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + + // try { + // await exec({ + // scripts: { + // postbump: "node -e \"throw new Error('postbump' + ' fail')\"" + // } + // }) + // await exec('--patch') + // /* istanbul ignore next */ + // throw new Error('Unexpected success') + // } catch (error) { + // error.message.should.match(/postbump fail/) + // } + // }) + // }) + // }) + + // describe('manual-release', function () { + // describe('release-types', function () { + // const regularTypes = ['major', 'minor', 'patch'] + // const nextVersion = { major: '2.0.0', minor: '1.1.0', patch: '1.0.1' } + + // regularTypes.forEach(function (type) { + // it('creates a ' + type + ' release', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + // await exec('--release-as ' + type) + // getPackageVersion().should.equal(nextVersion[type]) + // }) + // }) + + // // this is for pre-releases + // regularTypes.forEach(function (type) { + // it('creates a pre' + type + ' release', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + // await exec('--release-as ' + type + ' --prerelease ' + type) + // getPackageVersion().should.equal(`${nextVersion[type]}-${type}.0`) + // }) + // }) + // }) + + // describe('release-as-exact', function () { + // it('releases as v100.0.0', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + // await exec('--release-as v100.0.0') + // getPackageVersion().should.equal('100.0.0') + // }) + + // it('releases as 200.0.0-amazing', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + // await exec('--release-as 200.0.0-amazing') + // getPackageVersion().should.equal('200.0.0-amazing') + // }) + + // it('releases as 100.0.0 with prerelease amazing', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' }, + // pkg: { + // version: '1.0.0' + // } + // }) + // await exec('--release-as 100.0.0 --prerelease amazing') + // should.equal(getPackageVersion(), '100.0.0-amazing.0') + // }) + + // it('release 100.0.0 with prerelease amazing bumps build', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' }, + // pkg: { + // version: '100.0.0-amazing.0' + // } + // }) + // await exec('--release-as 100.0.0 --prerelease amazing') + // should.equal(getPackageVersion(), '100.0.0-amazing.1') + // }) + + // it('release 100.0.0-amazing.0 with prerelease amazing bumps build', async function () { + // mock({ + // bump: 'patch', + // fs: { 'CHANGELOG.md': 'legacy header format\n' }, + // pkg: { + // version: '100.0.0-amazing.0' + // } + // }) + // await exec('--release-as 100.0.0-amazing.0 --prerelease amazing') + // should.equal(getPackageVersion(), '100.0.0-amazing.1') + // }) + // }) + + // it('creates a prerelease with a new minor version after two prerelease patches', async function () { + // let releaseType = 'patch' + // const bump = (_, cb) => cb(null, { releaseType }) + // mock({ + // bump, + // fs: { 'CHANGELOG.md': 'legacy header format\n' } + // }) + + // await exec('--release-as patch --prerelease dev') + // getPackageVersion().should.equal('1.0.1-dev.0') + + // await exec('--prerelease dev') + // getPackageVersion().should.equal('1.0.1-dev.1') + + // releaseType = 'minor' + // await exec('--release-as minor --prerelease dev') + // getPackageVersion().should.equal('1.1.0-dev.0') + + // await exec('--release-as minor --prerelease dev') + // getPackageVersion().should.equal('1.1.0-dev.1') + + // await exec('--prerelease dev') + // getPackageVersion().should.equal('1.1.0-dev.2') + // }) + // }) + + // it('appends line feed at end of package.json', async function () { + // mock({ bump: 'patch' }) + // await exec() + // const pkgJson = fs.readFileSync('package.json', 'utf-8') + // pkgJson.should.equal('{\n "version": "1.0.1"\n}\n') + // }) + + // it('preserves indentation of tabs in package.json', async function () { + // mock({ + // bump: 'patch', + // fs: { 'package.json': '{\n\t"version": "1.0.0"\n}\n' } + // }) + // await exec() + // const pkgJson = fs.readFileSync('package.json', 'utf-8') + // pkgJson.should.equal('{\n\t"version": "1.0.1"\n}\n') + // }) + + // it('preserves indentation of spaces in package.json', async function () { + // mock({ + // bump: 'patch', + // fs: { 'package.json': '{\n "version": "1.0.0"\n}\n' } + // }) + // await exec() + // const pkgJson = fs.readFileSync('package.json', 'utf-8') + // pkgJson.should.equal('{\n "version": "1.0.1"\n}\n') + // }) + + // it('preserves carriage return + line feed in package.json', async function () { + // mock({ + // bump: 'patch', + // fs: { 'package.json': '{\r\n "version": "1.0.0"\r\n}\r\n' } + // }) + // await exec() + // const pkgJson = fs.readFileSync('package.json', 'utf-8') + // pkgJson.should.equal('{\r\n "version": "1.0.1"\r\n}\r\n') + // }) + + // it('does not print output when the --silent flag is passed', async function () { + // const flush = mock() + // await exec('--silent') + // flush().should.eql({ stdout: [], stderr: [] }) + // }) +}) diff --git a/test/core.spec.ts b/test/core.spec.ts index 096e1f2a8..7be002858 100644 --- a/test/core.spec.ts +++ b/test/core.spec.ts @@ -7,18 +7,13 @@ import mockFS from 'mock-fs' import mockery from 'mockery' import stdMocks from 'std-mocks' import stripAnsi from 'strip-ansi' - -const cli = require('../command') -const formatCommitMessage = require('../lib/format-commit-message') +import { cmdParser } from '../command'; const should = require('chai').should() -// set by mock() -let standardVersion - function exec (opt = '', git) { if (typeof opt === 'string') { - opt = cli.parse(`commit-and-tag-version ${opt}`) + opt = cmdParser.parseSync(`commit-and-tag-version ${opt}`) } if (!git) opt.skip = Object.assign({}, opt.skip, { commit: true, tag: true }) return standardVersion(opt) @@ -106,370 +101,6 @@ function unmock () { } } -describe('format-commit-message', function () { - it('works for no {{currentTag}}', function () { - formatCommitMessage('chore(release): 1.0.0', '1.0.0').should.equal( - 'chore(release): 1.0.0' - ) - }) - it('works for one {{currentTag}}', function () { - formatCommitMessage('chore(release): {{currentTag}}', '1.0.0').should.equal( - 'chore(release): 1.0.0' - ) - }) - it('works for two {{currentTag}}', function () { - formatCommitMessage( - 'chore(release): {{currentTag}} \n\n* CHANGELOG: https://github.com/absolute-version/commit-and-tag-version/blob/v{{currentTag}}/CHANGELOG.md', - '1.0.0' - ).should.equal( - 'chore(release): 1.0.0 \n\n* CHANGELOG: https://github.com/absolute-version/commit-and-tag-version/blob/v1.0.0/CHANGELOG.md' - ) - }) -}) - -describe('cli', function () { - afterEach(unmock) - - describe('CHANGELOG.md does not exist', function () { - it('populates changelog with commits since last tag by default', async function () { - mock({ bump: 'patch', changelog: 'patch release\n', tags: ['v1.0.0'] }) - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.match(/patch release/) - }) - - it('includes all commits if --first-release is true', async function () { - mock({ - bump: 'minor', - changelog: 'first commit\npatch release\n', - pkg: { version: '1.0.1' } - }) - await exec('--first-release') - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.match(/patch release/) - content.should.match(/first commit/) - }) - - it('skipping changelog will not create a changelog file', async function () { - mock({ bump: 'minor', changelog: 'foo\n' }) - await exec('--skip.changelog true') - getPackageVersion().should.equal('1.1.0') - try { - fs.readFileSync('CHANGELOG.md', 'utf-8') - throw new Error('File should not exist') - } catch (err) { - err.code.should.equal('ENOENT') - } - }) - }) - - describe('CHANGELOG.md exists', function () { - it('appends the new release above the last release, removing the old header (legacy format)', async function () { - mock({ - bump: 'patch', - changelog: 'release 1.0.1\n', - fs: { 'CHANGELOG.md': 'legacy header format\n' }, - tags: ['v1.0.0'] - }) - await exec() - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.match(/1\.0\.1/) - content.should.not.match(/legacy header format/) - }) - - it('appends the new release above the last release, removing the old header (new format)', async function () { - const { header } = require('../defaults') - const changelog1 = - '### [1.0.1](/compare/v1.0.0...v1.0.1) (YYYY-MM-DD)\n\n\n### Bug Fixes\n\n* patch release ABCDEFXY\n' - mock({ bump: 'patch', changelog: changelog1, tags: ['v1.0.0'] }) - await exec() - let content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.equal(header + '\n' + changelog1) - - const changelog2 = - '### [1.0.2](/compare/v1.0.1...v1.0.2) (YYYY-MM-DD)\n\n\n### Bug Fixes\n\n* another patch release ABCDEFXY\n' - unmock() - mock({ - bump: 'patch', - changelog: changelog2, - fs: { 'CHANGELOG.md': content }, - tags: ['v1.0.0', 'v1.0.1'] - }) - await exec() - content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.equal(header + '\n' + changelog2 + changelog1) - }) - - it('[DEPRECATED] (--changelogHeader) allows for a custom changelog header', async function () { - const header = '# Pork Chop Log' - mock({ - bump: 'minor', - changelog: header + '\n', - fs: { 'CHANGELOG.md': '' } - }) - await exec(`--changelogHeader="${header}"`) - const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - content.should.match(new RegExp(header)) - }) - - it('[DEPRECATED] (--changelogHeader) exits with error if changelog header matches last version search regex', async function () { - mock({ bump: 'minor', fs: { 'CHANGELOG.md': '' } }) - try { - await exec('--changelogHeader="## 3.0.2"') - throw new Error('That should not have worked') - } catch (error) { - error.message.should.match(/custom changelog header must not match/) - } - }) - }) - - describe('lifecycle scripts', () => { - describe('prerelease hook', function () { - it('should run the prerelease hook when provided', async function () { - const flush = mock({ - bump: 'minor', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - - await exec({ - scripts: { - prerelease: "node -e \"console.error('prerelease' + ' ran')\"" - } - }) - const { stderr } = flush() - stderr.join('\n').should.match(/prerelease ran/) - }) - - it('should abort if the hook returns a non-zero exit code', async function () { - mock({ - bump: 'minor', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - - try { - await exec({ - scripts: { - prerelease: "node -e \"throw new Error('prerelease' + ' fail')\"" - } - }) - /* istanbul ignore next */ - throw new Error('Unexpected success') - } catch (error) { - error.message.should.match(/prerelease fail/) - } - }) - }) - - describe('prebump hook', function () { - it('should allow prebump hook to return an alternate version #', async function () { - const flush = mock({ - bump: 'minor', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - - await exec({ - scripts: { - prebump: "node -e \"console.log(Array.of(9, 9, 9).join('.'))\"" - } - }) - const { stdout } = flush() - stdout.join('').should.match(/9\.9\.9/) - }) - }) - - describe('postbump hook', function () { - it('should run the postbump hook when provided', async function () { - const flush = mock({ - bump: 'minor', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - - await exec({ - scripts: { - postbump: "node -e \"console.error('postbump' + ' ran')\"" - } - }) - const { stderr } = flush() - stderr.join('\n').should.match(/postbump ran/) - }) - - it('should run the postbump and exit with error when postbump fails', async function () { - mock({ - bump: 'minor', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - - try { - await exec({ - scripts: { - postbump: "node -e \"throw new Error('postbump' + ' fail')\"" - } - }) - await exec('--patch') - /* istanbul ignore next */ - throw new Error('Unexpected success') - } catch (error) { - error.message.should.match(/postbump fail/) - } - }) - }) - }) - - describe('manual-release', function () { - describe('release-types', function () { - const regularTypes = ['major', 'minor', 'patch'] - const nextVersion = { major: '2.0.0', minor: '1.1.0', patch: '1.0.1' } - - regularTypes.forEach(function (type) { - it('creates a ' + type + ' release', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - await exec('--release-as ' + type) - getPackageVersion().should.equal(nextVersion[type]) - }) - }) - - // this is for pre-releases - regularTypes.forEach(function (type) { - it('creates a pre' + type + ' release', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - await exec('--release-as ' + type + ' --prerelease ' + type) - getPackageVersion().should.equal(`${nextVersion[type]}-${type}.0`) - }) - }) - }) - - describe('release-as-exact', function () { - it('releases as v100.0.0', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - await exec('--release-as v100.0.0') - getPackageVersion().should.equal('100.0.0') - }) - - it('releases as 200.0.0-amazing', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - await exec('--release-as 200.0.0-amazing') - getPackageVersion().should.equal('200.0.0-amazing') - }) - - it('releases as 100.0.0 with prerelease amazing', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' }, - pkg: { - version: '1.0.0' - } - }) - await exec('--release-as 100.0.0 --prerelease amazing') - should.equal(getPackageVersion(), '100.0.0-amazing.0') - }) - - it('release 100.0.0 with prerelease amazing bumps build', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' }, - pkg: { - version: '100.0.0-amazing.0' - } - }) - await exec('--release-as 100.0.0 --prerelease amazing') - should.equal(getPackageVersion(), '100.0.0-amazing.1') - }) - - it('release 100.0.0-amazing.0 with prerelease amazing bumps build', async function () { - mock({ - bump: 'patch', - fs: { 'CHANGELOG.md': 'legacy header format\n' }, - pkg: { - version: '100.0.0-amazing.0' - } - }) - await exec('--release-as 100.0.0-amazing.0 --prerelease amazing') - should.equal(getPackageVersion(), '100.0.0-amazing.1') - }) - }) - - it('creates a prerelease with a new minor version after two prerelease patches', async function () { - let releaseType = 'patch' - const bump = (_, cb) => cb(null, { releaseType }) - mock({ - bump, - fs: { 'CHANGELOG.md': 'legacy header format\n' } - }) - - await exec('--release-as patch --prerelease dev') - getPackageVersion().should.equal('1.0.1-dev.0') - - await exec('--prerelease dev') - getPackageVersion().should.equal('1.0.1-dev.1') - - releaseType = 'minor' - await exec('--release-as minor --prerelease dev') - getPackageVersion().should.equal('1.1.0-dev.0') - - await exec('--release-as minor --prerelease dev') - getPackageVersion().should.equal('1.1.0-dev.1') - - await exec('--prerelease dev') - getPackageVersion().should.equal('1.1.0-dev.2') - }) - }) - - it('appends line feed at end of package.json', async function () { - mock({ bump: 'patch' }) - await exec() - const pkgJson = fs.readFileSync('package.json', 'utf-8') - pkgJson.should.equal('{\n "version": "1.0.1"\n}\n') - }) - - it('preserves indentation of tabs in package.json', async function () { - mock({ - bump: 'patch', - fs: { 'package.json': '{\n\t"version": "1.0.0"\n}\n' } - }) - await exec() - const pkgJson = fs.readFileSync('package.json', 'utf-8') - pkgJson.should.equal('{\n\t"version": "1.0.1"\n}\n') - }) - - it('preserves indentation of spaces in package.json', async function () { - mock({ - bump: 'patch', - fs: { 'package.json': '{\n "version": "1.0.0"\n}\n' } - }) - await exec() - const pkgJson = fs.readFileSync('package.json', 'utf-8') - pkgJson.should.equal('{\n "version": "1.0.1"\n}\n') - }) - - it('preserves carriage return + line feed in package.json', async function () { - mock({ - bump: 'patch', - fs: { 'package.json': '{\r\n "version": "1.0.0"\r\n}\r\n' } - }) - await exec() - const pkgJson = fs.readFileSync('package.json', 'utf-8') - pkgJson.should.equal('{\r\n "version": "1.0.1"\r\n}\r\n') - }) - - it('does not print output when the --silent flag is passed', async function () { - const flush = mock() - await exec('--silent') - flush().should.eql({ stdout: [], stderr: [] }) - }) -}) - describe('commit-and-tag-version', function () { afterEach(unmock) diff --git a/test/format-commit-message.spec.ts b/test/format-commit-message.spec.ts new file mode 100644 index 000000000..13cefc283 --- /dev/null +++ b/test/format-commit-message.spec.ts @@ -0,0 +1,24 @@ +import formatCommitMessage from '../lib/format-commit-message'; + +const should = require('chai').should() + +describe('format-commit-message', function () { + it('works for no {{currentTag}}', function () { + formatCommitMessage('chore(release): 1.0.0', '1.0.0').should.equal( + 'chore(release): 1.0.0' + ) + }) + it('works for one {{currentTag}}', function () { + formatCommitMessage('chore(release): {{currentTag}}', '1.0.0').should.equal( + 'chore(release): 1.0.0' + ) + }) + it('works for two {{currentTag}}', function () { + formatCommitMessage( + 'chore(release): {{currentTag}} \n\n* CHANGELOG: https://github.com/absolute-version/commit-and-tag-version/blob/v{{currentTag}}/CHANGELOG.md', + '1.0.0' + ).should.equal( + 'chore(release): 1.0.0 \n\n* CHANGELOG: https://github.com/absolute-version/commit-and-tag-version/blob/v1.0.0/CHANGELOG.md' + ) + }) +}); diff --git a/test/preset.spec.ts b/test/preset.spec.ts index facd34557..e6a9060c0 100644 --- a/test/preset.spec.ts +++ b/test/preset.spec.ts @@ -39,7 +39,6 @@ describe('presets', () => { it('Conventional Commits (default)', async function () { await exec() const content = fs.readFileSync('CHANGELOG.md', 'utf-8') - console.log(content); content.should.contain('### Features') content.should.not.contain('### Performance Improvements') content.should.not.contain('### Custom') diff --git a/test/test-utils.ts b/test/test-utils.ts new file mode 100644 index 000000000..1100b57ca --- /dev/null +++ b/test/test-utils.ts @@ -0,0 +1,100 @@ +import shell from 'shelljs' +import fs from 'fs' +import { cmdParser } from '../command' +import { FileConfig, Task } from '../lib/opts/types' +import cli from '../index'; + +export function writePackageJson(version: string, option?: any) { + const pkg = Object.assign({}, option || {}, { version }) + fs.writeFileSync('package.json', JSON.stringify(pkg), 'utf-8') +} + +export function getPackageVersion () { + return JSON.parse(fs.readFileSync('package.json', 'utf-8')).version +} + +export function useTmpDir() { + shell.rm('-rf', 'tmp') + shell.config.silent = true + shell.mkdir('tmp') + shell.cd('tmp') +} + +export function removeTmpDir() { + shell.cd('../') + shell.rm('-rf', 'tmp') +} + +export function beforeEachTestIdDir(testId: string) { + shell.mkdir(testId); + shell.cd(testId); +} + +export function afterEachTestIdDir(testId: string) { + shell.cd('../'); + shell.rm('-rf', testId); +} + +export function ensureArray(target: T | T[]): T[] { + return Array.isArray(target) ? target : [target]; +} + +type ArgV = ReturnType; + +export function getArgv({ cliArgs, overrides }: ExecParams = {}): ArgV { + const options = ensureArray(cliArgs || []).join(' '); + const argv = cmdParser.parseSync(`commit-and-tag-version ${options} --silent`) + return { + ...argv, + ...(overrides || {}), + }; +} + +interface ExecParams { + cliArgs?: string | string[] | undefined; + overrides?: Partial | undefined; +} + +export function exec({ cliArgs, overrides }: ExecParams = {}) { + const argv = getArgv({ cliArgs, overrides }); + return cli(argv); +} + +type CommitType = + | 'initial' + | 'feat' + | 'perf' + | 'chore' + | 'ci' + | 'custom' + | 'fix'; + +const messages: Record = { + initial: 'initial commit', + feat: 'feat: A feature commit', + perf: 'perf: A performance commit', + chore: 'chore: A chore commit', + ci: 'ci: A ci commit', + custom: 'custom: A custom commit', + fix: 'fix: A superb bug fix', +} + +export const git = { + init(...types: CommitType[]) { + shell.exec('git init') + shell.exec('git config commit.gpgSign false') + shell.exec('git config core.autocrlf false') + git.commitType(...types); + }, + commitType(...types: CommitType[]) { + types.forEach((t) => { + git.commitMsg(messages[t]); + }); + }, + commitMsg(msg: string) { + shell.exec(`git commit --allow-empty -m "${msg}"`); + }, + tag(version: string) { + shell.exec(`git tag v${version}`); + }, +}; diff --git a/tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md b/tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md deleted file mode 100644 index b778d431c..000000000 --- a/tmp/PRtnG4LPuPmaiUvDAbJ5u/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. - -## [11.2.2](https://github.com/absolute-version/commit-and-tag-version/compare/v11.2.1...v11.2.2) (2023-04-13) - - -### Bug Fixes - -* correct imports in index.ts ([f2aa8bd](https://github.com/absolute-version/commit-and-tag-version/commit/f2aa8bda05533a78ca0041ef0622fe1bc4d2b0d5)) diff --git a/tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md b/tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md deleted file mode 100644 index b778d431c..000000000 --- a/tmp/mZjFsgUfcRWkFk4kW68o4/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. - -## [11.2.2](https://github.com/absolute-version/commit-and-tag-version/compare/v11.2.1...v11.2.2) (2023-04-13) - - -### Bug Fixes - -* correct imports in index.ts ([f2aa8bd](https://github.com/absolute-version/commit-and-tag-version/commit/f2aa8bda05533a78ca0041ef0622fe1bc4d2b0d5))