diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..603eac3 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json", + "extends": ["./packages/tools/oxc/oxlintrc.json"], + "ignorePatterns": [ + "**/dist", + "**/build", + "**/docs", + "**/.tsbuildinfo", + "!scratchpad/**/*", + // TODO: This should be in a nested .oxlintrc.json, but it does not work + // See related issue: https://github.com/oxc-project/oxc/issues/13204 + "packages/amp/src/Protobuf/**/*" + ], + "jsPlugins": [ + "@amp/oxc/oxlint" + ], + "overrides": [ + { + "files": [ + "**/{test,dtslint,examples,benchmark,bundle,scripts,scratchpad}/**" + ], + "rules": { + "eslint/no-console": "off", + "effect/no-import-from-barrel-package": "off" + } + } + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..1a118e9 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,6 @@ +{ + "recommendations": [ + "oxc.oxc-vscode", + "dprint.dprint" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 60680c3..8919983 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,32 +1,27 @@ { + "dprint.path": "node_modules/dprint/dprint", "typescript.tsdk": "node_modules/typescript/lib", "typescript.preferences.importModuleSpecifier": "relative", "typescript.enablePromptUseWorkspaceTsdk": true, - "eslint.format.enable": true, - "eslint.validate": [ - "javascript", - "typescript" - ], - "[javascript][javascriptreact][typescript][typescriptreact]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "dbaeumer.vscode-eslint", - "editor.codeActionsOnSave": { - "source.fixAll.eslint": "explicit" - }, - "editor.quickSuggestions": { - "other": true, - "comments": false, - "strings": false - }, - "editor.acceptSuggestionOnCommitCharacter": true, - "editor.acceptSuggestionOnEnter": "on", - "editor.quickSuggestionsDelay": 10, - "editor.suggestOnTriggerCharacters": true, - "editor.tabCompletion": "off", - "editor.suggest.localityBonus": true, - "editor.suggestSelection": "recentlyUsed", - "editor.wordBasedSuggestions": "matchingDocuments", - "editor.parameterHints.enabled": true, - "files.insertFinalNewline": true, + "editor.formatOnSave": true, + "editor.defaultFormatter": "dprint.dprint", + "editor.formatOnSaveMode": "file", + "editor.codeActionsOnSave": { + "source.fixAll.oxc": "explicit" }, + "editor.quickSuggestions": { + "other": true, + "comments": false, + "strings": false + }, + "editor.acceptSuggestionOnCommitCharacter": true, + "editor.acceptSuggestionOnEnter": "on", + "editor.quickSuggestionsDelay": 10, + "editor.suggestOnTriggerCharacters": true, + "editor.tabCompletion": "off", + "editor.suggest.localityBonus": true, + "editor.suggestSelection": "recentlyUsed", + "editor.wordBasedSuggestions": "matchingDocuments", + "editor.parameterHints.enabled": true, + "files.insertFinalNewline": true } diff --git a/dprint.json b/dprint.json new file mode 100644 index 0000000..76a3fc9 --- /dev/null +++ b/dprint.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://dprint.dev/schemas/v0.json", + "includes": ["**/*.{ts,tsx,js,jsx,json,md}"], + "indentWidth": 2, + "lineWidth": 120, + "newLineKind": "lf", + "typescript": { + "semiColons": "asi", + "quoteStyle": "alwaysDouble", + "trailingCommas": "never", + "operatorPosition": "maintain", + "arrowFunction.useParentheses": "force" + }, + "excludes": [ + "**/dist", + "**/build", + "**/docs", + "**/coverage", + "!scratchpad/**/*", + // TODO: move to nested configuration if possible + "packages/amp/src/Protobuf/**" + ], + "plugins": [ + "https://plugins.dprint.dev/typescript-0.93.4.wasm", + "https://plugins.dprint.dev/markdown-0.20.0.wasm", + "https://plugins.dprint.dev/json-0.21.1.wasm" + ] +} diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 3ad77ad..0000000 --- a/eslint.config.js +++ /dev/null @@ -1,155 +0,0 @@ -import * as effectEslint from "@effect/eslint-plugin" -import eslint from "@eslint/js" -import * as tsResolver from "eslint-import-resolver-typescript" -import importPlugin from "eslint-plugin-import-x" -import simpleImportSort from "eslint-plugin-simple-import-sort" -import sortDestructureKeys from "eslint-plugin-sort-destructure-keys" -import unusedImports from "eslint-plugin-unused-imports" -import { defineConfig } from "eslint/config" -import tseslint from "typescript-eslint" - -export default defineConfig( - { - ignores: ["**/dist", "**/docs", "**/.tsbuildinfo", "**/*.md"] - }, - eslint.configs.recommended, - tseslint.configs.strict, - importPlugin.flatConfigs.recommended, - importPlugin.flatConfigs.typescript, - effectEslint.configs.dprint, - { - plugins: { - "simple-import-sort": simpleImportSort, - "sort-destructure-keys": sortDestructureKeys - }, - - languageOptions: { - parser: tseslint.parser, - ecmaVersion: 2018, - sourceType: "module" - }, - - settings: { - "import-x/resolver": { - name: "tsResolver", - resolver: tsResolver, - options: { - alwaysTryTypes: true - } - }, - "local-rules": { - rulesPaths: ["./eslint-local-rules.cjs"] - } - }, - - rules: { - "no-fallthrough": "off", - "no-irregular-whitespace": "off", - "object-shorthand": "error", - "prefer-destructuring": "off", - "sort-imports": "off", - - "no-restricted-syntax": [ - "error", - { - selector: "CallExpression[callee.property.name='push'] > SpreadElement.arguments", - message: "Do not use spread arguments in Array.push" - } - ], - - "no-unused-vars": "off", - "require-yield": "off", - "prefer-rest-params": "off", - "prefer-spread": "off", - "import-x/export": "off", - "import-x/first": "error", - "import-x/newline-after-import": "error", - "import-x/no-duplicates": "error", - "import-x/no-named-as-default-member": "off", - "import-x/no-unresolved": "off", - "import-x/order": "off", - "simple-import-sort/imports": "off", - "sort-destructure-keys/sort-destructure-keys": "error", - "deprecation/deprecation": "off", - - "@typescript-eslint/array-type": [ - "warn", - { - default: "generic", - readonly: "generic" - } - ], - "@typescript-eslint/no-dynamic-delete": "off", - "@typescript-eslint/ban-ts-comment": "off", - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/camelcase": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/consistent-type-imports": "warn", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/member-delimiter-style": 0, - "@typescript-eslint/no-array-constructor": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-empty-interface": "off", - "@typescript-eslint/no-empty-object-type": "off", - "@typescript-eslint/no-invalid-void-type": "off", - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unsafe-function-type": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { - argsIgnorePattern: "^_", - varsIgnorePattern: "^_" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/prefer-for-of": "off", - "@typescript-eslint/unified-signatures": "off", - - "@effect/dprint": [ - "error", - { - config: { - indentWidth: 2, - lineWidth: 120, - semiColons: "asi", - quoteStyle: "alwaysDouble", - trailingCommas: "never", - operatorPosition: "maintain", - "arrowFunction.useParentheses": "force" - } - } - ] - } - }, - { - files: ["packages/*/src/**/*.ts", "packages/*/test/**/*.ts"], - rules: { - "no-console": "error" - } - }, - { - files: ["scratchpad/eslint/**/*"], - plugins: { - "unused-imports": unusedImports - }, - rules: { - "unused-imports/no-unused-imports": "error", - "@effect/dprint": [ - "error", - { - config: { - indentWidth: 2, - lineWidth: 80, - semiColons: "asi", - quoteStyle: "alwaysDouble", - trailingCommas: "never", - operatorPosition: "maintain", - "arrowFunction.useParentheses": "force" - } - } - ] - } - } -) diff --git a/package.json b/package.json index 10c3077..8ac8928 100644 --- a/package.json +++ b/package.json @@ -5,28 +5,23 @@ "scripts": { "check": "tspc -b tsconfig.json", "clean": "node scripts/clean.mjs", - "lint": "eslint \"**/{src,test,examples,dtslint}/**/*.{ts,mjs}\"", - "lint-fix": "pnpm lint --fix", + "lint": "oxlint && dprint check", + "lint-fix": "oxlint --fix && dprint fmt", "test": "vitest" }, "devDependencies": { - "@effect/eslint-plugin": "^0.3.2", + "@amp/oxc": "workspace:^", "@effect/language-service": "^0.62.4", "@effect/platform-node": "^0.104.0", "@effect/vitest": "^0.27.0", - "@eslint/js": "^9.39.2", "@types/node": "^25.0.3", "@vitest/coverage-v8": "^4.0.16", "@vitest/ui": "^4.0.16", + "dprint": "^0.51.1", "effect": "^3.19.13", - "eslint": "^9.39.2", - "eslint-import-resolver-typescript": "^4.4.4", - "eslint-plugin-import-x": "^4.16.1", - "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-sort-destructure-keys": "^2.0.0", - "eslint-plugin-unused-imports": "^4.3.0", "glob": "^13.0.0", "globals": "^16.5.0", + "oxlint": "^1.38.0", "ts-patch": "^3.3.0", "typescript": "^5.9.3", "typescript-eslint": "^8.50.0", diff --git a/packages/amp/README.md b/packages/amp/README.md index cf3f630..33651cb 100644 --- a/packages/amp/README.md +++ b/packages/amp/README.md @@ -5,5 +5,5 @@ **Enabling TypeScript's `erasableSyntaxOnly` Feature** For some completely absurd reason, the `@bufbuild/protoc-gen-es` plugin does not support generating enum values as anything other than TypeScript enums at this time, so we cannot yet enable this flag. - + See the [related `protobuf-es` issue](https://github.com/bufbuild/protobuf-es/issues/1139) for more information. diff --git a/packages/amp/tsconfig.build.json b/packages/amp/tsconfig.build.json index dcdf446..c716fcb 100644 --- a/packages/amp/tsconfig.build.json +++ b/packages/amp/tsconfig.build.json @@ -1,6 +1,6 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "./tsconfig.src.jsonc", + "extends": "./tsconfig.src.json", "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", "outDir": "dist", diff --git a/packages/amp/tsconfig.json b/packages/amp/tsconfig.json index 86025d1..5b723cc 100644 --- a/packages/amp/tsconfig.json +++ b/packages/amp/tsconfig.json @@ -1,6 +1,6 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "../../tsconfig.base.jsonc", + "extends": "../../tsconfig.base.json", "include": [], "references": [ { "path": "tsconfig.src.json" }, diff --git a/packages/amp/tsconfig.src.json b/packages/amp/tsconfig.src.json index 1144997..3be24ee 100644 --- a/packages/amp/tsconfig.src.json +++ b/packages/amp/tsconfig.src.json @@ -1,6 +1,6 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "../../tsconfig.base.jsonc", + "extends": "../../tsconfig.base.json", "include": ["src"], "compilerOptions": { "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", diff --git a/packages/amp/tsconfig.test.json b/packages/amp/tsconfig.test.json index c579c26..8fdc0cc 100644 --- a/packages/amp/tsconfig.test.json +++ b/packages/amp/tsconfig.test.json @@ -1,6 +1,6 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "../../tsconfig.base.jsonc", + "extends": "../../tsconfig.base.json", "include": ["test"], "references": [{ "path": "tsconfig.src.json" }], "compilerOptions": { diff --git a/packages/tools/oxc/oxlintrc.json b/packages/tools/oxc/oxlintrc.json new file mode 100644 index 0000000..3dea8b4 --- /dev/null +++ b/packages/tools/oxc/oxlintrc.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json", + "plugins": ["typescript", "import", "oxc", "eslint", "unicorn", "node"], + "categories": { + "correctness": "error", + "suspicious": "error", + "perf": "error" + }, + "rules": { + // Effect custom rules + "effect/no-import-from-barrel-package": [ + "error", + { + "checkPatterns": [ + "^effect$", + "^effect/(.+/)?[a-z][a-z0-9]*$", + "^@effect/[^/]+$", + "^@effect/[^/]+/(.+/)?[a-z][a-z0-9]*$" + ], + "checkRelativeIndexImports": true + } + ], + "effect/no-js-extension-imports": "error", + "effect/no-opaque-instance-fields": "error", + // Tune native rules + // Import rules + "typescript/no-import-type-side-effects": "error", + "import/no-duplicates": "error", + "import/no-self-import": "error", + "import/no-empty-named-blocks": "error", + // TypeScript cleanup + "typescript/no-unnecessary-type-assertion": "error", + "typescript/no-unnecessary-type-constraint": "error", + "typescript/no-useless-empty-export": "error", + // Code quality + "eslint/no-console": "error", + "eslint/no-var": "error", + "eslint/no-useless-constructor": "error", + "unicorn/no-abusive-eslint-disable": "error", + "eslint/no-unneeded-ternary": "error", + "eslint/no-useless-concat": "error", + "oxc/misrefactored-assign-op": "error", + // Unicorn + "unicorn/prefer-array-flat-map": "error", + "unicorn/no-accessor-recursion": "error", + "oxc/no-map-spread": "off", + "eslint/object-shorthand": "off", + "eslint/no-unused-vars": "off", + "eslint/require-yield": "off", + "eslint/no-fallthrough": "off", + "eslint/no-await-in-loop": "off", + "unicorn/no-new-array": "off", + "unicorn/consistent-function-scoping": "off", + "unicorn/no-array-sort": "off", + "unicorn/no-array-reverse": "off", + "unicorn/require-post-message-target-origin": "off", + "unicorn/prefer-add-event-listener": "off", + "unicorn/prefer-set-has": "off", + "typescript/no-explicit-any": "off", + "typescript/no-empty-interface": "off", + "typescript/ban-ts-comment": "off", + "typescript/no-namespace": "off", + "typescript/no-non-null-assertion": "off", + "typescript/no-dynamic-delete": "off", + "typescript/no-invalid-void-type": "off", + "typescript/no-unsafe-function-type": "off", + "typescript/unified-signatures": "off", + "typescript/no-empty-object-type": "off", + "typescript/no-confusing-non-null-assertion": "off", + "typescript/array-type": [ + "error", + { + "default": "generic", + "readonly": "generic" + } + ], + "typescript/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "varsIgnorePattern": "^_" + } + ] + } +} diff --git a/packages/tools/oxc/package.json b/packages/tools/oxc/package.json new file mode 100644 index 0000000..d9fb817 --- /dev/null +++ b/packages/tools/oxc/package.json @@ -0,0 +1,63 @@ +{ + "name": "@amp/oxc", + "version": "0.0.1", + "type": "module", + "private": true, + "license": "MIT", + "description": "Opinionated linting and formatting configuration for Amp", + "homepage": "https://www.edgeandnode.com/amp-dev", + "repository": { + "type": "git", + "url": "https://github.com/amp/amp-typescript.git", + "directory": "packages/tools/oxc" + }, + "sideEffects": [], + "bugs": { + "url": "https://github.com/amp/amp-typescript/issues" + }, + "tags": [ + "typescript", + "formatting", + "linting", + "oxc" + ], + "keywords": [ + "typescript", + "formatting", + "linting", + "oxc" + ], + "exports": { + "./package.json": "./package.json", + "./oxlint": "./src/oxlint/index.ts", + "./oxlint/rules/*": "./src/oxlint/rules/*.ts", + "./oxlintrc.json": "./oxlintrc.json" + }, + "files": [ + "oxlintrc.json", + "src/**/*.ts", + "dist/**/*.js", + "dist/**/*.js.map", + "dist/**/*.d.ts", + "dist/**/*.d.ts.map" + ], + "publishConfig": { + "provenance": true, + "exports": { + "./package.json": "./package.json", + "./oxlint": "./dist/oxlint/index.js", + "./oxlint/rules/*": "./dist/oxlint/rules/*.js", + "./oxlintrc.json": "./oxlintrc.json" + } + }, + "scripts": { + "build": "tsc -b tsconfig.build.json && pnpm babel", + "check": "tsc -b tsconfig.json", + "test": "vitest", + "coverage": "vitest --coverage" + }, + "devDependencies": { + "@types/node": "^25.0.2", + "vitest": "^4.0.0" + } +} diff --git a/packages/tools/oxc/src/oxlint/index.ts b/packages/tools/oxc/src/oxlint/index.ts new file mode 100644 index 0000000..8d82032 --- /dev/null +++ b/packages/tools/oxc/src/oxlint/index.ts @@ -0,0 +1,14 @@ +import noImportFromBarrelPackage from "./rules/no-import-from-barrel-package.ts" +import noJsExtensionImports from "./rules/no-js-extension-imports.ts" +import noOpaqueInstanceFields from "./rules/no-opaque-instance-fields.ts" + +export default { + meta: { + name: "effect" + }, + rules: { + "no-import-from-barrel-package": noImportFromBarrelPackage, + "no-js-extension-imports": noJsExtensionImports, + "no-opaque-instance-fields": noOpaqueInstanceFields + } +} diff --git a/packages/tools/oxc/src/oxlint/rules/no-import-from-barrel-package.ts b/packages/tools/oxc/src/oxlint/rules/no-import-from-barrel-package.ts new file mode 100644 index 0000000..ab337ad --- /dev/null +++ b/packages/tools/oxc/src/oxlint/rules/no-import-from-barrel-package.ts @@ -0,0 +1,144 @@ +import * as fs from "node:fs" +import * as path from "node:path" +import type { CreateRule, ESTree, Visitor } from "oxlint" + +interface RuleOptions { + checkPatterns?: Array + checkRelativeIndexImports?: boolean +} + +const extensions = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"] + +function getModuleName(specifier: ESTree.ImportSpecifier): string { + return specifier.imported.type === "Identifier" + ? specifier.imported.name + : specifier.imported.value +} + +function isRelativeImport(source: string): boolean { + return source.startsWith("./") || source.startsWith("../") +} + +function hasIndexFile(dirPath: string): boolean { + for (const ext of extensions) { + if (fs.existsSync(path.join(dirPath, `index${ext}`))) { + return true + } + } + return false +} + +function isIndexImport(importPath: string): boolean { + const basename = path.basename(importPath) + return basename === "index" || /^index\.(ts|tsx|js|jsx|mts|cts|mjs|cjs)$/.test(basename) +} + +function resolvesToBarrel(importSource: string, currentFile: string): boolean { + const dir = path.dirname(currentFile) + const resolved = path.resolve(dir, importSource) + + if (isIndexImport(importSource)) { + return true + } + + if (hasIndexFile(resolved)) { + return true + } + + return false +} + +function createBarrelMatcher(options: RuleOptions): (source: string, currentFile: string) => boolean { + const patterns = (options.checkPatterns ?? []).map((p) => new RegExp(p)) + const checkRelative = options.checkRelativeIndexImports !== false + + return (source: string, currentFile: string): boolean => { + if (isRelativeImport(source)) { + return checkRelative && resolvesToBarrel(source, currentFile) + } + + for (const pattern of patterns) { + if (pattern.test(source)) { + return true + } + } + + return false + } +} + +const rule: CreateRule = { + meta: { + type: "suggestion", + docs: { + description: "Disallow importing from barrel files (index.ts), encourage importing specific modules instead" + }, + schema: [ + { + type: "object", + properties: { + checkPatterns: { + type: "array", + items: { type: "string" }, + description: "Regex patterns to match barrel imports" + }, + checkRelativeIndexImports: { + type: "boolean", + description: "Whether to check relative imports that resolve to index files" + } + }, + additionalProperties: false + } + ] + }, + create(context) { + const currentFile = context.filename + const options: RuleOptions = (context.options[0] as RuleOptions) ?? {} + const isBarrelImport = createBarrelMatcher(options) + + return { + ImportDeclaration(node: ESTree.ImportDeclaration) { + if (node.importKind === "type") return + + const importSource = node.source.value + + if (!isBarrelImport(importSource, currentFile)) return + + const namespaceSpecifiers: Array = [] + const namedValueSpecifiers: Array = [] + + for (const specifier of node.specifiers) { + if (specifier.type === "ImportNamespaceSpecifier") { + namespaceSpecifiers.push(specifier) + } else if (specifier.type === "ImportSpecifier") { + if (specifier.importKind !== "type") { + namedValueSpecifiers.push(specifier) + } + } + } + + for (const specifier of namespaceSpecifiers) { + context.report({ + node: specifier, + message: + `Do not use namespace import from barrel file "${importSource}", import from specific modules instead` + }) + } + + for (const specifier of namedValueSpecifiers) { + const moduleName = getModuleName(specifier) + const localName = specifier.local.name + const message = isRelativeImport(importSource) + ? `Do not import "${moduleName}" from barrel file "${importSource}", import from specific module instead` + : `Use import * as ${localName} from "${importSource}/${moduleName}" instead` + context.report({ + node: specifier, + message + }) + } + } + } as Visitor + } +} + +export default rule diff --git a/packages/tools/oxc/src/oxlint/rules/no-js-extension-imports.ts b/packages/tools/oxc/src/oxlint/rules/no-js-extension-imports.ts new file mode 100644 index 0000000..f095513 --- /dev/null +++ b/packages/tools/oxc/src/oxlint/rules/no-js-extension-imports.ts @@ -0,0 +1,73 @@ +import type { CreateRule, ESTree, Fixer, Visitor } from "oxlint" + +const jsExtensions = [".js", ".jsx", ".mjs", ".cjs"] +const extensionMap: Record = { + ".js": ".ts", + ".jsx": ".tsx", + ".mjs": ".mts", + ".cjs": ".cts" +} + +function isRelativeImport(source: string): boolean { + return source.startsWith("./") || source.startsWith("../") +} + +function getJsExtension(source: string): string | undefined { + for (const ext of jsExtensions) { + if (source.endsWith(ext)) { + return ext + } + } + return undefined +} + +const rule: CreateRule = { + meta: { + type: "problem", + docs: { + description: + "Disallow .js, .jsx, .mjs and .cjs extensions in relative imports, use .ts, .tsx, .mts or .cts instead" + }, + fixable: "code" + }, + create(context) { + function checkSource(source: ESTree.StringLiteral) { + const value = source.value + if (!isRelativeImport(value)) return + + const ext = getJsExtension(value) + if (!ext) return + + const tsExt = extensionMap[ext] + const fixedSource = value.slice(0, -ext.length) + tsExt + + context.report({ + node: source, + message: `Use "${tsExt}" extension instead of "${ext}" for relative imports`, + fix: (fixer: Fixer) => fixer.replaceTextRange(source.range, `"${fixedSource}"`) + }) + } + + function handleImportDeclaration(node: ESTree.ImportDeclaration) { + checkSource(node.source) + } + + function handleExportAllDeclaration(node: ESTree.ExportAllDeclaration) { + checkSource(node.source) + } + + function handleExportNamedDeclaration(node: ESTree.ExportNamedDeclaration) { + if (node.source) { + checkSource(node.source) + } + } + + return { + ImportDeclaration: handleImportDeclaration, + ExportAllDeclaration: handleExportAllDeclaration, + ExportNamedDeclaration: handleExportNamedDeclaration + } as Visitor + } +} + +export default rule diff --git a/packages/tools/oxc/src/oxlint/rules/no-opaque-instance-fields.ts b/packages/tools/oxc/src/oxlint/rules/no-opaque-instance-fields.ts new file mode 100644 index 0000000..d4985d1 --- /dev/null +++ b/packages/tools/oxc/src/oxlint/rules/no-opaque-instance-fields.ts @@ -0,0 +1,92 @@ +import type { CreateRule, ESTree, Visitor } from "oxlint" + +const SCHEMA_SOURCES = new Set(["effect", "effect/Schema"]) +const SCHEMA_NAMESPACE_SOURCES = new Set(["effect/Schema"]) + +const rule: CreateRule = { + meta: { + type: "problem", + docs: { description: "Disallow instance members in Schema.Opaque classes" } + }, + create(context) { + // Track identifiers that point to Schema or Opaque imported from Schema. + // Local names that refer to the Schema module (Schema or namespace import). + // Example: `import { Schema } from "effect"` or `import * as S from "effect/Schema"`. + const schemaIdentifiers = new Set() + // Local names that refer to Opaque imported directly from the Schema module. + // Example: `import { Opaque as MyOpaque } from "effect/Schema"`. + const opaqueIdentifiers = new Set() + + // Match `class X extends Schema.Opaque(...)` or `class X extends Opaque(...)` when + // the identifiers are tied to the Schema module via imports. + function isSchemaOpaqueExtension(node: ESTree.Class): boolean { + const sc = node.superClass + if (!sc || sc.type !== "CallExpression") return false + const inner = sc.callee + if (!inner || inner.type !== "CallExpression") return false + return isOpaqueCallee(inner.callee) + } + + // Validate the outer `Opaque` call, allowing either `Opaque` or `.Opaque`. + function isOpaqueCallee(node: ESTree.Expression | null | undefined): boolean { + if (!node) return false + if (node.type === "Identifier") return opaqueIdentifiers.has(node.name) + if (node.type !== "MemberExpression") return false + if (node.property?.type !== "Identifier" || node.property.name !== "Opaque") return false + return isSchemaObject(node.object) + } + + // Ensure `.Opaque` is actually Schema (imported from Schema module). + function isSchemaObject(node: ESTree.Expression | null | undefined): boolean { + if (!node) return false + if (node.type === "Identifier") return schemaIdentifiers.has(node.name) + return false + } + + function checkClass(node: ESTree.Class) { + if (!isSchemaOpaqueExtension(node)) return + for (const element of node.body.body) { + if (element.type === "PropertyDefinition" && !element.static) { + context.report({ + node: element, + message: "Classes extending Schema.Opaque must not have instance members" + }) + } else if (element.type === "MethodDefinition" && !element.static) { + context.report({ + node: element, + message: "Classes extending Schema.Opaque must not have instance members" + }) + } + } + } + + return { + // Record identifiers for Schema/Opaque imports so we don't match unrelated modules. + ImportDeclaration(node: ESTree.ImportDeclaration) { + if (node.importKind === "type") return + const source = node.source.value + if (typeof source !== "string" || !SCHEMA_SOURCES.has(source)) return + + for (const specifier of node.specifiers) { + if (specifier.type === "ImportNamespaceSpecifier") { + if (SCHEMA_NAMESPACE_SOURCES.has(source)) { + schemaIdentifiers.add(specifier.local.name) + } + } else if (specifier.type === "ImportSpecifier" && specifier.importKind !== "type") { + if (specifier.imported.type !== "Identifier") continue + const importedName = specifier.imported.name + if (importedName === "Schema") { + schemaIdentifiers.add(specifier.local.name) + } else if (importedName === "Opaque") { + opaqueIdentifiers.add(specifier.local.name) + } + } + } + }, + ClassDeclaration: checkClass, + ClassExpression: checkClass + } as Visitor + } +} + +export default rule diff --git a/packages/tools/oxc/test/no-import-from-barrel-package.test.ts b/packages/tools/oxc/test/no-import-from-barrel-package.test.ts new file mode 100644 index 0000000..9d95a7d --- /dev/null +++ b/packages/tools/oxc/test/no-import-from-barrel-package.test.ts @@ -0,0 +1,182 @@ +import rule from "@amp/oxc/oxlint/rules/no-import-from-barrel-package" +import { describe, expect, it } from "vitest" +import { runRule } from "./utils.ts" + +describe("no-import-from-barrel-package", () => { + const testOptions = { + filename: "/test/file.ts", + cwd: "/test", + ruleOptions: [{ checkPatterns: ["^effect$"] }] + } + + const createImportDeclaration = ( + source: string, + specifiers: Array, + importKind?: "type" | "value" + ) => { + const base = { + type: "ImportDeclaration" as const, + source: { value: source }, + specifiers, + range: [0, 50] as [number, number] + } + return importKind !== undefined ? { ...base, importKind } : base + } + + const createNamedSpecifier = ( + name: string, + local?: string, + importKind?: "type" | "value" + ) => { + const base = { + type: "ImportSpecifier" as const, + imported: { type: "Identifier" as const, name }, + local: { name: local ?? name } + } + return importKind !== undefined ? { ...base, importKind } : base + } + + it("should not report for imports from non-barrel packages", () => { + const node = createImportDeclaration("effect/Effect", [ + createNamedSpecifier("Effect") + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(0) + }) + + it("should report for named imports from effect barrel", () => { + const node = createImportDeclaration("effect", [ + createNamedSpecifier("Effect") + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe( + `Use import * as Effect from "effect/Effect" instead` + ) + }) + + it("should report for multiple named imports from effect barrel", () => { + const node = createImportDeclaration("effect", [ + createNamedSpecifier("Effect"), + createNamedSpecifier("Option"), + createNamedSpecifier("Either") + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(3) + }) + + it("should not report for type-only import declarations", () => { + const node = createImportDeclaration( + "effect", + [createNamedSpecifier("Effect")], + "type" + ) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(0) + }) + + it("should not report for type imports within named specifiers", () => { + const node = createImportDeclaration("effect", [ + createNamedSpecifier("Effect", "Effect", "type") + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(0) + }) + + it("should handle aliased imports", () => { + const node = createImportDeclaration("effect", [ + createNamedSpecifier("Effect", "Eff") + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe( + `Use import * as Eff from "effect/Effect" instead` + ) + }) + + it("should report for namespace imports from barrel", () => { + const node = createImportDeclaration("effect", [ + { + type: "ImportNamespaceSpecifier", + local: { name: "Effect" } + } + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe( + `Do not use namespace import from barrel file "effect", import from specific modules instead` + ) + }) + + it("should not report for namespace imports from module paths", () => { + const node = createImportDeclaration("effect/Effect", [ + { + type: "ImportNamespaceSpecifier", + local: { name: "Effect" } + } + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(0) + }) + + it("should not report for default imports", () => { + const node = createImportDeclaration("effect", [ + { + type: "ImportDefaultSpecifier", + local: { name: "Effect" } + } + ]) + const errors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(errors).toHaveLength(0) + }) + + describe("configuration", () => { + it("should match regex patterns", () => { + const node = createImportDeclaration("@myorg/utils", [ + createNamedSpecifier("helper") + ]) + // No patterns configured - doesn't match + const defaultErrors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(defaultErrors).toHaveLength(0) + + // Pattern matches @myorg/* + const customErrors = runRule(rule, "ImportDeclaration", node, { + ...testOptions, + ruleOptions: [{ checkPatterns: ["^@myorg/"] }] + }) + expect(customErrors).toHaveLength(1) + }) + + it("should match exact package with pattern", () => { + const node = createImportDeclaration("lodash", [ + createNamedSpecifier("map") + ]) + // No patterns - doesn't match + const defaultErrors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(defaultErrors).toHaveLength(0) + + // Exact match pattern + const customErrors = runRule(rule, "ImportDeclaration", node, { + ...testOptions, + ruleOptions: [{ checkPatterns: ["^lodash$"] }] + }) + expect(customErrors).toHaveLength(1) + }) + + it("should disable relative index checking when configured", () => { + const node = createImportDeclaration("./index.ts", [ + createNamedSpecifier("foo") + ]) + // Default checks relative imports + const defaultErrors = runRule(rule, "ImportDeclaration", node, testOptions) + expect(defaultErrors).toHaveLength(1) + + // Disabled relative checking + const customErrors = runRule(rule, "ImportDeclaration", node, { + ...testOptions, + ruleOptions: [{ checkRelativeIndexImports: false }] + }) + expect(customErrors).toHaveLength(0) + }) + }) +}) diff --git a/packages/tools/oxc/test/no-js-extension-imports.test.ts b/packages/tools/oxc/test/no-js-extension-imports.test.ts new file mode 100644 index 0000000..eb74970 --- /dev/null +++ b/packages/tools/oxc/test/no-js-extension-imports.test.ts @@ -0,0 +1,120 @@ +import rule from "@amp/oxc/oxlint/rules/no-js-extension-imports" +import { describe, expect, it } from "vitest" +import { runRule } from "./utils.ts" + +describe("no-js-extension-imports", () => { + const createImportDeclaration = (source: string) => ({ + type: "ImportDeclaration", + source: { value: source, range: [8, 8 + source.length + 2] as [number, number] }, + range: [0, 50] as [number, number] + }) + + const createExportAllDeclaration = (source: string) => ({ + type: "ExportAllDeclaration", + source: { value: source, range: [14, 14 + source.length + 2] as [number, number] }, + range: [0, 50] as [number, number] + }) + + const createExportNamedDeclaration = (source: string) => ({ + type: "ExportNamedDeclaration", + source: { value: source, range: [9, 9 + source.length + 2] as [number, number] }, + range: [0, 50] as [number, number] + }) + + describe("ImportDeclaration", () => { + it("should report .js extension in relative imports", () => { + const node = createImportDeclaration("./foo.js") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".ts" extension instead of ".js" for relative imports`) + }) + + it("should report .jsx extension in relative imports", () => { + const node = createImportDeclaration("./component.jsx") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".tsx" extension instead of ".jsx" for relative imports`) + }) + + it("should report .mjs extension in relative imports", () => { + const node = createImportDeclaration("../utils.mjs") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".mts" extension instead of ".mjs" for relative imports`) + }) + + it("should report .cjs extension in relative imports", () => { + const node = createImportDeclaration("./config.cjs") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".cts" extension instead of ".cjs" for relative imports`) + }) + + it("should not report .ts extension in relative imports", () => { + const node = createImportDeclaration("./foo.ts") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should not report .tsx extension in relative imports", () => { + const node = createImportDeclaration("./component.tsx") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should not report for package imports with .js extension", () => { + const node = createImportDeclaration("some-package/utils.js") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should not report for bare package imports", () => { + const node = createImportDeclaration("effect") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should handle deeply nested relative imports", () => { + const node = createImportDeclaration("../../lib/utils.js") + const errors = runRule(rule, "ImportDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".ts" extension instead of ".js" for relative imports`) + }) + }) + + describe("ExportAllDeclaration", () => { + it("should report .js extension in relative re-exports", () => { + const node = createExportAllDeclaration("./foo.js") + const errors = runRule(rule, "ExportAllDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".ts" extension instead of ".js" for relative imports`) + }) + + it("should not report .ts extension in relative re-exports", () => { + const node = createExportAllDeclaration("./foo.ts") + const errors = runRule(rule, "ExportAllDeclaration", node) + expect(errors).toHaveLength(0) + }) + }) + + describe("ExportNamedDeclaration", () => { + it("should report .js extension in relative named exports", () => { + const node = createExportNamedDeclaration("./foo.js") + const errors = runRule(rule, "ExportNamedDeclaration", node) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe(`Use ".ts" extension instead of ".js" for relative imports`) + }) + + it("should not report .ts extension in relative named exports", () => { + const node = createExportNamedDeclaration("./foo.ts") + const errors = runRule(rule, "ExportNamedDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should handle export without source", () => { + const node = { type: "ExportNamedDeclaration", source: null } + const errors = runRule(rule, "ExportNamedDeclaration", node) + expect(errors).toHaveLength(0) + }) + }) +}) diff --git a/packages/tools/oxc/test/no-opaque-instance-fields.test.ts b/packages/tools/oxc/test/no-opaque-instance-fields.test.ts new file mode 100644 index 0000000..11ad864 --- /dev/null +++ b/packages/tools/oxc/test/no-opaque-instance-fields.test.ts @@ -0,0 +1,276 @@ +import rule from "@amp/oxc/oxlint/rules/no-opaque-instance-fields" +import { describe, expect, it } from "vitest" +import { createTestContext, runRule } from "./utils.ts" + +function runRuleWithNodes(nodes: Array<{ visitor: string; node: unknown }>) { + const { context, errors } = createTestContext() + const visitors = rule.create(context as never) + for (const { visitor, node } of nodes) { + const handler = visitors[visitor as keyof typeof visitors] + if (handler) { + ;(handler as (node: unknown) => void)(node) + } + } + return errors +} + +describe("no-opaque-instance-fields", () => { + const createOpaqueClass = ( + callee: { type: string; name?: string; object?: unknown; property?: unknown }, + members: Array<{ type: string; static: boolean }> + ) => ({ + type: "ClassDeclaration", + superClass: { + type: "CallExpression", + callee: { + type: "CallExpression", + callee + } + }, + body: { + body: members + } + }) + + const createSchemaOpaqueClass = (members: Array<{ type: string; static: boolean }>) => + createOpaqueClass({ + type: "MemberExpression", + object: { type: "Identifier", name: "Schema" }, + property: { type: "Identifier", name: "Opaque" } + }, members) + + const createSchemaImport = () => ({ + type: "ImportDeclaration", + source: { type: "Literal", value: "effect" }, + specifiers: [{ + type: "ImportSpecifier", + imported: { type: "Identifier", name: "Schema" }, + local: { type: "Identifier", name: "Schema" }, + importKind: "value" + }], + importKind: "value" + }) + + const createOpaqueImport = (localName = "Opaque") => ({ + type: "ImportDeclaration", + source: { type: "Literal", value: "effect/Schema" }, + specifiers: [{ + type: "ImportSpecifier", + imported: { type: "Identifier", name: "Opaque" }, + local: { type: "Identifier", name: localName }, + importKind: "value" + }], + importKind: "value" + }) + + const createSchemaNamespaceImport = (localName = "S") => ({ + type: "ImportDeclaration", + source: { type: "Literal", value: "effect/Schema" }, + specifiers: [{ + type: "ImportNamespaceSpecifier", + local: { type: "Identifier", name: localName } + }], + importKind: "value" + }) + + const createOtherOpaqueImport = (localName = "Opaque") => ({ + type: "ImportDeclaration", + source: { type: "Literal", value: "other" }, + specifiers: [{ + type: "ImportSpecifier", + imported: { type: "Identifier", name: "Opaque" }, + local: { type: "Identifier", name: localName }, + importKind: "value" + }], + importKind: "value" + }) + + const createOtherNamespaceImport = (localName = "S") => ({ + type: "ImportDeclaration", + source: { type: "Literal", value: "other" }, + specifiers: [{ + type: "ImportNamespaceSpecifier", + local: { type: "Identifier", name: localName } + }], + importKind: "value" + }) + + const createRegularClass = (members: Array<{ type: string; static: boolean }>) => ({ + type: "ClassDeclaration", + superClass: { + type: "Identifier", + name: "SomeClass" + }, + body: { + body: members + } + }) + + it("should not report for class without instance fields", () => { + const node = createSchemaOpaqueClass([]) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(0) + }) + + it("should not report for static fields in Schema.Opaque class", () => { + const node = createSchemaOpaqueClass([ + { type: "PropertyDefinition", static: true } + ]) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(0) + }) + + it("should report for instance fields in Schema.Opaque class", () => { + const node = createSchemaOpaqueClass([ + { type: "PropertyDefinition", static: false } + ]) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(1) + expect(errors[0].message).toBe("Classes extending Schema.Opaque must not have instance members") + }) + + it("should not report when Schema.Opaque has no Schema import", () => { + const node = createSchemaOpaqueClass([ + { type: "PropertyDefinition", static: false } + ]) + const errors = runRule(rule, "ClassDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should report for instance fields in Opaque class", () => { + const node = createOpaqueClass( + { type: "Identifier", name: "Opaque" }, + [{ type: "PropertyDefinition", static: false }] + ) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createOpaqueImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(1) + }) + + it("should report for instance fields in aliased Opaque class", () => { + const node = createOpaqueClass( + { + type: "MemberExpression", + object: { type: "Identifier", name: "S" }, + property: { type: "Identifier", name: "Opaque" } + }, + [{ type: "PropertyDefinition", static: false }] + ) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaNamespaceImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(1) + }) + + it("should not report for Opaque import from other module", () => { + const node = createOpaqueClass( + { type: "Identifier", name: "Opaque" }, + [{ type: "PropertyDefinition", static: false }] + ) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createOtherOpaqueImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(0) + }) + + it("should not report for namespace Opaque from other module", () => { + const node = createOpaqueClass( + { + type: "MemberExpression", + object: { type: "Identifier", name: "S" }, + property: { type: "Identifier", name: "Opaque" } + }, + [{ type: "PropertyDefinition", static: false }] + ) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createOtherNamespaceImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(0) + }) + + it("should report for multiple instance fields", () => { + const node = createSchemaOpaqueClass([ + { type: "PropertyDefinition", static: false }, + { type: "PropertyDefinition", static: true }, + { type: "PropertyDefinition", static: false } + ]) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(2) + }) + + it("should report for instance methods", () => { + const node = createSchemaOpaqueClass([ + { type: "MethodDefinition", static: false } + ]) + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaImport() }, + { visitor: "ClassDeclaration", node } + ]) + expect(errors).toHaveLength(1) + }) + + it("should not report for non-Schema.Opaque classes", () => { + const node = createRegularClass([ + { type: "PropertyDefinition", static: false } + ]) + const errors = runRule(rule, "ClassDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should work with ClassExpression", () => { + const node = { + ...createSchemaOpaqueClass([ + { type: "PropertyDefinition", static: false } + ]), + type: "ClassExpression" + } + const errors = runRuleWithNodes([ + { visitor: "ImportDeclaration", node: createSchemaImport() }, + { visitor: "ClassExpression", node } + ]) + expect(errors).toHaveLength(1) + }) + + it("should not report for class without superClass", () => { + const node = { + type: "ClassDeclaration", + body: { + body: [{ type: "PropertyDefinition", static: false }] + } + } + const errors = runRule(rule, "ClassDeclaration", node) + expect(errors).toHaveLength(0) + }) + + it("should not report for class with non-CallExpression superClass", () => { + const node = { + type: "ClassDeclaration", + superClass: { + type: "Identifier", + name: "BaseClass" + }, + body: { + body: [{ type: "PropertyDefinition", static: false }] + } + } + const errors = runRule(rule, "ClassDeclaration", node) + expect(errors).toHaveLength(0) + }) +}) diff --git a/packages/tools/oxc/test/utils.ts b/packages/tools/oxc/test/utils.ts new file mode 100644 index 0000000..51d5ac4 --- /dev/null +++ b/packages/tools/oxc/test/utils.ts @@ -0,0 +1,56 @@ +import type { CreateRule, Visitor } from "oxlint" + +export interface ReportedError { + node: unknown + message: string +} + +export interface TestContextOptions { + sourceCode?: string + filename?: string + cwd?: string + ruleOptions?: Array +} + +export const createTestContext = (options: TestContextOptions = {}) => { + const { + sourceCode = "", + filename = "/test/file.ts", + cwd = "/test", + ruleOptions = [] + } = options + + const errors: Array = [] + const context = { + id: "test/rule", + filename, + physicalFilename: filename, + options: ruleOptions, + getFilename: () => filename, + getCwd: () => cwd, + report(reportOptions: ReportedError) { + errors.push(reportOptions) + }, + sourceCode: { + getText(_node?: unknown) { + return sourceCode + } + } + } + return { errors, context } +} + +export const runRule = ( + rule: CreateRule, + visitor: keyof Visitor, + node: unknown, + options: TestContextOptions = {} +): Array => { + const { context, errors } = createTestContext(options) + const visitors = rule.create(context as never) + const handler = visitors[visitor] + if (handler) { + ;(handler as (node: unknown) => void)(node) + } + return errors +} diff --git a/packages/tools/oxc/tsconfig.build.json b/packages/tools/oxc/tsconfig.build.json new file mode 100644 index 0000000..02c325c --- /dev/null +++ b/packages/tools/oxc/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "./tsconfig.src.json", + "compilerOptions": { + "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo", + "outDir": "dist", + "types": ["node"], + "stripInternal": true + } +} diff --git a/packages/tools/oxc/tsconfig.json b/packages/tools/oxc/tsconfig.json new file mode 100644 index 0000000..9f86127 --- /dev/null +++ b/packages/tools/oxc/tsconfig.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "../../../tsconfig.base.json", + "include": [], + "references": [ + { "path": "tsconfig.src.json" }, + { "path": "tsconfig.test.json" } + ] +} diff --git a/packages/tools/oxc/tsconfig.src.json b/packages/tools/oxc/tsconfig.src.json new file mode 100644 index 0000000..93f47f8 --- /dev/null +++ b/packages/tools/oxc/tsconfig.src.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "../../../tsconfig.base.json", + "include": ["src"], + "compilerOptions": { + "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo", + "outDir": ".tsbuildinfo/src", + "types": ["node"], + "rootDir": "src" + } +} diff --git a/packages/tools/oxc/tsconfig.test.json b/packages/tools/oxc/tsconfig.test.json new file mode 100644 index 0000000..cb626a7 --- /dev/null +++ b/packages/tools/oxc/tsconfig.test.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json.schemastore.org/tsconfig", + "extends": "../../../tsconfig.base.json", + "include": ["test"], + "references": [{ "path": "tsconfig.src.json" }], + "compilerOptions": { + "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo", + "outDir": ".tsbuildinfo/test", + "rootDir": "test", + "paths": { + // TODO: Ideally we avoid setting *any* path aliases. + "@amp/oxc": ["./src/index.ts"], + "@amp/oxc/*": ["./src/*/index.ts", "./src/*.ts"] + }, + "types": ["node"] + } +} diff --git a/packages/tools/oxc/vitest.config.ts b/packages/tools/oxc/vitest.config.ts new file mode 100644 index 0000000..c8a52c1 --- /dev/null +++ b/packages/tools/oxc/vitest.config.ts @@ -0,0 +1,6 @@ +import { mergeConfig, type ViteUserConfig } from "vitest/config" +import shared from "../../../vitest.shared.ts" + +const config: ViteUserConfig = {} + +export default mergeConfig(shared, config) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95437e9..828b6a4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,9 @@ importers: .: devDependencies: - '@effect/eslint-plugin': - specifier: ^0.3.2 - version: 0.3.2 + '@amp/oxc': + specifier: workspace:^ + version: link:packages/tools/oxc '@effect/language-service': specifier: ^0.62.4 version: 0.62.4 @@ -20,9 +20,6 @@ importers: '@effect/vitest': specifier: ^0.27.0 version: 0.27.0(effect@3.19.13)(vitest@4.0.16) - '@eslint/js': - specifier: ^9.39.2 - version: 9.39.2 '@types/node': specifier: ^25.0.3 version: 25.0.3 @@ -32,33 +29,21 @@ importers: '@vitest/ui': specifier: ^4.0.16 version: 4.0.16(vitest@4.0.16) + dprint: + specifier: ^0.51.1 + version: 0.51.1 effect: specifier: ^3.19.13 version: 3.19.13 - eslint: - specifier: ^9.39.2 - version: 9.39.2 - eslint-import-resolver-typescript: - specifier: ^4.4.4 - version: 4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2))(eslint@9.39.2) - eslint-plugin-import-x: - specifier: ^4.16.1 - version: 4.16.1(@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) - eslint-plugin-simple-import-sort: - specifier: ^12.1.1 - version: 12.1.1(eslint@9.39.2) - eslint-plugin-sort-destructure-keys: - specifier: ^2.0.0 - version: 2.0.0(eslint@9.39.2) - eslint-plugin-unused-imports: - specifier: ^4.3.0 - version: 4.3.0(@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) glob: specifier: ^13.0.0 version: 13.0.0 globals: specifier: ^16.5.0 version: 16.5.0 + oxlint: + specifier: ^1.38.0 + version: 1.38.0 ts-patch: specifier: ^3.3.0 version: 3.3.0 @@ -106,6 +91,15 @@ importers: specifier: ^3.19.13 version: 3.19.13 + packages/tools/oxc: + devDependencies: + '@types/node': + specifier: ^25.0.2 + version: 25.0.3 + vitest: + specifier: ^4.0.0 + version: 4.0.16(@types/node@25.0.3)(@vitest/ui@4.0.16) + scratchpad: dependencies: '@edgeandnode/amp': @@ -213,11 +207,60 @@ packages: peerDependencies: '@bufbuild/protobuf': ^2.7.0 - '@dprint/formatter@0.4.1': - resolution: {integrity: sha512-IB/GXdlMOvi0UhQQ9mcY15Fxcrc2JPadmo6tqefCNV0bptFq7YBpggzpqYXldBXDa04CbKJ+rDwO2eNRPE2+/g==} + '@dprint/darwin-arm64@0.51.1': + resolution: {integrity: sha512-C7fkaz0/NGf/X4G9Cq65izdJgerND5jWShOaPiOgGs4A0CyCMKMLRd45m3xKIttuO8x0IQiZVixD22qmVglXmQ==} + cpu: [arm64] + os: [darwin] + + '@dprint/darwin-x64@0.51.1': + resolution: {integrity: sha512-/CESb4SJejshTWb/nO2gucrioKdLD/fK2gKB5Immi4XecAjhkV1HZpUMRLsIeVDQ6ha7xktKbnnvudJRI0maSg==} + cpu: [x64] + os: [darwin] + + '@dprint/linux-arm64-glibc@0.51.1': + resolution: {integrity: sha512-W+QD/4TkQKMPq02uz+ZIz/EI91YEtS2zHBu/Jihx2lfNh3HjUKgyY1KfqCTg2WGJVDkJtPc5KDw+M8yd4rI+Rg==} + cpu: [arm64] + os: [linux] + + '@dprint/linux-arm64-musl@0.51.1': + resolution: {integrity: sha512-P4Cfn8wrdSvdoMoz0HtsC5zZpbh8Kk3OjRzgG4qs/gub5Ba3CCLcVaQvQmIOCvgPzdhPB41eSn5qAK87mh7vCQ==} + cpu: [arm64] + os: [linux] + + '@dprint/linux-loong64-glibc@0.51.1': + resolution: {integrity: sha512-dxDShELBrSGB9PktRqhYrm1UWCL+7N430rGuDTFg+i4d1wL4JD7EI5NDS/5IVbg3lrKJUu6gAJoY9NWF4sZ0mQ==} + cpu: [loong64] + os: [linux] + + '@dprint/linux-loong64-musl@0.51.1': + resolution: {integrity: sha512-l+uNPzUBNxkywGN1HgvTV0CzUDpzXC+s6VEvjYRdVAEKl9TAsIfLMfZifS8rnlOi9hz/0sckmpny+wL40G6dhQ==} + cpu: [loong64] + os: [linux] + + '@dprint/linux-riscv64-glibc@0.51.1': + resolution: {integrity: sha512-YI6SemJRMsLUrtognhkAYOJ67j/AkiufHfx6+cPv/7qO6zBoBL6otR1e5yFYvAgEJOzRZD5g51EdqCcuK19B+g==} + cpu: [riscv64] + os: [linux] + + '@dprint/linux-x64-glibc@0.51.1': + resolution: {integrity: sha512-Hm9ntOWeclXU6/rZGYIN2XjuAhsRUZ77lRJC5EiM1rP6Ayh0J/YMsDdqlPAs+xZGdFFzt8ZeUpqJJJsbc54ZjQ==} + cpu: [x64] + os: [linux] + + '@dprint/linux-x64-musl@0.51.1': + resolution: {integrity: sha512-iUs/9Z4Ky6+2GAK+i1jF1ZwM27CSIGaqw3LxTXtmE8eBCRwyCW+opzn9bzaFtlT9REUAGMC5PXihAPmzP3ttWg==} + cpu: [x64] + os: [linux] + + '@dprint/win32-arm64@0.51.1': + resolution: {integrity: sha512-oXjEL7Blf/160/j7U8MapRzSOVQvLIdAKEZbslIHA4Fwj10fvoDizqpfVU/aVj/BVrlIcZ/+AH8kfSC9XAyjLw==} + cpu: [arm64] + os: [win32] - '@dprint/typescript@0.91.8': - resolution: {integrity: sha512-tuKn4leCPItox1O4uunHcQF0QllDCvPWklnNQIh2PiWWVtRAGltJJnM4Cwj5AciplosD1Hiz7vAY3ew3crLb3A==} + '@dprint/win32-x64@0.51.1': + resolution: {integrity: sha512-RM9thb/+Jm6GkXJS+eW+0Pzmz2PNeDk8ZOWcjunE1jv2RabHgm+GbeGpS+WZPOM9W3LSntswv6f4wjzfUkWD0g==} + cpu: [x64] + os: [win32] '@effect/cluster@0.56.0': resolution: {integrity: sha512-ovhsC8jQkgoHkelpGL/EQtoQsPXG9hj7DHVc7A9Vyzptd/DaCP+W1aQKlJrJoe2W+KI/CjrYN8H89M5xiL6FBg==} @@ -228,9 +271,6 @@ packages: '@effect/workflow': ^0.16.0 effect: ^3.19.13 - '@effect/eslint-plugin@0.3.2': - resolution: {integrity: sha512-c4Vs9t3r54A4Zpl+wo8+PGzZz3JWYsip41H+UrebRLjQ2Hk/ap63IeCgN/HWcYtxtyhRopjp7gW9nOQ2Snbl+g==} - '@effect/experimental@0.58.0': resolution: {integrity: sha512-IEP9sapjF6rFy5TkoqDPc86st/fnqUfjT7Xa3pWJrFGr1hzaMXHo+mWsYOZS9LAOVKnpHuVziDK97EP5qsCHVA==} peerDependencies: @@ -298,15 +338,6 @@ packages: '@effect/rpc': ^0.73.0 effect: ^3.19.13 - '@emnapi/core@1.7.1': - resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} - - '@emnapi/runtime@1.7.1': - resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} - - '@emnapi/wasi-threads@1.1.0': - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@esbuild/aix-ppc64@0.27.2': resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} engines: {node: '>=18'} @@ -565,9 +596,6 @@ packages: cpu: [x64] os: [win32] - '@napi-rs/wasm-runtime@0.2.12': - resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} - '@noble/ciphers@1.3.0': resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} engines: {node: ^14.21.3 || >=16} @@ -580,6 +608,46 @@ packages: resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} + '@oxlint/darwin-arm64@1.38.0': + resolution: {integrity: sha512-9rN3047QTyA4i73FKikDUBdczRcLtOsIwZ5TsEx5Q7jr5nBjolhYQOFQf9QdhBLdInxw1iX4+lgdMCf1g74zjg==} + cpu: [arm64] + os: [darwin] + + '@oxlint/darwin-x64@1.38.0': + resolution: {integrity: sha512-Y1UHW4KOlg5NvyrSn/bVBQP8/LRuid7Pnu+BWGbAVVsFcK0b565YgMSO3Eu9nU3w8ke91dr7NFpUmS+bVkdkbw==} + cpu: [x64] + os: [darwin] + + '@oxlint/linux-arm64-gnu@1.38.0': + resolution: {integrity: sha512-ZiVxPZizlXSnAMdkEFWX/mAj7U3bNiku8p6I9UgLrXzgGSSAhFobx8CaFGwVoKyWOd+gQgZ/ogCrunvx2k0CFg==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-arm64-musl@1.38.0': + resolution: {integrity: sha512-ELtlCIGZ72A65ATZZHFxHMFrkRtY+DYDCKiNKg6v7u5PdeOFey+OlqRXgXtXlxWjCL+g7nivwI2FPVsWqf05Qw==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-x64-gnu@1.38.0': + resolution: {integrity: sha512-E1OcDh30qyng1m0EIlsOuapYkqk5QB6o6IMBjvDKqIoo6IrjlVAasoJfS/CmSH998gXRL3BcAJa6Qg9IxPFZnQ==} + cpu: [x64] + os: [linux] + + '@oxlint/linux-x64-musl@1.38.0': + resolution: {integrity: sha512-4AfpbM/4sQnr6S1dMijEPfsq4stQbN5vJ2jsahSy/QTcvIVbFkgY+RIhrA5UWlC6eb0rD5CdaPQoKGMJGeXpYw==} + cpu: [x64] + os: [linux] + + '@oxlint/win32-arm64@1.38.0': + resolution: {integrity: sha512-OvUVYdI68OwXh3d1RjH9N/okCxb6PrOGtEtzXyqGA7Gk+IxyZcX0/QCTBwV8FNbSSzDePSSEHOKpoIB+VXdtvg==} + cpu: [arm64] + os: [win32] + + '@oxlint/win32-x64@1.38.0': + resolution: {integrity: sha512-7IuZMYiZiOcgg5zHvpJY6jRlEwh8EB/uq7GsoQJO9hANq96TIjyntGByhIjFSsL4asyZmhTEki+MO/u5Fb/WQA==} + cpu: [x64] + os: [win32] + '@parcel/watcher-android-arm64@2.5.1': resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} engines: {node: '>= 10.0.0'} @@ -787,9 +855,6 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@types/body-parser@1.19.6': resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} @@ -876,10 +941,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.48.0': - resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.50.0': resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -906,101 +967,6 @@ packages: peerDependencies: typescript: '*' - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} - cpu: [arm] - os: [android] - - '@unrs/resolver-binding-android-arm64@1.11.1': - resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} - cpu: [arm64] - os: [android] - - '@unrs/resolver-binding-darwin-arm64@1.11.1': - resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} - cpu: [arm64] - os: [darwin] - - '@unrs/resolver-binding-darwin-x64@1.11.1': - resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} - cpu: [x64] - os: [darwin] - - '@unrs/resolver-binding-freebsd-x64@1.11.1': - resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} - cpu: [x64] - os: [freebsd] - - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} - cpu: [arm] - os: [linux] - - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} - cpu: [arm] - os: [linux] - - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} - cpu: [arm64] - os: [linux] - - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} - cpu: [arm64] - os: [linux] - - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} - cpu: [ppc64] - os: [linux] - - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} - cpu: [riscv64] - os: [linux] - - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} - cpu: [riscv64] - os: [linux] - - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} - cpu: [s390x] - os: [linux] - - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} - cpu: [x64] - os: [linux] - - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} - cpu: [x64] - os: [linux] - - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} - cpu: [arm64] - os: [win32] - - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} - cpu: [ia32] - os: [win32] - - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} - cpu: [x64] - os: [win32] - '@vitest/coverage-v8@4.0.16': resolution: {integrity: sha512-2rNdjEIsPRzsdu6/9Eq0AYAzYdpP6Bx9cje9tL3FE5XzXRQF1fNU9pe/1yE8fCrS0HD+fBtt6gLPh6LI57tX7A==} peerDependencies: @@ -1118,10 +1084,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - comment-parser@1.4.1: - resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} - engines: {node: '>= 12.0.0'} - concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1150,6 +1112,10 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} + dprint@0.51.1: + resolution: {integrity: sha512-CEx+wYARxLAe9o7RCZ77GKae6DF7qjn5Rd98xbWdA3hB4PFBr+kHwLANmNHscNumBAIrCg5ZJj/Kz+OYbJ+GBA==} + hasBin: true + effect@3.19.13: resolution: {integrity: sha512-8MZ783YuHRwHZX2Mmm+bpGxq+7XPd88sWwYAz2Ysry80sEKpftDZXs2Hg9ZyjESi1IBTNHF0oDKe0zJRkUlyew==} @@ -1165,61 +1131,6 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-import-context@0.1.9: - resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - peerDependencies: - unrs-resolver: ^1.0.0 - peerDependenciesMeta: - unrs-resolver: - optional: true - - eslint-import-resolver-typescript@4.4.4: - resolution: {integrity: sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==} - engines: {node: ^16.17.0 || >=18.6.0} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - eslint-plugin-import-x: '*' - peerDependenciesMeta: - eslint-plugin-import: - optional: true - eslint-plugin-import-x: - optional: true - - eslint-plugin-import-x@4.16.1: - resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/utils': ^8.0.0 - eslint: ^8.57.0 || ^9.0.0 - eslint-import-resolver-node: '*' - peerDependenciesMeta: - '@typescript-eslint/utils': - optional: true - eslint-import-resolver-node: - optional: true - - eslint-plugin-simple-import-sort@12.1.1: - resolution: {integrity: sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==} - peerDependencies: - eslint: '>=5.0.0' - - eslint-plugin-sort-destructure-keys@2.0.0: - resolution: {integrity: sha512-4w1UQCa3o/YdfWaLr9jY8LfGowwjwjmwClyFLxIsToiyIdZMq3x9Ti44nDn34DtTPP7PWg96tUONKVmATKhYGQ==} - engines: {node: '>=12'} - peerDependencies: - eslint: 5 - 9 - - eslint-plugin-unused-imports@4.3.0: - resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 - eslint: ^9.0.0 || ^8.0.0 - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - eslint-scope@8.4.0: resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1279,9 +1190,6 @@ packages: fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -1330,9 +1238,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - get-tsconfig@4.13.0: - resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -1387,9 +1292,6 @@ packages: resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - is-bun-module@2.0.0: - resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} - is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} @@ -1534,14 +1436,6 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - napi-postinstall@0.3.4: - resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - hasBin: true - - natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -1567,6 +1461,16 @@ packages: typescript: optional: true + oxlint@1.38.0: + resolution: {integrity: sha512-XT7tBinQS+hVLxtfJOnokJ9qVBiQvZqng40tDgR6qEJMRMnpVq/JwYfbYyGntSq8MO+Y+N9M1NG4bAMFUtCJiw==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.10.0' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -1616,10 +1520,6 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1631,9 +1531,6 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -1668,10 +1565,6 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - stable-hash-x@0.2.0: - resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} - engines: {node: '>=12.0.0'} - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -1737,9 +1630,6 @@ packages: typescript: optional: true - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -1768,9 +1658,6 @@ packages: resolution: {integrity: sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==} engines: {node: '>=20.18.1'} - unrs-resolver@1.11.1: - resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1983,9 +1870,38 @@ snapshots: dependencies: '@bufbuild/protobuf': 2.10.2 - '@dprint/formatter@0.4.1': {} + '@dprint/darwin-arm64@0.51.1': + optional: true + + '@dprint/darwin-x64@0.51.1': + optional: true + + '@dprint/linux-arm64-glibc@0.51.1': + optional: true + + '@dprint/linux-arm64-musl@0.51.1': + optional: true + + '@dprint/linux-loong64-glibc@0.51.1': + optional: true + + '@dprint/linux-loong64-musl@0.51.1': + optional: true + + '@dprint/linux-riscv64-glibc@0.51.1': + optional: true + + '@dprint/linux-x64-glibc@0.51.1': + optional: true + + '@dprint/linux-x64-musl@0.51.1': + optional: true + + '@dprint/win32-arm64@0.51.1': + optional: true - '@dprint/typescript@0.91.8': {} + '@dprint/win32-x64@0.51.1': + optional: true '@effect/cluster@0.56.0(@effect/platform@0.94.0(effect@3.19.13))(@effect/rpc@0.73.0(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13))(@effect/sql@0.49.0(@effect/experimental@0.58.0(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13))(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13))(@effect/workflow@0.16.0(@effect/experimental@0.58.0(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13))(@effect/platform@0.94.0(effect@3.19.13))(@effect/rpc@0.73.0(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13))(effect@3.19.13))(effect@3.19.13)': dependencies: @@ -1996,12 +1912,6 @@ snapshots: effect: 3.19.13 kubernetes-types: 1.30.0 - '@effect/eslint-plugin@0.3.2': - dependencies: - '@dprint/formatter': 0.4.1 - '@dprint/typescript': 0.91.8 - prettier-linter-helpers: 1.0.0 - '@effect/experimental@0.58.0(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13)': dependencies: '@effect/platform': 0.94.0(effect@3.19.13) @@ -2071,22 +1981,6 @@ snapshots: '@effect/rpc': 0.73.0(@effect/platform@0.94.0(effect@3.19.13))(effect@3.19.13) effect: 3.19.13 - '@emnapi/core@1.7.1': - dependencies: - '@emnapi/wasi-threads': 1.1.0 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@1.7.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.1.0': - dependencies: - tslib: 2.8.1 - optional: true - '@esbuild/aix-ppc64@0.27.2': optional: true @@ -2255,13 +2149,6 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': optional: true - '@napi-rs/wasm-runtime@0.2.12': - dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 - '@tybys/wasm-util': 0.10.1 - optional: true - '@noble/ciphers@1.3.0': {} '@noble/curves@1.9.1': @@ -2270,6 +2157,30 @@ snapshots: '@noble/hashes@1.8.0': {} + '@oxlint/darwin-arm64@1.38.0': + optional: true + + '@oxlint/darwin-x64@1.38.0': + optional: true + + '@oxlint/linux-arm64-gnu@1.38.0': + optional: true + + '@oxlint/linux-arm64-musl@1.38.0': + optional: true + + '@oxlint/linux-x64-gnu@1.38.0': + optional: true + + '@oxlint/linux-x64-musl@1.38.0': + optional: true + + '@oxlint/win32-arm64@1.38.0': + optional: true + + '@oxlint/win32-x64@1.38.0': + optional: true + '@parcel/watcher-android-arm64@2.5.1': optional: true @@ -2413,11 +2324,6 @@ snapshots: '@standard-schema/spec@1.1.0': {} - '@tybys/wasm-util@0.10.1': - dependencies: - tslib: 2.8.1 - optional: true - '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 @@ -2537,8 +2443,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.48.0': {} - '@typescript-eslint/types@8.50.0': {} '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': @@ -2579,65 +2483,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - optional: true - - '@unrs/resolver-binding-android-arm64@1.11.1': - optional: true - - '@unrs/resolver-binding-darwin-arm64@1.11.1': - optional: true - - '@unrs/resolver-binding-darwin-x64@1.11.1': - optional: true - - '@unrs/resolver-binding-freebsd-x64@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - optional: true - - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - optional: true - - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - dependencies: - '@napi-rs/wasm-runtime': 0.2.12 - optional: true - - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - optional: true - - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - optional: true - - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - optional: true - '@vitest/coverage-v8@4.0.16(vitest@4.0.16)': dependencies: '@bcoe/v8-coverage': 1.0.2 @@ -2768,8 +2613,6 @@ snapshots: color-name@1.1.4: {} - comment-parser@1.4.1: {} - concat-map@0.0.1: {} cross-spawn@7.0.6: @@ -2789,6 +2632,20 @@ snapshots: detect-libc@2.1.2: optional: true + dprint@0.51.1: + optionalDependencies: + '@dprint/darwin-arm64': 0.51.1 + '@dprint/darwin-x64': 0.51.1 + '@dprint/linux-arm64-glibc': 0.51.1 + '@dprint/linux-arm64-musl': 0.51.1 + '@dprint/linux-loong64-glibc': 0.51.1 + '@dprint/linux-loong64-musl': 0.51.1 + '@dprint/linux-riscv64-glibc': 0.51.1 + '@dprint/linux-x64-glibc': 0.51.1 + '@dprint/linux-x64-musl': 0.51.1 + '@dprint/win32-arm64': 0.51.1 + '@dprint/win32-x64': 0.51.1 + effect@3.19.13: dependencies: '@standard-schema/spec': 1.1.0 @@ -2827,60 +2684,6 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-import-context@0.1.9(unrs-resolver@1.11.1): - dependencies: - get-tsconfig: 4.13.0 - stable-hash-x: 0.2.0 - optionalDependencies: - unrs-resolver: 1.11.1 - - eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2))(eslint@9.39.2): - dependencies: - debug: 4.4.3 - eslint: 9.39.2 - eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - get-tsconfig: 4.13.0 - is-bun-module: 2.0.0 - stable-hash-x: 0.2.0 - tinyglobby: 0.2.15 - unrs-resolver: 1.11.1 - optionalDependencies: - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2) - transitivePeerDependencies: - - supports-color - - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): - dependencies: - '@typescript-eslint/types': 8.48.0 - comment-parser: 1.4.1 - debug: 4.4.3 - eslint: 9.39.2 - eslint-import-context: 0.1.9(unrs-resolver@1.11.1) - is-glob: 4.0.3 - minimatch: 10.1.1 - semver: 7.7.3 - stable-hash-x: 0.2.0 - unrs-resolver: 1.11.1 - optionalDependencies: - '@typescript-eslint/utils': 8.50.0(eslint@9.39.2)(typescript@5.9.3) - transitivePeerDependencies: - - supports-color - - eslint-plugin-simple-import-sort@12.1.1(eslint@9.39.2): - dependencies: - eslint: 9.39.2 - - eslint-plugin-sort-destructure-keys@2.0.0(eslint@9.39.2): - dependencies: - eslint: 9.39.2 - natural-compare-lite: 1.4.0 - - eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2): - dependencies: - eslint: 9.39.2 - optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2)(typescript@5.9.3) - eslint-scope@8.4.0: dependencies: esrecurse: 4.3.0 @@ -2961,8 +2764,6 @@ snapshots: fast-deep-equal@3.1.3: {} - fast-diff@1.3.0: {} - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} @@ -3000,10 +2801,6 @@ snapshots: function-bind@1.1.2: {} - get-tsconfig@4.13.0: - dependencies: - resolve-pkg-maps: 1.0.0 - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -3047,10 +2844,6 @@ snapshots: ini@4.1.3: {} - is-bun-module@2.0.0: - dependencies: - semver: 7.7.3 - is-core-module@2.16.1: dependencies: hasown: 2.0.2 @@ -3186,10 +2979,6 @@ snapshots: nanoid@3.3.11: {} - napi-postinstall@0.3.4: {} - - natural-compare-lite@1.4.0: {} - natural-compare@1.4.0: {} node-addon-api@7.1.1: {} @@ -3225,6 +3014,17 @@ snapshots: transitivePeerDependencies: - zod + oxlint@1.38.0: + optionalDependencies: + '@oxlint/darwin-arm64': 1.38.0 + '@oxlint/darwin-x64': 1.38.0 + '@oxlint/linux-arm64-gnu': 1.38.0 + '@oxlint/linux-arm64-musl': 1.38.0 + '@oxlint/linux-x64-gnu': 1.38.0 + '@oxlint/linux-x64-musl': 1.38.0 + '@oxlint/win32-arm64': 1.38.0 + '@oxlint/win32-x64': 1.38.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 @@ -3264,18 +3064,12 @@ snapshots: prelude-ls@1.2.1: {} - prettier-linter-helpers@1.0.0: - dependencies: - fast-diff: 1.3.0 - punycode@2.3.1: {} pure-rand@6.1.0: {} resolve-from@4.0.0: {} - resolve-pkg-maps@1.0.0: {} - resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -3328,8 +3122,6 @@ snapshots: source-map-js@1.2.1: {} - stable-hash-x@0.2.0: {} - stackback@0.0.2: {} std-env@3.10.0: {} @@ -3380,9 +3172,6 @@ snapshots: optionalDependencies: typescript: 5.9.3 - tslib@2.8.1: - optional: true - type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -3406,30 +3195,6 @@ snapshots: undici@7.16.0: {} - unrs-resolver@1.11.1: - dependencies: - napi-postinstall: 0.3.4 - optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.11.1 - '@unrs/resolver-binding-android-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-x64': 1.11.1 - '@unrs/resolver-binding-freebsd-x64': 1.11.1 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 - '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-musl': 1.11.1 - '@unrs/resolver-binding-wasm32-wasi': 1.11.1 - '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 - '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 - '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - uri-js@4.4.1: dependencies: punycode: 2.3.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2e86197..28ba6c2 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,5 @@ packages: - scratchpad + - scripts - packages/* + - packages/tools/* diff --git a/scratchpad/index.ts b/scratchpad/index.ts index 336ce12..a7fbab4 100644 --- a/scratchpad/index.ts +++ b/scratchpad/index.ts @@ -1 +1,2 @@ +// oxlint-disable-next-line eslint-plugin-unicorn(require-module-specifiers) export {} diff --git a/scratchpad/tsconfig.json b/scratchpad/tsconfig.json index 8eae6e8..7ef50c2 100644 --- a/scratchpad/tsconfig.json +++ b/scratchpad/tsconfig.json @@ -1,9 +1,7 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "../tsconfig.base.jsonc", - "include": [ - "**/*.ts" - ], + "extends": "../tsconfig.base.json", + "include": ["**/*.ts"], "compilerOptions": { "noEmit": true, "declaration": false, diff --git a/tsconfig.base.jsonc b/tsconfig.base.json similarity index 87% rename from tsconfig.base.jsonc rename to tsconfig.base.json index f924861..dfae800 100644 --- a/tsconfig.base.jsonc +++ b/tsconfig.base.json @@ -8,7 +8,6 @@ "target": "ES2022", "module": "NodeNext", "moduleDetection": "force", // Treat every non-declaration file as a module. - "esModuleInterop": false, // Do not fiddle with import/export statements "verbatimModuleSyntax": true, // Only transform/eliminate type-only import/export statements. "allowJs": false, // If you touch this, a puppy dies. "rewriteRelativeImportExtensions": true, // Rewrite `.ts` imports to `.js` at build time. @@ -30,7 +29,10 @@ { "name": "@effect/language-service", "transform": "@effect/language-service/transform", - "namespaceImportPackages": ["effect", "@effect/*"] + "namespaceImportPackages": ["effect", "@effect/*"], + "diagnosticSeverity": { + "globalErrorInEffectFailure": "off" // TODO: Check if we should fix the warnings this reports + } } ] } diff --git a/tsconfig.build.json b/tsconfig.build.json index 540bdfc..5551018 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,10 +1,7 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "./tsconfig.base.jsonc", + "extends": "./tsconfig.base.json", "include": [], - "compilerOptions": { - "stripInternal": true - }, "references": [ { "path": "packages/amp/tsconfig.build.json" } ] diff --git a/tsconfig.json b/tsconfig.json index 80a019a..84ab3b1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,10 @@ { "$schema": "http://json.schemastore.org/tsconfig", - "extends": "./tsconfig.base.jsonc", - "include": [], + "extends": "./tsconfig.base.json", + "include": ["*.ts"], + "compilerOptions": { + "noEmit": true + }, "references": [ { "path": "packages/amp" } ] diff --git a/vitest.config.ts b/vitest.config.ts index fda3ed1..363918a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,6 +3,9 @@ import { defineConfig } from "vitest/config" export default defineConfig({ test: { globals: true, - projects: ["packages/*/vitest.config.ts"] + projects: [ + "packages/*/vitest.config.ts", + "packages/tools/*/vitest.config.ts" + ] } }) diff --git a/vitest.setup.ts b/vitest.setup.ts index f12d839..9658eb4 100644 --- a/vitest.setup.ts +++ b/vitest.setup.ts @@ -1,21 +1,4 @@ +// oxlint-disable-next-line effect/no-import-from-barrel-package import { addEqualityTesters } from "@effect/vitest" addEqualityTesters() - -// Ignore warnings from usage of experimental features to declutter test output. -const ignore = ["ExperimentalWarning"] -const emitWarning = process.emitWarning -process.emitWarning = (warning, ...args) => { - const [head] = args - if (head != null) { - if (typeof head === "string" && ignore.includes(head)) { - return - } - - if (typeof head === "object" && ignore.includes(head.type)) { - return - } - } - - return emitWarning(warning, ...args) -} diff --git a/vitest.shared.ts b/vitest.shared.ts index 479b6c4..768549f 100644 --- a/vitest.shared.ts +++ b/vitest.shared.ts @@ -1,12 +1,13 @@ import * as path from "node:path" -import viteTsconfigPaths from "vite-tsconfig-paths" import type { ViteUserConfig } from "vitest/config" const config: ViteUserConfig = { - plugins: [viteTsconfigPaths()], esbuild: { target: "es2020" }, + optimizeDeps: { + exclude: ["bun:sqlite"] + }, test: { setupFiles: [path.join(__dirname, "vitest.setup.ts")], fakeTimers: { @@ -15,7 +16,7 @@ const config: ViteUserConfig = { sequence: { concurrent: true }, - include: ["test/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], + include: ["test/**/*.test.ts"], coverage: { provider: "v8", reporter: ["html"],