laymos 0.0.2 → 0.0.3

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 (133) hide show
  1. package/package.json +3 -3
  2. package/dist/architecture/analyze-project/analyze-project.d.ts +0 -9
  3. package/dist/architecture/analyze-project/analyze-project.d.ts.map +0 -1
  4. package/dist/architecture/analyze-project/analyze-project.js +0 -47
  5. package/dist/architecture/analyze-project/index.d.ts +0 -3
  6. package/dist/architecture/analyze-project/index.d.ts.map +0 -1
  7. package/dist/architecture/analyze-project/index.js +0 -1
  8. package/dist/architecture/build-report/build-report.d.ts +0 -7
  9. package/dist/architecture/build-report/build-report.d.ts.map +0 -1
  10. package/dist/architecture/build-report/build-report.js +0 -80
  11. package/dist/architecture/build-report/index.d.ts +0 -2
  12. package/dist/architecture/build-report/index.d.ts.map +0 -1
  13. package/dist/architecture/build-report/index.js +0 -1
  14. package/dist/architecture/errors.d.ts +0 -11
  15. package/dist/architecture/errors.d.ts.map +0 -1
  16. package/dist/architecture/errors.js +0 -3
  17. package/dist/architecture/extract-dependencies/extract-dependencies.d.ts +0 -12
  18. package/dist/architecture/extract-dependencies/extract-dependencies.d.ts.map +0 -1
  19. package/dist/architecture/extract-dependencies/extract-dependencies.js +0 -162
  20. package/dist/architecture/extract-dependencies/index.d.ts +0 -3
  21. package/dist/architecture/extract-dependencies/index.d.ts.map +0 -1
  22. package/dist/architecture/extract-dependencies/index.js +0 -1
  23. package/dist/architecture/resolve-architecture/index.d.ts +0 -3
  24. package/dist/architecture/resolve-architecture/index.d.ts.map +0 -1
  25. package/dist/architecture/resolve-architecture/index.js +0 -1
  26. package/dist/architecture/resolve-architecture/resolve-architecture.d.ts +0 -24
  27. package/dist/architecture/resolve-architecture/resolve-architecture.d.ts.map +0 -1
  28. package/dist/architecture/resolve-architecture/resolve-architecture.js +0 -74
  29. package/dist/architecture/validate-rules/index.d.ts +0 -3
  30. package/dist/architecture/validate-rules/index.d.ts.map +0 -1
  31. package/dist/architecture/validate-rules/index.js +0 -1
  32. package/dist/architecture/validate-rules/validate-rules.d.ts +0 -10
  33. package/dist/architecture/validate-rules/validate-rules.d.ts.map +0 -1
  34. package/dist/architecture/validate-rules/validate-rules.js +0 -80
  35. package/dist/cli/deps/dependency-tree.d.ts +0 -3
  36. package/dist/cli/deps/dependency-tree.d.ts.map +0 -1
  37. package/dist/cli/deps/dependency-tree.js +0 -39
  38. package/dist/cli/deps/deps.d.ts +0 -7
  39. package/dist/cli/deps/deps.d.ts.map +0 -1
  40. package/dist/cli/deps/deps.js +0 -26
  41. package/dist/cli/deps/index.d.ts +0 -2
  42. package/dist/cli/deps/index.d.ts.map +0 -1
  43. package/dist/cli/deps/index.js +0 -2
  44. package/dist/config/define-config.d.ts +0 -8
  45. package/dist/config/define-config.d.ts.map +0 -1
  46. package/dist/config/define-config.js +0 -373
  47. package/dist/config/index.d.ts +0 -11
  48. package/dist/config/index.d.ts.map +0 -1
  49. package/dist/config/index.js +0 -6
  50. package/dist/config/layer-graph.d.ts +0 -7
  51. package/dist/config/layer-graph.d.ts.map +0 -1
  52. package/dist/config/layer-graph.js +0 -26
  53. package/dist/config/layer.d.ts +0 -5
  54. package/dist/config/layer.d.ts.map +0 -1
  55. package/dist/config/layer.js +0 -8
  56. package/dist/config/load-config/index.d.ts +0 -2
  57. package/dist/config/load-config/index.d.ts.map +0 -1
  58. package/dist/config/load-config/index.js +0 -1
  59. package/dist/config/load-config/load-config.d.ts +0 -34
  60. package/dist/config/load-config/load-config.d.ts.map +0 -1
  61. package/dist/config/load-config/load-config.js +0 -127
  62. package/dist/config/module.d.ts +0 -11
  63. package/dist/config/module.d.ts.map +0 -1
  64. package/dist/config/module.js +0 -22
  65. package/dist/config/path.d.ts +0 -4
  66. package/dist/config/path.d.ts.map +0 -1
  67. package/dist/config/path.js +0 -32
  68. package/dist/config/project-narrative.d.ts +0 -15
  69. package/dist/config/project-narrative.d.ts.map +0 -1
  70. package/dist/config/project-narrative.js +0 -11
  71. package/dist/config/types.d.ts +0 -38
  72. package/dist/config/types.d.ts.map +0 -1
  73. package/dist/config/types.js +0 -1
  74. package/dist/domain/architecture-analysis/modules/unexposed-modules.d.ts +0 -3
  75. package/dist/domain/architecture-analysis/modules/unexposed-modules.d.ts.map +0 -1
  76. package/dist/domain/architecture-analysis/modules/unexposed-modules.js +0 -10
  77. package/dist/domain/project-config/validation/modules/containment.d.ts +0 -3
  78. package/dist/domain/project-config/validation/modules/containment.d.ts.map +0 -1
  79. package/dist/domain/project-config/validation/modules/containment.js +0 -24
  80. package/dist/domain/project-config/validation/modules/kinds.d.ts +0 -3
  81. package/dist/domain/project-config/validation/modules/kinds.d.ts.map +0 -1
  82. package/dist/domain/project-config/validation/modules/kinds.js +0 -18
  83. package/dist/domain/project-config/validation/modules/nested.d.ts +0 -3
  84. package/dist/domain/project-config/validation/modules/nested.d.ts.map +0 -1
  85. package/dist/domain/project-config/validation/modules/nested.js +0 -34
  86. package/dist/domain/project-config/validation/modules/subpaths.d.ts +0 -3
  87. package/dist/domain/project-config/validation/modules/subpaths.d.ts.map +0 -1
  88. package/dist/domain/project-config/validation/modules/subpaths.js +0 -40
  89. package/dist/entrypoints/cli/cli.d.ts +0 -3
  90. package/dist/entrypoints/cli/cli.d.ts.map +0 -1
  91. package/dist/entrypoints/cli/cli.js +0 -6
  92. package/dist/entrypoints/cli/run.d.ts +0 -13
  93. package/dist/entrypoints/cli/run.d.ts.map +0 -1
  94. package/dist/entrypoints/cli/run.js +0 -155
  95. package/dist/entrypoints/cli/test-output.d.ts +0 -17
  96. package/dist/entrypoints/cli/test-output.d.ts.map +0 -1
  97. package/dist/entrypoints/cli/test-output.js +0 -244
  98. package/dist/entrypoints/node/index.d.ts +0 -24
  99. package/dist/entrypoints/node/index.d.ts.map +0 -1
  100. package/dist/entrypoints/node/index.js +0 -27
  101. package/dist/entrypoints/report/index.d.ts +0 -2
  102. package/dist/entrypoints/report/index.d.ts.map +0 -1
  103. package/dist/entrypoints/report/index.js +0 -1
  104. package/dist/markdown/index.d.ts +0 -3
  105. package/dist/markdown/index.d.ts.map +0 -1
  106. package/dist/markdown/index.js +0 -1
  107. package/dist/markdown/markdown.d.ts +0 -7
  108. package/dist/markdown/markdown.d.ts.map +0 -1
  109. package/dist/markdown/markdown.js +0 -13
  110. package/dist/orchestrator/query-dependencies/index.d.ts +0 -3
  111. package/dist/orchestrator/query-dependencies/index.d.ts.map +0 -1
  112. package/dist/orchestrator/query-dependencies/index.js +0 -4
  113. package/dist/orchestrator/query-dependencies/query-dependencies.d.ts +0 -12
  114. package/dist/orchestrator/query-dependencies/query-dependencies.d.ts.map +0 -1
  115. package/dist/orchestrator/query-dependencies/query-dependencies.js +0 -20
  116. package/dist/report/architecture.d.ts +0 -104
  117. package/dist/report/architecture.d.ts.map +0 -1
  118. package/dist/report/architecture.js +0 -1
  119. package/dist/report/index.d.ts +0 -4
  120. package/dist/report/index.d.ts.map +0 -1
  121. package/dist/report/index.js +0 -2
  122. package/dist/report/tests.d.ts +0 -411
  123. package/dist/report/tests.d.ts.map +0 -1
  124. package/dist/report/tests.js +0 -102
  125. package/dist/tests/authoring/index.d.ts +0 -72
  126. package/dist/tests/authoring/index.d.ts.map +0 -1
  127. package/dist/tests/authoring/index.js +0 -312
  128. package/dist/tests/run-tests/index.d.ts +0 -3
  129. package/dist/tests/run-tests/index.d.ts.map +0 -1
  130. package/dist/tests/run-tests/index.js +0 -1
  131. package/dist/tests/run-tests/run-tests.d.ts +0 -26
  132. package/dist/tests/run-tests/run-tests.d.ts.map +0 -1
  133. package/dist/tests/run-tests/run-tests.js +0 -284
@@ -1 +0,0 @@
1
- {"version":3,"file":"dependency-tree.d.ts","sourceRoot":"","sources":["../../../src/cli/deps/dependency-tree.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAG1C,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,eAAe,EAAE,GAClC,MAAM,CAIR"}
@@ -1,39 +0,0 @@
1
- import * as colors from 'yoctocolors';
2
- import { groupByPath } from '../../domain/file-graph/index.js';
3
- export function renderDependencyTree(target, entries) {
4
- return [renderLegend(), '', ...renderRoot(groupByPath(target, entries))].join('\n');
5
- }
6
- // A lone root drawn with a "└── " connector reads oddly when it's the only
7
- // thing at that level (nothing else for the connector to distinguish it
8
- // from) — print it bare and start the connectors one level down instead.
9
- function renderRoot(nodes) {
10
- if (nodes.length !== 1)
11
- return renderNodes(nodes, '');
12
- const root = nodes[0];
13
- const label = root.kind === undefined ? root.name : colorize(root.name, root.kind);
14
- return [label, ...renderNodes(root.children, '')];
15
- }
16
- function renderLegend() {
17
- return [
18
- `${colors.green('■')} target`,
19
- `${colors.yellow('■')} direct dependency`,
20
- `${colors.gray('■')} transitive dependency`,
21
- ].join(' ');
22
- }
23
- function renderNodes(nodes, prefix) {
24
- return nodes.flatMap((node, index) => {
25
- const isLast = index === nodes.length - 1;
26
- const connector = isLast ? '└── ' : '├── ';
27
- const childPrefix = prefix + (isLast ? ' ' : '│ ');
28
- const label = node.kind === undefined ? node.name : colorize(node.name, node.kind);
29
- return [
30
- `${prefix}${connector}${label}`,
31
- ...renderNodes(node.children, childPrefix),
32
- ];
33
- });
34
- }
35
- function colorize(label, kind) {
36
- if (kind === 'target')
37
- return colors.green(label);
38
- return kind === 'direct' ? colors.yellow(label) : colors.gray(label);
39
- }
@@ -1,7 +0,0 @@
1
- import { Effect } from 'effect';
2
- import { Command } from 'effect/unstable/cli';
3
- export declare function makeDepsCommand<R>(configPath: Effect.Effect<string, never, R>): Command.Command<"deps", {
4
- readonly path: string;
5
- readonly recursive: boolean;
6
- }, {}, import("../../index.js").ConfigError | import("../../index.js").CruiseError | import("../../orchestrator/query-dependencies/query-dependencies.js").DependencyTargetNotFound, Exclude<R, "effect/unstable/cli/GlobalFlag/log-level">>;
7
- //# sourceMappingURL=deps.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/cli/deps/deps.ts"],"names":[],"mappings":"AAEA,OAAO,EAAW,MAAM,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAY,OAAO,EAAQ,MAAM,qBAAqB,CAAC;AAc9D,wBAAgB,eAAe,CAAC,CAAC,EAC/B,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;;;6OAyB5C"}
@@ -1,26 +0,0 @@
1
- import { dirname, relative, resolve, sep } from 'node:path';
2
- import { Console, Effect } from 'effect';
3
- import { Argument, Command, Flag } from 'effect/unstable/cli';
4
- import { queryDependencies } from '../../orchestrator/query-dependencies/index.js';
5
- import { renderDependencyTree } from './dependency-tree.js';
6
- const pathArgument = Argument.path('path', { mustExist: true }).pipe(Argument.withDescription('Project-relative file or folder to query.'));
7
- const recursiveFlag = Flag.boolean('recursive').pipe(Flag.withDefault(false), Flag.withDescription('Follow dependencies transitively, not just one hop.'));
8
- export function makeDepsCommand(configPath) {
9
- return Command.make('deps', {
10
- path: pathArgument,
11
- recursive: recursiveFlag,
12
- }, ({ path, recursive }) => Effect.gen(function* () {
13
- const configuredPath = yield* configPath;
14
- const absoluteConfigPath = resolve(configuredPath);
15
- const baseDir = dirname(absoluteConfigPath);
16
- const target = toPosixRelative(baseDir, path);
17
- const entries = yield* queryDependencies(absoluteConfigPath, target, {
18
- recursive,
19
- });
20
- yield* Console.log(renderDependencyTree(target, entries));
21
- })).pipe(Command.withDescription('Print the direct (and, with --recursive, transitive) dependencies of a file or folder.'));
22
- }
23
- function toPosixRelative(baseDir, path) {
24
- const relativePath = relative(baseDir, resolve(baseDir, path));
25
- return sep === '/' ? relativePath : relativePath.split(sep).join('/');
26
- }
@@ -1,2 +0,0 @@
1
- export { makeDepsCommand } from './deps.js';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/deps/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
@@ -1,2 +0,0 @@
1
- // The root CLI uses this to create the config-aware `deps` subcommand.
2
- export { makeDepsCommand } from './deps.js';
@@ -1,8 +0,0 @@
1
- import type { LaymosConfig } from './types.js';
2
- export declare function defineConfig(config: LaymosConfig): LaymosConfig;
3
- export interface ConfigValidation {
4
- readonly config: LaymosConfig;
5
- readonly issues: readonly string[];
6
- }
7
- export declare function validateConfig(config: LaymosConfig): ConfigValidation;
8
- //# sourceMappingURL=define-config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"define-config.d.ts","sourceRoot":"","sources":["../../src/config/define-config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAS,YAAY,EAA0B,MAAM,YAAY,CAAC;AAK9E,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAE/D;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAuFrE"}
@@ -1,373 +0,0 @@
1
- import { Option, Schema } from 'effect';
2
- import { normalizeConfigPath, pathContains } from './path.js';
3
- const ErrorMessageSchema = Schema.Struct({ message: Schema.String });
4
- export function defineConfig(config) {
5
- return config;
6
- }
7
- export function validateConfig(config) {
8
- const normalizationIssues = [];
9
- const normalizePath = (subject, path) => {
10
- try {
11
- return normalizeConfigPath(path);
12
- }
13
- catch (cause) {
14
- const error = Schema.decodeUnknownOption(ErrorMessageSchema)(cause);
15
- normalizationIssues.push(`${subject}: ${Option.isSome(error) ? error.value.message : String(cause)}`);
16
- return path;
17
- }
18
- };
19
- const layers = new Map();
20
- const normalizeLayer = (layer) => {
21
- const existing = layers.get(layer);
22
- if (existing !== undefined)
23
- return existing;
24
- const normalized = {
25
- ...layer,
26
- paths: layer.paths.map((path) => normalizePath(`Layer "${layer.name}" path`, path)),
27
- };
28
- layers.set(layer, normalized);
29
- return normalized;
30
- };
31
- const modules = new Map();
32
- const normalizeModule = (module) => {
33
- const existing = modules.get(module);
34
- if (existing !== undefined)
35
- return existing;
36
- const normalized = {
37
- ...module,
38
- path: normalizePath('Module path', module.path),
39
- };
40
- modules.set(module, normalized);
41
- return normalized;
42
- };
43
- const normalizedModules = config.modules?.map(normalizeModule);
44
- const normalizedRules = config.moduleRules?.map((rule) => ({
45
- ...rule,
46
- module: normalizeModule(rule.module),
47
- ...(rule.canImport === undefined
48
- ? {}
49
- : { canImport: rule.canImport.map(normalizeModule) }),
50
- ...(rule.canImportedBy === undefined
51
- ? {}
52
- : { canImportedBy: rule.canImportedBy.map(normalizeModule) }),
53
- }));
54
- const normalizedConfig = {
55
- ...config,
56
- sourceRoots: config.sourceRoots.map((path) => normalizePath('Source root', path)),
57
- graphs: config.graphs.map((graph) => ({
58
- ...graph,
59
- layers: graph.layers.map(normalizeLayer),
60
- edges: graph.edges.map((edge) => ({
61
- from: normalizeLayer(edge.from),
62
- to: normalizeLayer(edge.to),
63
- })),
64
- })),
65
- ...(normalizedModules === undefined ? {} : { modules: normalizedModules }),
66
- ...(normalizedRules === undefined ? {} : { moduleRules: normalizedRules }),
67
- ...(config.ignore === undefined
68
- ? {}
69
- : {
70
- ignore: config.ignore.map((path) => normalizePath('Ignored path', path)),
71
- }),
72
- };
73
- const issues = [
74
- ...normalizationIssues,
75
- ...builderIssues(normalizedConfig),
76
- ...sourceRootIssues(normalizedConfig),
77
- ...duplicateGraphNames(normalizedConfig),
78
- ...duplicateLayerNames(normalizedConfig),
79
- ...duplicateLayerPaths(normalizedConfig),
80
- ...duplicateIgnoredPaths(normalizedConfig),
81
- ...unionCycles(normalizedConfig),
82
- ...architectureIntentIssues(normalizedConfig),
83
- ...moduleIssues(normalizedConfig),
84
- ...projectNarrativeIssues(normalizedConfig),
85
- ];
86
- return { config: normalizedConfig, issues };
87
- }
88
- function builderIssues(config) {
89
- const issues = [];
90
- for (const graph of config.graphs) {
91
- if (graph.name.trim().length === 0) {
92
- issues.push('Layer Graph name must not be empty');
93
- }
94
- const edges = new Set();
95
- for (const edge of graph.edges) {
96
- if (edge.from === edge.to || edge.from.name === edge.to.name) {
97
- issues.push(`Layer Graph "${graph.name}" contains self-edge "${edge.from.name} -> ${edge.to.name}"`);
98
- }
99
- const key = `${edge.from.name}\0${edge.to.name}`;
100
- if (edges.has(key)) {
101
- issues.push(`Layer Graph "${graph.name}" contains duplicate edge "${edge.from.name} -> ${edge.to.name}"`);
102
- }
103
- edges.add(key);
104
- }
105
- for (const layer of graph.layers) {
106
- if (layer.name.trim().length === 0) {
107
- issues.push('Layer name must not be empty');
108
- }
109
- if (layer.paths.length === 0) {
110
- issues.push(`Layer "${layer.name}" must have at least 1 path`);
111
- }
112
- if (new Set(layer.paths).size !== layer.paths.length) {
113
- issues.push(`Layer "${layer.name}" contains duplicate paths`);
114
- }
115
- }
116
- }
117
- for (const module of config.modules ?? []) {
118
- if (module.path.trim().length === 0) {
119
- issues.push('Module path must not be empty');
120
- }
121
- }
122
- for (const rule of config.moduleRules ?? []) {
123
- if (rule.canImport === undefined && rule.canImportedBy === undefined) {
124
- issues.push(`Rules for module "${rule.module.path}" must declare canImport or canImportedBy`);
125
- }
126
- }
127
- return issues;
128
- }
129
- function architectureIntentIssues(config) {
130
- const issues = [];
131
- for (const graph of config.graphs) {
132
- if (typeof graph.description !== 'string' ||
133
- graph.description.trim().length === 0) {
134
- issues.push(`Layer Graph "${graph.name}" description must not be empty`);
135
- }
136
- }
137
- const layers = new Set(config.graphs.flatMap((graph) => graph.layers));
138
- for (const layer of layers) {
139
- if (typeof layer.description !== 'string' ||
140
- layer.description.trim().length === 0) {
141
- issues.push(`Layer "${layer.name}" description must not be empty`);
142
- }
143
- }
144
- for (const moduleDef of config.modules ?? []) {
145
- if (typeof moduleDef.description !== 'string' ||
146
- moduleDef.description.trim().length === 0) {
147
- issues.push(`Module "${moduleDef.path}" description must not be empty`);
148
- }
149
- }
150
- return issues;
151
- }
152
- function projectNarrativeIssues(config) {
153
- if (config.project === undefined)
154
- return [];
155
- const project = config.project;
156
- const issues = [];
157
- if (project.kind !== 'project-narrative') {
158
- issues.push('Project Narrative has an invalid kind');
159
- }
160
- if (project.name.trim().length === 0) {
161
- issues.push('Project Narrative name must not be empty');
162
- }
163
- if (project.content.kind !== 'markdown' ||
164
- project.content.content.trim().length === 0) {
165
- issues.push('Project Narrative Markdown content must not be empty');
166
- }
167
- return issues;
168
- }
169
- function sourceRootIssues(config) {
170
- const issues = [];
171
- for (let index = 0; index < config.sourceRoots.length; index++) {
172
- const root = config.sourceRoots[index];
173
- for (let otherIndex = 0; otherIndex < index; otherIndex++) {
174
- const other = config.sourceRoots[otherIndex];
175
- if (root === other) {
176
- issues.push(`Source root "${root}" is declared more than once`);
177
- }
178
- else if (pathContains(root, other) || pathContains(other, root)) {
179
- issues.push(`Source roots "${other}" and "${root}" overlap`);
180
- }
181
- }
182
- }
183
- if (config.sourceRoots.length === 0) {
184
- issues.push('At least one source root is required');
185
- }
186
- const configuredPaths = [
187
- ...layerPathEntries(config).map(([path]) => ['Layer', path]),
188
- ...(config.modules ?? []).map(({ path }) => ['Module', path]),
189
- ...(config.ignore ?? []).map((path) => ['Ignored', path]),
190
- ];
191
- for (const [kind, path] of configuredPaths) {
192
- if (!config.sourceRoots.some((root) => pathContains(root, path))) {
193
- issues.push(`${kind} path "${path}" is not inside any source root`);
194
- }
195
- }
196
- return issues;
197
- }
198
- function duplicateGraphNames(config) {
199
- const seen = new Set();
200
- const issues = [];
201
- for (const graph of config.graphs) {
202
- if (seen.has(graph.name)) {
203
- issues.push(`Duplicate graph name "${graph.name}"`);
204
- }
205
- seen.add(graph.name);
206
- }
207
- return issues;
208
- }
209
- function duplicateLayerNames(config) {
210
- const seen = new Map();
211
- const issues = [];
212
- for (const graph of config.graphs) {
213
- for (const layer of graph.layers) {
214
- const existing = seen.get(layer.name);
215
- if (existing && existing !== layer) {
216
- issues.push(`Layer name "${layer.name}" has multiple definitions — define the layer once and reuse the value`);
217
- }
218
- seen.set(layer.name, existing ?? layer);
219
- }
220
- }
221
- return issues;
222
- }
223
- function layerPathEntries(config) {
224
- const layers = new Set(config.graphs.flatMap((g) => [...g.layers]));
225
- return [...layers].flatMap((layer) => layer.paths.map((path) => [path, layer.name]));
226
- }
227
- function duplicateLayerPaths(config) {
228
- const seen = new Map();
229
- const issues = [];
230
- for (const [path, layerName] of layerPathEntries(config)) {
231
- const existing = seen.get(path);
232
- if (existing !== undefined && existing !== layerName) {
233
- issues.push(`Path "${path}" is declared by both layers "${existing}" and "${layerName}"`);
234
- }
235
- seen.set(path, existing ?? layerName);
236
- }
237
- return issues;
238
- }
239
- function duplicateIgnoredPaths(config) {
240
- const seen = new Set();
241
- const issues = [];
242
- for (const path of config.ignore ?? []) {
243
- if (seen.has(path))
244
- issues.push(`Duplicate ignored path "${path}"`);
245
- seen.add(path);
246
- }
247
- return issues;
248
- }
249
- function moduleIssues(config) {
250
- const issues = [];
251
- const layerPaths = layerPathEntries(config);
252
- const modules = new Map();
253
- for (const def of config.modules ?? []) {
254
- const path = def.path;
255
- const existing = modules.get(path);
256
- if (existing !== undefined) {
257
- issues.push(`Module "${path}" is declared more than once`);
258
- }
259
- else
260
- modules.set(path, def);
261
- }
262
- const paths = [...modules.keys()];
263
- for (let i = 0; i < paths.length; i++) {
264
- for (let j = i + 1; j < paths.length; j++) {
265
- const [a, b] = [paths[i], paths[j]];
266
- if (pathContains(a, b) || pathContains(b, a)) {
267
- issues.push(`Modules "${a}" and "${b}" nest — modules must be flat`);
268
- }
269
- }
270
- }
271
- for (const path of paths) {
272
- let best;
273
- for (const [layerPath, layerName] of layerPaths) {
274
- if (pathContains(layerPath, path) &&
275
- (best === undefined || layerPath.length > best[0].length)) {
276
- best = [layerPath, layerName];
277
- }
278
- }
279
- if (best === undefined) {
280
- issues.push(`Module "${path}" is not inside any layer`);
281
- continue;
282
- }
283
- for (const [layerPath, layerName] of layerPaths) {
284
- if (path !== layerPath &&
285
- pathContains(path, layerPath) &&
286
- layerName !== best[1]) {
287
- issues.push(`Layer "${layerName}" has path "${layerPath}" inside module "${path}" — the module would straddle layers`);
288
- }
289
- }
290
- }
291
- const seenRules = new Set();
292
- for (const rule of config.moduleRules ?? []) {
293
- const from = rule.module.path;
294
- if (seenRules.has(from)) {
295
- issues.push(`Module "${from}" has more than one rules declaration`);
296
- }
297
- seenRules.add(from);
298
- if (modules.get(from) !== rule.module) {
299
- issues.push(`Rules module "${from}" must reuse a value declared in config.modules`);
300
- }
301
- for (const [ruleName, definitions] of [
302
- ['canImport', rule.canImport ?? []],
303
- ['canImportedBy', rule.canImportedBy ?? []],
304
- ]) {
305
- const seenTargets = new Set();
306
- for (const def of definitions) {
307
- const to = def.path;
308
- if (seenTargets.has(to)) {
309
- issues.push(`Rule ${ruleName} on module "${from}" references module "${to}" more than once`);
310
- }
311
- seenTargets.add(to);
312
- if (modules.get(to) !== def) {
313
- issues.push(`Rule ${ruleName} on module "${from}" must reuse module "${to}" from config.modules`);
314
- }
315
- }
316
- }
317
- }
318
- return issues;
319
- }
320
- function unionCycles(config) {
321
- const adjacency = new Map();
322
- for (const graph of config.graphs) {
323
- for (const edge of graph.edges) {
324
- if (!adjacency.has(edge.from.name)) {
325
- adjacency.set(edge.from.name, new Set());
326
- }
327
- adjacency.get(edge.from.name).add(edge.to.name);
328
- if (!adjacency.has(edge.to.name)) {
329
- adjacency.set(edge.to.name, new Set());
330
- }
331
- }
332
- }
333
- const index = new Map();
334
- const lowLink = new Map();
335
- const onStack = new Set();
336
- const stack = [];
337
- const cycles = [];
338
- let counter = 0;
339
- const visit = (node) => {
340
- index.set(node, counter);
341
- lowLink.set(node, counter);
342
- counter++;
343
- stack.push(node);
344
- onStack.add(node);
345
- for (const next of adjacency.get(node) ?? []) {
346
- if (!index.has(next)) {
347
- visit(next);
348
- lowLink.set(node, Math.min(lowLink.get(node), lowLink.get(next)));
349
- }
350
- else if (onStack.has(next)) {
351
- lowLink.set(node, Math.min(lowLink.get(node), index.get(next)));
352
- }
353
- }
354
- if (lowLink.get(node) === index.get(node)) {
355
- const component = [];
356
- let popped;
357
- do {
358
- popped = stack.pop();
359
- onStack.delete(popped);
360
- component.push(popped);
361
- } while (popped !== node);
362
- if (component.length > 1) {
363
- cycles.push(component.reverse());
364
- }
365
- }
366
- };
367
- for (const node of adjacency.keys()) {
368
- if (!index.has(node)) {
369
- visit(node);
370
- }
371
- }
372
- return cycles.map((cycle) => `Union cycle: ${cycle.join(' -> ')} -> ${cycle[0]}`);
373
- }
@@ -1,11 +0,0 @@
1
- export { defineConfig } from './define-config.js';
2
- export type { ConfigValidation } from './define-config.js';
3
- export type { Layer, LayerEdge, LayerGraph, LaymosConfig, ModuleDef, ModuleRules, } from './types.js';
4
- export { edge, layerGraph } from './layer-graph.js';
5
- export { layer } from './layer.js';
6
- export { module, rules } from './module.js';
7
- export { markdown } from '../markdown/index.js';
8
- export type { MarkdownContent } from '../markdown/index.js';
9
- export { projectNarrative } from './project-narrative.js';
10
- export type { ProjectNarrativeDef } from './project-narrative.js';
11
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,YAAY,EACV,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,EACT,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1,6 +0,0 @@
1
- export { defineConfig } from './define-config.js';
2
- export { edge, layerGraph } from './layer-graph.js';
3
- export { layer } from './layer.js';
4
- export { module, rules } from './module.js';
5
- export { markdown } from '../markdown/index.js';
6
- export { projectNarrative } from './project-narrative.js';
@@ -1,7 +0,0 @@
1
- import type { Layer, LayerEdge, LayerGraph } from './types.js';
2
- export declare function edge(from: Layer, to: Layer): LayerEdge;
3
- export declare function edge(from: Layer, to: readonly Layer[]): LayerEdge[];
4
- export declare function layerGraph(name: string, edges: ReadonlyArray<LayerEdge | LayerEdge[]>, options: {
5
- readonly description: string;
6
- }): LayerGraph;
7
- //# sourceMappingURL=layer-graph.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"layer-graph.d.ts","sourceRoot":"","sources":["../../src/config/layer-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE/D,wBAAgB,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,GAAG,SAAS,CAAC;AACxD,wBAAgB,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,KAAK,EAAE,GAAG,SAAS,EAAE,CAAC;AAerE,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,aAAa,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC,EAC7C,OAAO,EAAE;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACxC,UAAU,CAkBZ"}
@@ -1,26 +0,0 @@
1
- export function edge(from, to) {
2
- if (Array.isArray(to)) {
3
- return to.map((target) => singleEdge(from, target));
4
- }
5
- return singleEdge(from, to);
6
- }
7
- function singleEdge(from, to) {
8
- return { from, to };
9
- }
10
- export function layerGraph(name, edges, options) {
11
- const flatEdges = edges.flat();
12
- const layers = [];
13
- for (const e of flatEdges) {
14
- for (const l of [e.from, e.to]) {
15
- if (!layers.includes(l))
16
- layers.push(l);
17
- }
18
- }
19
- return {
20
- kind: 'layer-graph',
21
- name,
22
- layers,
23
- edges: flatEdges,
24
- description: options.description,
25
- };
26
- }
@@ -1,5 +0,0 @@
1
- import type { Layer } from './types.js';
2
- export declare function layer(name: string, paths: readonly string[], options: {
3
- readonly description: string;
4
- }): Layer;
5
- //# sourceMappingURL=layer.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"layer.d.ts","sourceRoot":"","sources":["../../src/config/layer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,EAAE;IAAE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACxC,KAAK,CAOP"}
@@ -1,8 +0,0 @@
1
- export function layer(name, paths, options) {
2
- return {
3
- kind: 'layer',
4
- name,
5
- paths,
6
- description: options.description,
7
- };
8
- }
@@ -1,2 +0,0 @@
1
- export * from './load-config.js';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/load-config/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC"}
@@ -1 +0,0 @@
1
- export * from './load-config.js';
@@ -1,34 +0,0 @@
1
- import { Effect } from 'effect';
2
- import type { LaymosConfig } from '../types.js';
3
- declare const ConfigNotFoundError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
4
- readonly _tag: "ConfigNotFoundError";
5
- } & Readonly<A>;
6
- export declare class ConfigNotFoundError extends ConfigNotFoundError_base<{
7
- readonly path: string;
8
- }> {
9
- }
10
- declare const ConfigImportError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
11
- readonly _tag: "ConfigImportError";
12
- } & Readonly<A>;
13
- export declare class ConfigImportError extends ConfigImportError_base<{
14
- readonly path: string;
15
- readonly message: string;
16
- }> {
17
- }
18
- declare const ConfigValidationError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
19
- readonly _tag: "ConfigValidationError";
20
- } & Readonly<A>;
21
- export declare class ConfigValidationError extends ConfigValidationError_base<{
22
- readonly path: string;
23
- readonly issues: readonly string[];
24
- readonly message: string;
25
- }> {
26
- }
27
- export type LoadConfigError = ConfigNotFoundError | ConfigImportError | ConfigValidationError;
28
- export interface LoadConfigRequest {
29
- readonly projectDir: string;
30
- }
31
- /** Loads and validates the Laymos config at the project root. */
32
- export declare const loadConfig: ({ projectDir, }: LoadConfigRequest) => Effect.Effect<LaymosConfig, LoadConfigError>;
33
- export {};
34
- //# sourceMappingURL=load-config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../../src/config/load-config/load-config.ts"],"names":[],"mappings":"AAGA,OAAO,EAAQ,MAAM,EAAyB,MAAM,QAAQ,CAAC;AAI7D,OAAO,KAAK,EAIV,YAAY,EAGb,MAAM,aAAa,CAAC;;;;AAKrB,qBAAa,mBAAoB,SAAQ,yBAEvC;IACA,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;CAAG;;;;AAEL,qBAAa,iBAAkB,SAAQ,uBAAsC;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;;;;AAEL,qBAAa,qBAAsB,SAAQ,2BAEzC;IACA,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,iBAAiB,GACjB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,iEAAiE;AACjE,eAAO,MAAM,UAAU,oBAEpB,iBAAiB,KAAG,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,eAAe,CAcjE,CAAC"}