corsa-oxlint 0.50.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/context.d.ts +2 -2
- package/dist/context.js +9 -9
- package/dist/context.js.map +1 -1
- package/dist/plugin.d.ts +6 -1
- package/dist/plugin.js +14 -9
- package/dist/plugin.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,6 +24,30 @@ The design goal is simple: performance-critical pieces live in Rust, `napi-rs`
|
|
|
24
24
|
bridges them into Node, and end users still get to author custom plugins and
|
|
25
25
|
custom rules in plain JS/TS.
|
|
26
26
|
|
|
27
|
+
## Plugin-Owned Runtime Resolution
|
|
28
|
+
|
|
29
|
+
If a plugin ships its own `@typescript/native-preview` dependency, pass a
|
|
30
|
+
module anchor to `definePlugin()` so `corsa-oxlint` can resolve that runtime
|
|
31
|
+
even when package managers like pnpm do not hoist it to the consumer root.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { definePlugin } from "corsa-oxlint";
|
|
35
|
+
|
|
36
|
+
export default definePlugin({
|
|
37
|
+
meta: {
|
|
38
|
+
name: "example-plugin",
|
|
39
|
+
},
|
|
40
|
+
resolveFrom: import.meta.url,
|
|
41
|
+
rules: {
|
|
42
|
+
// ...
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Consumer overrides still win. `CORSA_EXECUTABLE`,
|
|
48
|
+
`parserOptions.corsa.executable`, and `settings.corsaOxlint` continue to take
|
|
49
|
+
priority over the plugin anchor.
|
|
50
|
+
|
|
27
51
|
## Configuration
|
|
28
52
|
|
|
29
53
|
Oxlint does not expose arbitrary parser options at runtime, so
|
package/dist/context.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ContextWithParserOptions, ResolvedProjectConfig, TypeAwareParserOptions } from "./types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/bindings/nodejs/corsa_oxlint/ts/context.d.ts
|
|
4
|
-
declare function defaultCorsaExecutable(rootDir: string, platform?: NodeJS.Platform): string;
|
|
4
|
+
declare function defaultCorsaExecutable(rootDir: string, platform?: NodeJS.Platform, resolveFrom?: string): string;
|
|
5
5
|
declare function resolveProjectConfig(context: ContextWithParserOptions): ResolvedProjectConfig;
|
|
6
6
|
/**
|
|
7
7
|
* Resolves the type-aware parser options visible to a rule.
|
|
@@ -17,7 +17,7 @@ declare function resolveProjectConfig(context: ContextWithParserOptions): Resolv
|
|
|
17
17
|
* parserOptions.corsa?.mode;
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
|
-
declare function resolveTypeAwareParserOptions(context: ContextWithParserOptions, defaults?: TypeAwareParserOptionDefaults): TypeAwareParserOptions;
|
|
20
|
+
declare function resolveTypeAwareParserOptions(context: ContextWithParserOptions, defaults?: TypeAwareParserOptionDefaults, resolveFrom?: string): TypeAwareParserOptions;
|
|
21
21
|
type TypeAwareParserOptionDefaults = {
|
|
22
22
|
readonly corsa?: boolean;
|
|
23
23
|
readonly projectService?: boolean;
|
package/dist/context.js
CHANGED
|
@@ -14,12 +14,12 @@ const DEFAULT_TS_CONFIG = { compilerOptions: {
|
|
|
14
14
|
target: "es2022",
|
|
15
15
|
strict: true
|
|
16
16
|
} };
|
|
17
|
-
function defaultCorsaExecutable(rootDir, platform = process.platform) {
|
|
18
|
-
const nativePreview =
|
|
17
|
+
function defaultCorsaExecutable(rootDir, platform = process.platform, resolveFrom) {
|
|
18
|
+
const nativePreview = resolveNativePreviewExecutableFrom(resolve(rootDir, "package.json")) ?? (resolveFrom ? resolveNativePreviewExecutableFrom(resolveFrom) : void 0);
|
|
19
19
|
if (nativePreview) return nativePreview;
|
|
20
20
|
const fallback = resolve(rootDir, platform === "win32" ? ".cache/corsa.exe" : ".cache/corsa");
|
|
21
21
|
if (existsSync(fallback)) return fallback;
|
|
22
|
-
throw new Error(["corsa-oxlint could not locate a Corsa runtime executable.", "Install `@typescript/native-preview`, set `CORSA_EXECUTABLE`,
|
|
22
|
+
throw new Error(["corsa-oxlint could not locate a Corsa runtime executable.", "Install `@typescript/native-preview`, set `CORSA_EXECUTABLE`, configure `parserOptions.corsa.executable`, or pass `resolveFrom` to `definePlugin`."].join(" "));
|
|
23
23
|
}
|
|
24
24
|
function resolveProjectConfig(context) {
|
|
25
25
|
const filename = resolve(context.filename);
|
|
@@ -49,9 +49,9 @@ function resolveProjectConfig(context) {
|
|
|
49
49
|
* parserOptions.corsa?.mode;
|
|
50
50
|
* ```
|
|
51
51
|
*/
|
|
52
|
-
function resolveTypeAwareParserOptions(context, defaults = {}) {
|
|
52
|
+
function resolveTypeAwareParserOptions(context, defaults = {}, resolveFrom) {
|
|
53
53
|
const parserOptions = mergeTypeAwareParserOptions(resolveSettingsParserOptions(context.settings?.corsaOxlint), mergeTypeAwareParserOptions(context.parserOptions, context.languageOptions?.parserOptions));
|
|
54
|
-
return applyTypeAwareParserOptionDefaults(parserOptions, defaults, resolve(parserOptions.tsconfigRootDir ?? context.cwd));
|
|
54
|
+
return applyTypeAwareParserOptionDefaults(parserOptions, defaults, resolve(parserOptions.tsconfigRootDir ?? context.cwd), resolveFrom);
|
|
55
55
|
}
|
|
56
56
|
function resolveRuntimeOptions(rootDir, parserOptions) {
|
|
57
57
|
const runtime = parserOptions.corsa;
|
|
@@ -104,8 +104,8 @@ function globMatch(value, pattern) {
|
|
|
104
104
|
function asArray(value) {
|
|
105
105
|
return value ? Array.isArray(value) ? value : [value] : [];
|
|
106
106
|
}
|
|
107
|
-
function
|
|
108
|
-
const requireFromRoot = createRequire(
|
|
107
|
+
function resolveNativePreviewExecutableFrom(anchor) {
|
|
108
|
+
const requireFromRoot = createRequire(anchor);
|
|
109
109
|
const packageJsonPath = resolveOptional(requireFromRoot, "@typescript/native-preview/package.json");
|
|
110
110
|
if (packageJsonPath) {
|
|
111
111
|
const binPath = nativePreviewBinPath(packageJsonPath);
|
|
@@ -135,13 +135,13 @@ function resolveSettingsParserOptions(settings) {
|
|
|
135
135
|
const { parserOptions, ...inline } = settings;
|
|
136
136
|
return mergeTypeAwareParserOptions(inline, parserOptions);
|
|
137
137
|
}
|
|
138
|
-
function applyTypeAwareParserOptionDefaults(parserOptions, defaults, rootDir) {
|
|
138
|
+
function applyTypeAwareParserOptionDefaults(parserOptions, defaults, rootDir, resolveFrom) {
|
|
139
139
|
let resolved = parserOptions;
|
|
140
140
|
if (defaults.projectService === true && parserOptions.projectService === void 0 && parserOptions.project === void 0) resolved = {
|
|
141
141
|
...resolved,
|
|
142
142
|
projectService: true
|
|
143
143
|
};
|
|
144
|
-
if (defaults.corsa === true && resolved.corsa?.executable === void 0) resolved = mergeTypeAwareParserOptions(resolved, { corsa: { executable: process.env.CORSA_EXECUTABLE ?? defaultCorsaExecutable(rootDir) } });
|
|
144
|
+
if (defaults.corsa === true && resolved.corsa?.executable === void 0) resolved = mergeTypeAwareParserOptions(resolved, { corsa: { executable: process.env.CORSA_EXECUTABLE ?? defaultCorsaExecutable(rootDir, void 0, resolveFrom) } });
|
|
145
145
|
return resolved;
|
|
146
146
|
}
|
|
147
147
|
function mergeTypeAwareParserOptions(base, override) {
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../ts/context.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, resolve } from \"node:path\";\n\nimport type {\n ContextWithParserOptions,\n CorsaOxlintSettings,\n ProjectServiceOptions,\n ResolvedProjectConfig,\n ResolvedRuntimeOptions,\n TypeAwareParserOptions,\n} from \"./types\";\n\nconst DEFAULT_CACHE_LIFETIME_MS = 250;\nconst DEFAULT_PROJECT_PATTERNS = [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"];\nconst DEFAULT_TS_CONFIG = {\n compilerOptions: {\n module: \"esnext\",\n target: \"es2022\",\n strict: true,\n },\n};\n\nexport function defaultCorsaExecutable(rootDir: string, platform = process.platform): string {\n const nativePreview = resolveNativePreviewExecutable(rootDir);\n if (nativePreview) {\n return nativePreview;\n }\n const fallback = resolve(rootDir, platform === \"win32\" ? \".cache/corsa.exe\" : \".cache/corsa\");\n if (existsSync(fallback)) {\n return fallback;\n }\n throw new Error(\n [\n \"corsa-oxlint could not locate a Corsa runtime executable.\",\n \"Install `@typescript/native-preview`, set `CORSA_EXECUTABLE`, or configure `parserOptions.corsa.executable`.\",\n ].join(\" \"),\n );\n}\n\nexport function resolveProjectConfig(context: ContextWithParserOptions): ResolvedProjectConfig {\n const filename = resolve(context.filename);\n const parserOptions = resolveTypeAwareParserOptions(context);\n const rootDir = resolve(parserOptions.tsconfigRootDir ?? context.cwd);\n const runtime = resolveRuntimeOptions(rootDir, parserOptions);\n const configPath =\n resolveExplicitProject(rootDir, parserOptions) ??\n discoverTsconfig(filename, rootDir) ??\n resolveDefaultProject(rootDir, filename, parserOptions.projectService);\n if (!configPath) {\n throw new Error(`corsa oxlint could not resolve a tsconfig for ${filename}`);\n }\n return { filename, rootDir, configPath, runtime };\n}\n\n/**\n * Resolves the type-aware parser options visible to a rule.\n *\n * Oxlint exposes a fixed `context.languageOptions.parserOptions` object at\n * runtime, so `corsa oxlint` stores its richer configuration under\n * `settings.corsaOxlint` and rehydrates the rule-facing parser options\n * shape from there.\n *\n * @example\n * ```ts\n * const parserOptions = resolveTypeAwareParserOptions(context);\n * parserOptions.corsa?.mode;\n * ```\n */\nexport function resolveTypeAwareParserOptions(\n context: ContextWithParserOptions,\n defaults: TypeAwareParserOptionDefaults = {},\n): TypeAwareParserOptions {\n const parserOptions = mergeTypeAwareParserOptions(\n resolveSettingsParserOptions(context.settings?.corsaOxlint),\n mergeTypeAwareParserOptions(context.parserOptions, context.languageOptions?.parserOptions),\n );\n const rootDir = resolve(parserOptions.tsconfigRootDir ?? context.cwd);\n return applyTypeAwareParserOptionDefaults(parserOptions, defaults, rootDir);\n}\n\ntype TypeAwareParserOptionDefaults = {\n readonly corsa?: boolean;\n readonly projectService?: boolean;\n};\n\nfunction resolveRuntimeOptions(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): ResolvedRuntimeOptions {\n const runtime = parserOptions.corsa;\n return {\n executable: resolve(\n runtime?.executable ?? process.env.CORSA_EXECUTABLE ?? defaultCorsaExecutable(rootDir),\n ),\n cwd: resolve(runtime?.cwd ?? rootDir),\n mode: runtime?.mode ?? \"msgpack\",\n cacheLifetimeMs: runtime?.cacheLifetimeMs ?? DEFAULT_CACHE_LIFETIME_MS,\n };\n}\n\nfunction resolveExplicitProject(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): string | undefined {\n const projects = asArray(parserOptions.project).map((project) => {\n return resolve(rootDir, project);\n });\n return projects.find(existsSync);\n}\n\nfunction discoverTsconfig(filename: string, rootDir: string): string | undefined {\n let current = dirname(filename);\n const boundary = resolve(rootDir);\n while (current.startsWith(boundary)) {\n const candidate = resolve(current, \"tsconfig.json\");\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n return undefined;\n}\n\nfunction resolveDefaultProject(\n rootDir: string,\n filename: string,\n projectService: boolean | ProjectServiceOptions | undefined,\n): string | undefined {\n if (!projectService) {\n return undefined;\n }\n if (projectService !== true && projectService.defaultProject) {\n return resolve(rootDir, projectService.defaultProject);\n }\n if (!matchesDefaultProject(filename, projectService as true | ProjectServiceOptions)) {\n return undefined;\n }\n const id = Buffer.from(filename).toString(\"hex\").slice(0, 24);\n const cacheDir = resolve(rootDir, \".cache/corsa_oxlint/default\");\n const configPath = resolve(cacheDir, `${id}.tsconfig.json`);\n if (!existsSync(configPath)) {\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(\n configPath,\n JSON.stringify(\n {\n ...DEFAULT_TS_CONFIG,\n files: [filename],\n },\n null,\n 2,\n ),\n );\n }\n return configPath;\n}\n\nfunction matchesDefaultProject(\n filename: string,\n projectService: true | ProjectServiceOptions,\n): boolean {\n const patterns =\n (projectService === true ? undefined : projectService.allowDefaultProject) ??\n DEFAULT_PROJECT_PATTERNS;\n return patterns.some((pattern: string) => globMatch(filename, pattern));\n}\n\nfunction globMatch(value: string, pattern: string): boolean {\n const escaped = pattern.replaceAll(\".\", \"\\\\.\").replaceAll(\"*\", \".*\");\n return new RegExp(`${escaped}$`).test(value);\n}\n\nfunction asArray(value: string | string[] | undefined): string[] {\n return value ? (Array.isArray(value) ? value : [value]) : [];\n}\n\nfunction resolveNativePreviewExecutable(rootDir: string): string | undefined {\n const requireFromRoot = createRequire(resolve(rootDir, \"package.json\"));\n const packageJsonPath = resolveOptional(\n requireFromRoot,\n \"@typescript/native-preview/package.json\",\n );\n if (packageJsonPath) {\n const binPath = nativePreviewBinPath(packageJsonPath);\n if (binPath && existsSync(binPath)) {\n return binPath;\n }\n }\n const packageEntry = resolveOptional(requireFromRoot, \"@typescript/native-preview\");\n return packageEntry && existsSync(packageEntry) ? packageEntry : undefined;\n}\n\nfunction resolveOptional(requireFromRoot: NodeJS.Require, specifier: string): string | undefined {\n try {\n return requireFromRoot.resolve(specifier);\n } catch {\n return undefined;\n }\n}\n\nfunction nativePreviewBinPath(packageJsonPath: string): string | undefined {\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n readonly bin?: string | Record<string, string>;\n };\n const bin =\n typeof packageJson.bin === \"string\"\n ? packageJson.bin\n : (packageJson.bin?.tsgo ?? Object.values(packageJson.bin ?? {})[0]);\n return bin ? resolve(dirname(packageJsonPath), bin) : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveSettingsParserOptions(\n settings: CorsaOxlintSettings | undefined,\n): TypeAwareParserOptions {\n if (!settings) {\n return {};\n }\n const { parserOptions, ...inline } = settings;\n return mergeTypeAwareParserOptions(inline, parserOptions);\n}\n\nfunction applyTypeAwareParserOptionDefaults(\n parserOptions: TypeAwareParserOptions,\n defaults: TypeAwareParserOptionDefaults,\n rootDir: string,\n): TypeAwareParserOptions {\n let resolved = parserOptions;\n if (\n defaults.projectService === true &&\n parserOptions.projectService === undefined &&\n parserOptions.project === undefined\n ) {\n resolved = {\n ...resolved,\n projectService: true,\n };\n }\n if (defaults.corsa === true && resolved.corsa?.executable === undefined) {\n resolved = mergeTypeAwareParserOptions(resolved, {\n corsa: {\n executable: process.env.CORSA_EXECUTABLE ?? defaultCorsaExecutable(rootDir),\n },\n });\n }\n return resolved;\n}\n\nexport function mergeTypeAwareParserOptions(\n base: TypeAwareParserOptions | undefined,\n override: TypeAwareParserOptions | undefined,\n): TypeAwareParserOptions {\n if (!base) {\n return normalizeTypeAwareParserOptions(override ?? {});\n }\n if (!override) {\n return normalizeTypeAwareParserOptions(base);\n }\n const runtime = {\n ...base.corsa,\n ...override.corsa,\n };\n return {\n ...base,\n ...override,\n project: override.project ?? base.project,\n projectService: mergeProjectService(base.projectService, override.projectService),\n tsconfigRootDir: override.tsconfigRootDir ?? base.tsconfigRootDir,\n ...(Object.keys(runtime).length > 0 ? { corsa: runtime } : {}),\n };\n}\n\nfunction normalizeTypeAwareParserOptions(options: TypeAwareParserOptions): TypeAwareParserOptions {\n const runtime = options.corsa;\n if (!runtime) {\n return options;\n }\n return {\n ...options,\n corsa: runtime,\n };\n}\n\nfunction mergeProjectService(\n base: boolean | ProjectServiceOptions | undefined,\n override: boolean | ProjectServiceOptions | undefined,\n): boolean | ProjectServiceOptions | undefined {\n if (override === undefined) {\n return base;\n }\n if (typeof override === \"boolean\") {\n return override;\n }\n if (base === undefined || typeof base === \"boolean\") {\n return override;\n }\n return {\n ...base,\n ...override,\n allowDefaultProject: override.allowDefaultProject ?? base.allowDefaultProject,\n defaultProject: override.defaultProject ?? base.defaultProject,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../ts/context.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, resolve } from \"node:path\";\n\nimport type {\n ContextWithParserOptions,\n CorsaOxlintSettings,\n ProjectServiceOptions,\n ResolvedProjectConfig,\n ResolvedRuntimeOptions,\n TypeAwareParserOptions,\n} from \"./types\";\n\nconst DEFAULT_CACHE_LIFETIME_MS = 250;\nconst DEFAULT_PROJECT_PATTERNS = [\"*.ts\", \"*.tsx\", \"*.js\", \"*.jsx\"];\nconst DEFAULT_TS_CONFIG = {\n compilerOptions: {\n module: \"esnext\",\n target: \"es2022\",\n strict: true,\n },\n};\n\nexport function defaultCorsaExecutable(\n rootDir: string,\n platform = process.platform,\n resolveFrom?: string,\n): string {\n const nativePreview =\n resolveNativePreviewExecutableFrom(resolve(rootDir, \"package.json\")) ??\n (resolveFrom ? resolveNativePreviewExecutableFrom(resolveFrom) : undefined);\n if (nativePreview) {\n return nativePreview;\n }\n const fallback = resolve(rootDir, platform === \"win32\" ? \".cache/corsa.exe\" : \".cache/corsa\");\n if (existsSync(fallback)) {\n return fallback;\n }\n throw new Error(\n [\n \"corsa-oxlint could not locate a Corsa runtime executable.\",\n \"Install `@typescript/native-preview`, set `CORSA_EXECUTABLE`, configure `parserOptions.corsa.executable`, or pass `resolveFrom` to `definePlugin`.\",\n ].join(\" \"),\n );\n}\n\nexport function resolveProjectConfig(context: ContextWithParserOptions): ResolvedProjectConfig {\n const filename = resolve(context.filename);\n const parserOptions = resolveTypeAwareParserOptions(context);\n const rootDir = resolve(parserOptions.tsconfigRootDir ?? context.cwd);\n const runtime = resolveRuntimeOptions(rootDir, parserOptions);\n const configPath =\n resolveExplicitProject(rootDir, parserOptions) ??\n discoverTsconfig(filename, rootDir) ??\n resolveDefaultProject(rootDir, filename, parserOptions.projectService);\n if (!configPath) {\n throw new Error(`corsa oxlint could not resolve a tsconfig for ${filename}`);\n }\n return { filename, rootDir, configPath, runtime };\n}\n\n/**\n * Resolves the type-aware parser options visible to a rule.\n *\n * Oxlint exposes a fixed `context.languageOptions.parserOptions` object at\n * runtime, so `corsa oxlint` stores its richer configuration under\n * `settings.corsaOxlint` and rehydrates the rule-facing parser options\n * shape from there.\n *\n * @example\n * ```ts\n * const parserOptions = resolveTypeAwareParserOptions(context);\n * parserOptions.corsa?.mode;\n * ```\n */\nexport function resolveTypeAwareParserOptions(\n context: ContextWithParserOptions,\n defaults: TypeAwareParserOptionDefaults = {},\n resolveFrom?: string,\n): TypeAwareParserOptions {\n const parserOptions = mergeTypeAwareParserOptions(\n resolveSettingsParserOptions(context.settings?.corsaOxlint),\n mergeTypeAwareParserOptions(context.parserOptions, context.languageOptions?.parserOptions),\n );\n const rootDir = resolve(parserOptions.tsconfigRootDir ?? context.cwd);\n return applyTypeAwareParserOptionDefaults(parserOptions, defaults, rootDir, resolveFrom);\n}\n\ntype TypeAwareParserOptionDefaults = {\n readonly corsa?: boolean;\n readonly projectService?: boolean;\n};\n\nfunction resolveRuntimeOptions(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): ResolvedRuntimeOptions {\n const runtime = parserOptions.corsa;\n return {\n executable: resolve(\n runtime?.executable ?? process.env.CORSA_EXECUTABLE ?? defaultCorsaExecutable(rootDir),\n ),\n cwd: resolve(runtime?.cwd ?? rootDir),\n mode: runtime?.mode ?? \"msgpack\",\n cacheLifetimeMs: runtime?.cacheLifetimeMs ?? DEFAULT_CACHE_LIFETIME_MS,\n };\n}\n\nfunction resolveExplicitProject(\n rootDir: string,\n parserOptions: TypeAwareParserOptions,\n): string | undefined {\n const projects = asArray(parserOptions.project).map((project) => {\n return resolve(rootDir, project);\n });\n return projects.find(existsSync);\n}\n\nfunction discoverTsconfig(filename: string, rootDir: string): string | undefined {\n let current = dirname(filename);\n const boundary = resolve(rootDir);\n while (current.startsWith(boundary)) {\n const candidate = resolve(current, \"tsconfig.json\");\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(current);\n if (parent === current) {\n break;\n }\n current = parent;\n }\n return undefined;\n}\n\nfunction resolveDefaultProject(\n rootDir: string,\n filename: string,\n projectService: boolean | ProjectServiceOptions | undefined,\n): string | undefined {\n if (!projectService) {\n return undefined;\n }\n if (projectService !== true && projectService.defaultProject) {\n return resolve(rootDir, projectService.defaultProject);\n }\n if (!matchesDefaultProject(filename, projectService as true | ProjectServiceOptions)) {\n return undefined;\n }\n const id = Buffer.from(filename).toString(\"hex\").slice(0, 24);\n const cacheDir = resolve(rootDir, \".cache/corsa_oxlint/default\");\n const configPath = resolve(cacheDir, `${id}.tsconfig.json`);\n if (!existsSync(configPath)) {\n mkdirSync(cacheDir, { recursive: true });\n writeFileSync(\n configPath,\n JSON.stringify(\n {\n ...DEFAULT_TS_CONFIG,\n files: [filename],\n },\n null,\n 2,\n ),\n );\n }\n return configPath;\n}\n\nfunction matchesDefaultProject(\n filename: string,\n projectService: true | ProjectServiceOptions,\n): boolean {\n const patterns =\n (projectService === true ? undefined : projectService.allowDefaultProject) ??\n DEFAULT_PROJECT_PATTERNS;\n return patterns.some((pattern: string) => globMatch(filename, pattern));\n}\n\nfunction globMatch(value: string, pattern: string): boolean {\n const escaped = pattern.replaceAll(\".\", \"\\\\.\").replaceAll(\"*\", \".*\");\n return new RegExp(`${escaped}$`).test(value);\n}\n\nfunction asArray(value: string | string[] | undefined): string[] {\n return value ? (Array.isArray(value) ? value : [value]) : [];\n}\n\nfunction resolveNativePreviewExecutableFrom(anchor: string): string | undefined {\n const requireFromRoot = createRequire(anchor);\n const packageJsonPath = resolveOptional(\n requireFromRoot,\n \"@typescript/native-preview/package.json\",\n );\n if (packageJsonPath) {\n const binPath = nativePreviewBinPath(packageJsonPath);\n if (binPath && existsSync(binPath)) {\n return binPath;\n }\n }\n const packageEntry = resolveOptional(requireFromRoot, \"@typescript/native-preview\");\n return packageEntry && existsSync(packageEntry) ? packageEntry : undefined;\n}\n\nfunction resolveOptional(requireFromRoot: NodeJS.Require, specifier: string): string | undefined {\n try {\n return requireFromRoot.resolve(specifier);\n } catch {\n return undefined;\n }\n}\n\nfunction nativePreviewBinPath(packageJsonPath: string): string | undefined {\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n readonly bin?: string | Record<string, string>;\n };\n const bin =\n typeof packageJson.bin === \"string\"\n ? packageJson.bin\n : (packageJson.bin?.tsgo ?? Object.values(packageJson.bin ?? {})[0]);\n return bin ? resolve(dirname(packageJsonPath), bin) : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveSettingsParserOptions(\n settings: CorsaOxlintSettings | undefined,\n): TypeAwareParserOptions {\n if (!settings) {\n return {};\n }\n const { parserOptions, ...inline } = settings;\n return mergeTypeAwareParserOptions(inline, parserOptions);\n}\n\nfunction applyTypeAwareParserOptionDefaults(\n parserOptions: TypeAwareParserOptions,\n defaults: TypeAwareParserOptionDefaults,\n rootDir: string,\n resolveFrom?: string,\n): TypeAwareParserOptions {\n let resolved = parserOptions;\n if (\n defaults.projectService === true &&\n parserOptions.projectService === undefined &&\n parserOptions.project === undefined\n ) {\n resolved = {\n ...resolved,\n projectService: true,\n };\n }\n if (defaults.corsa === true && resolved.corsa?.executable === undefined) {\n resolved = mergeTypeAwareParserOptions(resolved, {\n corsa: {\n executable:\n process.env.CORSA_EXECUTABLE ?? defaultCorsaExecutable(rootDir, undefined, resolveFrom),\n },\n });\n }\n return resolved;\n}\n\nexport function mergeTypeAwareParserOptions(\n base: TypeAwareParserOptions | undefined,\n override: TypeAwareParserOptions | undefined,\n): TypeAwareParserOptions {\n if (!base) {\n return normalizeTypeAwareParserOptions(override ?? {});\n }\n if (!override) {\n return normalizeTypeAwareParserOptions(base);\n }\n const runtime = {\n ...base.corsa,\n ...override.corsa,\n };\n return {\n ...base,\n ...override,\n project: override.project ?? base.project,\n projectService: mergeProjectService(base.projectService, override.projectService),\n tsconfigRootDir: override.tsconfigRootDir ?? base.tsconfigRootDir,\n ...(Object.keys(runtime).length > 0 ? { corsa: runtime } : {}),\n };\n}\n\nfunction normalizeTypeAwareParserOptions(options: TypeAwareParserOptions): TypeAwareParserOptions {\n const runtime = options.corsa;\n if (!runtime) {\n return options;\n }\n return {\n ...options,\n corsa: runtime,\n };\n}\n\nfunction mergeProjectService(\n base: boolean | ProjectServiceOptions | undefined,\n override: boolean | ProjectServiceOptions | undefined,\n): boolean | ProjectServiceOptions | undefined {\n if (override === undefined) {\n return base;\n }\n if (typeof override === \"boolean\") {\n return override;\n }\n if (base === undefined || typeof base === \"boolean\") {\n return override;\n }\n return {\n ...base,\n ...override,\n allowDefaultProject: override.allowDefaultProject ?? base.allowDefaultProject,\n defaultProject: override.defaultProject ?? base.defaultProject,\n };\n}\n"],"mappings":"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"}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ import { Diagnostic, Plugin as Plugin$1, Rule as Rule$1, RuleMeta } from "@oxlin
|
|
|
5
5
|
|
|
6
6
|
//#region src/bindings/nodejs/corsa_oxlint/ts/plugin.d.ts
|
|
7
7
|
type Plugin = Omit<Plugin$1, "rules"> & {
|
|
8
|
+
/**
|
|
9
|
+
* Optional module URL or absolute path used to resolve the plugin's own
|
|
10
|
+
* runtime dependencies when they are not visible from the consumer root.
|
|
11
|
+
*/
|
|
12
|
+
readonly resolveFrom?: string;
|
|
8
13
|
readonly rules: Record<string, Rule>;
|
|
9
14
|
} & Record<string, unknown>;
|
|
10
15
|
type Rule = Rule$1 & Record<string, unknown>;
|
|
@@ -67,7 +72,7 @@ declare function definePlugin(plugin: Plugin): Plugin;
|
|
|
67
72
|
*/
|
|
68
73
|
declare function defineRule<MessageId extends string = string, const Options extends readonly unknown[] = readonly unknown[]>(rule: RuleDefinition<MessageId, Options>): Rule;
|
|
69
74
|
declare function compatPlugin(plugin: Plugin): Plugin;
|
|
70
|
-
declare function decorateRule(rule: Rule): Rule;
|
|
75
|
+
declare function decorateRule(rule: Rule, resolveFrom?: string): Rule;
|
|
71
76
|
//#endregion
|
|
72
77
|
export { Plugin, Rule, RuleContext, RuleDefinition, RuleDiagnostic, RuleDocs, RuleMetaWithMessages, Visitor, VisitorWithHooks, compatPlugin, decorateRule, definePlugin, defineRule };
|
|
73
78
|
//# sourceMappingURL=plugin.d.ts.map
|
package/dist/plugin.js
CHANGED
|
@@ -6,10 +6,15 @@ const defineOxlintPlugin = oxlintPluginApi.definePlugin;
|
|
|
6
6
|
const defineOxlintRule = oxlintPluginApi.defineRule;
|
|
7
7
|
const baseCompatPlugin = Reflect.get(oxlintPluginApi, ["es", "lintCompatPlugin"].join(""));
|
|
8
8
|
function definePlugin(plugin) {
|
|
9
|
-
|
|
9
|
+
const defined = defineOxlintPlugin({
|
|
10
10
|
...plugin,
|
|
11
|
-
rules: wrapRules(plugin.rules ?? {})
|
|
11
|
+
rules: wrapRules(plugin.rules ?? {}, plugin.resolveFrom)
|
|
12
12
|
});
|
|
13
|
+
if (plugin.resolveFrom === void 0) return defined;
|
|
14
|
+
return {
|
|
15
|
+
...defined,
|
|
16
|
+
resolveFrom: plugin.resolveFrom
|
|
17
|
+
};
|
|
13
18
|
}
|
|
14
19
|
function defineRule(rule) {
|
|
15
20
|
return defineOxlintRule(decorateRule(rule));
|
|
@@ -17,30 +22,30 @@ function defineRule(rule) {
|
|
|
17
22
|
function compatPlugin(plugin) {
|
|
18
23
|
return baseCompatPlugin(definePlugin(plugin));
|
|
19
24
|
}
|
|
20
|
-
function decorateRule(rule) {
|
|
25
|
+
function decorateRule(rule, resolveFrom) {
|
|
21
26
|
if (rule.create) return {
|
|
22
27
|
...rule,
|
|
23
28
|
create(context) {
|
|
24
|
-
return rule.create(decorateContext(context, rule));
|
|
29
|
+
return rule.create(decorateContext(context, rule, resolveFrom));
|
|
25
30
|
}
|
|
26
31
|
};
|
|
27
32
|
if ("createOnce" in rule && typeof rule.createOnce === "function") return {
|
|
28
33
|
...rule,
|
|
29
34
|
createOnce(context) {
|
|
30
|
-
return rule.createOnce(decorateContext(context, rule));
|
|
35
|
+
return rule.createOnce(decorateContext(context, rule, resolveFrom));
|
|
31
36
|
}
|
|
32
37
|
};
|
|
33
38
|
return rule;
|
|
34
39
|
}
|
|
35
|
-
function wrapRules(rules) {
|
|
36
|
-
return Object.fromEntries(Object.entries(rules).map(([name, rule]) => [name, decorateRule(rule)]));
|
|
40
|
+
function wrapRules(rules, resolveFrom) {
|
|
41
|
+
return Object.fromEntries(Object.entries(rules).map(([name, rule]) => [name, decorateRule(rule, resolveFrom)]));
|
|
37
42
|
}
|
|
38
|
-
function decorateContext(context, rule) {
|
|
43
|
+
function decorateContext(context, rule, resolveFrom) {
|
|
39
44
|
const typeAware = requiresTypeChecking(rule);
|
|
40
45
|
const parserOptions = Object.freeze(resolveTypeAwareParserOptions(context, {
|
|
41
46
|
corsa: typeAware,
|
|
42
47
|
projectService: typeAware
|
|
43
|
-
}));
|
|
48
|
+
}, resolveFrom));
|
|
44
49
|
const baseLanguageOptions = context.languageOptions;
|
|
45
50
|
const languageOptions = Object.freeze({
|
|
46
51
|
...baseLanguageOptions,
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../ts/plugin.ts"],"sourcesContent":["import * as oxlintPluginApi from \"@oxlint/plugins\";\nimport type {\n Context as OxlintContext,\n Diagnostic,\n Plugin as OxlintPlugin,\n Rule as OxlintRule,\n RuleMeta as OxlintRuleMeta,\n} from \"@oxlint/plugins\";\n\nimport { AST_NODE_TYPES } from \"./compat\";\nimport { resolveTypeAwareParserOptions } from \"./context\";\nimport type { ESTree as PublicESTree } from \"./index\";\nimport { getParserServices } from \"./parser_services\";\nimport type { ContextWithParserOptions, ParserServices } from \"./types\";\n\nexport type Plugin = Omit<OxlintPlugin, \"rules\"> & {\n readonly rules: Record<string, Rule>;\n} & Record<string, unknown>;\nexport type Rule = OxlintRule & Record<string, unknown>;\nexport type RuleDiagnostic<MessageId extends string = string> = Diagnostic & {\n readonly messageId?: MessageId | null | undefined;\n};\nexport type RuleContext<\n MessageId extends string = string,\n Options extends readonly unknown[] = readonly unknown[],\n> = Omit<ContextWithParserOptions, \"options\" | \"report\"> & {\n readonly options: Readonly<Options>;\n report(this: void, diagnostic: RuleDiagnostic<MessageId>): void;\n};\nexport type RuleDocs = {\n readonly description?: string;\n readonly recommended?: unknown;\n readonly url?: string;\n /**\n * Enables corsa-oxlint's type-aware parser service defaults for this rule.\n *\n * @default false\n */\n readonly requiresTypeChecking?: boolean;\n};\nexport type RuleMetaWithMessages<MessageId extends string = string> = Omit<\n OxlintRuleMeta,\n \"docs\" | \"messages\"\n> & {\n readonly docs?: RuleDocs;\n readonly messages?: Record<MessageId, string>;\n};\ntype CorsaAstNodeType = keyof typeof AST_NODE_TYPES;\ntype BivariantVisitorHandler<Handler extends (...args: any[]) => any> = {\n bivarianceHack(...args: Parameters<Handler>): ReturnType<Handler>;\n}[\"bivarianceHack\"];\ntype VisitorNode<Kind extends CorsaAstNodeType> = PublicESTree[Kind];\n\nexport type Visitor = {\n [Kind in CorsaAstNodeType]?: BivariantVisitorHandler<(node: VisitorNode<Kind>) => void>;\n} & {\n [Kind in CorsaAstNodeType as `${Kind}:exit`]?: BivariantVisitorHandler<\n (node: VisitorNode<Kind>) => void\n >;\n} & Record<string, BivariantVisitorHandler<(node: PublicESTree.Node) => void> | undefined>;\n\nexport type VisitorWithHooks = Visitor & {\n readonly before?: () => boolean | void;\n readonly after?: () => void;\n};\nexport type RuleDefinition<\n MessageId extends string = string,\n Options extends readonly unknown[] = readonly unknown[],\n> = Record<string, unknown> & {\n readonly defaultOptions?: Options;\n readonly meta?: RuleMetaWithMessages<MessageId>;\n} & (\n | {\n readonly create: (context: RuleContext<MessageId, Options>) => Visitor;\n readonly createOnce?: never;\n }\n | {\n readonly create?: (context: RuleContext<MessageId, Options>) => Visitor;\n readonly createOnce: (context: RuleContext<MessageId, Options>) => VisitorWithHooks;\n }\n );\n\nconst defineOxlintPlugin = oxlintPluginApi.definePlugin;\nconst defineOxlintRule = oxlintPluginApi.defineRule;\nconst baseCompatPlugin = Reflect.get(\n oxlintPluginApi as object,\n [\"es\", \"lintCompatPlugin\"].join(\"\"),\n) as typeof oxlintPluginApi.definePlugin;\n\nexport function definePlugin(plugin: Plugin): Plugin {\n
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../ts/plugin.ts"],"sourcesContent":["import * as oxlintPluginApi from \"@oxlint/plugins\";\nimport type {\n Context as OxlintContext,\n Diagnostic,\n Plugin as OxlintPlugin,\n Rule as OxlintRule,\n RuleMeta as OxlintRuleMeta,\n} from \"@oxlint/plugins\";\n\nimport { AST_NODE_TYPES } from \"./compat\";\nimport { resolveTypeAwareParserOptions } from \"./context\";\nimport type { ESTree as PublicESTree } from \"./index\";\nimport { getParserServices } from \"./parser_services\";\nimport type { ContextWithParserOptions, ParserServices } from \"./types\";\n\nexport type Plugin = Omit<OxlintPlugin, \"rules\"> & {\n /**\n * Optional module URL or absolute path used to resolve the plugin's own\n * runtime dependencies when they are not visible from the consumer root.\n */\n readonly resolveFrom?: string;\n readonly rules: Record<string, Rule>;\n} & Record<string, unknown>;\nexport type Rule = OxlintRule & Record<string, unknown>;\nexport type RuleDiagnostic<MessageId extends string = string> = Diagnostic & {\n readonly messageId?: MessageId | null | undefined;\n};\nexport type RuleContext<\n MessageId extends string = string,\n Options extends readonly unknown[] = readonly unknown[],\n> = Omit<ContextWithParserOptions, \"options\" | \"report\"> & {\n readonly options: Readonly<Options>;\n report(this: void, diagnostic: RuleDiagnostic<MessageId>): void;\n};\nexport type RuleDocs = {\n readonly description?: string;\n readonly recommended?: unknown;\n readonly url?: string;\n /**\n * Enables corsa-oxlint's type-aware parser service defaults for this rule.\n *\n * @default false\n */\n readonly requiresTypeChecking?: boolean;\n};\nexport type RuleMetaWithMessages<MessageId extends string = string> = Omit<\n OxlintRuleMeta,\n \"docs\" | \"messages\"\n> & {\n readonly docs?: RuleDocs;\n readonly messages?: Record<MessageId, string>;\n};\ntype CorsaAstNodeType = keyof typeof AST_NODE_TYPES;\ntype BivariantVisitorHandler<Handler extends (...args: any[]) => any> = {\n bivarianceHack(...args: Parameters<Handler>): ReturnType<Handler>;\n}[\"bivarianceHack\"];\ntype VisitorNode<Kind extends CorsaAstNodeType> = PublicESTree[Kind];\n\nexport type Visitor = {\n [Kind in CorsaAstNodeType]?: BivariantVisitorHandler<(node: VisitorNode<Kind>) => void>;\n} & {\n [Kind in CorsaAstNodeType as `${Kind}:exit`]?: BivariantVisitorHandler<\n (node: VisitorNode<Kind>) => void\n >;\n} & Record<string, BivariantVisitorHandler<(node: PublicESTree.Node) => void> | undefined>;\n\nexport type VisitorWithHooks = Visitor & {\n readonly before?: () => boolean | void;\n readonly after?: () => void;\n};\nexport type RuleDefinition<\n MessageId extends string = string,\n Options extends readonly unknown[] = readonly unknown[],\n> = Record<string, unknown> & {\n readonly defaultOptions?: Options;\n readonly meta?: RuleMetaWithMessages<MessageId>;\n} & (\n | {\n readonly create: (context: RuleContext<MessageId, Options>) => Visitor;\n readonly createOnce?: never;\n }\n | {\n readonly create?: (context: RuleContext<MessageId, Options>) => Visitor;\n readonly createOnce: (context: RuleContext<MessageId, Options>) => VisitorWithHooks;\n }\n );\n\nconst defineOxlintPlugin = oxlintPluginApi.definePlugin;\nconst defineOxlintRule = oxlintPluginApi.defineRule;\nconst baseCompatPlugin = Reflect.get(\n oxlintPluginApi as object,\n [\"es\", \"lintCompatPlugin\"].join(\"\"),\n) as typeof oxlintPluginApi.definePlugin;\n\nexport function definePlugin(plugin: Plugin): Plugin {\n const defined = defineOxlintPlugin({\n ...plugin,\n rules: wrapRules(plugin.rules ?? {}, plugin.resolveFrom),\n } as OxlintPlugin) as Plugin;\n if (plugin.resolveFrom === undefined) {\n return defined;\n }\n return {\n ...defined,\n resolveFrom: plugin.resolveFrom,\n };\n}\n\n/**\n * Defines a single Oxlint rule with type-aware parser services.\n *\n * @example\n * ```ts\n * export default defineRule({\n * meta: { schema: [], messages: { demo: \"demo\" } },\n * create(context) {\n * const services = context.parserServices;\n * return {};\n * },\n * });\n * ```\n */\nexport function defineRule<\n MessageId extends string = string,\n const Options extends readonly unknown[] = readonly unknown[],\n>(rule: RuleDefinition<MessageId, Options>): Rule;\nexport function defineRule(rule: RuleDefinition): Rule {\n return defineOxlintRule(decorateRule(rule as unknown as Rule) as OxlintRule) as Rule;\n}\n\nexport function compatPlugin(plugin: Plugin): Plugin {\n return baseCompatPlugin(definePlugin(plugin)) as Plugin;\n}\n\nexport function decorateRule(rule: Rule, resolveFrom?: string): Rule {\n if (rule.create) {\n return {\n ...rule,\n create(context) {\n return rule.create!(decorateContext(context, rule, resolveFrom));\n },\n } as Rule;\n }\n if (\"createOnce\" in rule && typeof (rule as any).createOnce === \"function\") {\n return {\n ...rule,\n createOnce(context) {\n return (rule as any).createOnce(decorateContext(context, rule, resolveFrom));\n },\n } as Rule;\n }\n return rule;\n}\n\nfunction wrapRules(rules: Record<string, Rule>, resolveFrom?: string): Record<string, Rule> {\n return Object.fromEntries(\n Object.entries(rules).map(([name, rule]) => [name, decorateRule(rule, resolveFrom)]),\n );\n}\n\nfunction decorateContext(\n context: ContextWithParserOptions,\n rule: Rule,\n resolveFrom?: string,\n): ContextWithParserOptions {\n const typeAware = requiresTypeChecking(rule);\n const parserOptions = Object.freeze(\n resolveTypeAwareParserOptions(\n context,\n {\n corsa: typeAware,\n projectService: typeAware,\n },\n resolveFrom,\n ),\n );\n const baseLanguageOptions = context.languageOptions;\n const languageOptions = Object.freeze({\n ...baseLanguageOptions,\n parserOptions,\n });\n return Object.create(context as OxlintContext, {\n languageOptions: {\n configurable: true,\n enumerable: true,\n get() {\n return languageOptions;\n },\n },\n parserOptions: {\n configurable: true,\n enumerable: false,\n get() {\n return parserOptions;\n },\n },\n parserServices: {\n configurable: true,\n enumerable: false,\n get(): ParserServices {\n return getParserServices(context);\n },\n },\n }) as ContextWithParserOptions;\n}\n\nfunction requiresTypeChecking(rule: Rule): boolean {\n return (\n (rule.meta as { readonly docs?: { readonly requiresTypeChecking?: unknown } } | undefined)?.docs\n ?.requiresTypeChecking === true\n );\n}\n"],"mappings":";;;;AAuFA,MAAM,qBAAqB,gBAAgB;AAC3C,MAAM,mBAAmB,gBAAgB;AACzC,MAAM,mBAAmB,QAAQ,IAC/B,iBACA,CAAC,MAAM,kBAAkB,EAAE,KAAK,EAAE,CACpC;AAEA,SAAgB,aAAa,QAAwB;CACnD,MAAM,UAAU,mBAAmB;EACjC,GAAG;EACH,OAAO,UAAU,OAAO,SAAS,CAAC,GAAG,OAAO,WAAW;CACzD,CAAiB;CACjB,IAAI,OAAO,gBAAgB,KAAA,GACzB,OAAO;CAET,OAAO;EACL,GAAG;EACH,aAAa,OAAO;CACtB;AACF;AAoBA,SAAgB,WAAW,MAA4B;CACrD,OAAO,iBAAiB,aAAa,IAAuB,CAAe;AAC7E;AAEA,SAAgB,aAAa,QAAwB;CACnD,OAAO,iBAAiB,aAAa,MAAM,CAAC;AAC9C;AAEA,SAAgB,aAAa,MAAY,aAA4B;CACnE,IAAI,KAAK,QACP,OAAO;EACL,GAAG;EACH,OAAO,SAAS;GACd,OAAO,KAAK,OAAQ,gBAAgB,SAAS,MAAM,WAAW,CAAC;EACjE;CACF;CAEF,IAAI,gBAAgB,QAAQ,OAAQ,KAAa,eAAe,YAC9D,OAAO;EACL,GAAG;EACH,WAAW,SAAS;GAClB,OAAQ,KAAa,WAAW,gBAAgB,SAAS,MAAM,WAAW,CAAC;EAC7E;CACF;CAEF,OAAO;AACT;AAEA,SAAS,UAAU,OAA6B,aAA4C;CAC1F,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,MAAM,UAAU,CAAC,MAAM,aAAa,MAAM,WAAW,CAAC,CAAC,CACrF;AACF;AAEA,SAAS,gBACP,SACA,MACA,aAC0B;CAC1B,MAAM,YAAY,qBAAqB,IAAI;CAC3C,MAAM,gBAAgB,OAAO,OAC3B,8BACE,SACA;EACE,OAAO;EACP,gBAAgB;CAClB,GACA,WACF,CACF;CACA,MAAM,sBAAsB,QAAQ;CACpC,MAAM,kBAAkB,OAAO,OAAO;EACpC,GAAG;EACH;CACF,CAAC;CACD,OAAO,OAAO,OAAO,SAA0B;EAC7C,iBAAiB;GACf,cAAc;GACd,YAAY;GACZ,MAAM;IACJ,OAAO;GACT;EACF;EACA,eAAe;GACb,cAAc;GACd,YAAY;GACZ,MAAM;IACJ,OAAO;GACT;EACF;EACA,gBAAgB;GACd,cAAc;GACd,YAAY;GACZ,MAAsB;IACpB,OAAO,kBAAkB,OAAO;GAClC;EACF;CACF,CAAC;AACH;AAEA,SAAS,qBAAqB,MAAqB;CACjD,OACG,KAAK,MAAsF,MACxF,yBAAyB;AAEjC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corsa-oxlint",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.51.0",
|
|
4
4
|
"description": "Type-aware Oxlint helpers powered by Corsa",
|
|
5
5
|
"homepage": "https://github.com/ubugeeei-prod/corsa-bind/tree/main/src/bindings/nodejs/corsa_oxlint",
|
|
6
6
|
"bugs": {
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"./package.json": "./package.json"
|
|
102
102
|
},
|
|
103
103
|
"dependencies": {
|
|
104
|
-
"@corsa-bind/napi": "0.
|
|
104
|
+
"@corsa-bind/napi": "0.51.0"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
107
|
"@oxlint/plugins": "1.69.0",
|