diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 570d0af..2a1c2e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,6 +56,19 @@ jobs: run: npm install - name: Check Types run: npm run test:types + are_the_types_wrong: + name: Are the types wrong? + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "lts/*" + - name: Install Packages + run: npm install + - name: Check validity of type definitions + run: npm run lint:types jsr_test: name: Verify JSR Publish runs-on: ubuntu-latest diff --git a/jsr.json b/jsr.json index ec35108..a509886 100644 --- a/jsr.json +++ b/jsr.json @@ -1,12 +1,10 @@ { "name": "@eslint/json", "version": "0.14.0", - "exports": "./dist/esm/index.js", + "exports": "./dist/index.js", "publish": { "include": [ - "dist/esm/index.js", - "dist/esm/index.d.ts", - "dist/esm/types.ts", + "dist", "README.md", "jsr.json", "LICENSE" diff --git a/package.json b/package.json index e46c23d..a0066e9 100644 --- a/package.json +++ b/package.json @@ -4,26 +4,15 @@ "description": "JSON linting plugin for ESLint", "author": "Nicholas C. Zakas", "type": "module", - "main": "dist/esm/index.js", - "types": "dist/esm/index.d.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "exports": { ".": { - "require": { - "types": "./dist/cjs/index.d.cts", - "default": "./dist/cjs/index.cjs" - }, - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - } + "types": "./dist/index.d.ts", + "default": "./dist/index.js" }, "./types": { - "require": { - "types": "./dist/cjs/types.cts" - }, - "import": { - "types": "./dist/esm/types.d.ts" - } + "types": "./dist/types.d.ts" } }, "files": [ @@ -41,10 +30,7 @@ "prettier --write" ], "!(*.js)": "prettier --write --ignore-unknown", - "README.md": [ - "npm run build:update-rules-docs" - ], - "{src/rules/*.js,tools/update-rules-docs.js}": [ + "{src/rules/*.js,tools/update-rules-docs.js,README.md}": [ "npm run build:update-rules-docs", "git add README.md" ] @@ -58,20 +44,20 @@ }, "homepage": "https://github.com/eslint/json#readme", "scripts": { - "build:dedupe-types": "node tools/dedupe-types.js dist/cjs/index.cjs dist/esm/index.js", - "build:cts": "node tools/build-cts.js", + "build": "npm run build:rules && npm run build:types && npm run build:update-rules-docs", "build:rules": "node tools/build-rules.js", - "build": "npm run build:rules && rollup -c && npm run build:dedupe-types && tsc -p tsconfig.esm.json && npm run build:cts", + "build:types": "tsc", "build:update-rules-docs": "node tools/update-rules-docs.js", "prepare": "npm run build", "pretest": "npm run build", "lint": "eslint", "lint:fix": "eslint --fix", + "lint:types": "attw --pack --profile esm-only", "fmt": "prettier --write .", "fmt:check": "prettier --check .", "test": "mocha \"tests/**/*.test.js\"", "test:coverage": "c8 npm test", - "test:jsr": "npx jsr@latest publish --dry-run", + "test:jsr": "npx -y jsr@latest publish --dry-run", "test:types": "tsc -p tests/types/tsconfig.json" }, "keywords": [ @@ -89,6 +75,7 @@ "natural-compare": "^1.4.0" }, "devDependencies": { + "@arethetypeswrong/cli": "^0.18.2", "c8": "^10.1.3", "dedent": "^1.5.3", "eslint": "^9.39.2", @@ -99,9 +86,6 @@ "mdast-util-from-markdown": "^2.0.2", "mocha": "^11.3.0", "prettier": "^3.4.1", - "rollup": "^4.52.3", - "rollup-plugin-copy": "^3.5.0", - "rollup-plugin-delete": "^3.0.1", "typescript": "^5.9.2", "yorkie": "^2.0.0" }, diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index cf06b2d..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,26 +0,0 @@ -import copy from "rollup-plugin-copy"; -import del from "rollup-plugin-delete"; - -export default { - input: "src/index.js", - output: [ - { - file: "dist/cjs/index.cjs", - format: "cjs", - }, - { - file: "dist/esm/index.js", - format: "esm", - banner: '// @ts-self-types="./index.d.ts"', - }, - ], - plugins: [ - del({ targets: "dist/*" }), - copy({ - targets: [ - { src: "src/types.ts", dest: "dist/cjs", rename: "types.cts" }, - { src: "src/types.ts", dest: "dist/esm" }, - ], - }), - ], -}; diff --git a/src/languages/json-source-code.js b/src/languages/json-source-code.js index 0ddae71..2472cfd 100644 --- a/src/languages/json-source-code.js +++ b/src/languages/json-source-code.js @@ -22,7 +22,7 @@ import { /** * @import { DocumentNode, AnyNode, Token, LocationRange } from "@humanwhocodes/momoa"; * @import { FileProblem, DirectiveType, RulesConfig } from "@eslint/core"; - * @import { JSONSyntaxElement } from "../types.ts"; + * @import { JSONSyntaxElement } from "../types.js"; * @import { JSONLanguageOptions } from "./json-language.js"; */ diff --git a/src/rules/no-duplicate-keys.js b/src/rules/no-duplicate-keys.js index 05fa9ec..611453a 100644 --- a/src/rules/no-duplicate-keys.js +++ b/src/rules/no-duplicate-keys.js @@ -15,7 +15,7 @@ import { getKey, getRawKey } from "../util.js"; /** * @import { MemberNode } from "@humanwhocodes/momoa"; - * @import { JSONRuleDefinition } from "../types.ts"; + * @import { JSONRuleDefinition } from "../types.js"; * @typedef {"duplicateKey"} NoDuplicateKeysMessageIds * @typedef {JSONRuleDefinition<{ MessageIds: NoDuplicateKeysMessageIds }>} NoDuplicateKeysRuleDefinition */ diff --git a/src/rules/no-empty-keys.js b/src/rules/no-empty-keys.js index 7422488..4f6e3d0 100644 --- a/src/rules/no-empty-keys.js +++ b/src/rules/no-empty-keys.js @@ -14,7 +14,7 @@ import { getKey } from "../util.js"; //----------------------------------------------------------------------------- /** - * @import { JSONRuleDefinition } from "../types.ts"; + * @import { JSONRuleDefinition } from "../types.js"; * @typedef {"emptyKey"} NoEmptyKeysMessageIds * @typedef {JSONRuleDefinition<{ MessageIds: NoEmptyKeysMessageIds }>} NoEmptyKeysRuleDefinition */ diff --git a/src/rules/no-unnormalized-keys.js b/src/rules/no-unnormalized-keys.js index 5baa669..0186a24 100644 --- a/src/rules/no-unnormalized-keys.js +++ b/src/rules/no-unnormalized-keys.js @@ -14,7 +14,7 @@ import { getKey } from "../util.js"; //----------------------------------------------------------------------------- /** - * @import { JSONRuleDefinition } from "../types.ts"; + * @import { JSONRuleDefinition } from "../types.js"; * @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds * @typedef {{ form: string }} NoUnnormalizedKeysOptions * @typedef {JSONRuleDefinition<{ RuleOptions: [NoUnnormalizedKeysOptions], MessageIds: NoUnnormalizedKeysMessageIds }>} NoUnnormalizedKeysRuleDefinition diff --git a/src/rules/no-unsafe-values.js b/src/rules/no-unsafe-values.js index 1eae5db..ee9b6f5 100644 --- a/src/rules/no-unsafe-values.js +++ b/src/rules/no-unsafe-values.js @@ -8,7 +8,7 @@ //----------------------------------------------------------------------------- /** - * @import { JSONRuleDefinition } from "../types.ts"; + * @import { JSONRuleDefinition } from "../types.js"; * @typedef {"unsafeNumber"|"unsafeInteger"|"unsafeZero"|"subnormal"|"loneSurrogate"} NoUnsafeValuesMessageIds * @typedef {JSONRuleDefinition<{ MessageIds: NoUnsafeValuesMessageIds }>} NoUnsafeValuesRuleDefinition */ diff --git a/src/rules/sort-keys.js b/src/rules/sort-keys.js index fc1cc10..66fe197 100644 --- a/src/rules/sort-keys.js +++ b/src/rules/sort-keys.js @@ -16,7 +16,7 @@ import { getKey, getRawKey } from "../util.js"; //----------------------------------------------------------------------------- /** - * @import { JSONRuleDefinition } from "../types.ts"; + * @import { JSONRuleDefinition } from "../types.js"; * @import { MemberNode } from "@humanwhocodes/momoa"; * @typedef {Object} SortOptions * @property {boolean} caseSensitive Whether key comparisons are case-sensitive. diff --git a/src/rules/top-level-interop.js b/src/rules/top-level-interop.js index 579e735..d203892 100644 --- a/src/rules/top-level-interop.js +++ b/src/rules/top-level-interop.js @@ -8,7 +8,7 @@ //----------------------------------------------------------------------------- /** - * @import { JSONRuleDefinition } from "../types.ts"; + * @import { JSONRuleDefinition } from "../types.js"; * @typedef {"topLevel"} TopLevelInteropMessageIds * @typedef {JSONRuleDefinition<{ MessageIds: TopLevelInteropMessageIds }>} TopLevelInteropRuleDefinition */ diff --git a/tools/build-cts.js b/tools/build-cts.js deleted file mode 100644 index 873a2ae..0000000 --- a/tools/build-cts.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @fileoverview Rewrites import expressions for CommonJS compatibility. - * This script creates "dist/cjs/index.d.cts" from "dist/esm/index.d.ts" by modifying imports - * from `"./types.ts"` to `"./types.cts"`. - * - * Also updates "types.cts" to reference "index.cts" - * - * @author Francesco Trotta - */ - -import { readFile, writeFile } from "node:fs/promises"; - -const oldSourceText = await readFile("dist/esm/index.d.ts", "utf-8"); -const newSourceText = oldSourceText.replaceAll('"./types.ts"', '"./types.cts"'); -await writeFile("dist/cjs/index.d.cts", newSourceText); - -// Now update the types.cts to reference index.cts -const typesText = await readFile("dist/cjs/types.cts", "utf-8"); -const updatedTypesText = typesText.replaceAll('"./index.js"', '"./index.cjs"'); - -await writeFile("dist/cjs/types.cts", updatedTypesText); diff --git a/tools/dedupe-types.js b/tools/dedupe-types.js deleted file mode 100644 index 7d043bd..0000000 --- a/tools/dedupe-types.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @fileoverview Strips typedef aliases from the rolled-up file. This - * is necessary because the TypeScript compiler throws an error when - * it encounters a duplicate typedef. - * - * Usage: - * node tools/dedupe-types.js filename1.js filename2.js ... - * - * @author Nicholas C. Zakas - */ - -//----------------------------------------------------------------------------- -// Imports -//----------------------------------------------------------------------------- - -import fs from "node:fs"; - -//----------------------------------------------------------------------------- -// Main -//----------------------------------------------------------------------------- - -const importRegExp = - /^\s*\*\s*@import\s*\{(?[^,}]+(?:,[^,}]+)*)\}\s*from\s*"(?[^"]+)"/u; - -// read files from the command line -const files = process.argv.slice(2); - -files.forEach(filePath => { - const lines = fs.readFileSync(filePath, "utf8").split(/\r?\n/gu); - const imports = new Map(); - - // find all imports and remove them - const remainingLines = lines.filter(line => { - if (!line.startsWith(" * @import")) { - return true; - } - - const match = importRegExp.exec(line); - - if (!match) { - throw Error("Something is very wrong"); - } - - const source = match.groups.source; - const ids = match.groups.ids.split(/,/gu).map(id => id.trim()); - - // save the import data - - if (!imports.has(source)) { - imports.set(source, new Set()); - } - - const existingIds = imports.get(source); - ids.forEach(id => existingIds.add(id)); - - return false; - }); - - // create a new import statement for each unique import - const jsdocBlock = ["/**"]; - - imports.forEach((ids, source) => { - // if it's a local file, we don't need it - if (source.startsWith("./")) { - return; - } - - const idList = Array.from(ids).join(", "); - jsdocBlock.push(` * @import { ${idList} } from "${source}"`); - }); - - // add the new import statements to the top of the file - jsdocBlock.push(" */"); - remainingLines.unshift(...jsdocBlock); - remainingLines.unshift(""); // add a blank line before the block - - // replace references to ../types.ts with ./types.ts - const text = remainingLines - .join("\n") - .replace(/\.\.\/types\.ts/gu, "./types.ts"); - - fs.writeFileSync(filePath, text, "utf8"); -}); diff --git a/tsconfig.esm.json b/tsconfig.esm.json deleted file mode 100644 index 40ece13..0000000 --- a/tsconfig.esm.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "./tsconfig.json", - "files": ["dist/esm/index.js"] -} diff --git a/tsconfig.json b/tsconfig.json index 51a114c..d52d3f9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,13 @@ { - "files": ["src/index.js"], + "include": ["src/**/*.js", "src/**/*.ts"], "compilerOptions": { "declaration": true, - "emitDeclarationOnly": true, "allowJs": true, "checkJs": true, - "outDir": "dist/esm", + "outDir": "dist", "target": "ESNext", "moduleResolution": "NodeNext", "module": "NodeNext", - "allowImportingTsExtensions": true, "types": [] } }