archprint 0.13.1 → 0.15.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +21 -12
  3. package/dist/cli/adopted-rules.d.ts +30 -2
  4. package/dist/cli/adopted-rules.d.ts.map +1 -1
  5. package/dist/cli/adopted-rules.js +158 -2
  6. package/dist/cli/adopted-rules.js.map +1 -1
  7. package/dist/cli/allow.d.ts.map +1 -1
  8. package/dist/cli/allow.js +21 -4
  9. package/dist/cli/allow.js.map +1 -1
  10. package/dist/cli/allowed-evidence.d.ts.map +1 -1
  11. package/dist/cli/allowed-evidence.js +183 -1
  12. package/dist/cli/allowed-evidence.js.map +1 -1
  13. package/dist/cli/check-evaluate.d.ts.map +1 -1
  14. package/dist/cli/check-evaluate.js +124 -0
  15. package/dist/cli/check-evaluate.js.map +1 -1
  16. package/dist/cli/generate.d.ts +4 -4
  17. package/dist/cli/generate.d.ts.map +1 -1
  18. package/dist/cli/generate.js +115 -42
  19. package/dist/cli/generate.js.map +1 -1
  20. package/dist/cli/layout.d.ts +5 -2
  21. package/dist/cli/layout.d.ts.map +1 -1
  22. package/dist/cli/layout.js +43 -10
  23. package/dist/cli/layout.js.map +1 -1
  24. package/dist/cli/migrate.d.ts.map +1 -1
  25. package/dist/cli/migrate.js +1 -2
  26. package/dist/cli/migrate.js.map +1 -1
  27. package/dist/cli/program.d.ts.map +1 -1
  28. package/dist/cli/program.js +10 -6
  29. package/dist/cli/program.js.map +1 -1
  30. package/dist/cli/recommend.d.ts +3 -0
  31. package/dist/cli/recommend.d.ts.map +1 -1
  32. package/dist/cli/recommend.js +28 -8
  33. package/dist/cli/recommend.js.map +1 -1
  34. package/dist/cli/report.js +1 -1
  35. package/dist/cli/report.js.map +1 -1
  36. package/dist/detector/cycle-detector.d.ts +5 -0
  37. package/dist/detector/cycle-detector.d.ts.map +1 -1
  38. package/dist/detector/cycle-detector.js +20 -0
  39. package/dist/detector/cycle-detector.js.map +1 -1
  40. package/dist/detector/dependency-internals-detector.d.ts.map +1 -1
  41. package/dist/detector/dependency-internals-detector.js +6 -20
  42. package/dist/detector/dependency-internals-detector.js.map +1 -1
  43. package/dist/detector/entry-purity-detector.d.ts +7 -0
  44. package/dist/detector/entry-purity-detector.d.ts.map +1 -1
  45. package/dist/detector/entry-purity-detector.js +21 -10
  46. package/dist/detector/entry-purity-detector.js.map +1 -1
  47. package/dist/detector/phantom-dependency-detector.d.ts +7 -0
  48. package/dist/detector/phantom-dependency-detector.d.ts.map +1 -1
  49. package/dist/detector/phantom-dependency-detector.js +18 -39
  50. package/dist/detector/phantom-dependency-detector.js.map +1 -1
  51. package/dist/detector/server-client-detector.d.ts +5 -0
  52. package/dist/detector/server-client-detector.d.ts.map +1 -1
  53. package/dist/detector/server-client-detector.js +8 -3
  54. package/dist/detector/server-client-detector.js.map +1 -1
  55. package/dist/generator/app-isolation-emitters.d.ts +1 -0
  56. package/dist/generator/app-isolation-emitters.d.ts.map +1 -1
  57. package/dist/generator/app-isolation-emitters.js +2 -1
  58. package/dist/generator/app-isolation-emitters.js.map +1 -1
  59. package/dist/generator/depcruise-exempt.d.ts +4 -0
  60. package/dist/generator/depcruise-exempt.d.ts.map +1 -1
  61. package/dist/generator/depcruise-exempt.js +7 -0
  62. package/dist/generator/depcruise-exempt.js.map +1 -1
  63. package/dist/generator/dependency-internals-emitters.d.ts +2 -1
  64. package/dist/generator/dependency-internals-emitters.d.ts.map +1 -1
  65. package/dist/generator/dependency-internals-emitters.js +7 -3
  66. package/dist/generator/dependency-internals-emitters.js.map +1 -1
  67. package/dist/generator/entry-purity-emitters.d.ts +7 -3
  68. package/dist/generator/entry-purity-emitters.d.ts.map +1 -1
  69. package/dist/generator/entry-purity-emitters.js +19 -5
  70. package/dist/generator/entry-purity-emitters.js.map +1 -1
  71. package/dist/generator/env-access-emitters.d.ts +1 -0
  72. package/dist/generator/env-access-emitters.d.ts.map +1 -1
  73. package/dist/generator/env-access-emitters.js +1 -0
  74. package/dist/generator/env-access-emitters.js.map +1 -1
  75. package/dist/generator/eslint-app-emitter.d.ts +59 -0
  76. package/dist/generator/eslint-app-emitter.d.ts.map +1 -0
  77. package/dist/generator/eslint-app-emitter.js +275 -0
  78. package/dist/generator/eslint-app-emitter.js.map +1 -0
  79. package/dist/generator/eslint-preset-emitter.d.ts +2 -2
  80. package/dist/generator/eslint-preset-emitter.d.ts.map +1 -1
  81. package/dist/generator/eslint-preset-emitter.js +6 -6
  82. package/dist/generator/eslint-preset-emitter.js.map +1 -1
  83. package/dist/generator/feature-slice-emitters.d.ts +1 -0
  84. package/dist/generator/feature-slice-emitters.d.ts.map +1 -1
  85. package/dist/generator/feature-slice-emitters.js +2 -1
  86. package/dist/generator/feature-slice-emitters.js.map +1 -1
  87. package/dist/generator/layer-emitters.d.ts.map +1 -1
  88. package/dist/generator/layer-emitters.js +2 -6
  89. package/dist/generator/layer-emitters.js.map +1 -1
  90. package/dist/generator/phantom-dependency-emitters.d.ts +2 -1
  91. package/dist/generator/phantom-dependency-emitters.d.ts.map +1 -1
  92. package/dist/generator/phantom-dependency-emitters.js +7 -3
  93. package/dist/generator/phantom-dependency-emitters.js.map +1 -1
  94. package/dist/generator/role-layering-emitters.d.ts +2 -0
  95. package/dist/generator/role-layering-emitters.d.ts.map +1 -1
  96. package/dist/generator/role-layering-emitters.js +2 -1
  97. package/dist/generator/role-layering-emitters.js.map +1 -1
  98. package/dist/generator/server-client-emitters.d.ts +10 -3
  99. package/dist/generator/server-client-emitters.d.ts.map +1 -1
  100. package/dist/generator/server-client-emitters.js +23 -4
  101. package/dist/generator/server-client-emitters.js.map +1 -1
  102. package/dist/generator/stories-isolation-emitters.d.ts +1 -0
  103. package/dist/generator/stories-isolation-emitters.d.ts.map +1 -1
  104. package/dist/generator/stories-isolation-emitters.js +2 -1
  105. package/dist/generator/stories-isolation-emitters.js.map +1 -1
  106. package/dist/generator/ui-data-isolation-emitters.d.ts +1 -0
  107. package/dist/generator/ui-data-isolation-emitters.d.ts.map +1 -1
  108. package/dist/generator/ui-data-isolation-emitters.js +2 -1
  109. package/dist/generator/ui-data-isolation-emitters.js.map +1 -1
  110. package/dist/generator/workspace-package-emitters.d.ts +1 -0
  111. package/dist/generator/workspace-package-emitters.d.ts.map +1 -1
  112. package/dist/generator/workspace-package-emitters.js +1 -0
  113. package/dist/generator/workspace-package-emitters.js.map +1 -1
  114. package/dist/scanner/directives.d.ts +6 -0
  115. package/dist/scanner/directives.d.ts.map +1 -0
  116. package/dist/scanner/directives.js +35 -0
  117. package/dist/scanner/directives.js.map +1 -0
  118. package/dist/scanner/package-name.d.ts +10 -0
  119. package/dist/scanner/package-name.d.ts.map +1 -0
  120. package/dist/scanner/package-name.js +37 -0
  121. package/dist/scanner/package-name.js.map +1 -0
  122. package/dist/scanner/resolve-import.d.ts +5 -0
  123. package/dist/scanner/resolve-import.d.ts.map +1 -1
  124. package/dist/scanner/resolve-import.js +22 -19
  125. package/dist/scanner/resolve-import.js.map +1 -1
  126. package/dist/scanner/role-classifier.d.ts +11 -2
  127. package/dist/scanner/role-classifier.d.ts.map +1 -1
  128. package/dist/scanner/role-classifier.js +13 -39
  129. package/dist/scanner/role-classifier.js.map +1 -1
  130. package/package.json +2 -2
  131. package/dist/generator/eslint-layer-emitter.d.ts +0 -29
  132. package/dist/generator/eslint-layer-emitter.d.ts.map +0 -1
  133. package/dist/generator/eslint-layer-emitter.js +0 -121
  134. package/dist/generator/eslint-layer-emitter.js.map +0 -1
@@ -0,0 +1,59 @@
1
+ import type { LayerBoundary } from '../detector/layer-detector.js';
2
+ import { type LayerAlias } from '../detector/layer-paths.js';
3
+ import { type ServerClientAnalysis } from '../detector/server-client-detector.js';
4
+ import type { DependencyInternalsAnalysis } from '../detector/dependency-internals-detector.js';
5
+ import { type EntryPurityAnalysis } from '../detector/entry-purity-detector.js';
6
+ import type { PhantomDependencyAnalysis } from '../detector/phantom-dependency-detector.js';
7
+ /** A rule that applies to the app's files, with the files it exempts (known and allowed exceptions). */
8
+ export interface AppRule {
9
+ name: string;
10
+ message: string;
11
+ ignore: string[];
12
+ }
13
+ export interface LayerRuleSpec extends AppRule {
14
+ from: string;
15
+ to: string;
16
+ }
17
+ export interface PhantomRuleSpec extends AppRule {
18
+ /** The package.json files read for declared dependencies when ESLint loads the config. */
19
+ packageJsons: string[];
20
+ workspacePackages: string[];
21
+ }
22
+ export interface ServerClientRuleSpec extends AppRule {
23
+ serverModules: string[];
24
+ }
25
+ export interface EntryRuleSpec extends AppRule {
26
+ entryRoles: string[];
27
+ /** The `importer -> entry` imports that existed when the rule was generated. */
28
+ exemptImports: string[];
29
+ }
30
+ /** The app the rules enforce: where it is, its import aliases, and the gitignored paths the scan left out. */
31
+ export interface AppScope {
32
+ appDir: string;
33
+ aliases: LayerAlias[];
34
+ ignored: string[];
35
+ }
36
+ export interface EslintAppRules extends AppScope {
37
+ layers: LayerRuleSpec[];
38
+ phantom: PhantomRuleSpec | null;
39
+ serverClient: ServerClientRuleSpec | null;
40
+ internals: AppRule | null;
41
+ entry: EntryRuleSpec | null;
42
+ }
43
+ type AllowedFor = (ruleId: string) => readonly string[];
44
+ export declare const layerRuleSpecs: (boundaries: readonly LayerBoundary[], allowedFor: AllowedFor) => LayerRuleSpec[];
45
+ export declare const phantomRuleSpec: (analysis: PhantomDependencyAnalysis, packageJsons: readonly string[], workspacePackages: readonly string[], allowedFor: AllowedFor) => PhantomRuleSpec;
46
+ export declare const serverClientRuleSpec: (analysis: ServerClientAnalysis, allowedFor: AllowedFor) => ServerClientRuleSpec;
47
+ export declare const internalsRuleSpec: (analysis: DependencyInternalsAnalysis, allowedFor: AllowedFor) => AppRule;
48
+ export declare const entryRuleSpec: (analysis: EntryPurityAnalysis, allowedFor: AllowedFor) => EntryRuleSpec;
49
+ export declare const hasAppRules: (rules: EslintAppRules) => boolean;
50
+ export interface RenderedAppRules {
51
+ imports: string;
52
+ source: string;
53
+ rules: string;
54
+ config: string;
55
+ }
56
+ /** The pieces of the generated ESLint file that enforce app-scoped rules, located relative to that file. */
57
+ export declare function renderEslintAppRules(rules: EslintAppRules, outDir: string): RenderedAppRules;
58
+ export {};
59
+ //# sourceMappingURL=eslint-app-emitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint-app-emitter.d.ts","sourceRoot":"","sources":["../../src/generator/eslint-app-emitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,KAAK,UAAU,EAAkC,MAAM,4BAA4B,CAAC;AAC7F,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAC;AAChG,OAAO,EAAe,KAAK,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC7F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAa5F,wGAAwG;AACxG,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAgB,SAAQ,OAAO;IAC9C,0FAA0F;IAC1F,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,OAAO;IAC5C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,gFAAgF;IAChF,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,8GAA8G;AAC9G,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,QAAQ;IAC9C,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,YAAY,EAAE,oBAAoB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CAC7B;AAED,KAAK,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,CAAC;AAKxD,eAAO,MAAM,cAAc,GACzB,YAAY,SAAS,aAAa,EAAE,EACpC,YAAY,UAAU,KACrB,aAAa,EAcZ,CAAC;AAEL,eAAO,MAAM,eAAe,GAC1B,UAAU,yBAAyB,EACnC,cAAc,SAAS,MAAM,EAAE,EAC/B,mBAAmB,SAAS,MAAM,EAAE,EACpC,YAAY,UAAU,KACrB,eAUD,CAAC;AAEH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,oBAAoB,EAC9B,YAAY,UAAU,KACrB,oBASD,CAAC;AAEH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,2BAA2B,EACrC,YAAY,UAAU,KACrB,OASD,CAAC;AAIH,eAAO,MAAM,aAAa,GACxB,UAAU,mBAAmB,EAC7B,YAAY,UAAU,KACrB,aAOD,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,OAAO,cAAc,KAAG,OAE6C,CAAC;AA6JlG,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,4GAA4G;AAC5G,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAwE5F"}
@@ -0,0 +1,275 @@
1
+ import * as path from 'node:path';
2
+ import { layerRootOf, resolveImportPath } from '../detector/layer-paths.js';
3
+ import { SERVER_ONLY_PACKAGE, } from '../detector/server-client-detector.js';
4
+ import { ENTRY_ROLES } from '../detector/entry-purity-detector.js';
5
+ import { hasLeadingDirective } from '../scanner/directives.js';
6
+ import { declaredPackages, isPackageInternal, packageName } from '../scanner/package-name.js';
7
+ import { firstPartyCandidates } from '../scanner/resolve-import.js';
8
+ import { firstMatchingRule, ROLE_PATTERNS, ROLE_RULE_SOURCES } from '../scanner/role-classifier.js';
9
+ import { isSkippedFolder, isSourceFileName } from '../scanner/source-paths.js';
10
+ import { LINTED_FILES } from './eslint-plugin-emitter.js';
11
+ import { layerRuleName } from './layer-emitters.js';
12
+ import { DEPENDENCY_INTERNALS_RULE } from './dependency-internals-emitters.js';
13
+ import { ENTRY_PURITY_RULE } from './entry-purity-emitters.js';
14
+ import { PHANTOM_DEPENDENCY_RULE } from './phantom-dependency-emitters.js';
15
+ import { SERVER_CLIENT_RULE } from './server-client-emitters.js';
16
+ const exempting = (name, files, allowedFor) => [...new Set([...files, ...allowedFor(name)])].sort();
17
+ export const layerRuleSpecs = (boundaries, allowedFor) => boundaries.map((boundary) => {
18
+ const name = layerRuleName(boundary);
19
+ return {
20
+ name,
21
+ from: boundary.from,
22
+ to: boundary.to,
23
+ message: boundary.description,
24
+ ignore: exempting(name, boundary.violations.map((violation) => violation.file), allowedFor),
25
+ };
26
+ });
27
+ export const phantomRuleSpec = (analysis, packageJsons, workspacePackages, allowedFor) => ({
28
+ name: PHANTOM_DEPENDENCY_RULE,
29
+ message: 'Import only packages declared in package.json (archprint: the code already does).',
30
+ ignore: exempting(PHANTOM_DEPENDENCY_RULE, analysis.violations.map((violation) => violation.file), allowedFor),
31
+ packageJsons: [...packageJsons],
32
+ workspacePackages: [...workspacePackages],
33
+ });
34
+ export const serverClientRuleSpec = (analysis, allowedFor) => ({
35
+ name: SERVER_CLIENT_RULE,
36
+ message: `A "use client" module must not import a server-only module (archprint: the code already does not).`,
37
+ ignore: exempting(SERVER_CLIENT_RULE, analysis.violations.map((violation) => violation.file), allowedFor),
38
+ serverModules: [...analysis.serverModules],
39
+ });
40
+ export const internalsRuleSpec = (analysis, allowedFor) => ({
41
+ name: DEPENDENCY_INTERNALS_RULE,
42
+ message: 'Import a package by its public entry, not its src or internal folders (archprint: the code already does).',
43
+ ignore: exempting(DEPENDENCY_INTERNALS_RULE, analysis.violations.map((violation) => violation.file), allowedFor),
44
+ });
45
+ const importPair = (importer, entry) => `${importer} -> ${entry}`;
46
+ export const entryRuleSpec = (analysis, allowedFor) => ({
47
+ name: ENTRY_PURITY_RULE,
48
+ message: 'A page, layout or route handler is loaded by the framework; do not import it (archprint: the code already does not).',
49
+ ignore: exempting(ENTRY_PURITY_RULE, [], allowedFor),
50
+ entryRoles: [...ENTRY_ROLES],
51
+ exemptImports: analysis.imports.map(({ importer, file }) => importPair(importer, file)).sort(),
52
+ });
53
+ export const hasAppRules = (rules) => rules.layers.length > 0 ||
54
+ [rules.phantom, rules.serverClient, rules.internals, rules.entry].some((spec) => spec !== null);
55
+ const APP_RUNTIME = `function realPathOf(filename) {
56
+ try {
57
+ return realpathSync(filename);
58
+ } catch {
59
+ try {
60
+ return join(realpathSync(dirname(filename)), basename(filename));
61
+ } catch {
62
+ return filename;
63
+ }
64
+ }
65
+ }
66
+
67
+ function isValueImport(node) {
68
+ return (
69
+ node.importKind !== 'type' &&
70
+ (node.specifiers.length === 0 ||
71
+ node.specifiers.some((specifier) => specifier.type !== 'ImportSpecifier' || specifier.importKind !== 'type'))
72
+ );
73
+ }
74
+
75
+ function isScanned(file) {
76
+ const segments = file.split('/');
77
+ return (
78
+ isSourceFileName(segments.pop()) &&
79
+ !segments.some(isSkippedFolder) &&
80
+ !APP.ignored.some((path) => file === path || file.startsWith(path + '/'))
81
+ );
82
+ }
83
+
84
+ function appRelativePath(filename) {
85
+ const relativePath = relative(APP_DIR, realPathOf(filename));
86
+ return relativePath.startsWith('..') || isAbsolute(relativePath)
87
+ ? null
88
+ : relativePath.split(sep).join('/');
89
+ }
90
+
91
+ function importVisitors(check) {
92
+ return {
93
+ ImportDeclaration(node) {
94
+ if (node.parent.type === 'Program' && isValueImport(node)) check(node, node.source.value);
95
+ },
96
+ ImportExpression(node) {
97
+ if (node.source.type === 'Literal' && typeof node.source.value === 'string') {
98
+ check(node, node.source.value);
99
+ }
100
+ },
101
+ };
102
+ }
103
+
104
+ function isTestFile(file) {
105
+ return APP_TESTS.some((test) => test.test(file));
106
+ }
107
+
108
+ function appRule(spec, create) {
109
+ return {
110
+ meta: { type: 'problem', schema: [], messages: { forbidden: spec.message } },
111
+ create(context) {
112
+ const file = appRelativePath(context.physicalFilename);
113
+ if (file === null || !isScanned(file)) return {};
114
+ if (isTestFile(file) || spec.ignore.includes(file)) return {};
115
+ return create(context, file);
116
+ },
117
+ };
118
+ }`;
119
+ const LAYER_RUNTIME = `function makeLayerRule(spec) {
120
+ return appRule(spec, (context, file) =>
121
+ layerRootOf(file)?.layer !== spec.from
122
+ ? {}
123
+ : importVisitors((node, specifier) => {
124
+ const target = resolveImportPath(file, specifier, APP.aliases);
125
+ if (target !== null && layerRootOf(target)?.layer === spec.to) {
126
+ context.report({ node, messageId: 'forbidden' });
127
+ }
128
+ }),
129
+ );
130
+ }`;
131
+ const PACKAGE_RUNTIME = `const APP_ALIAS_PREFIXES = APP.aliases.map((alias) => alias.prefix);
132
+ const BUILTINS = new Set(builtinModules);`;
133
+ const TARGET_RUNTIME = `function firstPartyTarget(file, specifier) {
134
+ const base = resolveImportPath(file, specifier, APP.aliases);
135
+ if (base === null) return null;
136
+ return firstPartyCandidates(base).find((candidate) => existsSync(join(APP_DIR, candidate))) ?? null;
137
+ }`;
138
+ const INTERNALS_RUNTIME = `function makeInternalsRule(spec) {
139
+ return appRule(spec, (context) =>
140
+ importVisitors((node, specifier) => {
141
+ const name = packageName(specifier, APP_ALIAS_PREFIXES, BUILTINS);
142
+ if (name !== null && isPackageInternal(specifier, name)) context.report({ node, messageId: 'forbidden' });
143
+ }),
144
+ );
145
+ }`;
146
+ const ENTRY_RUNTIME = `const APP_ROLES = APP_ROLE_RULES.map(({ role, source }) => ({ role, test: new RegExp(source) }));
147
+
148
+ function roleOf(file) {
149
+ return APP_ROLES[firstMatchingRule(file, APP_ROLES)]?.role ?? 'UNKNOWN';
150
+ }
151
+
152
+ function makeEntryRule(spec) {
153
+ return appRule(spec, (context, file) =>
154
+ spec.entryRoles.includes(roleOf(file))
155
+ ? {}
156
+ : importVisitors((node, specifier) => {
157
+ const target = firstPartyTarget(file, specifier);
158
+ if (
159
+ target !== null &&
160
+ isScanned(target) &&
161
+ !isTestFile(target) &&
162
+ spec.entryRoles.includes(roleOf(target)) &&
163
+ !spec.exemptImports.includes(file + ' -> ' + target)
164
+ ) {
165
+ context.report({ node, messageId: 'forbidden' });
166
+ }
167
+ }),
168
+ );
169
+ }`;
170
+ const PHANTOM_RUNTIME = `const PHANTOM_DECLARED = new Set([
171
+ ...PHANTOM.workspacePackages,
172
+ ...PHANTOM.packageJsons.flatMap((file) => {
173
+ try {
174
+ return declaredPackages(readFileSync(resolve(CONFIG_DIR, file), 'utf8'));
175
+ } catch {
176
+ return [];
177
+ }
178
+ }),
179
+ ]);
180
+
181
+ function makePhantomRule(spec) {
182
+ return appRule(spec, (context) =>
183
+ importVisitors((node, specifier) => {
184
+ const name = packageName(specifier, APP_ALIAS_PREFIXES, BUILTINS);
185
+ if (name !== null && !PHANTOM_DECLARED.has(name)) context.report({ node, messageId: 'forbidden' });
186
+ }),
187
+ );
188
+ }`;
189
+ const SERVER_CLIENT_RUNTIME = `const SERVER_MODULES = new Set(SERVER_CLIENT.serverModules);
190
+
191
+ function makeServerClientRule(spec) {
192
+ return appRule(spec, (context, file) =>
193
+ !hasLeadingDirective(context.sourceCode.text, 'use client')
194
+ ? {}
195
+ : importVisitors((node, specifier) => {
196
+ if (specifier === ${JSON.stringify(SERVER_ONLY_PACKAGE)} || SERVER_MODULES.has(firstPartyTarget(file, specifier))) {
197
+ context.report({ node, messageId: 'forbidden' });
198
+ }
199
+ }),
200
+ );
201
+ }`;
202
+ /** The pieces of the generated ESLint file that enforce app-scoped rules, located relative to that file. */
203
+ export function renderEslintAppRules(rules, outDir) {
204
+ const relativeToConfig = (file) => path.relative(outDir, file).split(path.sep).join('/') || '.';
205
+ const app = {
206
+ app: relativeToConfig(rules.appDir),
207
+ aliases: rules.aliases,
208
+ ignored: rules.ignored,
209
+ tests: (ROLE_PATTERNS.get('TEST') ?? []).map((pattern) => pattern.source),
210
+ };
211
+ const { layers, phantom, serverClient, internals, entry } = rules;
212
+ const json = (value) => JSON.stringify(value, null, 2);
213
+ const specs = [
214
+ ...layers.map((spec) => ({ spec, make: 'makeLayerRule' })),
215
+ ...(phantom === null ? [] : [{ spec: phantom, make: 'makePhantomRule' }]),
216
+ ...(serverClient === null ? [] : [{ spec: serverClient, make: 'makeServerClientRule' }]),
217
+ ...(internals === null ? [] : [{ spec: internals, make: 'makeInternalsRule' }]),
218
+ ...(entry === null ? [] : [{ spec: entry, make: 'makeEntryRule' }]),
219
+ ];
220
+ const needsPackages = phantom !== null || internals !== null;
221
+ const needsTargets = serverClient !== null || entry !== null;
222
+ const source = [
223
+ `const APP = ${json(app)};`,
224
+ `const APP_RULES = ${json(specs.map(({ spec, make }) => ({ ...spec, make })))};`,
225
+ 'const CONFIG_DIR = dirname(fileURLToPath(import.meta.url));',
226
+ 'const APP_DIR = realPathOf(resolve(CONFIG_DIR, APP.app));',
227
+ 'const APP_TESTS = APP.tests.map((source) => new RegExp(source));',
228
+ isSkippedFolder.toString(),
229
+ isSourceFileName.toString(),
230
+ resolveImportPath.toString(),
231
+ APP_RUNTIME,
232
+ ...(layers.length === 0 ? [] : [layerRootOf.toString(), LAYER_RUNTIME]),
233
+ ...(needsPackages ? [packageName.toString(), PACKAGE_RUNTIME] : []),
234
+ ...(needsTargets ? [firstPartyCandidates.toString(), TARGET_RUNTIME] : []),
235
+ ...(phantom === null
236
+ ? []
237
+ : [
238
+ `const PHANTOM = ${json({ packageJsons: phantom.packageJsons.map(relativeToConfig), workspacePackages: phantom.workspacePackages })};`,
239
+ declaredPackages.toString(),
240
+ PHANTOM_RUNTIME,
241
+ ]),
242
+ ...(serverClient === null
243
+ ? []
244
+ : [
245
+ `const SERVER_CLIENT = ${json({ serverModules: serverClient.serverModules })};`,
246
+ hasLeadingDirective.toString(),
247
+ SERVER_CLIENT_RUNTIME,
248
+ ]),
249
+ ...(internals === null ? [] : [isPackageInternal.toString(), INTERNALS_RUNTIME]),
250
+ ...(entry === null
251
+ ? []
252
+ : [
253
+ `const APP_ROLE_RULES = ${json(ROLE_RULE_SOURCES)};`,
254
+ firstMatchingRule.toString(),
255
+ ENTRY_RUNTIME,
256
+ ]),
257
+ `const APP_MAKERS = { ${[...new Set(specs.map(({ make }) => make))].join(', ')} };`,
258
+ ].join('\n\n');
259
+ return {
260
+ imports: [
261
+ "import { existsSync, readFileSync, realpathSync } from 'node:fs';",
262
+ "import { builtinModules } from 'node:module';",
263
+ "import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';",
264
+ "import { fileURLToPath } from 'node:url';",
265
+ ].join('\n'),
266
+ source,
267
+ rules: 'APP_RULES.map((spec) => [spec.name, APP_MAKERS[spec.make](spec)])',
268
+ config: `{
269
+ files: ${LINTED_FILES},
270
+ plugins: { archprint: plugin },
271
+ rules: Object.fromEntries(APP_RULES.map((spec) => ['archprint/' + spec.name, 'error'])),
272
+ }`,
273
+ };
274
+ }
275
+ //# sourceMappingURL=eslint-app-emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eslint-app-emitter.js","sourceRoot":"","sources":["../../src/generator/eslint-app-emitter.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
- import type { RenderedEslintLayers } from './eslint-layer-emitter.js';
1
+ import type { RenderedAppRules } from './eslint-app-emitter.js';
2
2
  import { type ForbiddenImportSpec } from './eslint-plugin-emitter.js';
3
3
  export declare function renderEslintPreset(specs: readonly ForbiddenImportSpec[], blocks: readonly unknown[], options?: {
4
4
  ignore?: string;
5
5
  adoptPath?: string;
6
- layers?: RenderedEslintLayers;
6
+ app?: RenderedAppRules;
7
7
  }): string;
8
8
  //# sourceMappingURL=eslint-preset-emitter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-preset-emitter.d.ts","sourceRoot":"","sources":["../../src/generator/eslint-preset-emitter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,4BAA4B,CAAC;AAEpC,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,MAAM,EAAE,SAAS,OAAO,EAAE,EAC1B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,oBAAoB,CAAA;CAAO,GACnF,MAAM,CAyBR"}
1
+ {"version":3,"file":"eslint-preset-emitter.d.ts","sourceRoot":"","sources":["../../src/generator/eslint-preset-emitter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,4BAA4B,CAAC;AAEpC,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,mBAAmB,EAAE,EACrC,MAAM,EAAE,SAAS,OAAO,EAAE,EAC1B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,gBAAgB,CAAA;CAAO,GAC5E,MAAM,CAyBR"}
@@ -2,22 +2,22 @@ import { MAKE_RULE_FUNCTION, PLUGIN_CONFIGS, } from './eslint-plugin-emitter.js'
2
2
  export function renderEslintPreset(specs, blocks, options = {}) {
3
3
  const ignore = options.ignore ?? '**/.archprint/**';
4
4
  const adoptPath = options.adoptPath ?? './.archprint/eslint.mjs';
5
- const { layers } = options;
5
+ const { app } = options;
6
6
  const header = `// archprint eslint rules (generated, self-contained). Regenerate with \`archprint generate\`; remove with \`archprint eject\`.
7
7
  // Adopt it in one line: import archprint from '${adoptPath}'; export default [...archprint];
8
- ${layers ? `${layers.imports}\n` : ''}`;
9
- const rules = layers
8
+ ${app ? `${app.imports}\n` : ''}`;
9
+ const rules = app
10
10
  ? `Object.fromEntries([
11
11
  ...SPECS.map((spec) => [spec.name, makeRule(spec)]),
12
- ...${layers.rules},
12
+ ...${app.rules},
13
13
  ])`
14
14
  : 'Object.fromEntries(SPECS.map((spec) => [spec.name, makeRule(spec)]))';
15
- const configs = layers ? `[...${PLUGIN_CONFIGS}, ${layers.config}]` : PLUGIN_CONFIGS;
15
+ const configs = app ? `[...${PLUGIN_CONFIGS}, ${app.config}]` : PLUGIN_CONFIGS;
16
16
  return `${header}const SPECS = ${JSON.stringify(specs, null, 2)};
17
17
  const BLOCKS = ${JSON.stringify(blocks, null, 2)};
18
18
 
19
19
  ${MAKE_RULE_FUNCTION}
20
- ${layers ? `\n${layers.source}\n` : ''}
20
+ ${app ? `\n${app.source}\n` : ''}
21
21
  const rules = ${rules};
22
22
  const plugin = { rules };
23
23
  const pluginConfigs = ${configs};
@@ -1 +1 @@
1
- {"version":3,"file":"eslint-preset-emitter.js","sourceRoot":"","sources":["../../src/generator/eslint-preset-emitter.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,kBAAkB,EAClB,cAAc,GACf,MAAM,4BAA4B,CAAC;AAEpC,MAAM,UAAU,kBAAkB,CAChC,KAAqC,EACrC,MAA0B,EAC1B,UAAkF,EAAE;IAEpF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,kBAAkB,CAAC;IACpD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,yBAAyB,CAAC;IACjE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC3B,MAAM,MAAM,GAAG;mDACkC,SAAS;EAC1D,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM;QAClB,CAAC,CAAC;;OAEC,MAAM,CAAC,KAAK;GAChB;QACC,CAAC,CAAC,sEAAsE,CAAC;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,cAAc,KAAK,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;IACrF,OAAO,GAAG,MAAM,iBAAiB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBAChD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;;EAE9C,kBAAkB;EAClB,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE;gBACtB,KAAK;;wBAEG,OAAO;;+BAEA,MAAM;CACpC,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"eslint-preset-emitter.js","sourceRoot":"","sources":["../../src/generator/eslint-preset-emitter.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,kBAAkB,EAClB,cAAc,GACf,MAAM,4BAA4B,CAAC;AAEpC,MAAM,UAAU,kBAAkB,CAChC,KAAqC,EACrC,MAA0B,EAC1B,UAA2E,EAAE;IAE7E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,kBAAkB,CAAC;IACpD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,yBAAyB,CAAC;IACjE,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;IACxB,MAAM,MAAM,GAAG;mDACkC,SAAS;EAC1D,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,GAAG;QACf,CAAC,CAAC;;OAEC,GAAG,CAAC,KAAK;GACb;QACC,CAAC,CAAC,sEAAsE,CAAC;IAC3E,MAAM,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,OAAO,cAAc,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC;IAC/E,OAAO,GAAG,MAAM,iBAAiB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBAChD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;;EAE9C,kBAAkB;EAClB,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE;gBAChB,KAAK;;wBAEG,OAAO;;+BAEA,MAAM;CACpC,CAAC;AACF,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { GenerationStatus } from '../detector/confidence-gate.js';
2
2
  import type { FeatureSliceGroup } from '../detector/feature-slice-detector.js';
3
+ export declare const featureSliceRuleName: (container: string) => string;
3
4
  export interface CrossSliceRule {
4
5
  name: string;
5
6
  comment: string;
@@ -1 +1 @@
1
- {"version":3,"file":"feature-slice-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/feature-slice-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAU/E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,OAAO,GAAE,SAAS,gBAAgB,EAAa,GAC9C,gBAAgB,CAclB"}
1
+ {"version":3,"file":"feature-slice-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/feature-slice-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAO/E,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,KAAG,MACpB,CAAC;AAKtC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,SAAS,iBAAiB,EAAE,EACpC,OAAO,GAAE,SAAS,gBAAgB,EAAa,GAC9C,gBAAgB,CAclB"}
@@ -1,5 +1,6 @@
1
1
  const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
2
2
  const slug = (container) => container.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '');
3
+ export const featureSliceRuleName = (container) => `no-cross-slice-${slug(container)}`;
3
4
  const confidencePct = (group) => `${(group.gate.conditions.confidence.value * 100).toFixed(0)}%`;
4
5
  export function toDependencyCruiserFeatureSlice(groups, include = ['AUTO']) {
5
6
  const forbidden = groups
@@ -7,7 +8,7 @@ export function toDependencyCruiserFeatureSlice(groups, include = ['AUTO']) {
7
8
  .map((group) => {
8
9
  const container = escapeRegExp(group.container);
9
10
  return {
10
- name: `no-cross-slice-${slug(group.container)}`,
11
+ name: featureSliceRuleName(group.container),
11
12
  comment: `Archprint inferred slice isolation: the ${group.sliceCount} slices under "${group.container}" do not import each other (${group.sliceFileCount - group.crossImporterCount}/${group.sliceFileCount} slice files conform); cross-slice imports are forbidden (confidence ${confidencePct(group)}).`,
12
13
  severity: 'error',
13
14
  from: { path: `^${container}/([^/]+)/` },
@@ -1 +1 @@
1
- {"version":3,"file":"feature-slice-emitters.js","sourceRoot":"","sources":["../../src/generator/feature-slice-emitters.ts"],"names":[],"mappings":"AAGA,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAE7F,MAAM,IAAI,GAAG,CAAC,SAAiB,EAAU,EAAE,CACzC,SAAS,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAEjE,MAAM,aAAa,GAAG,CAAC,KAAwB,EAAU,EAAE,CACzD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAclE,MAAM,UAAU,+BAA+B,CAC7C,MAAoC,EACpC,UAAuC,CAAC,MAAM,CAAC;IAE/C,MAAM,SAAS,GAAG,MAAM;SACrB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SACtD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,kBAAkB,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;YAC/C,OAAO,EAAE,2CAA2C,KAAK,CAAC,UAAU,kBAAkB,KAAK,CAAC,SAAS,+BAA+B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,cAAc,wEAAwE,aAAa,CAAC,KAAK,CAAC,IAAI;YAC3S,QAAQ,EAAE,OAAgB;YAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,SAAS,WAAW,EAAE;YACxC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,SAAS,WAAW,EAAE,OAAO,EAAE,IAAI,SAAS,MAAM,EAAE;SACrE,CAAC;IACJ,CAAC,CAAC,CAAC;IACL,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"feature-slice-emitters.js","sourceRoot":"","sources":["../../src/generator/feature-slice-emitters.ts"],"names":[],"mappings":"AAGA,MAAM,YAAY,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAE7F,MAAM,IAAI,GAAG,CAAC,SAAiB,EAAU,EAAE,CACzC,SAAS,CAAC,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,SAAiB,EAAU,EAAE,CAChE,kBAAkB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;AAEtC,MAAM,aAAa,GAAG,CAAC,KAAwB,EAAU,EAAE,CACzD,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAclE,MAAM,UAAU,+BAA+B,CAC7C,MAAoC,EACpC,UAAuC,CAAC,MAAM,CAAC;IAE/C,MAAM,SAAS,GAAG,MAAM;SACrB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SACtD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,oBAAoB,CAAC,KAAK,CAAC,SAAS,CAAC;YAC3C,OAAO,EAAE,2CAA2C,KAAK,CAAC,UAAU,kBAAkB,KAAK,CAAC,SAAS,+BAA+B,KAAK,CAAC,cAAc,GAAG,KAAK,CAAC,kBAAkB,IAAI,KAAK,CAAC,cAAc,wEAAwE,aAAa,CAAC,KAAK,CAAC,IAAI;YAC3S,QAAQ,EAAE,OAAgB;YAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,SAAS,WAAW,EAAE;YACxC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,SAAS,WAAW,EAAE,OAAO,EAAE,IAAI,SAAS,MAAM,EAAE;SACrE,CAAC;IACJ,CAAC,CAAC,CAAC;IACL,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"layer-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/layer-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAKnE,eAAO,MAAM,aAAa,GAAI,cAAc;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,KAAG,MACpD,CAAC;AAkBxB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC;IACpD,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACrD;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,qBAAqB,EAAE,CAAC;CACpC;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,OAAO,GAAE,SAAS,gBAAgB,EAAa,EAC/C,OAAO,SAAM,EACb,UAAU,GAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,MAAM,EAAa,GAC3D,uBAAuB,CAkBzB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE;QAAE,qBAAqB,EAAE,uBAAuB,EAAE,CAAA;KAAE,CAAC;IAC/D,KAAK,EAAE;QACL,0BAA0B,EAAE,CAAC,OAAO,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,oBAAoB,EAAE,CAAA;SAAE,CAAC,CAAC;KAC5F,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,OAAO,GAAE,SAAS,gBAAgB,EAAa,GAC9C,sBAAsB,CA6BxB"}
1
+ {"version":3,"file":"layer-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/layer-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAKnE,eAAO,MAAM,aAAa,GAAI,cAAc;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,KAAG,MACpD,CAAC;AAaxB,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC;IACpD,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACrD;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,qBAAqB,EAAE,CAAC;CACpC;AAED,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,OAAO,GAAE,SAAS,gBAAgB,EAAa,EAC/C,OAAO,SAAM,EACb,UAAU,GAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,MAAM,EAAa,GAC3D,uBAAuB,CAkBzB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE;QAAE,qBAAqB,EAAE,uBAAuB,EAAE,CAAA;KAAE,CAAC;IAC/D,KAAK,EAAE;QACL,0BAA0B,EAAE,CAAC,OAAO,EAAE;YAAE,OAAO,EAAE,OAAO,CAAC;YAAC,KAAK,EAAE,oBAAoB,EAAE,CAAA;SAAE,CAAC,CAAC;KAC5F,CAAC;CACH;AAED,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,aAAa,EAAE,EACpC,OAAO,GAAE,SAAS,gBAAgB,EAAa,GAC9C,sBAAsB,CA6BxB"}
@@ -1,11 +1,7 @@
1
- import { exemptDepcruiseFrom, TEST_ROLE_REGEX } from './depcruise-exempt.js';
1
+ import { appPathPrefix, exemptDepcruiseFrom, TEST_ROLE_REGEX } from './depcruise-exempt.js';
2
2
  const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
3
3
  export const layerRuleName = ({ from, to }) => `no-${from}-to-${to}`;
4
- const appPrefix = (appPath) => {
5
- const normalized = appPath.replace(/\\/g, '/').replace(/\/+$/, '');
6
- return normalized === '' || normalized === '.' ? '' : `${escapeRegExp(normalized)}/`;
7
- };
8
- const layerPath = (dirs, appPath) => `^${appPrefix(appPath)}(?:${dirs.map(escapeRegExp).join('|')})/`;
4
+ const layerPath = (dirs, appPath) => `^${appPathPrefix(appPath)}(?:${dirs.map(escapeRegExp).join('|')})/`;
9
5
  const confidencePct = (boundary) => `${(boundary.gate.conditions.confidence.value * 100).toFixed(0)}%`;
10
6
  const selected = (boundaries, include) => boundaries.filter((boundary) => include.includes(boundary.gate.status));
11
7
  export function toDependencyCruiser(boundaries, include = ['AUTO'], appPath = '.', allowedFor = () => []) {
@@ -1 +1 @@
1
- {"version":3,"file":"layer-emitters.js","sourceRoot":"","sources":["../../src/generator/layer-emitters.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"layer-emitters.js","sourceRoot":"","sources":["../../src/generator/layer-emitters.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { PhantomDependencyAnalysis } from '../detector/phantom-dependency-detector.js';
2
+ export declare const PHANTOM_DEPENDENCY_RULE = "no-phantom-dependencies";
2
3
  export interface PhantomDependencyRule {
3
4
  name: string;
4
5
  comment: string;
@@ -13,5 +14,5 @@ export interface PhantomDependencyRule {
13
14
  export interface PhantomDependencyConfig {
14
15
  forbidden: PhantomDependencyRule[];
15
16
  }
16
- export declare function toDependencyCruiserPhantomDependencies(analysis: PhantomDependencyAnalysis): PhantomDependencyConfig;
17
+ export declare function toDependencyCruiserPhantomDependencies(analysis: PhantomDependencyAnalysis, allowedFor?: (ruleId: string) => readonly string[]): PhantomDependencyConfig;
17
18
  //# sourceMappingURL=phantom-dependency-emitters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"phantom-dependency-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/phantom-dependency-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAG5F,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC;IACrC,EAAE,EAAE;QAAE,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,qBAAqB,EAAE,CAAC;CACpC;AAED,wBAAgB,sCAAsC,CACpD,QAAQ,EAAE,yBAAyB,GAClC,uBAAuB,CAmBzB"}
1
+ {"version":3,"file":"phantom-dependency-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/phantom-dependency-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAG5F,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;KAAE,CAAC;IACrC,EAAE,EAAE;QAAE,eAAe,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,qBAAqB,EAAE,CAAC;CACpC;AAED,wBAAgB,sCAAsC,CACpD,QAAQ,EAAE,yBAAyB,EACnC,UAAU,GAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,MAAM,EAAa,GAC3D,uBAAuB,CAyBzB"}
@@ -1,5 +1,6 @@
1
1
  import { exemptDepcruiseFrom, TEST_ROLE_REGEX } from './depcruise-exempt.js';
2
- export function toDependencyCruiserPhantomDependencies(analysis) {
2
+ export const PHANTOM_DEPENDENCY_RULE = 'no-phantom-dependencies';
3
+ export function toDependencyCruiserPhantomDependencies(analysis, allowedFor = () => []) {
3
4
  if (analysis.externalImporterCount === 0 || analysis.gate.status !== 'AUTO') {
4
5
  return { forbidden: [] };
5
6
  }
@@ -8,11 +9,14 @@ export function toDependencyCruiserPhantomDependencies(analysis) {
8
9
  return {
9
10
  forbidden: [
10
11
  {
11
- name: 'no-phantom-dependencies',
12
+ name: PHANTOM_DEPENDENCY_RULE,
12
13
  comment: `Archprint inferred dependency declaration: ${conform}/${analysis.externalImporterCount} files import only packages declared in package.json; importing an undeclared (phantom/transitive) dependency is forbidden (confidence ${floor}).`,
13
14
  severity: 'error',
14
15
  from: {
15
- pathNot: exemptDepcruiseFrom([TEST_ROLE_REGEX, 'node_modules'], analysis.violations),
16
+ pathNot: exemptDepcruiseFrom([TEST_ROLE_REGEX, 'node_modules'], [
17
+ ...analysis.violations,
18
+ ...allowedFor(PHANTOM_DEPENDENCY_RULE).map((file) => ({ file })),
19
+ ]),
16
20
  },
17
21
  to: { dependencyTypes: ['npm-no-pkg', 'npm-unknown'] },
18
22
  },
@@ -1 +1 @@
1
- {"version":3,"file":"phantom-dependency-emitters.js","sourceRoot":"","sources":["../../src/generator/phantom-dependency-emitters.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAc7E,MAAM,UAAU,sCAAsC,CACpD,QAAmC;IAEnC,IAAI,QAAQ,CAAC,qBAAqB,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC5E,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,qBAAqB,GAAG,QAAQ,CAAC,aAAa,CAAC;IACxE,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACjF,OAAO;QACL,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,yBAAyB;gBAC/B,OAAO,EAAE,8CAA8C,OAAO,IAAI,QAAQ,CAAC,qBAAqB,0IAA0I,KAAK,IAAI;gBACnP,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE;oBACJ,OAAO,EAAE,mBAAmB,CAAC,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC;iBACrF;gBACD,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE;aACvD;SACF;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"phantom-dependency-emitters.js","sourceRoot":"","sources":["../../src/generator/phantom-dependency-emitters.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7E,MAAM,CAAC,MAAM,uBAAuB,GAAG,yBAAyB,CAAC;AAcjE,MAAM,UAAU,sCAAsC,CACpD,QAAmC,EACnC,aAAoD,GAAG,EAAE,CAAC,EAAE;IAE5D,IAAI,QAAQ,CAAC,qBAAqB,KAAK,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC5E,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;IAC3B,CAAC;IACD,MAAM,OAAO,GAAG,QAAQ,CAAC,qBAAqB,GAAG,QAAQ,CAAC,aAAa,CAAC;IACxE,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACjF,OAAO;QACL,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,uBAAuB;gBAC7B,OAAO,EAAE,8CAA8C,OAAO,IAAI,QAAQ,CAAC,qBAAqB,0IAA0I,KAAK,IAAI;gBACnP,QAAQ,EAAE,OAAO;gBACjB,IAAI,EAAE;oBACJ,OAAO,EAAE,mBAAmB,CAC1B,CAAC,eAAe,EAAE,cAAc,CAAC,EACjC;wBACE,GAAG,QAAQ,CAAC,UAAU;wBACtB,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;qBACjE,CACF;iBACF;gBACD,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,YAAY,EAAE,aAAa,CAAC,EAAE;aACvD;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -1,5 +1,7 @@
1
1
  import type { GenerationStatus } from '../detector/confidence-gate.js';
2
2
  import type { RoleBoundary } from '../detector/role-layering-detector.js';
3
+ import type { Role } from '../scanner/role-classifier.js';
4
+ export declare const roleLayeringRuleName: (from: Role, to: Role) => string;
3
5
  export interface RoleLayeringRule {
4
6
  name: string;
5
7
  comment: string;
@@ -1 +1 @@
1
- {"version":3,"file":"role-layering-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/role-layering-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAY1E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,SAAS,YAAY,EAAE,EACnC,OAAO,GAAE,SAAS,gBAAgB,EAAa,GAC9C,kBAAkB,CAWpB"}
1
+ {"version":3,"file":"role-layering-emitters.d.ts","sourceRoot":"","sources":["../../src/generator/role-layering-emitters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAE1E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,+BAA+B,CAAC;AAO1D,eAAO,MAAM,oBAAoB,GAAI,MAAM,IAAI,EAAE,IAAI,IAAI,KAAG,MACT,CAAC;AAKpD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACvB,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,SAAS,YAAY,EAAE,EACnC,OAAO,GAAE,SAAS,gBAAgB,EAAa,GAC9C,kBAAkB,CAWpB"}
@@ -3,12 +3,13 @@ const rolePath = (role) => {
3
3
  const sources = (ROLE_PATTERNS.get(role) ?? []).map((pattern) => pattern.source);
4
4
  return sources.length === 1 ? sources[0] : `(${sources.join('|')})`;
5
5
  };
6
+ export const roleLayeringRuleName = (from, to) => `no-${from.toLowerCase()}-to-${to.toLowerCase()}`;
6
7
  const confidencePct = (boundary) => `${(boundary.gate.conditions.confidence.value * 100).toFixed(0)}%`;
7
8
  export function toDependencyCruiserRoleLayering(boundaries, include = ['AUTO']) {
8
9
  const forbidden = boundaries
9
10
  .filter((boundary) => include.includes(boundary.gate.status))
10
11
  .map((boundary) => ({
11
- name: `no-${boundary.from.toLowerCase()}-to-${boundary.to.toLowerCase()}`,
12
+ name: roleLayeringRuleName(boundary.from, boundary.to),
12
13
  comment: `Archprint inferred role layering: ${boundary.reverseFlow} ${boundary.to} file(s) depend on ${boundary.from}, not the reverse; a ${boundary.from} must not import a ${boundary.to} (confidence ${confidencePct(boundary)}).`,
13
14
  severity: 'error',
14
15
  from: { path: rolePath(boundary.from) },
@@ -1 +1 @@
1
- {"version":3,"file":"role-layering-emitters.js","sourceRoot":"","sources":["../../src/generator/role-layering-emitters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAU,EAAE;IACtC,MAAM,OAAO,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjF,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACvE,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,QAAsB,EAAU,EAAE,CACvD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAcrE,MAAM,UAAU,+BAA+B,CAC7C,UAAmC,EACnC,UAAuC,CAAC,MAAM,CAAC;IAE/C,MAAM,SAAS,GAAG,UAAU;SACzB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC5D,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClB,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,QAAQ,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE;QACzE,OAAO,EAAE,qCAAqC,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,EAAE,sBAAsB,QAAQ,CAAC,IAAI,wBAAwB,QAAQ,CAAC,IAAI,sBAAsB,QAAQ,CAAC,EAAE,gBAAgB,aAAa,CAAC,QAAQ,CAAC,IAAI;QACrO,QAAQ,EAAE,OAAgB;QAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QACvC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;KACpC,CAAC,CAAC,CAAC;IACN,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"role-layering-emitters.js","sourceRoot":"","sources":["../../src/generator/role-layering-emitters.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAG9D,MAAM,QAAQ,GAAG,CAAC,IAAU,EAAU,EAAE;IACtC,MAAM,OAAO,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACjF,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACvE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAU,EAAE,EAAQ,EAAU,EAAE,CACnE,MAAM,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AAEpD,MAAM,aAAa,GAAG,CAAC,QAAsB,EAAU,EAAE,CACvD,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AAcrE,MAAM,UAAU,+BAA+B,CAC7C,UAAmC,EACnC,UAAuC,CAAC,MAAM,CAAC;IAE/C,MAAM,SAAS,GAAG,UAAU;SACzB,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC5D,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAClB,IAAI,EAAE,oBAAoB,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC;QACtD,OAAO,EAAE,qCAAqC,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,EAAE,sBAAsB,QAAQ,CAAC,IAAI,wBAAwB,QAAQ,CAAC,IAAI,sBAAsB,QAAQ,CAAC,EAAE,gBAAgB,aAAa,CAAC,QAAQ,CAAC,IAAI;QACrO,QAAQ,EAAE,OAAgB;QAC1B,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QACvC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE;KACpC,CAAC,CAAC,CAAC;IACN,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC"}
@@ -1,17 +1,24 @@
1
- import type { ServerClientAnalysis } from '../detector/server-client-detector.js';
1
+ import { type ServerClientAnalysis } from '../detector/server-client-detector.js';
2
+ export declare const SERVER_CLIENT_RULE = "no-server-only-in-client";
2
3
  export interface ServerClientRule {
3
4
  name: string;
4
5
  comment: string;
5
6
  severity: 'error' | 'warn' | 'info';
6
7
  from: {
7
8
  path: string;
9
+ pathNot: string | string[];
8
10
  };
9
11
  to: {
10
- path: string;
12
+ path: string | string[];
13
+ dependencyTypesNot: string[];
11
14
  };
12
15
  }
13
16
  export interface ServerClientConfig {
14
17
  forbidden: ServerClientRule[];
15
18
  }
16
- export declare function toDependencyCruiserServerClient(analysis: ServerClientAnalysis): ServerClientConfig;
19
+ /**
20
+ * The "use client" files the scan found must not import a server-only module or the server-only package. Files
21
+ * that become client components after generation are not covered until the next generate.
22
+ */
23
+ export declare function toDependencyCruiserServerClient(analysis: ServerClientAnalysis, appPath: string, allowedFor: (ruleId: string) => readonly string[]): ServerClientConfig;
17
24
  //# sourceMappingURL=server-client-emitters.d.ts.map