From ec5609b18c79ea9fc8183ae78e917801e6a8a3f4 Mon Sep 17 00:00:00 2001 From: Shinigami Date: Sun, 18 Feb 2024 22:43:16 +0100 Subject: chore: convert to esm (#2261) --- .eslintrc.cjs | 198 +++++++++++++++++++++++++++++ .eslintrc.js | 198 ----------------------------- .github/workflows/ci.yml | 3 + .github/workflows/commentCodeGeneration.ts | 6 +- .github/workflows/pr.yml | 4 +- .prettierrc.js | 5 +- package.json | 15 ++- test/faker.spec.ts | 5 +- test/locale-imports.spec.ts | 2 +- 9 files changed, 221 insertions(+), 215 deletions(-) create mode 100644 .eslintrc.cjs delete mode 100644 .eslintrc.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 00000000..bf6789c6 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,198 @@ +// @ts-check +const { defineConfig } = require('eslint-define-config'); +const { readGitignoreFiles } = require('eslint-gitignore'); + +/// +/// +/// +/// +/// + +module.exports = defineConfig({ + ignorePatterns: [ + ...readGitignoreFiles(), + '.eslintrc.cjs', // Skip self linting + ], + root: true, + env: { + browser: true, + node: true, + }, + reportUnusedDisableDirectives: true, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/strict-type-checked', + 'plugin:prettier/recommended', + 'plugin:deprecation/recommended', + 'plugin:jsdoc/recommended-typescript-error', + 'plugin:unicorn/recommended', + ], + parserOptions: { + project: ['./tsconfig.json'], + warnOnUnsupportedTypeScriptVersion: false, + }, + rules: { + eqeqeq: ['error', 'always', { null: 'ignore' }], + 'no-else-return': 'error', + 'no-restricted-globals': ['error', 'Intl'], + 'prefer-exponentiation-operator': 'error', + 'prefer-template': 'error', + + 'unicorn/no-nested-ternary': 'off', // incompatible with prettier + 'unicorn/no-null': 'off', // incompatible with TypeScript + 'unicorn/no-zero-fractions': 'off', // deactivated to raise awareness of floating operations + 'unicorn/number-literal-case': 'off', // incompatible with prettier + 'unicorn/prefer-ternary': 'off', // ternaries aren't always better + + // TODO @Shinigami92 2023-09-23: prefer-at should be turned on when we drop support for Node 14. + 'unicorn/prefer-at': 'off', + // TODO @Shinigami92 2023-09-23: prefer-string-replace-all should be turned on when we drop support for Node 14. + 'unicorn/prefer-string-replace-all': 'off', + // TODO @ST-DDT 2023-10-28: The following rule should be turned on when we switch to esm. + 'unicorn/prefer-top-level-await': 'off', + + // TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code. + // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. + 'unicorn/better-regex': 'off', + 'unicorn/consistent-function-scoping': 'off', + 'unicorn/import-style': 'off', + 'unicorn/no-array-callback-reference': 'off', + 'unicorn/no-await-expression-member': 'off', + 'unicorn/no-object-as-default-parameter': 'off', + 'unicorn/no-useless-switch-case': 'off', + 'unicorn/numeric-separators-style': 'off', + 'unicorn/prefer-export-from': 'off', + 'unicorn/prefer-string-slice': 'off', + 'unicorn/prevent-abbreviations': 'off', + 'unicorn/require-array-join-separator': 'off', + 'unicorn/switch-case-braces': 'off', + + '@typescript-eslint/array-type': [ + 'error', + { default: 'array-simple', readonly: 'generic' }, + ], + '@typescript-eslint/consistent-type-imports': 'error', + '@typescript-eslint/explicit-module-boundary-types': 'error', + '@typescript-eslint/naming-convention': [ + 'error', + { + format: ['PascalCase'], + selector: ['class', 'interface', 'typeAlias', 'enumMember'], + leadingUnderscore: 'forbid', + trailingUnderscore: 'forbid', + }, + { + format: ['PascalCase'], + selector: ['typeParameter'], + prefix: ['T'], + leadingUnderscore: 'forbid', + trailingUnderscore: 'forbid', + }, + ], + '@typescript-eslint/no-inferrable-types': [ + 'error', + { ignoreParameters: true }, + ], + '@typescript-eslint/no-unnecessary-condition': 'off', // requires `strictNullChecks` to be enabled + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: 'block-like', next: '*' }, + ], + '@typescript-eslint/prefer-regexp-exec': 'error', + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { allowNumber: true, allowBoolean: true }, + ], + '@typescript-eslint/switch-exhaustiveness-check': [ + 'error', + { requireDefaultForNonUnion: true }, + ], + '@typescript-eslint/unbound-method': 'off', + '@typescript-eslint/unified-signatures': 'off', // incompatible with our api docs generation + + // TODO @ST-DDT 2023-10-10: The following rules currently conflict with our code. + // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. + '@typescript-eslint/no-confusing-void-expression': 'off', + + 'jsdoc/require-jsdoc': 'off', // Enabled only for src/**/*.ts + 'jsdoc/require-returns': 'off', + 'jsdoc/sort-tags': [ + 'error', + { + tagSequence: [ + { tags: ['template'] }, + { tags: ['internal'] }, + { tags: ['param'] }, + { tags: ['returns'] }, + { tags: ['throws'] }, + { tags: ['see'] }, + { tags: ['example'] }, + { tags: ['since'] }, + { tags: ['default'] }, + { tags: ['deprecated'] }, + ], + }, + ], + 'jsdoc/tag-lines': 'off', + }, + settings: { + jsdoc: { + mode: 'typescript', + }, + }, + overrides: [ + { + files: ['src/**/*.ts'], + rules: { + 'jsdoc/require-jsdoc': 'error', + }, + }, + { + files: ['src/locale/**/*.ts'], + rules: { + 'unicorn/filename-case': 'off', // our locale files have a custom naming scheme + }, + }, + { + files: ['src/definitions/**/*.ts', 'src/locales/**/*.ts'], + rules: { + 'unicorn/filename-case': [ + 'error', + { + case: 'snakeCase', + // TODO @ST-DDT 2023-10-21: rename the definitions in v9 + ignore: [ + /chemicalElement\.ts$/, + /directoryPaths\.ts$/, + /mimeTypes\.ts$/, + ], + }, + ], + 'unicorn/text-encoding-identifier-case': 'off', + }, + }, + { + files: ['test/**/*.spec.ts'], + extends: ['plugin:vitest/recommended'], + rules: { + 'deprecation/deprecation': 'off', + + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowNumber: true, + allowBoolean: true, + allowAny: true, + }, + ], + + 'vitest/expect-expect': 'off', + 'vitest/prefer-each': 'error', + 'vitest/valid-expect': ['error', { maxArgs: 2 }], + }, + }, + ], +}); diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index f4bb960d..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,198 +0,0 @@ -// @ts-check -const { defineConfig } = require('eslint-define-config'); -const { readGitignoreFiles } = require('eslint-gitignore'); - -/// -/// -/// -/// -/// - -module.exports = defineConfig({ - ignorePatterns: [ - ...readGitignoreFiles(), - '.eslintrc.js', // Skip self linting - ], - root: true, - env: { - browser: true, - node: true, - }, - reportUnusedDisableDirectives: true, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/strict-type-checked', - 'plugin:prettier/recommended', - 'plugin:deprecation/recommended', - 'plugin:jsdoc/recommended-typescript-error', - 'plugin:unicorn/recommended', - ], - parserOptions: { - project: ['./tsconfig.json'], - warnOnUnsupportedTypeScriptVersion: false, - }, - rules: { - eqeqeq: ['error', 'always', { null: 'ignore' }], - 'no-else-return': 'error', - 'no-restricted-globals': ['error', 'Intl'], - 'prefer-exponentiation-operator': 'error', - 'prefer-template': 'error', - - 'unicorn/no-nested-ternary': 'off', // incompatible with prettier - 'unicorn/no-null': 'off', // incompatible with TypeScript - 'unicorn/no-zero-fractions': 'off', // deactivated to raise awareness of floating operations - 'unicorn/number-literal-case': 'off', // incompatible with prettier - 'unicorn/prefer-ternary': 'off', // ternaries aren't always better - - // TODO @Shinigami92 2023-09-23: prefer-at should be turned on when we drop support for Node 14. - 'unicorn/prefer-at': 'off', - // TODO @Shinigami92 2023-09-23: prefer-string-replace-all should be turned on when we drop support for Node 14. - 'unicorn/prefer-string-replace-all': 'off', - // TODO @ST-DDT 2023-10-28: The following rule should be turned on when we switch to esm. - 'unicorn/prefer-top-level-await': 'off', - - // TODO @Shinigami92 2023-09-23: The following rules currently conflict with our code. - // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. - 'unicorn/better-regex': 'off', - 'unicorn/consistent-function-scoping': 'off', - 'unicorn/import-style': 'off', - 'unicorn/no-array-callback-reference': 'off', - 'unicorn/no-await-expression-member': 'off', - 'unicorn/no-object-as-default-parameter': 'off', - 'unicorn/no-useless-switch-case': 'off', - 'unicorn/numeric-separators-style': 'off', - 'unicorn/prefer-export-from': 'off', - 'unicorn/prefer-string-slice': 'off', - 'unicorn/prevent-abbreviations': 'off', - 'unicorn/require-array-join-separator': 'off', - 'unicorn/switch-case-braces': 'off', - - '@typescript-eslint/array-type': [ - 'error', - { default: 'array-simple', readonly: 'generic' }, - ], - '@typescript-eslint/consistent-type-imports': 'error', - '@typescript-eslint/explicit-module-boundary-types': 'error', - '@typescript-eslint/naming-convention': [ - 'error', - { - format: ['PascalCase'], - selector: ['class', 'interface', 'typeAlias', 'enumMember'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - }, - { - format: ['PascalCase'], - selector: ['typeParameter'], - prefix: ['T'], - leadingUnderscore: 'forbid', - trailingUnderscore: 'forbid', - }, - ], - '@typescript-eslint/no-inferrable-types': [ - 'error', - { ignoreParameters: true }, - ], - '@typescript-eslint/no-unnecessary-condition': 'off', // requires `strictNullChecks` to be enabled - '@typescript-eslint/no-unsafe-assignment': 'off', - '@typescript-eslint/no-unsafe-call': 'off', - '@typescript-eslint/no-unsafe-member-access': 'off', - '@typescript-eslint/padding-line-between-statements': [ - 'error', - { blankLine: 'always', prev: 'block-like', next: '*' }, - ], - '@typescript-eslint/prefer-regexp-exec': 'error', - '@typescript-eslint/restrict-template-expressions': [ - 'error', - { allowNumber: true, allowBoolean: true }, - ], - '@typescript-eslint/switch-exhaustiveness-check': [ - 'error', - { requireDefaultForNonUnion: true }, - ], - '@typescript-eslint/unbound-method': 'off', - '@typescript-eslint/unified-signatures': 'off', // incompatible with our api docs generation - - // TODO @ST-DDT 2023-10-10: The following rules currently conflict with our code. - // Each rule should be checked whether it should be enabled/configured and the problems fixed, or stay disabled permanently. - '@typescript-eslint/no-confusing-void-expression': 'off', - - 'jsdoc/require-jsdoc': 'off', // Enabled only for src/**/*.ts - 'jsdoc/require-returns': 'off', - 'jsdoc/sort-tags': [ - 'error', - { - tagSequence: [ - { tags: ['template'] }, - { tags: ['internal'] }, - { tags: ['param'] }, - { tags: ['returns'] }, - { tags: ['throws'] }, - { tags: ['see'] }, - { tags: ['example'] }, - { tags: ['since'] }, - { tags: ['default'] }, - { tags: ['deprecated'] }, - ], - }, - ], - 'jsdoc/tag-lines': 'off', - }, - settings: { - jsdoc: { - mode: 'typescript', - }, - }, - overrides: [ - { - files: ['src/**/*.ts'], - rules: { - 'jsdoc/require-jsdoc': 'error', - }, - }, - { - files: ['src/locale/**/*.ts'], - rules: { - 'unicorn/filename-case': 'off', // our locale files have a custom naming scheme - }, - }, - { - files: ['src/definitions/**/*.ts', 'src/locales/**/*.ts'], - rules: { - 'unicorn/filename-case': [ - 'error', - { - case: 'snakeCase', - // TODO @ST-DDT 2023-10-21: rename the definitions in v9 - ignore: [ - /chemicalElement\.ts$/, - /directoryPaths\.ts$/, - /mimeTypes\.ts$/, - ], - }, - ], - 'unicorn/text-encoding-identifier-case': 'off', - }, - }, - { - files: ['test/**/*.spec.ts'], - extends: ['plugin:vitest/recommended'], - rules: { - 'deprecation/deprecation': 'off', - - '@typescript-eslint/restrict-template-expressions': [ - 'error', - { - allowNumber: true, - allowBoolean: true, - allowAny: true, - }, - ], - - 'vitest/expect-expect': 'off', - 'vitest/prefer-each': 'error', - 'vitest/valid-expect': ['error', { maxArgs: 2 }], - }, - }, - ], -}); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6524af14..401eceb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -173,6 +173,9 @@ jobs: env: CYPRESS_INSTALL_BINARY: 0 + - name: Build types + run: pnpm run build:types + - name: Check scripts run: pnpm run ts-check diff --git a/.github/workflows/commentCodeGeneration.ts b/.github/workflows/commentCodeGeneration.ts index f456e563..ed5258d5 100644 --- a/.github/workflows/commentCodeGeneration.ts +++ b/.github/workflows/commentCodeGeneration.ts @@ -10,11 +10,11 @@ import type { context as ctx, GitHub } from '@actions/github/lib/utils'; * @param context An object containing the context of the workflow run * @param isSuccess A boolean indicating whether the workflow was successful */ -module.exports = async ( +export async function script( github: InstanceType, context: typeof ctx, isSuccess: boolean -) => { +): Promise { const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, @@ -45,4 +45,4 @@ module.exports = async ( body, }); } -}; +} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e250f9e4..6b913830 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -50,13 +50,13 @@ jobs: continue-on-error: true - name: Transpile ts - run: pnpm exec tsc .github/workflows/commentCodeGeneration.ts --outDir .github/workflows + run: pnpm tsup-node .github/workflows/commentCodeGeneration.ts --format cjs --clean false --out-dir .github/workflows - name: Comment uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | - const script = require('${{ github.workspace }}/.github/workflows/commentCodeGeneration.js') + const { script } = require('${{ github.workspace }}/.github/workflows/commentCodeGeneration.cjs') await script(github, context, ${{ steps.generate.outcome == 'success' && steps.diff.outcome == 'success' }}) - name: Status diff --git a/.prettierrc.js b/.prettierrc.js index a81147f9..063dc85a 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,9 +1,9 @@ // @ts-check /** - * @type {import('prettier').Options} + * @type {import('prettier').Config} */ -module.exports = { +export default { plugins: ['prettier-plugin-organize-imports'], singleQuote: true, trailingComma: 'es5', @@ -20,6 +20,7 @@ module.exports = { { files: '*.md', options: { + // @ts-expect-error: known property organizeImportsSkipDestructiveCodeActions: true, }, }, diff --git a/package.json b/package.json index 6a8f60ac..3fa55398 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,9 @@ ], "bugs": "https://github.com/faker-js/faker/issues", "license": "MIT", - "main": "dist/index.js", - "module": "dist/index.mjs", + "type": "module", + "main": "dist/index.cjs", + "module": "dist/index.js", "types": "index.d.ts", "typesVersions": { ">=4.0": { @@ -41,13 +42,15 @@ "exports": { ".": { "types": "./dist/types/index.d.ts", - "require": "./dist/index.js", - "import": "./dist/index.mjs" + "import": "./dist/index.js", + "require": "./dist/index.cjs", + "default": "./dist/index.js" }, "./locale/*": { "types": "./dist/types/locale/*.d.ts", - "require": "./dist/locale/*.js", - "import": "./dist/locale/*.mjs" + "import": "./dist/locale/*.js", + "require": "./dist/locale/*.cjs", + "default": "./dist/locale/*.js" }, "./package.json": "./package.json" }, diff --git a/test/faker.spec.ts b/test/faker.spec.ts index a026577b..63ae794e 100644 --- a/test/faker.spec.ts +++ b/test/faker.spec.ts @@ -13,15 +13,14 @@ describe('faker', () => { ); }); - it('should not log anything on startup', () => { + it('should not log anything on startup', async () => { const spies: MockInstance[] = keys(console) .filter((key) => typeof console[key] === 'function') .map((methodName) => vi.spyOn(console, methodName as keyof typeof console) ); - // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module -- Using import() requires types being build but the CI / TS-Check runs without them. - require('..').faker; + (await import('..')).default; new Faker({ locale: { metadata: { title: '' } } }); diff --git a/test/locale-imports.spec.ts b/test/locale-imports.spec.ts index 5f07056b..4c1197c8 100644 --- a/test/locale-imports.spec.ts +++ b/test/locale-imports.spec.ts @@ -6,7 +6,7 @@ import { keys } from '../src/internal/keys'; describe.each(keys(allLocales))('locale imports', (locale) => { it(`should be possible to directly require('@faker-js/faker/locale/${locale}')`, () => { // eslint-disable-next-line @typescript-eslint/no-var-requires, unicorn/prefer-module - const { faker } = require(`../dist/locale/${locale}`) as { + const { faker } = require(`../dist/locale/${locale}.cjs`) as { faker: Faker; }; -- cgit v1.2.3