@domainlang/language 0.1.20

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 (212) hide show
  1. package/README.md +163 -0
  2. package/out/ast-augmentation.d.ts +6 -0
  3. package/out/ast-augmentation.js +2 -0
  4. package/out/ast-augmentation.js.map +1 -0
  5. package/out/domain-lang-module.d.ts +57 -0
  6. package/out/domain-lang-module.js +67 -0
  7. package/out/domain-lang-module.js.map +1 -0
  8. package/out/generated/ast.d.ts +759 -0
  9. package/out/generated/ast.js +556 -0
  10. package/out/generated/ast.js.map +1 -0
  11. package/out/generated/grammar.d.ts +6 -0
  12. package/out/generated/grammar.js +2407 -0
  13. package/out/generated/grammar.js.map +1 -0
  14. package/out/generated/module.d.ts +13 -0
  15. package/out/generated/module.js +21 -0
  16. package/out/generated/module.js.map +1 -0
  17. package/out/index.d.ts +16 -0
  18. package/out/index.js +22 -0
  19. package/out/index.js.map +1 -0
  20. package/out/lsp/domain-lang-code-actions.d.ts +55 -0
  21. package/out/lsp/domain-lang-code-actions.js +143 -0
  22. package/out/lsp/domain-lang-code-actions.js.map +1 -0
  23. package/out/lsp/domain-lang-completion.d.ts +37 -0
  24. package/out/lsp/domain-lang-completion.js +452 -0
  25. package/out/lsp/domain-lang-completion.js.map +1 -0
  26. package/out/lsp/domain-lang-formatter.d.ts +15 -0
  27. package/out/lsp/domain-lang-formatter.js +43 -0
  28. package/out/lsp/domain-lang-formatter.js.map +1 -0
  29. package/out/lsp/domain-lang-naming.d.ts +34 -0
  30. package/out/lsp/domain-lang-naming.js +49 -0
  31. package/out/lsp/domain-lang-naming.js.map +1 -0
  32. package/out/lsp/domain-lang-scope.d.ts +59 -0
  33. package/out/lsp/domain-lang-scope.js +102 -0
  34. package/out/lsp/domain-lang-scope.js.map +1 -0
  35. package/out/lsp/domain-lang-workspace-manager.d.ts +21 -0
  36. package/out/lsp/domain-lang-workspace-manager.js +93 -0
  37. package/out/lsp/domain-lang-workspace-manager.js.map +1 -0
  38. package/out/lsp/hover/ddd-pattern-explanations.d.ts +50 -0
  39. package/out/lsp/hover/ddd-pattern-explanations.js +196 -0
  40. package/out/lsp/hover/ddd-pattern-explanations.js.map +1 -0
  41. package/out/lsp/hover/domain-lang-hover.d.ts +19 -0
  42. package/out/lsp/hover/domain-lang-hover.js +302 -0
  43. package/out/lsp/hover/domain-lang-hover.js.map +1 -0
  44. package/out/lsp/hover/domain-lang-keywords.d.ts +13 -0
  45. package/out/lsp/hover/domain-lang-keywords.js +47 -0
  46. package/out/lsp/hover/domain-lang-keywords.js.map +1 -0
  47. package/out/lsp/manifest-diagnostics.d.ts +82 -0
  48. package/out/lsp/manifest-diagnostics.js +230 -0
  49. package/out/lsp/manifest-diagnostics.js.map +1 -0
  50. package/out/main-browser.d.ts +1 -0
  51. package/out/main-browser.js +11 -0
  52. package/out/main-browser.js.map +1 -0
  53. package/out/main.d.ts +1 -0
  54. package/out/main.js +74 -0
  55. package/out/main.js.map +1 -0
  56. package/out/sdk/ast-augmentation.d.ts +136 -0
  57. package/out/sdk/ast-augmentation.js +62 -0
  58. package/out/sdk/ast-augmentation.js.map +1 -0
  59. package/out/sdk/index.d.ts +94 -0
  60. package/out/sdk/index.js +97 -0
  61. package/out/sdk/index.js.map +1 -0
  62. package/out/sdk/indexes.d.ts +16 -0
  63. package/out/sdk/indexes.js +97 -0
  64. package/out/sdk/indexes.js.map +1 -0
  65. package/out/sdk/loader-node.d.ts +51 -0
  66. package/out/sdk/loader-node.js +119 -0
  67. package/out/sdk/loader-node.js.map +1 -0
  68. package/out/sdk/loader.d.ts +49 -0
  69. package/out/sdk/loader.js +85 -0
  70. package/out/sdk/loader.js.map +1 -0
  71. package/out/sdk/patterns.d.ts +93 -0
  72. package/out/sdk/patterns.js +123 -0
  73. package/out/sdk/patterns.js.map +1 -0
  74. package/out/sdk/query.d.ts +90 -0
  75. package/out/sdk/query.js +679 -0
  76. package/out/sdk/query.js.map +1 -0
  77. package/out/sdk/resolution.d.ts +52 -0
  78. package/out/sdk/resolution.js +68 -0
  79. package/out/sdk/resolution.js.map +1 -0
  80. package/out/sdk/types.d.ts +280 -0
  81. package/out/sdk/types.js +8 -0
  82. package/out/sdk/types.js.map +1 -0
  83. package/out/services/dependency-analyzer.d.ts +58 -0
  84. package/out/services/dependency-analyzer.js +254 -0
  85. package/out/services/dependency-analyzer.js.map +1 -0
  86. package/out/services/dependency-resolver.d.ts +146 -0
  87. package/out/services/dependency-resolver.js +452 -0
  88. package/out/services/dependency-resolver.js.map +1 -0
  89. package/out/services/git-url-resolver.browser.d.ts +10 -0
  90. package/out/services/git-url-resolver.browser.js +19 -0
  91. package/out/services/git-url-resolver.browser.js.map +1 -0
  92. package/out/services/git-url-resolver.d.ts +158 -0
  93. package/out/services/git-url-resolver.js +416 -0
  94. package/out/services/git-url-resolver.js.map +1 -0
  95. package/out/services/governance-validator.d.ts +44 -0
  96. package/out/services/governance-validator.js +153 -0
  97. package/out/services/governance-validator.js.map +1 -0
  98. package/out/services/import-resolver.d.ts +77 -0
  99. package/out/services/import-resolver.js +240 -0
  100. package/out/services/import-resolver.js.map +1 -0
  101. package/out/services/performance-optimizer.d.ts +60 -0
  102. package/out/services/performance-optimizer.js +140 -0
  103. package/out/services/performance-optimizer.js.map +1 -0
  104. package/out/services/relationship-inference.d.ts +11 -0
  105. package/out/services/relationship-inference.js +98 -0
  106. package/out/services/relationship-inference.js.map +1 -0
  107. package/out/services/semver.d.ts +98 -0
  108. package/out/services/semver.js +195 -0
  109. package/out/services/semver.js.map +1 -0
  110. package/out/services/types.d.ts +340 -0
  111. package/out/services/types.js +46 -0
  112. package/out/services/types.js.map +1 -0
  113. package/out/services/workspace-manager.d.ts +123 -0
  114. package/out/services/workspace-manager.js +489 -0
  115. package/out/services/workspace-manager.js.map +1 -0
  116. package/out/syntaxes/domain-lang.monarch.d.ts +76 -0
  117. package/out/syntaxes/domain-lang.monarch.js +29 -0
  118. package/out/syntaxes/domain-lang.monarch.js.map +1 -0
  119. package/out/utils/import-utils.d.ts +49 -0
  120. package/out/utils/import-utils.js +128 -0
  121. package/out/utils/import-utils.js.map +1 -0
  122. package/out/validation/bounded-context.d.ts +11 -0
  123. package/out/validation/bounded-context.js +79 -0
  124. package/out/validation/bounded-context.js.map +1 -0
  125. package/out/validation/classification.d.ts +3 -0
  126. package/out/validation/classification.js +3 -0
  127. package/out/validation/classification.js.map +1 -0
  128. package/out/validation/constants.d.ts +180 -0
  129. package/out/validation/constants.js +235 -0
  130. package/out/validation/constants.js.map +1 -0
  131. package/out/validation/domain-lang-validator.d.ts +2 -0
  132. package/out/validation/domain-lang-validator.js +27 -0
  133. package/out/validation/domain-lang-validator.js.map +1 -0
  134. package/out/validation/domain.d.ts +11 -0
  135. package/out/validation/domain.js +63 -0
  136. package/out/validation/domain.js.map +1 -0
  137. package/out/validation/import.d.ts +68 -0
  138. package/out/validation/import.js +237 -0
  139. package/out/validation/import.js.map +1 -0
  140. package/out/validation/manifest.d.ts +144 -0
  141. package/out/validation/manifest.js +327 -0
  142. package/out/validation/manifest.js.map +1 -0
  143. package/out/validation/maps.d.ts +21 -0
  144. package/out/validation/maps.js +60 -0
  145. package/out/validation/maps.js.map +1 -0
  146. package/out/validation/metadata.d.ts +7 -0
  147. package/out/validation/metadata.js +16 -0
  148. package/out/validation/metadata.js.map +1 -0
  149. package/out/validation/model.d.ts +12 -0
  150. package/out/validation/model.js +29 -0
  151. package/out/validation/model.js.map +1 -0
  152. package/out/validation/relationships.d.ts +12 -0
  153. package/out/validation/relationships.js +94 -0
  154. package/out/validation/relationships.js.map +1 -0
  155. package/out/validation/shared.d.ts +6 -0
  156. package/out/validation/shared.js +12 -0
  157. package/out/validation/shared.js.map +1 -0
  158. package/package.json +110 -0
  159. package/src/ast-augmentation.ts +5 -0
  160. package/src/domain-lang-module.ts +112 -0
  161. package/src/domain-lang.langium +351 -0
  162. package/src/generated/ast.ts +986 -0
  163. package/src/generated/grammar.ts +2409 -0
  164. package/src/generated/module.ts +25 -0
  165. package/src/index.ts +24 -0
  166. package/src/lsp/domain-lang-code-actions.ts +189 -0
  167. package/src/lsp/domain-lang-completion.ts +514 -0
  168. package/src/lsp/domain-lang-formatter.ts +51 -0
  169. package/src/lsp/domain-lang-naming.ts +56 -0
  170. package/src/lsp/domain-lang-scope.ts +137 -0
  171. package/src/lsp/domain-lang-workspace-manager.ts +104 -0
  172. package/src/lsp/hover/ddd-pattern-explanations.ts +237 -0
  173. package/src/lsp/hover/domain-lang-hover.ts +338 -0
  174. package/src/lsp/hover/domain-lang-keywords.ts +50 -0
  175. package/src/lsp/manifest-diagnostics.ts +290 -0
  176. package/src/main-browser.ts +15 -0
  177. package/src/main.ts +85 -0
  178. package/src/sdk/README.md +297 -0
  179. package/src/sdk/ast-augmentation.ts +157 -0
  180. package/src/sdk/index.ts +126 -0
  181. package/src/sdk/indexes.ts +155 -0
  182. package/src/sdk/loader-node.ts +146 -0
  183. package/src/sdk/loader.ts +99 -0
  184. package/src/sdk/patterns.ts +147 -0
  185. package/src/sdk/query.ts +802 -0
  186. package/src/sdk/resolution.ts +78 -0
  187. package/src/sdk/types.ts +323 -0
  188. package/src/services/dependency-analyzer.ts +321 -0
  189. package/src/services/dependency-resolver.ts +551 -0
  190. package/src/services/git-url-resolver.browser.ts +26 -0
  191. package/src/services/git-url-resolver.ts +517 -0
  192. package/src/services/governance-validator.ts +177 -0
  193. package/src/services/import-resolver.ts +292 -0
  194. package/src/services/performance-optimizer.ts +170 -0
  195. package/src/services/relationship-inference.ts +121 -0
  196. package/src/services/semver.ts +213 -0
  197. package/src/services/types.ts +415 -0
  198. package/src/services/workspace-manager.ts +607 -0
  199. package/src/syntaxes/domain-lang.monarch.ts +29 -0
  200. package/src/utils/import-utils.ts +152 -0
  201. package/src/validation/bounded-context.ts +99 -0
  202. package/src/validation/classification.ts +5 -0
  203. package/src/validation/constants.ts +304 -0
  204. package/src/validation/domain-lang-validator.ts +33 -0
  205. package/src/validation/domain.ts +77 -0
  206. package/src/validation/import.ts +295 -0
  207. package/src/validation/manifest.ts +439 -0
  208. package/src/validation/maps.ts +76 -0
  209. package/src/validation/metadata.ts +18 -0
  210. package/src/validation/model.ts +37 -0
  211. package/src/validation/relationships.ts +154 -0
  212. package/src/validation/shared.ts +14 -0
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Dependency Analysis Service
3
+ *
4
+ * Provides tools for visualizing and analyzing dependency relationships:
5
+ * - Dependency tree visualization
6
+ * - Impact analysis (reverse dependencies)
7
+ * - Circular dependency detection
8
+ * - Version policy enforcement
9
+ */
10
+
11
+ import type { LockFile, DependencyTreeNode, ReverseDependency, VersionPolicy } from './types.js';
12
+ import path from 'node:path';
13
+ import fs from 'node:fs/promises';
14
+ import os from 'node:os';
15
+ import YAML from 'yaml';
16
+ import { sortVersionsDescending, isPreRelease } from './semver.js';
17
+
18
+ /**
19
+ * Analyzes dependency relationships and provides visualization/analysis tools.
20
+ */
21
+ export class DependencyAnalyzer {
22
+ /**
23
+ * Builds a dependency tree from a lock file.
24
+ *
25
+ * @param lockFile - The lock file to analyze
26
+ * @param workspaceRoot - Workspace root to load dependency metadata
27
+ * @returns Root nodes of the dependency tree
28
+ */
29
+ async buildDependencyTree(lockFile: LockFile, workspaceRoot: string): Promise<DependencyTreeNode[]> {
30
+ const manifestPath = path.join(workspaceRoot, 'model.yaml');
31
+
32
+ // Load root manifest to get direct dependencies
33
+ const rootDeps: Record<string, string> = {};
34
+ try {
35
+ const content = await fs.readFile(manifestPath, 'utf-8');
36
+ const manifest = YAML.parse(content) as {
37
+ dependencies?: Record<string, { source: string; version: string }>;
38
+ };
39
+
40
+ if (manifest.dependencies) {
41
+ for (const [, dep] of Object.entries(manifest.dependencies)) {
42
+ rootDeps[dep.source] = dep.version;
43
+ }
44
+ }
45
+ } catch {
46
+ // No manifest or parse error
47
+ }
48
+
49
+ // Build tree for each direct dependency
50
+ const rootNodes: DependencyTreeNode[] = [];
51
+ const visited = new Set<string>();
52
+
53
+ for (const packageKey of Object.keys(rootDeps)) {
54
+ const node = await this.buildTreeNode(packageKey, lockFile, workspaceRoot, 0, visited);
55
+ if (node) {
56
+ rootNodes.push(node);
57
+ }
58
+ }
59
+
60
+ return rootNodes;
61
+ }
62
+
63
+ /**
64
+ * Recursively builds a dependency tree node.
65
+ */
66
+ private async buildTreeNode(
67
+ packageKey: string,
68
+ lockFile: LockFile,
69
+ workspaceRoot: string,
70
+ depth: number,
71
+ visited: Set<string>
72
+ ): Promise<DependencyTreeNode | null> {
73
+ const locked = lockFile.dependencies[packageKey];
74
+ if (!locked) {
75
+ return null;
76
+ }
77
+
78
+ // Prevent infinite recursion
79
+ if (visited.has(packageKey)) {
80
+ return {
81
+ packageKey,
82
+ ref: locked.ref,
83
+ commit: locked.commit,
84
+ dependencies: [], // Don't recurse into already visited
85
+ depth,
86
+ };
87
+ }
88
+
89
+ visited.add(packageKey);
90
+
91
+ // Load package dependencies from cache
92
+ const cacheDir = this.getCacheDir(packageKey, locked.commit);
93
+ const packageDeps = await this.loadPackageDependencies(cacheDir);
94
+
95
+ // Build child nodes
96
+ const children: DependencyTreeNode[] = [];
97
+ for (const depKey of Object.keys(packageDeps)) {
98
+ const childNode = await this.buildTreeNode(depKey, lockFile, workspaceRoot, depth + 1, new Set(visited));
99
+ if (childNode) {
100
+ children.push(childNode);
101
+ }
102
+ }
103
+
104
+ return {
105
+ packageKey,
106
+ ref: locked.ref,
107
+ commit: locked.commit,
108
+ dependencies: children,
109
+ depth,
110
+ };
111
+ }
112
+
113
+ /**
114
+ * Finds all packages that depend on a given package.
115
+ *
116
+ * @param targetPackage - Package to analyze
117
+ * @param lockFile - Lock file with all dependencies
118
+ * @param workspaceRoot - Workspace root
119
+ * @returns List of reverse dependencies
120
+ */
121
+ async findReverseDependencies(
122
+ targetPackage: string,
123
+ lockFile: LockFile,
124
+ workspaceRoot: string
125
+ ): Promise<ReverseDependency[]> {
126
+ const reverseDeps: ReverseDependency[] = [];
127
+ const manifestPath = path.join(workspaceRoot, 'model.yaml');
128
+
129
+ // Check if target is a direct dependency of root
130
+ try {
131
+ const content = await fs.readFile(manifestPath, 'utf-8');
132
+ const manifest = YAML.parse(content) as {
133
+ dependencies?: Record<string, { source: string; version: string }>;
134
+ };
135
+
136
+ if (manifest.dependencies) {
137
+ for (const [, dep] of Object.entries(manifest.dependencies)) {
138
+ if (dep.source === targetPackage) {
139
+ reverseDeps.push({
140
+ dependentPackage: 'root',
141
+ ref: 'workspace',
142
+ type: 'direct',
143
+ });
144
+ }
145
+ }
146
+ }
147
+ } catch {
148
+ // Ignore
149
+ }
150
+
151
+ // Check all other packages in lock file
152
+ for (const [packageKey, locked] of Object.entries(lockFile.dependencies)) {
153
+ if (packageKey === targetPackage) {
154
+ continue;
155
+ }
156
+
157
+ const cacheDir = this.getCacheDir(packageKey, locked.commit);
158
+ const packageDeps = await this.loadPackageDependencies(cacheDir);
159
+
160
+ if (packageDeps[targetPackage]) {
161
+ reverseDeps.push({
162
+ dependentPackage: packageKey,
163
+ ref: locked.ref,
164
+ type: 'direct',
165
+ });
166
+ }
167
+ }
168
+
169
+ return reverseDeps;
170
+ }
171
+
172
+ /**
173
+ * Formats a dependency tree as a readable string.
174
+ */
175
+ formatDependencyTree(nodes: DependencyTreeNode[], options: { showCommits?: boolean } = {}): string {
176
+ const lines: string[] = [];
177
+
178
+ const formatNode = (node: DependencyTreeNode, prefix: string, isLast: boolean): void => {
179
+ const branch = isLast ? '└── ' : '├── ';
180
+ const refStr = options.showCommits
181
+ ? `${node.ref} (${node.commit.substring(0, 7)})`
182
+ : node.ref;
183
+
184
+ lines.push(`${prefix}${branch}${node.packageKey}@${refStr}`);
185
+
186
+ const childPrefix = prefix + (isLast ? ' ' : '│ ');
187
+ node.dependencies.forEach((child, index) => {
188
+ const isLastChild = index === node.dependencies.length - 1;
189
+ formatNode(child, childPrefix, isLastChild);
190
+ });
191
+ };
192
+
193
+ nodes.forEach((node, index) => {
194
+ formatNode(node, '', index === nodes.length - 1);
195
+ });
196
+
197
+ return lines.join('\n');
198
+ }
199
+
200
+ /**
201
+ * Detects circular dependencies in a dependency graph.
202
+ */
203
+ async detectCircularDependencies(lockFile: LockFile): Promise<string[][]> {
204
+ const cycles: string[][] = [];
205
+ const visiting = new Set<string>();
206
+ const completed = new Set<string>();
207
+
208
+ const dfs = async (packageKey: string, path: string[]): Promise<void> => {
209
+ if (visiting.has(packageKey)) {
210
+ const cycleStart = path.indexOf(packageKey);
211
+ const cycle = cycleStart >= 0
212
+ ? [...path.slice(cycleStart), packageKey]
213
+ : [...path, packageKey];
214
+ cycles.push(cycle);
215
+ return;
216
+ }
217
+
218
+ if (completed.has(packageKey)) {
219
+ return;
220
+ }
221
+
222
+ visiting.add(packageKey);
223
+
224
+ const locked = lockFile.dependencies[packageKey];
225
+ if (locked) {
226
+ const cacheDir = this.getCacheDir(packageKey, locked.commit);
227
+ const deps = await this.loadPackageDependencies(cacheDir);
228
+
229
+ for (const depKey of Object.keys(deps)) {
230
+ await dfs(depKey, [...path, packageKey]);
231
+ }
232
+ }
233
+
234
+ visiting.delete(packageKey);
235
+ completed.add(packageKey);
236
+ };
237
+
238
+ for (const packageKey of Object.keys(lockFile.dependencies)) {
239
+ await dfs(packageKey, []);
240
+ }
241
+
242
+ return cycles;
243
+ }
244
+
245
+ /**
246
+ * Resolves ref policies (latest, stable) to concrete refs.
247
+ */
248
+ async resolveVersionPolicy(
249
+ _packageKey: string,
250
+ policy: string,
251
+ availableRefs: string[]
252
+ ): Promise<VersionPolicy> {
253
+ if (policy === 'latest') {
254
+ // Return the most recent ref
255
+ const sorted = sortVersionsDescending(availableRefs);
256
+ return {
257
+ policy: 'latest',
258
+ ref: sorted[0] || 'main',
259
+ availableRefs: sorted,
260
+ };
261
+ }
262
+
263
+ if (policy === 'stable') {
264
+ // Return the most recent stable ref (exclude pre-release)
265
+ const stable = availableRefs.filter(v => !isPreRelease(v));
266
+ const sorted = sortVersionsDescending(stable);
267
+ return {
268
+ policy: 'stable',
269
+ ref: sorted[0] || 'main',
270
+ availableRefs: sorted,
271
+ };
272
+ }
273
+
274
+ // Pinned ref
275
+ return {
276
+ policy: 'pinned',
277
+ ref: policy,
278
+ };
279
+ }
280
+
281
+ /**
282
+ * Gets the cache directory for a package.
283
+ */
284
+ private getCacheDir(packageKey: string, commit: string): string {
285
+ const [owner, repo] = packageKey.split('/');
286
+ return path.join(
287
+ os.homedir(),
288
+ '.dlang',
289
+ 'cache',
290
+ 'github', // Assume GitHub for now
291
+ owner,
292
+ repo,
293
+ commit
294
+ );
295
+ }
296
+
297
+ /**
298
+ * Loads dependencies from a cached package.
299
+ */
300
+ private async loadPackageDependencies(cacheDir: string): Promise<Record<string, string>> {
301
+ const manifestPath = path.join(cacheDir, 'model.yaml');
302
+
303
+ try {
304
+ const content = await fs.readFile(manifestPath, 'utf-8');
305
+ const manifest = YAML.parse(content) as {
306
+ dependencies?: Record<string, { source: string; version: string }>;
307
+ };
308
+
309
+ const deps: Record<string, string> = {};
310
+ if (manifest.dependencies) {
311
+ for (const [, dep] of Object.entries(manifest.dependencies)) {
312
+ deps[dep.source] = dep.version;
313
+ }
314
+ }
315
+
316
+ return deps;
317
+ } catch {
318
+ return {};
319
+ }
320
+ }
321
+ }