dlinter-ts-react 0.2.0 → 0.3.1
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 +12 -4
- package/dist/cli/index.mjs +4 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +125 -54
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -132,13 +132,21 @@ bun run validate # typecheck + test
|
|
|
132
132
|
|
|
133
133
|
The repo self-hosts its own gate (lefthook: fallow audit + typecheck + test). Contributions follow strict TDD — a rule without a failing test proving it fires is a disabled rule — and conventional commits.
|
|
134
134
|
|
|
135
|
-
###
|
|
135
|
+
### Self-governance
|
|
136
|
+
|
|
137
|
+
This package enforces its own rules on itself. A permanent test (`src/__tests__/self-governance.test.ts`, part of `bun run validate`) lints `src/**` with the universal subset of the shipped rules — strict colocation, folder ownership, pure barrels, exported-variable JSDoc, `max-lines` — plus a layer contract on import direction:
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
```
|
|
140
|
+
src/index.ts → src/configs/ → src/plugin.ts → src/rules/ (src/cli/ is a standalone bin)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Every commit and release must pass the same architecture this package sells. Two documented exceptions: rule modules are exported const objects (the ESLint plugin contract requires it), and the package entrypoints (`main`, `bin`) are composition modules, not barrels.
|
|
144
|
+
|
|
145
|
+
### Releasing
|
|
138
146
|
|
|
139
|
-
|
|
147
|
+
Releases are automated with [release-please](https://github.com/googleapis/release-please): conventional commits on `main` drive the next semver (`fix:` → patch, `feat:` → minor, `feat!:`/`BREAKING CHANGE:` → major). The bot maintains a Release PR with the computed version and CHANGELOG; **merging that PR** cuts the GitHub release and publishes to npm — after the tarball end-to-end gate passes.
|
|
140
148
|
|
|
141
|
-
|
|
149
|
+
Publishing authenticates via [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) (OIDC): no tokens, nothing to rotate, provenance built in. The trusted publisher is configured in the package settings on npmjs.com, bound to this repository's `release-please.yml` workflow. Emergency escape hatch: publish locally with `npm publish` (2FA OTP applies).
|
|
142
150
|
|
|
143
151
|
## Roadmap
|
|
144
152
|
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { existsSync, writeFileSync } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
//#region src/cli/init.ts
|
|
4
|
+
//#region src/cli/init/init.constants.ts
|
|
5
|
+
/** Default lefthook pre-commit gate scaffolded into consumer projects. */
|
|
5
6
|
const lefthookTemplate = `pre-commit:
|
|
6
7
|
parallel: false
|
|
7
8
|
jobs:
|
|
@@ -14,6 +15,8 @@ const lefthookTemplate = `pre-commit:
|
|
|
14
15
|
- name: test
|
|
15
16
|
run: npm run test
|
|
16
17
|
`;
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/cli/init/init.ts
|
|
17
20
|
/**
|
|
18
21
|
* Scaffolds the dlinter pre-commit gate into a consumer project. Existing
|
|
19
22
|
* files are never overwritten — a hand-tuned gate always wins over the template.
|
package/dist/index.d.mts
CHANGED
|
@@ -1106,7 +1106,7 @@ interface Directive {
|
|
|
1106
1106
|
justification?: string;
|
|
1107
1107
|
}
|
|
1108
1108
|
//#endregion
|
|
1109
|
-
//#region src/configs/recommended.types.d.ts
|
|
1109
|
+
//#region src/configs/recommended/recommended.types.d.ts
|
|
1110
1110
|
/**
|
|
1111
1111
|
* Consumer-defined infrastructure edge: which import specifiers and runtime
|
|
1112
1112
|
* globals count as "infrastructure" that views must never touch directly.
|
|
@@ -1130,7 +1130,7 @@ interface RecommendedConfigOptions {
|
|
|
1130
1130
|
readonly tsconfigPath?: string;
|
|
1131
1131
|
}
|
|
1132
1132
|
//#endregion
|
|
1133
|
-
//#region src/configs/recommended.d.ts
|
|
1133
|
+
//#region src/configs/recommended/recommended.d.ts
|
|
1134
1134
|
/**
|
|
1135
1135
|
* Builds the full governance preset: bundled third-party plugin stack plus
|
|
1136
1136
|
* every dlinter architecture rule, composed with the glob topology proven in
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import tsParser from "@typescript-eslint/parser";
|
|
2
2
|
import js from "@eslint/js";
|
|
3
|
-
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
|
4
3
|
import { createTypeScriptImportResolver } from "eslint-import-resolver-typescript";
|
|
5
4
|
import checkFilePlugin from "eslint-plugin-check-file";
|
|
6
5
|
import { createNodeResolver, importX } from "eslint-plugin-import-x";
|
|
@@ -11,6 +10,7 @@ import reactHooksPlugin from "eslint-plugin-react-hooks";
|
|
|
11
10
|
import sonarjsPlugin from "eslint-plugin-sonarjs";
|
|
12
11
|
import { existsSync } from "node:fs";
|
|
13
12
|
import path from "node:path";
|
|
13
|
+
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
|
14
14
|
//#region src/configs/dumb-ui.ts
|
|
15
15
|
/**
|
|
16
16
|
* Dumb UI preset: every `.tsx` file is presentational. Side effects live in
|
|
@@ -33,9 +33,13 @@ function createDumbUiConfig(plugin) {
|
|
|
33
33
|
}];
|
|
34
34
|
}
|
|
35
35
|
//#endregion
|
|
36
|
-
//#region src/rules/composition-only-delivery.ts
|
|
36
|
+
//#region src/rules/composition-only-delivery/composition-only-delivery.constants.ts
|
|
37
|
+
/** Matches every built-in React hook name, including bare `use`. */
|
|
37
38
|
const reactHookNamePattern = "^use(State|Reducer|Effect|LayoutEffect|InsertionEffect|SyncExternalStore|Memo|Callback|Ref|Context|Transition|DeferredValue|ImperativeHandle|DebugValue|Id|Optimistic|ActionState)?$";
|
|
39
|
+
/** Matches module specifiers that resolve to a custom `use-*` hook file. */
|
|
38
40
|
const customHookModulePattern = /(^|\/)use-[^/]+$/u;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/rules/composition-only-delivery/composition-only-delivery.ts
|
|
39
43
|
/**
|
|
40
44
|
* Delivery Layer Rule: delivery files (App.tsx, app/**) compose feature
|
|
41
45
|
* entrypoints — they never orchestrate. No React hooks, no custom hook
|
|
@@ -76,13 +80,16 @@ const compositionOnlyDelivery = {
|
|
|
76
80
|
}
|
|
77
81
|
};
|
|
78
82
|
//#endregion
|
|
79
|
-
//#region src/rules/folder-ownership.ts
|
|
83
|
+
//#region src/rules/folder-ownership/folder-ownership.constants.ts
|
|
84
|
+
/** Role-file suffixes a split main module may own next to its entrypoint. */
|
|
80
85
|
const roleSuffixes = [
|
|
81
86
|
".constants.ts",
|
|
82
87
|
".helpers.ts",
|
|
83
88
|
".schema.ts",
|
|
84
89
|
".types.ts"
|
|
85
90
|
];
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/rules/folder-ownership/folder-ownership.ts
|
|
86
93
|
/**
|
|
87
94
|
* Split Module Ownership Rule: when a main module splits into role files
|
|
88
95
|
* (`*.helpers.ts`, `*.types.ts`, `*.constants.ts`, `*.schema.ts`), the whole
|
|
@@ -124,8 +131,11 @@ const folderOwnership = {
|
|
|
124
131
|
}
|
|
125
132
|
};
|
|
126
133
|
//#endregion
|
|
127
|
-
//#region src/rules/hook-anatomy.ts
|
|
134
|
+
//#region src/rules/hook-anatomy/hook-anatomy.constants.ts
|
|
135
|
+
/** Selector prefix targeting the body of every exported `use*` hook declaration. */
|
|
128
136
|
const hookBlock = "ExportNamedDeclaration > FunctionDeclaration[id.name=/^use[A-Z0-9]/] > BlockStatement";
|
|
137
|
+
//#endregion
|
|
138
|
+
//#region src/rules/hook-anatomy/hook-anatomy.ts
|
|
129
139
|
/**
|
|
130
140
|
* Hook Anatomy Rule: exported hooks follow one ordering — derived state
|
|
131
141
|
* (useMemo) before callbacks (useCallback) before effects (useEffect) — and
|
|
@@ -243,8 +253,11 @@ const noInfrastructureInView = {
|
|
|
243
253
|
}
|
|
244
254
|
};
|
|
245
255
|
//#endregion
|
|
246
|
-
//#region src/rules/no-view-effects.ts
|
|
256
|
+
//#region src/rules/no-view-effects/no-view-effects.constants.ts
|
|
257
|
+
/** Matches the React effect hooks that are forbidden inside view components. */
|
|
247
258
|
const effectHookPattern = /^use(?:Effect|LayoutEffect)$/u;
|
|
259
|
+
//#endregion
|
|
260
|
+
//#region src/rules/no-view-effects/no-view-effects.ts
|
|
248
261
|
/**
|
|
249
262
|
* Dumb UI Rule: view components (.tsx) must stay presentational. Side effects
|
|
250
263
|
* belong in the colocated `use-*.ts` hook, never in the view itself.
|
|
@@ -299,8 +312,11 @@ const pureIndexBarrel = {
|
|
|
299
312
|
}
|
|
300
313
|
};
|
|
301
314
|
//#endregion
|
|
302
|
-
//#region src/rules/readonly-props.ts
|
|
315
|
+
//#region src/rules/readonly-props/readonly-props.constants.ts
|
|
316
|
+
/** Selector fragment matching parameters annotated with a bare `*Props` type reference. */
|
|
303
317
|
const propsBoundary = "[typeAnnotation.typeAnnotation.type=\"TSTypeReference\"][typeAnnotation.typeAnnotation.typeName.name=/Props$/]";
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/rules/readonly-props/readonly-props.ts
|
|
304
320
|
/**
|
|
305
321
|
* Type Contract Rule: component props are immutable. Parameters use
|
|
306
322
|
* `Readonly<Props>` at the function boundary, and every field of a `*Props`
|
|
@@ -366,7 +382,11 @@ const requireExportedVariableJsdoc = {
|
|
|
366
382
|
}
|
|
367
383
|
};
|
|
368
384
|
//#endregion
|
|
369
|
-
//#region src/rules/strict-colocation.ts
|
|
385
|
+
//#region src/rules/strict-colocation/strict-colocation.constants.ts
|
|
386
|
+
/**
|
|
387
|
+
* Every check id the rule can enforce; the `checks` option narrows this set
|
|
388
|
+
* for role files that legitimately own a subset of declaration kinds.
|
|
389
|
+
*/
|
|
370
390
|
const allChecks = [
|
|
371
391
|
"root-variable",
|
|
372
392
|
"root-helper-function",
|
|
@@ -376,13 +396,86 @@ const allChecks = [
|
|
|
376
396
|
"inline-type-alias",
|
|
377
397
|
"zod-import"
|
|
378
398
|
];
|
|
399
|
+
/** Matches `zod` itself and any `zod/*` subpath import. */
|
|
379
400
|
const zodImportPattern = /^zod(?:\/.*)?$/u;
|
|
380
401
|
//#endregion
|
|
402
|
+
//#region src/rules/strict-colocation/strict-colocation.helpers.ts
|
|
403
|
+
/**
|
|
404
|
+
* Collects every identifier a module exports through specifier statements —
|
|
405
|
+
* `export default App` and `export { App }` — so root function declarations
|
|
406
|
+
* exported that way are recognized as main modules rather than helpers.
|
|
407
|
+
*/
|
|
408
|
+
function collectSpecifierExportedNames(program) {
|
|
409
|
+
const names = /* @__PURE__ */ new Set();
|
|
410
|
+
for (const statement of program.body) {
|
|
411
|
+
if (statement.type === "ExportDefaultDeclaration" && statement.declaration.type === "Identifier") names.add(statement.declaration.name);
|
|
412
|
+
if (statement.type === "ExportNamedDeclaration" && statement.declaration === null) {
|
|
413
|
+
for (const specifier of statement.specifiers) if (specifier.local.type === "Identifier") names.add(specifier.local.name);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return names;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Builds the visitor fragment owned by each check id; the rule merges the
|
|
420
|
+
* fragments for whichever checks its options enable.
|
|
421
|
+
*/
|
|
422
|
+
function createCheckVisitors(context) {
|
|
423
|
+
return {
|
|
424
|
+
"root-variable": { "Program > VariableDeclaration": (node) => {
|
|
425
|
+
context.report({
|
|
426
|
+
node,
|
|
427
|
+
messageId: "rootVariable"
|
|
428
|
+
});
|
|
429
|
+
} },
|
|
430
|
+
"root-helper-function": { "Program > FunctionDeclaration": (node) => {
|
|
431
|
+
if (node.type === "FunctionDeclaration" && node.parent.type === "Program") {
|
|
432
|
+
const exportedNames = collectSpecifierExportedNames(node.parent);
|
|
433
|
+
if (node.id !== null && exportedNames.has(node.id.name)) return;
|
|
434
|
+
}
|
|
435
|
+
context.report({
|
|
436
|
+
node,
|
|
437
|
+
messageId: "rootHelperFunction"
|
|
438
|
+
});
|
|
439
|
+
} },
|
|
440
|
+
"exported-const": { "Program > ExportNamedDeclaration > VariableDeclaration": (node) => {
|
|
441
|
+
context.report({
|
|
442
|
+
node,
|
|
443
|
+
messageId: "exportedConst"
|
|
444
|
+
});
|
|
445
|
+
} },
|
|
446
|
+
"default-arrow-export": { "Program > ExportDefaultDeclaration > ArrowFunctionExpression": (node) => {
|
|
447
|
+
context.report({
|
|
448
|
+
node,
|
|
449
|
+
messageId: "defaultArrowExport"
|
|
450
|
+
});
|
|
451
|
+
} },
|
|
452
|
+
"inline-interface": { TSInterfaceDeclaration: (node) => {
|
|
453
|
+
context.report({
|
|
454
|
+
node,
|
|
455
|
+
messageId: "inlineInterface"
|
|
456
|
+
});
|
|
457
|
+
} },
|
|
458
|
+
"inline-type-alias": { TSTypeAliasDeclaration: (node) => {
|
|
459
|
+
context.report({
|
|
460
|
+
node,
|
|
461
|
+
messageId: "inlineTypeAlias"
|
|
462
|
+
});
|
|
463
|
+
} },
|
|
464
|
+
"zod-import": { ImportDeclaration: (node) => {
|
|
465
|
+
if (node.type === "ImportDeclaration" && zodImportPattern.test(String(node.source.value))) context.report({
|
|
466
|
+
node,
|
|
467
|
+
messageId: "zodImport"
|
|
468
|
+
});
|
|
469
|
+
} }
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
//#endregion
|
|
381
473
|
//#region src/plugin.ts
|
|
382
474
|
/**
|
|
383
|
-
* Plugin core shared by every preset: metadata plus the dlinter rule registry
|
|
384
|
-
* Presets receive this object so config
|
|
385
|
-
* entrypoint back (which would create a
|
|
475
|
+
* Plugin core shared by every preset: metadata plus the dlinter rule registry
|
|
476
|
+
* keyed by published rule name. Presets receive this object so config
|
|
477
|
+
* factories never import the package entrypoint back (which would create a
|
|
478
|
+
* module cycle).
|
|
386
479
|
*/
|
|
387
480
|
const pluginBase = {
|
|
388
481
|
meta: {
|
|
@@ -423,49 +516,9 @@ const pluginBase = {
|
|
|
423
516
|
create(context) {
|
|
424
517
|
const configuredChecks = context.options[0]?.checks ?? allChecks;
|
|
425
518
|
const enabled = new Set(configuredChecks);
|
|
519
|
+
const checkVisitors = createCheckVisitors(context);
|
|
426
520
|
const visitor = {};
|
|
427
|
-
if (enabled.has(
|
|
428
|
-
context.report({
|
|
429
|
-
node,
|
|
430
|
-
messageId: "rootVariable"
|
|
431
|
-
});
|
|
432
|
-
};
|
|
433
|
-
if (enabled.has("root-helper-function")) visitor["Program > FunctionDeclaration"] = (node) => {
|
|
434
|
-
context.report({
|
|
435
|
-
node,
|
|
436
|
-
messageId: "rootHelperFunction"
|
|
437
|
-
});
|
|
438
|
-
};
|
|
439
|
-
if (enabled.has("exported-const")) visitor["Program > ExportNamedDeclaration > VariableDeclaration"] = (node) => {
|
|
440
|
-
context.report({
|
|
441
|
-
node,
|
|
442
|
-
messageId: "exportedConst"
|
|
443
|
-
});
|
|
444
|
-
};
|
|
445
|
-
if (enabled.has("default-arrow-export")) visitor["Program > ExportDefaultDeclaration > ArrowFunctionExpression"] = (node) => {
|
|
446
|
-
context.report({
|
|
447
|
-
node,
|
|
448
|
-
messageId: "defaultArrowExport"
|
|
449
|
-
});
|
|
450
|
-
};
|
|
451
|
-
if (enabled.has("inline-interface")) visitor["TSInterfaceDeclaration"] = (node) => {
|
|
452
|
-
context.report({
|
|
453
|
-
node,
|
|
454
|
-
messageId: "inlineInterface"
|
|
455
|
-
});
|
|
456
|
-
};
|
|
457
|
-
if (enabled.has("inline-type-alias")) visitor["TSTypeAliasDeclaration"] = (node) => {
|
|
458
|
-
context.report({
|
|
459
|
-
node,
|
|
460
|
-
messageId: "inlineTypeAlias"
|
|
461
|
-
});
|
|
462
|
-
};
|
|
463
|
-
if (enabled.has("zod-import")) visitor["ImportDeclaration"] = (node) => {
|
|
464
|
-
if (node.type === "ImportDeclaration" && zodImportPattern.test(String(node.source.value))) context.report({
|
|
465
|
-
node,
|
|
466
|
-
messageId: "zodImport"
|
|
467
|
-
});
|
|
468
|
-
};
|
|
521
|
+
for (const check of allChecks) if (enabled.has(check)) Object.assign(visitor, checkVisitors[check]);
|
|
469
522
|
return visitor;
|
|
470
523
|
}
|
|
471
524
|
}
|
|
@@ -488,8 +541,13 @@ function downgradeRuleSeverities(rules) {
|
|
|
488
541
|
}));
|
|
489
542
|
}
|
|
490
543
|
//#endregion
|
|
491
|
-
//#region src/configs/recommended.ts
|
|
544
|
+
//#region src/configs/recommended/recommended.constants.ts
|
|
545
|
+
/**
|
|
546
|
+
* The @typescript-eslint plugin object types its rules more richly than core
|
|
547
|
+
* ESLint's Plugin contract; the runtime shape is compatible.
|
|
548
|
+
*/
|
|
492
549
|
const typescriptPlugin = tsPlugin;
|
|
550
|
+
/** Extensions the import-x node resolver probes when resolving specifiers. */
|
|
493
551
|
const importXExtensions = [
|
|
494
552
|
".js",
|
|
495
553
|
".jsx",
|
|
@@ -497,15 +555,20 @@ const importXExtensions = [
|
|
|
497
555
|
".tsx",
|
|
498
556
|
".d.ts"
|
|
499
557
|
];
|
|
558
|
+
/** Globs identifying test files, which stay outside the architecture contract. */
|
|
500
559
|
const productionTestGlobs = [
|
|
501
560
|
"**/__tests__/**/*.{ts,tsx}",
|
|
502
561
|
"**/*.test.{ts,tsx}",
|
|
503
562
|
"src/test/**/*.{ts,tsx}",
|
|
504
563
|
"test/**/*.{ts,tsx}"
|
|
505
564
|
];
|
|
565
|
+
/** Globs for repository automation scripts that run under Node. */
|
|
506
566
|
const nodeScriptGlobs = ["scripts/**/*.{js,mjs,cjs}"];
|
|
567
|
+
/** Globs for application source that runs in the browser. */
|
|
507
568
|
const sourceBrowserGlobs = ["src/**/*.{ts,tsx,js,jsx}"];
|
|
569
|
+
/** Files exempt from the public-documentation contract: tests and documented-invalid fixtures. */
|
|
508
570
|
const documentationExemptGlobs = [...productionTestGlobs, "**/*.invalid.{ts,tsx,js,jsx}"];
|
|
571
|
+
/** Files that are not governed main modules: exempt files plus barrels and role files. */
|
|
509
572
|
const governedMainModuleExemptGlobs = [
|
|
510
573
|
...documentationExemptGlobs,
|
|
511
574
|
"**/index.ts",
|
|
@@ -514,6 +577,7 @@ const governedMainModuleExemptGlobs = [
|
|
|
514
577
|
"**/*.schema.ts",
|
|
515
578
|
"**/*.types.ts"
|
|
516
579
|
];
|
|
580
|
+
/** AST selector contexts that `jsdoc/require-jsdoc` treats as public documentation surface. */
|
|
517
581
|
const documentationContexts = [
|
|
518
582
|
"ExportNamedDeclaration > FunctionDeclaration",
|
|
519
583
|
"ExportNamedDeclaration > TSInterfaceDeclaration",
|
|
@@ -522,6 +586,7 @@ const documentationContexts = [
|
|
|
522
586
|
"ExportDefaultDeclaration > ArrowFunctionExpression",
|
|
523
587
|
"ExportDefaultDeclaration > CallExpression > ArrowFunctionExpression"
|
|
524
588
|
];
|
|
589
|
+
/** Full dlinter rule map at severity "off" — the final reset applied to test files. */
|
|
525
590
|
const allDlinterRulesOff = {
|
|
526
591
|
"dlinter/composition-only-delivery": "off",
|
|
527
592
|
"dlinter/folder-ownership": "off",
|
|
@@ -533,6 +598,8 @@ const allDlinterRulesOff = {
|
|
|
533
598
|
"dlinter/require-exported-variable-jsdoc": "off",
|
|
534
599
|
"dlinter/strict-colocation": "off"
|
|
535
600
|
};
|
|
601
|
+
//#endregion
|
|
602
|
+
//#region src/configs/recommended/recommended.ts
|
|
536
603
|
/**
|
|
537
604
|
* Builds the full governance preset: bundled third-party plugin stack plus
|
|
538
605
|
* every dlinter architecture rule, composed with the glob topology proven in
|
|
@@ -741,7 +808,11 @@ function createRecommendedConfig(options = {}) {
|
|
|
741
808
|
files: ["src/**/*.helpers.ts"],
|
|
742
809
|
ignores: productionTestGlobs,
|
|
743
810
|
plugins: { dlinter: pluginBase },
|
|
744
|
-
rules: { "dlinter/strict-colocation": ["error", { checks: [
|
|
811
|
+
rules: { "dlinter/strict-colocation": ["error", { checks: [
|
|
812
|
+
"root-variable",
|
|
813
|
+
"inline-interface",
|
|
814
|
+
"inline-type-alias"
|
|
815
|
+
] }] }
|
|
745
816
|
},
|
|
746
817
|
{
|
|
747
818
|
files: productionTestGlobs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dlinter-ts-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Deterministic architecture governance for TypeScript + React projects: custom ESLint rules, architecture-concept presets, and pre-commit gate scaffolding.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"bin": {
|
|
28
|
-
"dlinter": "
|
|
28
|
+
"dlinter": "dist/cli/index.mjs"
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"dist"
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"typescript": ">=5.0.0 <6.1.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
+
"@types/estree": "^1.0.9",
|
|
57
58
|
"@types/node": "^26.1.1",
|
|
58
59
|
"eslint": "^10.6.0",
|
|
59
60
|
"fallow": "^3.3.0",
|