diff --git a/.eslintrc.jest.yml b/.eslintrc.jest.yml index 4340ddd..0255384 100644 --- a/.eslintrc.jest.yml +++ b/.eslintrc.jest.yml @@ -8,3 +8,4 @@ rules: react/display-name: off # Disable for convenience react/prop-types: off + '@typescript-eslint/no-require-imports': off diff --git a/.eslintrc.production.yml b/.eslintrc.production.yml index ba58e9f..b63635d 100644 --- a/.eslintrc.production.yml +++ b/.eslintrc.production.yml @@ -30,7 +30,11 @@ rules: import/no-anonymous-default-export: error import/no-duplicates: error import/no-namespace: error - import/no-unassigned-import: error + import/no-unassigned-import: + - error + - allow: + - '**/*.css' + - dotenv/config settings: import/extensions: - .cjs diff --git a/.eslintrc.react.yml b/.eslintrc.react.yml index 923e17c..914d633 100644 --- a/.eslintrc.react.yml +++ b/.eslintrc.react.yml @@ -2,6 +2,3 @@ extends: - plugin:react/recommended plugins: - react -settings: - react: - version: 18.2.0 diff --git a/.eslintrc.typescript.yml b/.eslintrc.typescript.yml index 3ea0b00..5de2aeb 100644 --- a/.eslintrc.typescript.yml +++ b/.eslintrc.typescript.yml @@ -4,6 +4,9 @@ parser: '@typescript-eslint/parser' plugins: - '@typescript-eslint' rules: + # Shortening if-statement into &&, ||, or ternary operators. + '@typescript-eslint/no-unused-expressions': off + '@typescript-eslint/no-unused-vars': - error - argsIgnorePattern: ^_ diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 53e0965..d36f52f 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -1,7 +1,17 @@ name: Prepare release on: - workflow_dispatch: {} + workflow_dispatch: + inputs: + version-to-bump: + default: patch + description: Version to bump + options: + - major + - minor + - patch + required: true + type: choice jobs: call-workflow: @@ -10,3 +20,5 @@ jobs: id-token: write secrets: inherit uses: compulim/workflows/.github/workflows/prepare-release.yml@main + with: + version-to-bump: ${{ inputs.version-to-bump }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 359d8b5..dc82f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed +- 💢 Moved to ESM only, in PR [#27](https://github.com/compulim/version-from-git/pull/27) - Ported to TypeScript, in PR [#24](https://github.com/compulim/version-from-git/pull/24) - Bumped dependencies, in PR [#23](https://github.com/compulim/version-from-git/pull/23) - Production dependencies diff --git a/package.json b/package.json index a1cde0b..092c117 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,11 @@ ], "scripts": { "build": "npm run build --if-present --workspaces", - "bump": "npm run bump:prod && npm run bump:dev && npm run bump:auditfix && npm run bump:packages && npm run bump:eslintrc", - "bump:auditfix": "npm audit fix || exit 0", - "bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.localPeerDependencies // {}) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@latest\") | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", + "bump": "npm run bump:prod && npm run bump:dev && npm run bump:packages && npm run bump:eslintrc", + "bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localPeerDependencies // {}) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", "bump:eslintrc": "if [ -f node_modules/react/package.json ]; then docker run -e VERSION=$(cat node_modules/react/package.json | jq -r '.version') -i --rm mikefarah/yq '.settings.react.version = strenv(VERSION)' < ./.eslintrc.react.yml | tee /tmp/output.tmp && mv /tmp/output.tmp ./.eslintrc.react.yml; fi", "bump:packages": "npm run bump --if-present --workspaces", - "bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.localPeerDependencies // {}) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@latest\") | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", + "bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localPeerDependencies // {}) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", "postscaffold": "npm run postscaffold:eslint:react && npm run postscaffold --if-present --workspaces", "postscaffold:eslint:react": "npm run bump:eslintrc", "precommit": "npm run precommit --if-present --workspaces", diff --git a/packages/integration-test/.eslintrc.custom.yml b/packages/integration-test/.eslintrc.custom.yml new file mode 100644 index 0000000..5c9fc4c --- /dev/null +++ b/packages/integration-test/.eslintrc.custom.yml @@ -0,0 +1,2 @@ +env: + browser: true diff --git a/packages/integration-test/.eslintrc.yml b/packages/integration-test/.eslintrc.yml new file mode 100644 index 0000000..54b2959 --- /dev/null +++ b/packages/integration-test/.eslintrc.yml @@ -0,0 +1,2 @@ +extends: + - ./.eslintrc.custom.yml diff --git a/packages/integration-test/.gitignore b/packages/integration-test/.gitignore new file mode 100644 index 0000000..936e5c5 --- /dev/null +++ b/packages/integration-test/.gitignore @@ -0,0 +1,2 @@ +/node_modules/ +/package-lock.json diff --git a/packages/integration-test/jest.config.json b/packages/integration-test/jest.config.json new file mode 100644 index 0000000..9c305d4 --- /dev/null +++ b/packages/integration-test/jest.config.json @@ -0,0 +1,38 @@ +{ + "testMatch": ["**/__tests__/**/*.?([cm])[jt]s?(x)", "**/?(*.)+(spec|test).?([cm])[jt]s?(x)"], + "transform": { + "\\.cjsx?$": [ + "babel-jest", + { + "presets": [ + [ + "@babel/preset-react", + { + "runtime": "classic" + } + ] + ] + } + ], + "\\.mjsx?$": [ + "babel-jest", + { + "presets": [ + [ + "@babel/preset-react", + { + "runtime": "classic" + } + ], + [ + "@babel/preset-env", + { + "modules": "commonjs", + "targets": "defaults" + } + ] + ] + } + ] + } +} diff --git a/packages/integration-test/tsconfig.custom.json b/packages/integration-test/tsconfig.custom.json new file mode 100644 index 0000000..7a3b017 --- /dev/null +++ b/packages/integration-test/tsconfig.custom.json @@ -0,0 +1,3 @@ +{ + "extends": "@tsconfig/strictest/tsconfig.json" +} diff --git a/packages/integration-test/tsconfig.json b/packages/integration-test/tsconfig.json new file mode 100644 index 0000000..d910d6b --- /dev/null +++ b/packages/integration-test/tsconfig.json @@ -0,0 +1,7 @@ +// This configuration file is for VSCode only. +{ + "compilerOptions": { + "jsx": "react" + }, + "extends": "./tsconfig.custom.json" +} diff --git a/packages/pages/.eslintrc.custom.yml b/packages/pages/.eslintrc.custom.yml new file mode 100644 index 0000000..e69de29 diff --git a/packages/pages/.eslintrc.yml b/packages/pages/.eslintrc.yml new file mode 100644 index 0000000..a8f533d --- /dev/null +++ b/packages/pages/.eslintrc.yml @@ -0,0 +1,4 @@ +env: + browser: true +extends: + - ./.eslintrc.custom.yml diff --git a/packages/pages/.gitignore b/packages/pages/.gitignore new file mode 100644 index 0000000..eab9b2f --- /dev/null +++ b/packages/pages/.gitignore @@ -0,0 +1,2 @@ +/node_modules/ +/public/static/ diff --git a/packages/pages/src/tsconfig.custom.json b/packages/pages/src/tsconfig.custom.json new file mode 100644 index 0000000..7a3b017 --- /dev/null +++ b/packages/pages/src/tsconfig.custom.json @@ -0,0 +1,3 @@ +{ + "extends": "@tsconfig/strictest/tsconfig.json" +} diff --git a/packages/pages/src/tsconfig.json b/packages/pages/src/tsconfig.json new file mode 100644 index 0000000..017f0c9 --- /dev/null +++ b/packages/pages/src/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "allowImportingTsExtensions": true, + "esModuleInterop": true, + "jsx": "react", + "lib": [ + "DOM", + "ESNext", + "WebWorker" + ], + "moduleResolution": "Bundler", + "noEmit": true, + "strict": true, + "target": "ESNext", + "types": [] + }, + "extends": "./tsconfig.custom.json" +} diff --git a/packages/version-from-git/.eslintrc.custom.yml b/packages/version-from-git/.eslintrc.custom.yml new file mode 100644 index 0000000..e69de29 diff --git a/packages/version-from-git/.eslintrc.yml b/packages/version-from-git/.eslintrc.yml new file mode 100644 index 0000000..54b2959 --- /dev/null +++ b/packages/version-from-git/.eslintrc.yml @@ -0,0 +1,2 @@ +extends: + - ./.eslintrc.custom.yml diff --git a/packages/version-from-git/__tests__/__setup__/typingTestTransformer.js b/packages/version-from-git/__tests__/__setup__/typingTestTransformer.js new file mode 100644 index 0000000..b8d3ed5 --- /dev/null +++ b/packages/version-from-git/__tests__/__setup__/typingTestTransformer.js @@ -0,0 +1,89 @@ +// Notes: to test changes in this file, run "jest" with "--no-cache" argument. + +const run = ({ filename }) => { + const escapeStringRegexp = require('escape-string-regexp'); + const fs = require('fs/promises'); + const { extname } = require('path'); + const typeScript = require('typescript'); + + const TS_EXPECT_ERROR = /(\/\/\s+)(@ts-expect-error)[\s+(.*)]/gu; + const TSCONFIG = { + allowImportingTsExtensions: true, + allowSyntheticDefaultImports: true, + jsx: typeScript.JsxEmit.React, + noEmit: true, + skipLibCheck: true, + strict: true + }; + + async function compile(filename) { + const program = typeScript.createProgram([filename], TSCONFIG); + + const emitResult = program.emit(); + const allDiagnostics = typeScript.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + allDiagnostics.forEach(({ file, messageText, start }) => { + if (file && start) { + const { line, character } = file.getLineAndCharacterOfPosition(start); + const message = typeScript.flattenDiagnosticMessageText(messageText, '\n'); + + throw new Error(`Failed to compile ${file.fileName} (${line + 1},${character + 1}): ${message}`); + } else { + throw new Error(typeScript.flattenDiagnosticMessageText(messageText, '\n')); + } + }); + } + + async function checkExpectError(filename) { + const sourceText = await fs.readFile(filename, 'utf-8'); + const sourceTextWithoutExpectError = sourceText.replace(TS_EXPECT_ERROR, '$1'); + + const extension = extname(filename); + const tempFilename = filename.substring(0, filename.length - extension.length) + `.tmp${extension}`; + + await fs.writeFile(tempFilename, sourceTextWithoutExpectError); + + try { + const program = typeScript.createProgram([tempFilename], TSCONFIG); + + const emitResult = program.emit(); + const allDiagnostics = typeScript.getPreEmitDiagnostics(program).concat(emitResult.diagnostics); + + allDiagnostics.forEach(({ file, messageText, start }) => { + if (file && start) { + const { line } = file.getLineAndCharacterOfPosition(start); + const message = typeScript.flattenDiagnosticMessageText(messageText, '\n'); + + const expectedErrorLine = file.getFullText().split('\n')[line - 1]; + const expectedError = expectedErrorLine?.replace(/\s*\/\/\s+/u, '').trim(); + let expectedErrors = [expectedError]; + + try { + const parsed = JSON.parse(expectedError); + + if (Array.isArray(expectedErrors) && expectedErrors.every(value => typeof value === 'string')) { + expectedErrors = parsed; + } + } catch {} + + expect(message).toEqual(expect.stringMatching(new RegExp(expectedErrors.map(escapeStringRegexp).join('|')))); + } else { + throw new Error(typeScript.flattenDiagnosticMessageText(messageText, '\n')); + } + }); + } finally { + fs.unlink(tempFilename); + } + } + + describe(filename, () => { + test('should succeed', () => compile(filename)); + test('should have @ts-expect-error describing compile errors correctly', () => checkExpectError(filename)); + }); +}; + +module.exports = { + process(_, filename) { + return { code: `(${run})(${JSON.stringify({ filename })})` }; + } +}; diff --git a/packages/version-from-git/__tests__/types/.gitignore b/packages/version-from-git/__tests__/types/.gitignore new file mode 100644 index 0000000..5ad8225 --- /dev/null +++ b/packages/version-from-git/__tests__/types/.gitignore @@ -0,0 +1 @@ +*.tmp.tsx diff --git a/packages/version-from-git/jest.config.json b/packages/version-from-git/jest.config.json new file mode 100644 index 0000000..d49d9d7 --- /dev/null +++ b/packages/version-from-git/jest.config.json @@ -0,0 +1,40 @@ +{ + "testPathIgnorePatterns": [ + "/__setup__/", + "/lib/", + "/node_modules/", + "/__types__/", + "\\.pnp\\.[^\\/]+$" + ], + "transform": { + "/__tests__/types/": [ + "/__tests__/__setup__/typingTestTransformer.js" + ], + "\\.[jt]sx?$": [ + "babel-jest", + { + "presets": [ + [ + "@babel/preset-typescript", + { + "allowDeclareFields": true + } + ], + [ + "@babel/preset-env", + { + "modules": "commonjs", + "targets": { + "node": "18" + } + } + ] + ], + "sourceMaps": true + } + ] + }, + "watchPathIgnorePatterns": [ + "\\.tmp\\." + ] +} diff --git a/packages/version-from-git/package.json b/packages/version-from-git/package.json index 2e11b3c..9e28d0a 100644 --- a/packages/version-from-git/package.json +++ b/packages/version-from-git/package.json @@ -5,18 +5,18 @@ "files": [ "./dist/" ], - "main": "./dist/version-from-git.mjs", + "type": "module", + "main": "./dist/version-from-git.js", "bin": { - "version-from-git": "./dist/version-from-git.mjs" + "version-from-git": "./dist/version-from-git.js" }, "scripts": { "build": "tsup-node", - "bump": "npm run bump:prod && npm run bump:dev && npm run bump:auditfix", - "bump:auditfix": "npm audit fix || exit 0", - "bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.localPeerDependencies // {}) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@latest\") | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", - "bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.localPeerDependencies // {}) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@latest\") | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", + "bump": "npm run bump:prod && npm run bump:dev", + "bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localPeerDependencies // {}) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", + "bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localPeerDependencies // {}) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | has($K) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true", "precommit": "npm run precommit:eslint && npm run precommit:publint && npm run precommit:typescript:production", - "precommit:eslint": "eslint ./src/", + "precommit:eslint": "ESLINT_USE_FLAT_CONFIG=false eslint ./src/", "precommit:publint": "publint", "precommit:typescript:production": "tsc --noEmit --project ./src/tsconfig.precommit.production.json", "-precommit:typescript:test": "tsc --noEmit --project ./src/tsconfig.precommit.test.json", diff --git a/packages/version-from-git/src/index.mts b/packages/version-from-git/src/index.ts similarity index 99% rename from packages/version-from-git/src/index.mts rename to packages/version-from-git/src/index.ts index a78993c..7880b03 100755 --- a/packages/version-from-git/src/index.mts +++ b/packages/version-from-git/src/index.ts @@ -12,6 +12,7 @@ import { major, minor, patch } from 'semver'; const { green, magenta, red, yellow } = chalk; const { log } = console; + const ourPackageJSON = await readPackage({ cwd: join(fileURLToPath(import.meta.url), '../../') }); const DEFAULT_TEMPLATE = 'branch.short'; diff --git a/packages/version-from-git/src/tsconfig.custom.json b/packages/version-from-git/src/tsconfig.custom.json new file mode 100644 index 0000000..7a3b017 --- /dev/null +++ b/packages/version-from-git/src/tsconfig.custom.json @@ -0,0 +1,3 @@ +{ + "extends": "@tsconfig/strictest/tsconfig.json" +} diff --git a/packages/version-from-git/src/tsconfig.json b/packages/version-from-git/src/tsconfig.json index aca1502..ae51fef 100644 --- a/packages/version-from-git/src/tsconfig.json +++ b/packages/version-from-git/src/tsconfig.json @@ -10,9 +10,8 @@ "strict": true, "target": "ESNext", "types": [ - "jest", "node" ] }, - "extends": "@tsconfig/strictest/tsconfig.json" + "extends": "./tsconfig.custom.json" } diff --git a/packages/version-from-git/src/tsconfig.precommit.production.json b/packages/version-from-git/src/tsconfig.precommit.production.json index ed58ae3..68f3ff3 100644 --- a/packages/version-from-git/src/tsconfig.precommit.production.json +++ b/packages/version-from-git/src/tsconfig.precommit.production.json @@ -8,9 +8,7 @@ "noEmit": true, "strict": true, "target": "ESNext", - "types": [ - "node" - ] + "types": [] }, "exclude": [ "**/*.spec.ts", @@ -19,5 +17,5 @@ "**/*.test.tsx", "__tests__/**/*" ], - "extends": "@tsconfig/strictest/tsconfig.json" + "extends": "./tsconfig.custom.json" } diff --git a/packages/version-from-git/src/tsconfig.precommit.test.json b/packages/version-from-git/src/tsconfig.precommit.test.json index edc7eb3..54576c2 100644 --- a/packages/version-from-git/src/tsconfig.precommit.test.json +++ b/packages/version-from-git/src/tsconfig.precommit.test.json @@ -8,7 +8,10 @@ "noEmit": true, "strict": true, "target": "ESNext", - "types": ["jest", "node"] + "types": [ + "jest", + "node" + ] }, "extends": "@tsconfig/recommended/tsconfig.json", "include": [ diff --git a/packages/version-from-git/tsup.config.ts b/packages/version-from-git/tsup.config.ts index e610e6b..81816a6 100644 --- a/packages/version-from-git/tsup.config.ts +++ b/packages/version-from-git/tsup.config.ts @@ -2,10 +2,11 @@ import { defineConfig } from 'tsup'; export default defineConfig([ { + dts: true, entry: { - 'version-from-git': './src/index.mts' + 'version-from-git': './src/index.ts' }, - format: ['esm'], + format: 'esm', sourcemap: true } ]);