@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.
- package/out/domain-lang-module.js +3 -1
- package/out/domain-lang-module.js.map +1 -1
- package/out/generated/ast.d.ts +24 -0
- package/out/generated/ast.js.map +1 -1
- package/out/generated/grammar.js +22 -32
- package/out/generated/grammar.js.map +1 -1
- package/out/index.d.ts +2 -5
- package/out/index.js +10 -6
- package/out/index.js.map +1 -1
- package/out/lsp/domain-lang-code-actions.js +14 -8
- package/out/lsp/domain-lang-code-actions.js.map +1 -1
- package/out/lsp/domain-lang-completion.d.ts +3 -0
- package/out/lsp/domain-lang-completion.js +41 -13
- package/out/lsp/domain-lang-completion.js.map +1 -1
- package/out/lsp/domain-lang-formatter.js +24 -18
- package/out/lsp/domain-lang-formatter.js.map +1 -1
- package/out/lsp/domain-lang-index-manager.d.ts +102 -0
- package/out/lsp/domain-lang-index-manager.js +221 -0
- package/out/lsp/domain-lang-index-manager.js.map +1 -0
- package/out/lsp/domain-lang-scope.js +31 -17
- package/out/lsp/domain-lang-scope.js.map +1 -1
- package/out/lsp/domain-lang-workspace-manager.d.ts +51 -9
- package/out/lsp/domain-lang-workspace-manager.js +86 -63
- package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
- package/out/lsp/hover/domain-lang-hover.d.ts +45 -1
- package/out/lsp/hover/domain-lang-hover.js +308 -232
- package/out/lsp/hover/domain-lang-hover.js.map +1 -1
- package/out/lsp/hover/domain-lang-keywords.d.ts +3 -7
- package/out/lsp/hover/domain-lang-keywords.js +115 -38
- package/out/lsp/hover/domain-lang-keywords.js.map +1 -1
- package/out/lsp/manifest-diagnostics.js +95 -50
- package/out/lsp/manifest-diagnostics.js.map +1 -1
- package/out/main.js +109 -17
- package/out/main.js.map +1 -1
- package/out/services/import-resolver.d.ts +16 -2
- package/out/services/import-resolver.js +37 -11
- package/out/services/import-resolver.js.map +1 -1
- package/out/services/types.d.ts +2 -2
- package/out/services/workspace-manager.d.ts +33 -31
- package/out/services/workspace-manager.js +92 -148
- package/out/services/workspace-manager.js.map +1 -1
- package/out/utils/document-utils.d.ts +41 -0
- package/out/utils/document-utils.js +64 -0
- package/out/utils/document-utils.js.map +1 -0
- package/out/utils/import-utils.d.ts +0 -17
- package/out/utils/import-utils.js +2 -32
- package/out/utils/import-utils.js.map +1 -1
- package/out/utils/manifest-utils.d.ts +56 -0
- package/out/utils/manifest-utils.js +119 -0
- package/out/utils/manifest-utils.js.map +1 -0
- package/out/validation/import.d.ts +1 -2
- package/out/validation/import.js +33 -20
- package/out/validation/import.js.map +1 -1
- package/package.json +1 -1
- package/src/domain-lang-module.ts +4 -1
- package/src/domain-lang.langium +37 -13
- package/src/generated/ast.ts +24 -0
- package/src/generated/grammar.ts +22 -32
- package/src/index.ts +12 -6
- package/src/lsp/domain-lang-code-actions.ts +13 -8
- package/src/lsp/domain-lang-completion.ts +61 -13
- package/src/lsp/domain-lang-formatter.ts +28 -23
- package/src/lsp/domain-lang-index-manager.ts +256 -0
- package/src/lsp/domain-lang-scope.ts +29 -17
- package/src/lsp/domain-lang-workspace-manager.ts +89 -66
- package/src/lsp/hover/domain-lang-hover.ts +332 -226
- package/src/lsp/hover/domain-lang-keywords.ts +129 -43
- package/src/lsp/manifest-diagnostics.ts +100 -59
- package/src/main.ts +127 -16
- package/src/services/import-resolver.ts +39 -11
- package/src/services/types.ts +2 -2
- package/src/services/workspace-manager.ts +101 -175
- package/src/utils/document-utils.ts +80 -0
- package/src/utils/import-utils.ts +2 -40
- package/src/utils/manifest-utils.ts +132 -0
- package/src/validation/import.ts +32 -22
- package/out/lsp/hover/ddd-pattern-explanations.d.ts +0 -50
- package/out/lsp/hover/ddd-pattern-explanations.js +0 -196
- package/out/lsp/hover/ddd-pattern-explanations.js.map +0 -1
- package/out/services/dependency-analyzer.d.ts +0 -58
- package/out/services/dependency-analyzer.js +0 -254
- package/out/services/dependency-analyzer.js.map +0 -1
- package/out/services/dependency-resolver.d.ts +0 -146
- package/out/services/dependency-resolver.js +0 -452
- package/out/services/dependency-resolver.js.map +0 -1
- package/out/services/git-url-resolver.browser.d.ts +0 -10
- package/out/services/git-url-resolver.browser.js +0 -19
- package/out/services/git-url-resolver.browser.js.map +0 -1
- package/out/services/git-url-resolver.d.ts +0 -158
- package/out/services/git-url-resolver.js +0 -416
- package/out/services/git-url-resolver.js.map +0 -1
- package/out/services/governance-validator.d.ts +0 -44
- package/out/services/governance-validator.js +0 -153
- package/out/services/governance-validator.js.map +0 -1
- package/out/services/semver.d.ts +0 -98
- package/out/services/semver.js +0 -195
- package/out/services/semver.js.map +0 -1
- package/src/lsp/hover/ddd-pattern-explanations.ts +0 -237
- package/src/services/dependency-analyzer.ts +0 -321
- package/src/services/dependency-resolver.ts +0 -551
- package/src/services/git-url-resolver.browser.ts +0 -26
- package/src/services/git-url-resolver.ts +0 -517
- package/src/services/governance-validator.ts +0 -177
- 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(
|
|
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
|
|
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 };
|
package/src/validation/import.ts
CHANGED
|
@@ -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
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
242
|
-
|
|
246
|
+
try {
|
|
247
|
+
const workspaceRoot = this.workspaceManager.getWorkspaceRoot();
|
|
248
|
+
const cacheDir = this.getCacheDirectory(workspaceRoot, packageKey, lockedDep.commit);
|
|
243
249
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
-
}
|