@useinsider/eslint-config 4.0.0-beta.1 → 4.0.0-beta.2

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.
@@ -1,4 +1,6 @@
1
1
  import { type TSESTree } from '@typescript-eslint/types';
2
+ import { ESLINT_CONFIG_FILENAMES, type LayoutDiagnosis, LINT_MODULE_FILENAMES } from './layoutDiagnosis';
3
+ import { offerMigration } from './offerMigration';
2
4
  export interface ConfigStructureViolation {
3
5
  line: number;
4
6
  column: number;
@@ -8,8 +10,7 @@ export interface ValidateProgramStructureOptions {
8
10
  isInsiderImportSource?: (source: string, configPath: string) => boolean;
9
11
  expectedCallee?: string;
10
12
  }
11
- export declare const LINT_MODULE_FILENAMES: readonly string[];
12
- export declare const ESLINT_CONFIG_FILENAMES: readonly string[];
13
+ export { ESLINT_CONFIG_FILENAMES, LINT_MODULE_FILENAMES };
13
14
  export declare function defaultIsInsiderImportSource(source: string, configPath: string): boolean;
14
15
  export declare function validateProgramStructure(program: TSESTree.Program, configPath?: string, options?: ValidateProgramStructureOptions): ConfigStructureViolation[];
15
16
  export declare function validateLintModuleStructure(program: TSESTree.Program, configPath?: string, options?: ValidateProgramStructureOptions): ConfigStructureViolation[];
@@ -28,5 +29,8 @@ export declare function captureConsumerConfigDir(configPath: string | null): voi
28
29
  * getConsumerConfigDir(); // '/repo'
29
30
  */
30
31
  export declare function getConsumerConfigDir(): string;
31
- export declare function ensureConfigStructure(overridePath?: string | null): void;
32
- export {};
32
+ export interface RunValidationDeps {
33
+ diagnose?: (directory: string) => LayoutDiagnosis;
34
+ offer?: typeof offerMigration;
35
+ }
36
+ export declare function ensureConfigStructure(overridePath?: string | null, deps?: RunValidationDeps): void;
@@ -1,4 +1,5 @@
1
- export declare const OXLINT_CONFIG_FILENAMES: readonly string[];
1
+ import { OXLINT_CONFIG_FILENAMES } from './layoutDiagnosis';
2
+ export { OXLINT_CONFIG_FILENAMES };
2
3
  /**
3
4
  * Fails when the consumer enabled the ESLint-side oxlint suppression without a sibling oxlint
4
5
  * config to run the suppressed rules. Resolved against the directory
@@ -0,0 +1,63 @@
1
+ export declare const LINT_MODULE_FILENAMES: readonly string[];
2
+ export declare const ESLINT_CONFIG_FILENAMES: readonly string[];
3
+ export declare const OXLINT_CONFIG_FILENAMES: readonly string[];
4
+ export declare const OPT_OUT_ENV = "INSIDER_SKIP_CONFIG_VALIDATION";
5
+ export declare const MIGRATE_COMMAND = "npx @useinsider/eslint-config migrate";
6
+ export declare const SCAFFOLD_COMMAND = "npx @useinsider/eslint-config";
7
+ export declare const INSIDER_IMPORT_SOURCE = "@useinsider/eslint-config";
8
+ export declare const TARGET_CALLEE_NAME = "useInsider";
9
+ export declare const ESLINT_RENDERER_NAME = "useInsiderESLint";
10
+ export declare const OXC_RENDERER_NAME = "useInsiderOXC";
11
+ export declare const RENDERER_EXPORT = "export const { useInsiderESLint, useInsiderOXC } = useInsider({ ... })";
12
+ export declare const EXPECTED_LAYOUT: string;
13
+ export type LayoutCase = 'complete' | 'noConfig' | 'partial' | 'unmigratedV3';
14
+ export interface LayoutDiagnosis {
15
+ kind: LayoutCase;
16
+ directory: string;
17
+ lintModule: string | null;
18
+ eslintConfig: string | null;
19
+ oxlintConfig: string | null;
20
+ missing: string[];
21
+ autoMigratable: boolean;
22
+ }
23
+ export interface DiagnoseLayoutOptions {
24
+ fileExists?: (path: string) => boolean;
25
+ readSource?: (path: string) => string;
26
+ }
27
+ /**
28
+ * Whether a flat-config source is still the removed v3 shape: it imports `useInsider` and calls it
29
+ * itself, instead of importing a renderer from a sibling `insider.lint.*` module. Both the plain
30
+ * `export default useInsider({...})` form and the spread form are recognized.
31
+ * @example
32
+ * isV3EslintConfigSource("import { useInsider } from '@useinsider/eslint-config';\nexport default useInsider({});");
33
+ * // true
34
+ */
35
+ export declare function isV3EslintConfigSource(source: string): boolean;
36
+ /**
37
+ * What of the three-file layout is on disk in a directory, and which of the four guidance branches
38
+ * applies. `unmigratedV3` is the only branch the in-lint migration offer acts on, because it is the
39
+ * only one {@link import('../cli/migrate').runMigrate} can actually rewrite.
40
+ * @example
41
+ * diagnoseLayout('/repo').kind; // 'unmigratedV3' when eslint.config.js still calls useInsider()
42
+ */
43
+ export declare function diagnoseLayout(directory: string, options?: DiagnoseLayoutOptions): LayoutDiagnosis;
44
+ /**
45
+ * Import specifier for the consumer's lint module, naming the extension that is actually on disk so
46
+ * the suggested snippet resolves as printed.
47
+ * @example
48
+ * lintModuleSpecifier('/repo'); // './insider.lint.mts' when that is the file present
49
+ */
50
+ export declare function lintModuleSpecifier(directory: string, fileExists?: (path: string) => boolean): string;
51
+ export interface LayoutGuidanceInput {
52
+ headline: string;
53
+ diagnosis: LayoutDiagnosis;
54
+ detail?: readonly string[];
55
+ }
56
+ /**
57
+ * The consumer-facing failure text: a site-specific headline, then the branch that matches what is
58
+ * on disk, then the layout dump, then the bypass. The command to run always comes before the dump,
59
+ * because a consumer who reads only the first screen still has to be told about `migrate`.
60
+ * @example
61
+ * formatLayoutGuidance({ headline: 'no `insider.lint.*` module found in /repo.', diagnosis });
62
+ */
63
+ export declare function formatLayoutGuidance(input: LayoutGuidanceInput): string;
@@ -0,0 +1,42 @@
1
+ import { type LayoutDiagnosis } from './layoutDiagnosis';
2
+ export type LintHost = 'eslint' | 'oxlint' | 'unknown';
3
+ /**
4
+ * Which linter is hosting the current process. oxlint evaluates `oxlint.config.ts` inside the Node
5
+ * process that runs its own `bin/oxlint` wrapper, so `useInsider()` genuinely executes under both
6
+ * binaries and the two have to be told apart before anything is written to stdout.
7
+ * @example
8
+ * detectLintHost(['node', '/app/node_modules/oxlint/bin/oxlint', '.']); // 'oxlint'
9
+ */
10
+ export declare function detectLintHost(argv?: readonly string[]): LintHost;
11
+ export type OfferSkipReason = 'already-offered' | 'cli-not-found' | 'host-is-oxlint' | 'no-tty' | 'running-in-ci' | 'running-under-test' | 'suppressed';
12
+ export interface MigrationOfferResult {
13
+ offered: boolean;
14
+ skipReason?: OfferSkipReason;
15
+ accepted?: boolean;
16
+ }
17
+ export interface MigrationOfferDeps {
18
+ env?: NodeJS.ProcessEnv;
19
+ argv?: readonly string[];
20
+ interactive?: boolean;
21
+ resolveCliEntry?: () => string | null;
22
+ runCli?: (entry: string, args: readonly string[], cwd: string, env: NodeJS.ProcessEnv) => number;
23
+ warn?: (message: string) => void;
24
+ }
25
+ /**
26
+ * Absolute path to this package's own built CLI, or `null` when it is not on disk. Resolved by
27
+ * walking up from `startDir` — this module's own directory by default — rather than through
28
+ * `require.resolve`, so it works from `dist/` and from `src/` alike.
29
+ * @example
30
+ * resolveCliEntry(); // '/app/node_modules/@useinsider/eslint-config/dist/cli.cjs'
31
+ */
32
+ export declare function resolveCliEntry(startDir?: string): string | null;
33
+ /**
34
+ * Offers the guided migration for an outdated layout and runs it when the consumer accepts. Declines
35
+ * silently — returning a skip reason instead of prompting — whenever writing to stdout would be
36
+ * wrong: under oxlint, in CI, without a TTY, or when already inside a migration.
37
+ * @example
38
+ * offerMigration(diagnoseLayout('/repo')).accepted; // true after the consumer confirmed
39
+ */
40
+ export declare function offerMigration(diagnosis: LayoutDiagnosis, deps?: MigrationOfferDeps): MigrationOfferResult;
41
+ /** Clears the once-per-process latch {@link offerMigration} keeps, so a suite can exercise it twice. */
42
+ export declare function resetMigrationOffer(): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@useinsider/eslint-config",
3
3
  "type": "module",
4
- "version": "4.0.0-beta.1",
4
+ "version": "4.0.0-beta.2",
5
5
  "description": "A collection of ESLint configurations provided by @useinsider, offering support for various environments including Vanilla JS, TypeScript, and framework-specific setups such as Vue 3.",
6
6
  "keywords": [
7
7
  "useinsider",