@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,452 @@
1
+ /**
2
+ * Dependency Resolution Service
3
+ *
4
+ * Discovers and resolves transitive dependencies for DomainLang packages.
5
+ * Generates lock files for reproducible builds.
6
+ *
7
+ * Algorithm:
8
+ * 1. Parse root model.yaml
9
+ * 2. Download all direct dependencies
10
+ * 3. Parse each dependency's model.yaml
11
+ * 4. Recursively discover transitive dependencies
12
+ * 5. Resolve version constraints using "Latest Wins" strategy
13
+ * 6. Generate lock file with pinned commit hashes
14
+ *
15
+ * Resolution Strategy ("Latest Wins"):
16
+ * - SemVer tags (same major): Pick highest compatible version
17
+ * - Same branch: No conflict, resolve once
18
+ * - Commit pins: Error (explicit pins are intentional)
19
+ * - Major version mismatch: Error
20
+ * - Tag vs Branch: Error (incompatible intent)
21
+ */
22
+ import path from 'node:path';
23
+ import fs from 'node:fs/promises';
24
+ import YAML from 'yaml';
25
+ import { GitUrlParser, GitUrlResolver } from './git-url-resolver.js';
26
+ import { parseSemVer, pickLatestSemVer, detectRefType } from './semver.js';
27
+ export class DependencyResolver {
28
+ constructor(workspaceRoot, gitResolver) {
29
+ /** Override messages for CLI output */
30
+ this.overrideMessages = [];
31
+ /** Resolution messages from "Latest Wins" auto-resolution */
32
+ this.resolutionMessages = [];
33
+ this.workspaceRoot = workspaceRoot;
34
+ // Per PRS-010: Project-local cache at .dlang/packages/
35
+ const cacheDir = path.join(workspaceRoot, '.dlang', 'packages');
36
+ this.gitResolver = gitResolver || new GitUrlResolver(cacheDir);
37
+ }
38
+ /**
39
+ * Resolves all dependencies for a workspace.
40
+ *
41
+ * Process:
42
+ * 1. Load root model.yaml
43
+ * 2. Build dependency graph (discover transitive deps)
44
+ * 3. Resolve version constraints
45
+ * 4. Generate lock file
46
+ * 5. Download all dependencies to cache
47
+ *
48
+ * @returns Generated lock file
49
+ */
50
+ async resolveDependencies() {
51
+ // Load root package config
52
+ const rootConfig = await this.loadPackageConfig(this.workspaceRoot);
53
+ if (!rootConfig.dependencies || Object.keys(rootConfig.dependencies).length === 0) {
54
+ // No dependencies
55
+ return { version: '1', dependencies: {} };
56
+ }
57
+ // Build dependency graph
58
+ const graph = await this.buildDependencyGraph(rootConfig);
59
+ // Apply overrides before conflict detection
60
+ this.applyOverrides(graph, rootConfig.overrides);
61
+ // Detect version conflicts and package-level cycles before resolving
62
+ this.detectVersionConflicts(graph);
63
+ this.detectPackageCycles(graph);
64
+ // Resolve version constraints
65
+ await this.resolveVersions(graph);
66
+ // Generate and return lock file (caller writes to disk)
67
+ return this.generateLockFile(graph);
68
+ }
69
+ /**
70
+ * Applies ref overrides from model.yaml to resolve conflicts explicitly.
71
+ *
72
+ * Overrides take precedence over all other constraints.
73
+ *
74
+ * @example
75
+ * ```yaml
76
+ * overrides:
77
+ * domainlang/core: v2.0.0
78
+ * ```
79
+ */
80
+ applyOverrides(graph, overrides) {
81
+ if (!overrides)
82
+ return;
83
+ for (const [pkg, overrideRef] of Object.entries(overrides)) {
84
+ const node = graph.nodes[pkg];
85
+ if (node) {
86
+ // Override replaces all constraints with a single definitive ref
87
+ node.constraints = new Set([overrideRef]);
88
+ node.refConstraint = overrideRef;
89
+ // Track that this was an override for messaging
90
+ this.overrideMessages.push(`Override applied: ${pkg}@${overrideRef}`);
91
+ }
92
+ }
93
+ }
94
+ /**
95
+ * Returns any override messages from the last dependency resolution.
96
+ */
97
+ getOverrideMessages() {
98
+ return this.overrideMessages;
99
+ }
100
+ /**
101
+ * Builds the complete dependency graph by recursively discovering transitive dependencies.
102
+ */
103
+ async buildDependencyGraph(rootConfig) {
104
+ const graph = {
105
+ nodes: {},
106
+ root: rootConfig.name || 'root',
107
+ };
108
+ // Process root dependencies
109
+ const queue = [];
110
+ for (const [depName, refConstraint] of Object.entries(rootConfig.dependencies || {})) {
111
+ queue.push({
112
+ packageKey: depName,
113
+ refConstraint,
114
+ parent: graph.root
115
+ });
116
+ }
117
+ // BFS to discover all transitive dependencies
118
+ const visited = new Set();
119
+ while (queue.length > 0) {
120
+ const entry = queue.shift();
121
+ if (!entry)
122
+ break;
123
+ const { packageKey, refConstraint, parent } = entry;
124
+ // Skip if already processed
125
+ if (visited.has(packageKey)) {
126
+ // Update dependents list and record constraint
127
+ const existing = graph.nodes[packageKey];
128
+ if (!existing.dependents.includes(parent)) {
129
+ existing.dependents.push(parent);
130
+ }
131
+ if (!existing.constraints)
132
+ existing.constraints = new Set();
133
+ existing.constraints.add(refConstraint);
134
+ continue;
135
+ }
136
+ visited.add(packageKey);
137
+ // Parse package identifier
138
+ const gitInfo = GitUrlParser.parse(packageKey);
139
+ // Download package to get its model.yaml
140
+ const packageUri = await this.gitResolver.resolve(packageKey);
141
+ const packageDir = path.dirname(packageUri.fsPath);
142
+ // Load package config
143
+ const packageConfig = await this.loadPackageConfig(packageDir);
144
+ // Add to graph
145
+ graph.nodes[packageKey] = {
146
+ packageKey,
147
+ refConstraint,
148
+ constraints: new Set([refConstraint]),
149
+ repoUrl: gitInfo.repoUrl,
150
+ dependencies: packageConfig.dependencies || {},
151
+ dependents: [parent],
152
+ };
153
+ // Queue transitive dependencies
154
+ for (const [transDepName, transRefConstraint] of Object.entries(packageConfig.dependencies || {})) {
155
+ queue.push({
156
+ packageKey: transDepName,
157
+ refConstraint: transRefConstraint,
158
+ parent: packageKey,
159
+ });
160
+ }
161
+ }
162
+ return graph;
163
+ }
164
+ /**
165
+ * Resolves ref constraints to specific commits.
166
+ *
167
+ * Simple algorithm: Use the ref specified in the constraint.
168
+ * Detects refType (tag, branch, or commit) based on format.
169
+ */
170
+ async resolveVersions(graph) {
171
+ for (const [packageKey, node] of Object.entries(graph.nodes)) {
172
+ // Parse package to get repo info
173
+ const gitInfo = GitUrlParser.parse(packageKey);
174
+ // Extract ref from constraint
175
+ const ref = this.extractRefFromConstraint(node.refConstraint);
176
+ // Detect ref type based on format
177
+ const refType = detectRefType(ref);
178
+ // Resolve ref to commit hash
179
+ const commitHash = await this.resolveCommitHash(gitInfo.repoUrl, ref);
180
+ node.resolvedRef = ref;
181
+ node.refType = refType;
182
+ node.commitHash = commitHash;
183
+ }
184
+ }
185
+ /**
186
+ * Extracts a ref from a constraint string.
187
+ *
188
+ * Examples:
189
+ * - "^1.0.0" → "1.0.0" (treated as tag)
190
+ * - "~2.3.0" → "2.3.0" (treated as tag)
191
+ * - "1.5.0" → "1.5.0" (treated as tag)
192
+ * - "main" → "main" (treated as branch)
193
+ * - "abc123def" → "abc123def" (treated as commit)
194
+ * - "owner/repo@1.0.0" → "1.0.0"
195
+ */
196
+ extractRefFromConstraint(constraint) {
197
+ // Remove semver operators (legacy support)
198
+ let ref = constraint.replace(/^[\^~>=<]/, '');
199
+ // Extract ref from full import URL if present
200
+ if (ref.includes('@')) {
201
+ ref = ref.split('@')[1];
202
+ }
203
+ return ref || 'main';
204
+ }
205
+ /**
206
+ * Resolves a version (tag/branch) to a commit hash using git ls-remote.
207
+ */
208
+ async resolveCommitHash(repoUrl, version) {
209
+ // This is a placeholder - the actual implementation is in GitUrlResolver
210
+ // We need to extract it or call the resolver
211
+ const gitInfo = GitUrlParser.parse(`${repoUrl}@${version}`);
212
+ const uri = await this.gitResolver.resolve(gitInfo.original);
213
+ // Extract commit hash from cache path
214
+ // Per PRS-010: Project-local cache at .dlang/packages/{owner}/{repo}/{commit}/
215
+ const pathParts = uri.fsPath.split(path.sep);
216
+ const commitHashIndex = pathParts.length - 2; // Second to last segment
217
+ return pathParts[commitHashIndex];
218
+ }
219
+ /**
220
+ * Generates a lock file from the resolved dependency graph.
221
+ */
222
+ generateLockFile(graph) {
223
+ const dependencies = {};
224
+ for (const [packageKey, node] of Object.entries(graph.nodes)) {
225
+ if (!node.resolvedRef || !node.commitHash) {
226
+ throw new Error(`Failed to resolve ref for '${packageKey}'.\n` +
227
+ `Hint: Check that the package exists and the ref is valid.`);
228
+ }
229
+ dependencies[packageKey] = {
230
+ ref: node.resolvedRef,
231
+ refType: node.refType ?? 'commit',
232
+ resolved: node.repoUrl || '',
233
+ commit: node.commitHash,
234
+ // Future: Calculate integrity hash
235
+ };
236
+ }
237
+ return {
238
+ version: '1',
239
+ dependencies,
240
+ };
241
+ }
242
+ /**
243
+ * Loads and parses a package's model.yaml file.
244
+ */
245
+ async loadPackageConfig(packageDir) {
246
+ const yamlPath = path.join(packageDir, 'model.yaml');
247
+ try {
248
+ const yamlContent = await fs.readFile(yamlPath, 'utf-8');
249
+ return this.parseYaml(yamlContent);
250
+ }
251
+ catch {
252
+ // No model.yaml found
253
+ return {};
254
+ }
255
+ }
256
+ /**
257
+ * Parses model.yaml content.
258
+ *
259
+ * Expected structure:
260
+ * model:
261
+ * name: package-name
262
+ * version: 1.0.0
263
+ * entry: index.dlang
264
+ *
265
+ * dependencies:
266
+ * package-name:
267
+ * source: owner/repo
268
+ * ref: v1.0.0
269
+ */
270
+ parseYaml(content) {
271
+ const parsed = YAML.parse(content);
272
+ const config = {};
273
+ if (parsed.model) {
274
+ config.name = parsed.model.name;
275
+ config.version = parsed.model.version;
276
+ config.entry = parsed.model.entry;
277
+ }
278
+ if (parsed.dependencies) {
279
+ config.dependencies = {};
280
+ for (const [, depInfo] of Object.entries(parsed.dependencies)) {
281
+ if (depInfo.source) {
282
+ const refConstraint = depInfo.ref || 'main';
283
+ // Store as "source@ref" for consistency with import resolution
284
+ config.dependencies[depInfo.source] = refConstraint;
285
+ }
286
+ }
287
+ }
288
+ // Parse overrides section for explicit ref control
289
+ if (parsed.overrides) {
290
+ config.overrides = parsed.overrides;
291
+ }
292
+ return config;
293
+ }
294
+ /**
295
+ * Detects ref conflicts and applies "Latest Wins" resolution strategy.
296
+ *
297
+ * Resolution Rules:
298
+ * - SemVer tags (same major): Pick highest version automatically
299
+ * - Same branch refs: No conflict, use single resolution
300
+ * - Commit SHA conflicts: Error (explicit pins are intentional)
301
+ * - Major version mismatch: Error (breaking change)
302
+ * - Tag vs Branch: Error (incompatible intent)
303
+ *
304
+ * Modifies graph nodes in-place to set the resolved constraint.
305
+ * Throws an error only for unresolvable conflicts.
306
+ */
307
+ detectVersionConflicts(graph) {
308
+ const resolutionMessages = [];
309
+ for (const [pkg, node] of Object.entries(graph.nodes)) {
310
+ const constraints = node.constraints ?? new Set([node.refConstraint]);
311
+ if (constraints.size <= 1)
312
+ continue; // No conflict
313
+ const refs = Array.from(constraints);
314
+ const refTypes = refs.map(ref => ({
315
+ ref,
316
+ type: detectRefType(ref),
317
+ semver: parseSemVer(ref),
318
+ }));
319
+ // Check for mixed types (tag vs branch vs commit)
320
+ const types = new Set(refTypes.map(r => r.type));
321
+ // Case 1: All commits - must be exact match
322
+ if (types.size === 1 && types.has('commit')) {
323
+ this.throwConflictError(pkg, refs, node.dependents, 'Explicit commit pins cannot be automatically resolved.\n' +
324
+ 'Add an override in model.yaml:\n\n' +
325
+ ' overrides:\n' +
326
+ ` ${pkg}: ${refs[0]}`);
327
+ }
328
+ // Case 2: Mixed types (tag vs branch or tag vs commit)
329
+ if (types.size > 1) {
330
+ this.throwConflictError(pkg, refs, node.dependents, 'Cannot mix ref types (tags, branches, commits).\n' +
331
+ 'Add an override in model.yaml to specify which to use:\n\n' +
332
+ ' overrides:\n' +
333
+ ` ${pkg}: <ref>`);
334
+ }
335
+ // Case 3: All branches - must be same branch
336
+ if (types.size === 1 && types.has('branch')) {
337
+ const uniqueBranches = new Set(refs);
338
+ if (uniqueBranches.size > 1) {
339
+ this.throwConflictError(pkg, refs, node.dependents, 'Different branch refs cannot be automatically resolved.\n' +
340
+ 'Add an override in model.yaml:\n\n' +
341
+ ' overrides:\n' +
342
+ ` ${pkg}: ${refs[0]}`);
343
+ }
344
+ // Same branch - no conflict, continue
345
+ continue;
346
+ }
347
+ // Case 4: All SemVer tags - apply "Latest Wins"
348
+ const semvers = refTypes
349
+ .filter((r) => r.semver !== undefined)
350
+ .map(r => r.semver);
351
+ if (semvers.length !== refs.length) {
352
+ // Some refs don't parse as SemVer - can't auto-resolve
353
+ this.throwConflictError(pkg, refs, node.dependents, 'Not all refs are valid SemVer tags.\n' +
354
+ 'Add an override in model.yaml:\n\n' +
355
+ ' overrides:\n' +
356
+ ` ${pkg}: <ref>`);
357
+ }
358
+ // Check major version compatibility
359
+ const majors = new Set(semvers.map(s => s.major));
360
+ if (majors.size > 1) {
361
+ const majorList = Array.from(majors).sort().join(' vs ');
362
+ this.throwConflictError(pkg, refs, node.dependents, `Major version mismatch (v${majorList}). This may indicate breaking changes.\n` +
363
+ 'Add an override in model.yaml if you want to force a version:\n\n' +
364
+ ' overrides:\n' +
365
+ ` ${pkg}: ${refs[refs.length - 1]}`);
366
+ }
367
+ // All same major version - pick latest (Latest Wins!)
368
+ const latest = pickLatestSemVer(refs);
369
+ if (latest && latest !== node.refConstraint) {
370
+ // Update the node to use the resolved ref
371
+ node.refConstraint = latest;
372
+ // Log the resolution for user feedback
373
+ const otherRefs = refs.filter(r => r !== latest).join(', ');
374
+ resolutionMessages.push(`Resolved ${pkg}: using ${latest} (satisfies ${otherRefs})`);
375
+ }
376
+ }
377
+ // Store resolution messages for later output
378
+ if (resolutionMessages.length > 0) {
379
+ this.resolutionMessages = resolutionMessages;
380
+ }
381
+ }
382
+ /**
383
+ * Throws a formatted conflict error with actionable hints.
384
+ */
385
+ throwConflictError(pkg, refs, dependents, hint) {
386
+ const depLines = dependents.map((d, i) => ` └─ ${d} requires ${pkg}@${refs[i] || refs[0]}`).join('\n');
387
+ throw new Error(`Dependency ref conflict for '${pkg}'\n` +
388
+ depLines + '\n\n' +
389
+ hint);
390
+ }
391
+ /**
392
+ * Returns any resolution messages from the last dependency resolution.
393
+ * Useful for CLI output to inform users about auto-resolved conflicts.
394
+ */
395
+ getResolutionMessages() {
396
+ return this.resolutionMessages;
397
+ }
398
+ /**
399
+ * Detects package-level cycles in the dependency graph and throws a clear error.
400
+ */
401
+ detectPackageCycles(graph) {
402
+ const GRAY = 1, BLACK = 2;
403
+ const color = {};
404
+ const stack = [];
405
+ const visit = (pkg) => {
406
+ color[pkg] = GRAY;
407
+ stack.push(pkg);
408
+ const deps = Object.keys(graph.nodes[pkg]?.dependencies ?? {});
409
+ for (const dep of deps) {
410
+ if (!graph.nodes[dep])
411
+ continue; // Unknown dep will resolve later
412
+ if (color[dep] === GRAY) {
413
+ // Found a back edge: cycle
414
+ const cycleStart = stack.indexOf(dep);
415
+ const cyclePath = [...stack.slice(cycleStart), dep].join(' → ');
416
+ throw new Error(`Cyclic package dependency detected:\n` +
417
+ ` ${cyclePath}\n\n` +
418
+ `Hint: Extract shared types into a separate package that both can depend on.`);
419
+ }
420
+ if (color[dep] !== BLACK)
421
+ visit(dep);
422
+ }
423
+ stack.pop();
424
+ color[pkg] = BLACK;
425
+ };
426
+ for (const pkg of Object.keys(graph.nodes)) {
427
+ if (!color[pkg])
428
+ visit(pkg);
429
+ }
430
+ }
431
+ /**
432
+ * Loads an existing lock file from disk.
433
+ */
434
+ static async loadLockFile(workspaceRoot) {
435
+ const lockPath = path.join(workspaceRoot, 'model.lock');
436
+ try {
437
+ const content = await fs.readFile(lockPath, 'utf-8');
438
+ return JSON.parse(content);
439
+ }
440
+ catch {
441
+ // No lock file
442
+ return undefined;
443
+ }
444
+ }
445
+ /**
446
+ * Parses a lock file from JSON format.
447
+ */
448
+ static parseLockFile(content) {
449
+ return JSON.parse(content);
450
+ }
451
+ }
452
+ //# sourceMappingURL=dependency-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-resolver.js","sourceRoot":"","sources":["../../src/services/dependency-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { GitImportInfo } from './types.js';
2
+ export type { GitImportInfo } from './types.js';
3
+ export declare class GitUrlResolver {
4
+ constructor();
5
+ }
6
+ export declare const GitUrlParser: {
7
+ parse(_importStr: string): GitImportInfo;
8
+ isGitUrl(_importStr: string): boolean;
9
+ };
10
+ export declare function loadLockFile(): void;
@@ -0,0 +1,19 @@
1
+ // Browser stub for GitUrlResolver
2
+ // Git operations are not available in the browser environment
3
+ export class GitUrlResolver {
4
+ constructor() {
5
+ throw new Error('GitUrlResolver is not available in the browser.');
6
+ }
7
+ }
8
+ export const GitUrlParser = {
9
+ parse(_importStr) {
10
+ throw new Error('GitUrlParser is not available in the browser.');
11
+ },
12
+ isGitUrl(_importStr) {
13
+ throw new Error('GitUrlParser is not available in the browser.');
14
+ }
15
+ };
16
+ export function loadLockFile() {
17
+ throw new Error('loadLockFile is not available in the browser.');
18
+ }
19
+ //# sourceMappingURL=git-url-resolver.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-url-resolver.browser.js","sourceRoot":"","sources":["../../src/services/git-url-resolver.browser.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,8DAA8D;AAO9D,MAAM,OAAO,cAAc;IACvB;QACI,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACvE,CAAC;CACJ;AAED,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,KAAK,CAAC,UAAkB;QACpB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACrE,CAAC;IACD,QAAQ,CAAC,UAAkB;QACvB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACrE,CAAC;CACJ,CAAC;AAEF,MAAM,UAAU,YAAY;IACxB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;AACrE,CAAC"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Git Repository Resolver Service
3
+ *
4
+ * Resolves git-based package imports to local cached repositories.
5
+ * Supports simplified GitHub syntax (owner/repo@version) and full URLs.
6
+ *
7
+ * Design: Repository-level imports (not individual files)
8
+ * - Imports load entire package
9
+ * - Package entry point defined in model.yaml
10
+ * - Version pinning at repository level
11
+ */
12
+ import { URI } from 'langium';
13
+ import type { GitImportInfo, LockFile } from './types.js';
14
+ /**
15
+ * Parses import URLs into structured git import information.
16
+ *
17
+ * Supported formats:
18
+ * - owner/repo@version (GitHub assumed)
19
+ * - owner/repo (GitHub, defaults to main)
20
+ * - https://github.com/owner/repo@version
21
+ * - https://gitlab.com/owner/repo@version
22
+ * - https://git.example.com/owner/repo@version
23
+ */
24
+ export declare class GitUrlParser {
25
+ /**
26
+ * Determines if an import string is a git repository import.
27
+ */
28
+ static isGitUrl(importStr: string): boolean;
29
+ /**
30
+ * Parses a git import URL into structured components.
31
+ *
32
+ * @param importStr - The import URL string
33
+ * @returns Parsed git import information
34
+ * @throws Error if URL format is invalid
35
+ */
36
+ static parse(importStr: string): GitImportInfo;
37
+ /**
38
+ * Checks if string is GitHub shorthand format.
39
+ */
40
+ private static isGitHubShorthand;
41
+ /**
42
+ * Parses GitHub shorthand (owner/repo or owner/repo@version).
43
+ */
44
+ private static parseGitHubShorthand;
45
+ /**
46
+ * Parses full git URLs (https://...).
47
+ *
48
+ * Supported:
49
+ * - https://github.com/owner/repo@version
50
+ * - https://gitlab.com/owner/repo@version
51
+ * - https://git.example.com/owner/repo@version
52
+ */
53
+ private static parseFullUrl;
54
+ }
55
+ /**
56
+ * Resolves git repository imports to local entry point files.
57
+ *
58
+ * Implements a content-addressable cache:
59
+ * - Cache location: .dlang/packages/ (project-local, per PRS-010)
60
+ * - Cache key: {owner}/{repo}/{commit-hash}
61
+ * - Downloads entire repository on first use
62
+ * - Reads model.yaml to find entry point
63
+ * - Returns URI to entry point file
64
+ */
65
+ export declare class GitUrlResolver {
66
+ private cacheDir;
67
+ private lockFile?;
68
+ /**
69
+ * Creates a GitUrlResolver with a project-local cache directory.
70
+ *
71
+ * @param cacheDir - The cache directory path. Per PRS-010, this should be
72
+ * the project's `.dlang/packages/` directory for isolation
73
+ * and reproducibility (like node_modules).
74
+ */
75
+ constructor(cacheDir: string);
76
+ /**
77
+ * Sets the lock file for dependency resolution.
78
+ *
79
+ * When a lock file is set, all package imports will use
80
+ * the locked commit hashes instead of resolving versions.
81
+ * This ensures reproducible builds and handles transitive dependencies.
82
+ *
83
+ * @param lockFile - The parsed lock file from the workspace root
84
+ */
85
+ setLockFile(lockFile: LockFile | undefined): void;
86
+ /**
87
+ * Resolves a git import URL to the package's entry point file.
88
+ *
89
+ * Process:
90
+ * 1. Parse git URL
91
+ * 2. Check lock file for pinned version (transitive dependency support)
92
+ * 3. Resolve version to commit hash (if not locked)
93
+ * 4. Check cache
94
+ * 5. Download repository if not cached
95
+ * 6. Read model.yaml to find entry point
96
+ * 7. Return URI to entry point file
97
+ *
98
+ * @param importUrl - The git import URL
99
+ * @returns URI to the package's entry point file
100
+ */
101
+ resolve(importUrl: string, options?: {
102
+ allowNetwork?: boolean;
103
+ }): Promise<URI>;
104
+ /**
105
+ * Reads model.yaml to get the package entry point.
106
+ * Falls back to index.dlang if no model.yaml found.
107
+ */
108
+ private getEntryPoint;
109
+ /**
110
+ * Parses model.yaml content to extract entry point.
111
+ *
112
+ * Expected structure:
113
+ * model:
114
+ * entry: index.dlang
115
+ */
116
+ private parseYaml;
117
+ /**
118
+ * Resolves a version (tag/branch) to a commit hash using git ls-remote.
119
+ */
120
+ private resolveCommit;
121
+ /**
122
+ * Gets the local cache path for a git repository.
123
+ *
124
+ * Format: .dlang/packages/{owner}/{repo}/{version}/
125
+ *
126
+ * Per PRS-010: Project-local cache structure mirrors the Design Considerations
127
+ * section showing `.dlang/packages/{owner}/{repo}/{version}/` layout.
128
+ */
129
+ private getCachePath;
130
+ /**
131
+ * Checks if a file or directory exists in the cache.
132
+ */
133
+ private existsInCache;
134
+ /**
135
+ * Downloads a git repository to the cache.
136
+ *
137
+ * Uses shallow clone for efficiency (only downloads the specific commit).
138
+ */
139
+ private downloadRepo;
140
+ /**
141
+ * Clears the entire cache.
142
+ */
143
+ clearCache(): Promise<void>;
144
+ /**
145
+ * Gets cache statistics (size, number of cached repos, etc.).
146
+ *
147
+ * Cache structure: .dlang/packages/{owner}/{repo}/{version}/
148
+ */
149
+ getCacheStats(): Promise<{
150
+ totalSize: number;
151
+ repoCount: number;
152
+ cacheDir: string;
153
+ }>;
154
+ /**
155
+ * Gets the total size of a directory in bytes.
156
+ */
157
+ private getDirectorySize;
158
+ }