@domainlang/language 0.5.2 → 0.6.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 (104) hide show
  1. package/out/domain-lang-module.js +3 -1
  2. package/out/domain-lang-module.js.map +1 -1
  3. package/out/generated/ast.d.ts +24 -0
  4. package/out/generated/ast.js.map +1 -1
  5. package/out/generated/grammar.js +22 -32
  6. package/out/generated/grammar.js.map +1 -1
  7. package/out/index.d.ts +2 -5
  8. package/out/index.js +10 -6
  9. package/out/index.js.map +1 -1
  10. package/out/lsp/domain-lang-code-actions.js +14 -8
  11. package/out/lsp/domain-lang-code-actions.js.map +1 -1
  12. package/out/lsp/domain-lang-completion.d.ts +3 -0
  13. package/out/lsp/domain-lang-completion.js +41 -13
  14. package/out/lsp/domain-lang-completion.js.map +1 -1
  15. package/out/lsp/domain-lang-formatter.js +24 -18
  16. package/out/lsp/domain-lang-formatter.js.map +1 -1
  17. package/out/lsp/domain-lang-index-manager.d.ts +102 -0
  18. package/out/lsp/domain-lang-index-manager.js +221 -0
  19. package/out/lsp/domain-lang-index-manager.js.map +1 -0
  20. package/out/lsp/domain-lang-scope.js +31 -17
  21. package/out/lsp/domain-lang-scope.js.map +1 -1
  22. package/out/lsp/domain-lang-workspace-manager.d.ts +51 -9
  23. package/out/lsp/domain-lang-workspace-manager.js +86 -63
  24. package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
  25. package/out/lsp/hover/domain-lang-hover.d.ts +45 -1
  26. package/out/lsp/hover/domain-lang-hover.js +308 -232
  27. package/out/lsp/hover/domain-lang-hover.js.map +1 -1
  28. package/out/lsp/hover/domain-lang-keywords.d.ts +3 -7
  29. package/out/lsp/hover/domain-lang-keywords.js +115 -38
  30. package/out/lsp/hover/domain-lang-keywords.js.map +1 -1
  31. package/out/lsp/manifest-diagnostics.js +95 -50
  32. package/out/lsp/manifest-diagnostics.js.map +1 -1
  33. package/out/main.js +109 -17
  34. package/out/main.js.map +1 -1
  35. package/out/services/import-resolver.d.ts +16 -2
  36. package/out/services/import-resolver.js +37 -11
  37. package/out/services/import-resolver.js.map +1 -1
  38. package/out/services/types.d.ts +2 -2
  39. package/out/services/workspace-manager.d.ts +33 -31
  40. package/out/services/workspace-manager.js +92 -148
  41. package/out/services/workspace-manager.js.map +1 -1
  42. package/out/utils/document-utils.d.ts +41 -0
  43. package/out/utils/document-utils.js +64 -0
  44. package/out/utils/document-utils.js.map +1 -0
  45. package/out/utils/import-utils.d.ts +0 -17
  46. package/out/utils/import-utils.js +2 -32
  47. package/out/utils/import-utils.js.map +1 -1
  48. package/out/utils/manifest-utils.d.ts +56 -0
  49. package/out/utils/manifest-utils.js +119 -0
  50. package/out/utils/manifest-utils.js.map +1 -0
  51. package/out/validation/import.d.ts +1 -2
  52. package/out/validation/import.js +33 -20
  53. package/out/validation/import.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/domain-lang-module.ts +4 -1
  56. package/src/domain-lang.langium +37 -13
  57. package/src/generated/ast.ts +24 -0
  58. package/src/generated/grammar.ts +22 -32
  59. package/src/index.ts +12 -6
  60. package/src/lsp/domain-lang-code-actions.ts +13 -8
  61. package/src/lsp/domain-lang-completion.ts +61 -13
  62. package/src/lsp/domain-lang-formatter.ts +28 -23
  63. package/src/lsp/domain-lang-index-manager.ts +256 -0
  64. package/src/lsp/domain-lang-scope.ts +29 -17
  65. package/src/lsp/domain-lang-workspace-manager.ts +89 -66
  66. package/src/lsp/hover/domain-lang-hover.ts +332 -226
  67. package/src/lsp/hover/domain-lang-keywords.ts +129 -43
  68. package/src/lsp/manifest-diagnostics.ts +100 -59
  69. package/src/main.ts +127 -16
  70. package/src/services/import-resolver.ts +39 -11
  71. package/src/services/types.ts +2 -2
  72. package/src/services/workspace-manager.ts +101 -175
  73. package/src/utils/document-utils.ts +80 -0
  74. package/src/utils/import-utils.ts +2 -40
  75. package/src/utils/manifest-utils.ts +132 -0
  76. package/src/validation/import.ts +32 -22
  77. package/out/lsp/hover/ddd-pattern-explanations.d.ts +0 -50
  78. package/out/lsp/hover/ddd-pattern-explanations.js +0 -196
  79. package/out/lsp/hover/ddd-pattern-explanations.js.map +0 -1
  80. package/out/services/dependency-analyzer.d.ts +0 -58
  81. package/out/services/dependency-analyzer.js +0 -254
  82. package/out/services/dependency-analyzer.js.map +0 -1
  83. package/out/services/dependency-resolver.d.ts +0 -146
  84. package/out/services/dependency-resolver.js +0 -452
  85. package/out/services/dependency-resolver.js.map +0 -1
  86. package/out/services/git-url-resolver.browser.d.ts +0 -10
  87. package/out/services/git-url-resolver.browser.js +0 -19
  88. package/out/services/git-url-resolver.browser.js.map +0 -1
  89. package/out/services/git-url-resolver.d.ts +0 -158
  90. package/out/services/git-url-resolver.js +0 -416
  91. package/out/services/git-url-resolver.js.map +0 -1
  92. package/out/services/governance-validator.d.ts +0 -44
  93. package/out/services/governance-validator.js +0 -153
  94. package/out/services/governance-validator.js.map +0 -1
  95. package/out/services/semver.d.ts +0 -98
  96. package/out/services/semver.js +0 -195
  97. package/out/services/semver.js.map +0 -1
  98. package/src/lsp/hover/ddd-pattern-explanations.ts +0 -237
  99. package/src/services/dependency-analyzer.ts +0 -321
  100. package/src/services/dependency-resolver.ts +0 -551
  101. package/src/services/git-url-resolver.browser.ts +0 -26
  102. package/src/services/git-url-resolver.ts +0 -517
  103. package/src/services/governance-validator.ts +0 -177
  104. package/src/services/semver.ts +0 -213
@@ -1,7 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { URI, type LangiumDocument, type LangiumDocuments } from 'langium';
3
3
  import type { Model } from '../generated/ast.js';
4
- import type { GitUrlResolver } from '../services/git-url-resolver.js';
5
4
  import { WorkspaceManager } from '../services/workspace-manager.js';
6
5
  import { ImportResolver } from '../services/import-resolver.js';
7
6
  import type { DomainLangServices } from '../domain-lang-module.js';
@@ -27,7 +26,7 @@ let lastInitializedDir: string | undefined;
27
26
  async function getStandaloneImportResolver(startDir: string): Promise<ImportResolver> {
28
27
  // Re-initialize if directory changed (workspace boundary)
29
28
  if (lastInitializedDir !== startDir || !standaloneImportResolver) {
30
- standaloneWorkspaceManager = new WorkspaceManager({ autoResolve: false, allowNetwork: false });
29
+ standaloneWorkspaceManager = new WorkspaceManager();
31
30
  try {
32
31
  await standaloneWorkspaceManager.initialize(startDir);
33
32
  } catch (error) {
@@ -42,18 +41,6 @@ async function getStandaloneImportResolver(startDir: string): Promise<ImportReso
42
41
  return standaloneImportResolver;
43
42
  }
44
43
 
45
- /**
46
- * Gets the git URL resolver from a workspace manager.
47
- *
48
- * @param startDir - Directory to start workspace search from
49
- * @returns Promise resolving to the git URL resolver
50
- */
51
- async function getGitResolver(startDir: string): Promise<GitUrlResolver> {
52
- const workspaceManager = new WorkspaceManager({ autoResolve: false, allowNetwork: false });
53
- await workspaceManager.initialize(startDir);
54
- return workspaceManager.getGitResolver();
55
- }
56
-
57
44
  /**
58
45
  * Resolves an import path to an absolute file URI.
59
46
  *
@@ -115,7 +102,7 @@ export async function ensureImportGraphFromDocument(
115
102
  for (const imp of model.imports ?? []) {
116
103
  if (!imp.uri) continue;
117
104
 
118
- // Use new resolveImportPath that supports git URLs
105
+ // Use new resolveImportPath that supports external dependencies
119
106
  const resolvedUri = await resolveImportPath(doc, imp.uri);
120
107
  const childDoc = await langiumDocuments.getOrCreateDocument(resolvedUri);
121
108
  await visit(childDoc);
@@ -125,28 +112,3 @@ export async function ensureImportGraphFromDocument(
125
112
  await visit(document);
126
113
  return visited;
127
114
  }
128
-
129
- /**
130
- * Gets cache statistics for git imports.
131
- *
132
- * @returns Cache statistics including size and number of cached repositories
133
- */
134
- export async function getGitCacheStats(startDir: string = process.cwd()): Promise<{
135
- totalSize: number;
136
- repoCount: number;
137
- cacheDir: string;
138
- }> {
139
- const resolver = await getGitResolver(startDir);
140
- return await resolver.getCacheStats();
141
- }
142
-
143
- /**
144
- * Clears the git import cache.
145
- *
146
- * @param startDir - Starting directory for workspace resolution
147
- * @returns Promise that resolves when cache is cleared
148
- */
149
- export async function clearGitCache(startDir: string = process.cwd()): Promise<void> {
150
- const resolver = await getGitResolver(startDir);
151
- return await resolver.clearCache();
152
- }
@@ -0,0 +1,132 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs/promises';
3
+ import YAML from 'yaml';
4
+ import type { ModelManifest } from '../services/types.js';
5
+
6
+ const DEFAULT_MANIFEST_FILENAME = 'model.yaml';
7
+ const DEFAULT_ENTRY_FILE = 'index.dlang';
8
+
9
+ /**
10
+ * Checks if a file exists at the given path.
11
+ */
12
+ export async function fileExists(targetPath: string): Promise<boolean> {
13
+ try {
14
+ await fs.access(targetPath);
15
+ return true;
16
+ } catch (error) {
17
+ if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') {
18
+ return false;
19
+ }
20
+ throw error;
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Finds the nearest model.yaml manifest by walking up from startPath.
26
+ *
27
+ * @param startPath - Directory to start searching from
28
+ * @returns Absolute path to model.yaml, or undefined if not found
29
+ */
30
+ export async function findNearestManifest(startPath: string): Promise<string | undefined> {
31
+ let current = path.resolve(startPath);
32
+ const { root } = path.parse(current);
33
+
34
+ while (true) {
35
+ const candidate = path.join(current, DEFAULT_MANIFEST_FILENAME);
36
+ if (await fileExists(candidate)) {
37
+ return candidate;
38
+ }
39
+
40
+ if (current === root) {
41
+ return undefined;
42
+ }
43
+
44
+ const parent = path.dirname(current);
45
+ if (parent === current) {
46
+ return undefined;
47
+ }
48
+ current = parent;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Finds the workspace root (directory containing model.yaml).
54
+ *
55
+ * @param startPath - Directory to start searching from
56
+ * @returns Absolute path to workspace root, or undefined if no manifest found
57
+ */
58
+ export async function findWorkspaceRoot(startPath: string): Promise<string | undefined> {
59
+ const manifestPath = await findNearestManifest(startPath);
60
+ return manifestPath ? path.dirname(manifestPath) : undefined;
61
+ }
62
+
63
+ /**
64
+ * Reads and parses a model.yaml manifest.
65
+ *
66
+ * @param manifestPath - Absolute path to model.yaml
67
+ * @returns Parsed manifest, or undefined if file doesn't exist
68
+ * @throws Error if file exists but cannot be parsed
69
+ */
70
+ export async function readManifest(manifestPath: string): Promise<ModelManifest | undefined> {
71
+ try {
72
+ const content = await fs.readFile(manifestPath, 'utf-8');
73
+ return (YAML.parse(content) ?? {}) as ModelManifest;
74
+ } catch (error) {
75
+ if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') {
76
+ return undefined;
77
+ }
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Reads the entry point from a manifest file.
84
+ *
85
+ * @param manifestPath - Absolute path to model.yaml
86
+ * @returns Entry file path (relative), defaults to 'index.dlang'
87
+ */
88
+ export async function readEntryFromManifest(manifestPath: string): Promise<string> {
89
+ try {
90
+ const manifest = await readManifest(manifestPath);
91
+ return manifest?.model?.entry ?? DEFAULT_ENTRY_FILE;
92
+ } catch {
93
+ return DEFAULT_ENTRY_FILE;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Gets the absolute entry file path for a manifest.
99
+ *
100
+ * @param manifestPath - Absolute path to model.yaml
101
+ * @returns Absolute path to the entry file
102
+ */
103
+ export async function getEntryPath(manifestPath: string): Promise<string> {
104
+ const entry = await readEntryFromManifest(manifestPath);
105
+ return path.resolve(path.dirname(manifestPath), entry);
106
+ }
107
+
108
+ /**
109
+ * Discovers all manifest files within given directories.
110
+ * Only checks direct children, not recursive subdirectories.
111
+ *
112
+ * @param directories - Array of absolute directory paths to search
113
+ * @returns Array of manifest info objects
114
+ */
115
+ export async function findManifestsInDirectories(
116
+ directories: string[]
117
+ ): Promise<Array<{ manifestPath: string; entryPath: string }>> {
118
+ const results: Array<{ manifestPath: string; entryPath: string }> = [];
119
+
120
+ for (const dir of directories) {
121
+ const manifestPath = await findNearestManifest(dir);
122
+ if (manifestPath) {
123
+ const entryPath = await getEntryPath(manifestPath);
124
+ results.push({ manifestPath, entryPath });
125
+ }
126
+ }
127
+
128
+ return results;
129
+ }
130
+
131
+ /** Default manifest filename */
132
+ export { DEFAULT_MANIFEST_FILENAME, DEFAULT_ENTRY_FILE };
@@ -1,10 +1,9 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import type { ValidationAcceptor, ValidationChecks } from 'langium';
3
+ import type { ValidationAcceptor, ValidationChecks, LangiumDocument } from 'langium';
4
4
  import { Cancellation } from 'langium';
5
5
  import type { DomainLangAstType, ImportStatement } from '../generated/ast.js';
6
6
  import type { DomainLangServices } from '../domain-lang-module.js';
7
- import type { LangiumDocument } from 'langium';
8
7
  import type { WorkspaceManager } from '../services/workspace-manager.js';
9
8
  import type { ExtendedDependencySpec, ModelManifest, LockFile } from '../services/types.js';
10
9
  import { ValidationMessages, buildCodeDescription, IssueCodes } from './constants.js';
@@ -200,17 +199,23 @@ export class ImportValidator {
200
199
  return;
201
200
  }
202
201
 
203
- const workspaceRoot = this.workspaceManager.getWorkspaceRoot();
204
- const resolvedPath = path.resolve(workspaceRoot, dependencyPath);
205
- const relativeToWorkspace = path.relative(workspaceRoot, resolvedPath);
202
+ try {
203
+ const workspaceRoot = this.workspaceManager.getWorkspaceRoot();
204
+ const resolvedPath = path.resolve(workspaceRoot, dependencyPath);
205
+ const relativeToWorkspace = path.relative(workspaceRoot, resolvedPath);
206
206
 
207
- if (relativeToWorkspace.startsWith('..') || path.isAbsolute(relativeToWorkspace)) {
208
- accept('error', ValidationMessages.IMPORT_ESCAPES_WORKSPACE(alias), {
209
- node: imp,
210
- property: 'uri',
211
- codeDescription: buildCodeDescription('language.md', 'imports'),
212
- data: { code: IssueCodes.ImportEscapesWorkspace, alias }
213
- });
207
+ if (relativeToWorkspace.startsWith('..') || path.isAbsolute(relativeToWorkspace)) {
208
+ accept('error', ValidationMessages.IMPORT_ESCAPES_WORKSPACE(alias), {
209
+ node: imp,
210
+ property: 'uri',
211
+ codeDescription: buildCodeDescription('language.md', 'imports'),
212
+ data: { code: IssueCodes.ImportEscapesWorkspace, alias }
213
+ });
214
+ }
215
+ } catch (error) {
216
+ // WorkspaceManager not initialized - skip workspace boundary check
217
+ // This can happen for standalone files without model.yaml
218
+ console.warn(`Could not validate workspace boundary for path dependency: ${error}`);
214
219
  }
215
220
  }
216
221
 
@@ -238,17 +243,22 @@ export class ImportValidator {
238
243
  return;
239
244
  }
240
245
 
241
- const workspaceRoot = this.workspaceManager.getWorkspaceRoot();
242
- const cacheDir = this.getCacheDirectory(workspaceRoot, packageKey, lockedDep.commit);
246
+ try {
247
+ const workspaceRoot = this.workspaceManager.getWorkspaceRoot();
248
+ const cacheDir = this.getCacheDirectory(workspaceRoot, packageKey, lockedDep.commit);
243
249
 
244
- const cacheExists = await this.directoryExists(cacheDir);
245
- if (!cacheExists) {
246
- accept('error', ValidationMessages.IMPORT_NOT_INSTALLED(alias), {
247
- node: imp,
248
- property: 'uri',
249
- codeDescription: buildCodeDescription('language.md', 'imports'),
250
- data: { code: IssueCodes.ImportNotInstalled, alias }
251
- });
250
+ const cacheExists = await this.directoryExists(cacheDir);
251
+ if (!cacheExists) {
252
+ accept('error', ValidationMessages.IMPORT_NOT_INSTALLED(alias), {
253
+ node: imp,
254
+ property: 'uri',
255
+ codeDescription: buildCodeDescription('language.md', 'imports'),
256
+ data: { code: IssueCodes.ImportNotInstalled, alias }
257
+ });
258
+ }
259
+ } catch (error) {
260
+ // WorkspaceManager not initialized - log warning but continue
261
+ console.warn(`Could not validate cached package for ${alias}: ${error}`);
252
262
  }
253
263
  }
254
264
 
@@ -1,50 +0,0 @@
1
- /**
2
- * DDD Pattern Explanations for Hover Documentation
3
- *
4
- * Provides plain-English explanations for DDD integration patterns,
5
- * relationship types, and decision categories.
6
- */
7
- /**
8
- * Explanations for DDD integration role patterns (e.g., PL, ACL, SK).
9
- */
10
- export declare const rolePatternExplanations: Record<string, string>;
11
- /**
12
- * Explanations for relationship types (e.g., Partnership, CustomerSupplier).
13
- */
14
- export declare const relationshipTypeExplanations: Record<string, string>;
15
- /**
16
- * Explanations for relationship arrows.
17
- */
18
- export declare const arrowExplanations: Record<string, string>;
19
- /**
20
- * Explanations for decision categories.
21
- */
22
- export declare const decisionCategoryExplanations: Record<string, string>;
23
- /**
24
- * Explanations for common DDD classifications.
25
- */
26
- export declare const classificationExplanations: Record<string, string>;
27
- /**
28
- * Get explanation for a role pattern.
29
- */
30
- export declare function explainRolePattern(role: string): string | undefined;
31
- /**
32
- * Get explanation for a relationship type.
33
- */
34
- export declare function explainRelationshipType(type: string): string | undefined;
35
- /**
36
- * Get explanation for an arrow symbol.
37
- */
38
- export declare function explainArrow(arrow: string): string | undefined;
39
- /**
40
- * Get explanation for a decision category.
41
- */
42
- export declare function explainDecisionCategory(category: string): string | undefined;
43
- /**
44
- * Get explanation for a classification.
45
- */
46
- export declare function explainClassification(name: string): string | undefined;
47
- /**
48
- * Generate relationship explanation from roles and type.
49
- */
50
- export declare function generateRelationshipExplanation(leftRoles: string[] | undefined, arrow: string | undefined, rightRoles: string[] | undefined, type: string | undefined): string;
@@ -1,196 +0,0 @@
1
- /**
2
- * DDD Pattern Explanations for Hover Documentation
3
- *
4
- * Provides plain-English explanations for DDD integration patterns,
5
- * relationship types, and decision categories.
6
- */
7
- /**
8
- * Explanations for DDD integration role patterns (e.g., PL, ACL, SK).
9
- */
10
- export const rolePatternExplanations = {
11
- 'PL': `**Published Language (PL)**
12
-
13
- The upstream context provides a well-documented, stable API/model that downstream contexts consume.
14
-
15
- \`\`\`domain-lang
16
- [PL] UpstreamContext -> DownstreamContext
17
- \`\`\`
18
-
19
- *Use when:* Multiple consumers need a shared, stable interface.`,
20
- 'ACL': `**Anti-Corruption Layer (ACL)**
21
-
22
- Protects downstream from upstream changes by translating between models.
23
-
24
- \`\`\`domain-lang
25
- UpstreamContext -> [ACL] DownstreamContext
26
- \`\`\`
27
-
28
- *Use when:* You don't trust upstream stability or want isolation.`,
29
- 'SK': `**Shared Kernel (SK)**
30
-
31
- Both contexts share common domain model code requiring coordination.
32
-
33
- \`\`\`domain-lang
34
- [SK] Context1 <-> [SK] Context2 : SharedKernel
35
- \`\`\`
36
-
37
- *Use when:* Contexts are tightly coupled and teams can coordinate.`,
38
- 'CF': `**Conformist (CF)**
39
-
40
- Downstream accepts upstream model without translation.
41
-
42
- \`\`\`domain-lang
43
- UpstreamContext -> [CF] DownstreamContext
44
- \`\`\`
45
-
46
- *Use when:* Upstream model is acceptable and translation isn't worth it.`,
47
- 'OHS': `**Open Host Service (OHS)**
48
-
49
- Upstream defines a protocol/API for easy integration.
50
-
51
- \`\`\`domain-lang
52
- [OHS, PL] ApiContext -> ConsumerContext
53
- \`\`\`
54
-
55
- *Use when:* Multiple downstream contexts need integration.`,
56
- 'P': `**Partnership (P)**
57
-
58
- Teams coordinate development and align releases.
59
-
60
- \`\`\`domain-lang
61
- Context1 <-> Context2 : Partnership
62
- \`\`\`
63
-
64
- *Use when:* Mutual success dependency exists.`,
65
- 'BBoM': `**Big Ball of Mud (BBoM)**
66
-
67
- No clear boundaries - tangled models needing refactoring.
68
-
69
- \`\`\`domain-lang
70
- [BBoM] LegacySystem -> ModernContext
71
- \`\`\`
72
-
73
- *Use when:* Documenting legacy systems.`
74
- };
75
- /**
76
- * Explanations for relationship types (e.g., Partnership, CustomerSupplier).
77
- */
78
- export const relationshipTypeExplanations = {
79
- 'Partnership': '**Partnership**\n\nTwo contexts with mutual success dependency. Teams plan together and coordinate releases.\n\n*Example:* Sales and Order Fulfillment contexts that must evolve in sync.',
80
- 'SharedKernel': '**Shared Kernel**\n\nTwo contexts share a subset of code/model. Changes require agreement from both teams.\n\n*Example:* Two closely related contexts sharing common domain entities.',
81
- 'CustomerSupplier': '**Customer/Supplier**\n\nDownstream (customer) context depends on upstream (supplier) context. Supplier meets customer\'s needs through negotiation.\n\n*Example:* Payment context (customer) depends on Billing context (supplier).',
82
- 'UpstreamDownstream': '**Upstream/Downstream**\n\nUpstream context influences downstream context, but not vice versa. Downstream adapts to upstream changes.\n\n*Example:* Inventory (upstream) provides data to Reporting (downstream).',
83
- 'SeparateWays': '**Separate Ways**\n\nNo connection between contexts - they duplicate functionality rather than integrate.\n\n*Use when:* Integration cost exceeds benefit of sharing.'
84
- };
85
- /**
86
- * Explanations for relationship arrows.
87
- */
88
- export const arrowExplanations = {
89
- '<->': 'Bidirectional relationship - both contexts influence each other',
90
- '->': 'Downstream dependency - right depends on left (left is upstream)',
91
- '<-': 'Upstream dependency - left depends on right (right is upstream)',
92
- '><': 'Separate Ways - no integration between contexts',
93
- 'U/D': 'Upstream/Downstream - shorthand for upstream → downstream flow',
94
- 'u/d': 'Upstream/Downstream - shorthand for upstream → downstream flow',
95
- 'C/S': 'Customer/Supplier - shorthand for customer ← supplier relationship',
96
- 'c/s': 'Customer/Supplier - shorthand for customer ← supplier relationship'
97
- };
98
- /**
99
- * Explanations for decision categories.
100
- */
101
- export const decisionCategoryExplanations = {
102
- 'architectural': '**Architectural Decision**\n\nConcerns system structure, technology choices, or cross-cutting patterns.\n\n*Examples:* Microservices vs monolith, event sourcing, CQRS',
103
- 'arch': 'Short for "architectural" - concerns system structure and technology choices',
104
- 'business': '**Business Decision**\n\nConcerns business rules, policies, or domain logic.\n\n*Examples:* Pricing rules, refund policies, eligibility criteria',
105
- 'biz': 'Short for "business" - concerns business rules and domain logic',
106
- 'technical': '**Technical Decision**\n\nConcerns implementation details, algorithms, or technical constraints.\n\n*Examples:* Caching strategy, data structures, optimization approach',
107
- 'tech': 'Short for "technical" - concerns implementation details',
108
- 'compliance': '**Compliance Decision**\n\nConcerns legal, regulatory, or compliance requirements.\n\n*Examples:* GDPR data retention, SOX audit trails, HIPAA privacy',
109
- 'security': '**Security Decision**\n\nConcerns security, authentication, authorization, or data protection.\n\n*Examples:* OAuth vs JWT, encryption at rest, access control',
110
- 'operational': '**Operational Decision**\n\nConcerns deployment, monitoring, or operational procedures.\n\n*Examples:* Blue/green deployment, monitoring strategy, backup policy',
111
- 'ops': 'Short for "operational" - concerns deployment and operations'
112
- };
113
- /**
114
- * Explanations for common DDD classifications.
115
- */
116
- export const classificationExplanations = {
117
- 'Core': '**Core Domain**\n\nThe primary differentiator for your business - this is where you create unique value.\n\n*Invest heavily:* Best team, careful design, deep modeling.\n\n*Example:* Recommendation engine for Netflix, search for Google',
118
- 'Supporting': '**Supporting Subdomain**\n\nNecessary for the business but not a differentiator. Custom implementation needed but not the main focus.\n\n*Invest moderately:* Good team, solid implementation.\n\n*Example:* Inventory management, invoicing',
119
- 'Generic': '**Generic Subdomain**\n\nSolved problem - could use off-the-shelf solution. No competitive advantage.\n\n*Buy or reuse:* Use existing solutions when possible.\n\n*Example:* User authentication, email sending, payment processing',
120
- 'Strategic': '**Strategic** (Wardley Evolution)\n\nNovel, custom-built, competitive advantage. High value, low maturity.\n\n*Similar to Core Domain.*',
121
- 'Custom': '**Custom-Built** (Wardley Evolution)\n\nSpecialized solution, some precedent exists. Medium-high value, medium maturity.',
122
- 'Product': '**Product/Rental** (Wardley Evolution)\n\nStandardized product with features. Medium value, medium-high maturity.\n\n*Example:* SaaS tools, commercial software',
123
- 'Commodity': '**Commodity/Utility** (Wardley Evolution)\n\nUbiquitous, interchangeable, fully standardized. Low value, high maturity.\n\n*Example:* Cloud compute, email services'
124
- };
125
- /**
126
- * Get explanation for a role pattern.
127
- */
128
- export function explainRolePattern(role) {
129
- return rolePatternExplanations[role];
130
- }
131
- /**
132
- * Get explanation for a relationship type.
133
- */
134
- export function explainRelationshipType(type) {
135
- return relationshipTypeExplanations[type];
136
- }
137
- /**
138
- * Get explanation for an arrow symbol.
139
- */
140
- export function explainArrow(arrow) {
141
- return arrowExplanations[arrow];
142
- }
143
- /**
144
- * Get explanation for a decision category.
145
- */
146
- export function explainDecisionCategory(category) {
147
- return decisionCategoryExplanations[category];
148
- }
149
- /**
150
- * Get explanation for a classification.
151
- */
152
- export function explainClassification(name) {
153
- return classificationExplanations[name];
154
- }
155
- /**
156
- * Generate relationship explanation from roles and type.
157
- */
158
- export function generateRelationshipExplanation(leftRoles, arrow, rightRoles, type) {
159
- const parts = [];
160
- // Arrow explanation
161
- if (arrow) {
162
- const arrowExp = explainArrow(arrow);
163
- if (arrowExp) {
164
- parts.push(`**Arrow:** ${arrowExp}`);
165
- }
166
- }
167
- // Left roles
168
- if (leftRoles && leftRoles.length > 0) {
169
- parts.push('**Left Context Patterns:**');
170
- leftRoles.forEach(role => {
171
- const exp = explainRolePattern(role);
172
- if (exp) {
173
- parts.push(exp);
174
- }
175
- });
176
- }
177
- // Right roles
178
- if (rightRoles && rightRoles.length > 0) {
179
- parts.push('**Right Context Patterns:**');
180
- rightRoles.forEach(role => {
181
- const exp = explainRolePattern(role);
182
- if (exp) {
183
- parts.push(exp);
184
- }
185
- });
186
- }
187
- // Relationship type
188
- if (type) {
189
- const typeExp = explainRelationshipType(type);
190
- if (typeExp) {
191
- parts.push(typeExp);
192
- }
193
- }
194
- return parts.join('\n\n---\n\n');
195
- }
196
- //# sourceMappingURL=ddd-pattern-explanations.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ddd-pattern-explanations.js","sourceRoot":"","sources":["../../../src/lsp/hover/ddd-pattern-explanations.ts"],"names":[],"mappings":"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"}
@@ -1,58 +0,0 @@
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
- import type { LockFile, DependencyTreeNode, ReverseDependency, VersionPolicy } from './types.js';
11
- /**
12
- * Analyzes dependency relationships and provides visualization/analysis tools.
13
- */
14
- export declare class DependencyAnalyzer {
15
- /**
16
- * Builds a dependency tree from a lock file.
17
- *
18
- * @param lockFile - The lock file to analyze
19
- * @param workspaceRoot - Workspace root to load dependency metadata
20
- * @returns Root nodes of the dependency tree
21
- */
22
- buildDependencyTree(lockFile: LockFile, workspaceRoot: string): Promise<DependencyTreeNode[]>;
23
- /**
24
- * Recursively builds a dependency tree node.
25
- */
26
- private buildTreeNode;
27
- /**
28
- * Finds all packages that depend on a given package.
29
- *
30
- * @param targetPackage - Package to analyze
31
- * @param lockFile - Lock file with all dependencies
32
- * @param workspaceRoot - Workspace root
33
- * @returns List of reverse dependencies
34
- */
35
- findReverseDependencies(targetPackage: string, lockFile: LockFile, workspaceRoot: string): Promise<ReverseDependency[]>;
36
- /**
37
- * Formats a dependency tree as a readable string.
38
- */
39
- formatDependencyTree(nodes: DependencyTreeNode[], options?: {
40
- showCommits?: boolean;
41
- }): string;
42
- /**
43
- * Detects circular dependencies in a dependency graph.
44
- */
45
- detectCircularDependencies(lockFile: LockFile): Promise<string[][]>;
46
- /**
47
- * Resolves ref policies (latest, stable) to concrete refs.
48
- */
49
- resolveVersionPolicy(_packageKey: string, policy: string, availableRefs: string[]): Promise<VersionPolicy>;
50
- /**
51
- * Gets the cache directory for a package.
52
- */
53
- private getCacheDir;
54
- /**
55
- * Loads dependencies from a cached package.
56
- */
57
- private loadPackageDependencies;
58
- }