@domainlang/language 0.12.0 → 0.13.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/ast-augmentation.d.ts +7 -2
- package/out/diagram/context-map-diagram-generator.d.ts +9 -2
- package/out/diagram/context-map-diagram-generator.js +112 -63
- package/out/diagram/context-map-diagram-generator.js.map +1 -1
- package/out/generated/ast.d.ts +323 -51
- package/out/generated/ast.js +194 -33
- package/out/generated/ast.js.map +1 -1
- package/out/generated/grammar.js +418 -172
- package/out/generated/grammar.js.map +1 -1
- package/out/lsp/domain-lang-completion.js +39 -15
- package/out/lsp/domain-lang-completion.js.map +1 -1
- package/out/lsp/domain-lang-formatter.js +32 -0
- package/out/lsp/domain-lang-formatter.js.map +1 -1
- package/out/lsp/domain-lang-index-manager.d.ts +2 -3
- package/out/lsp/domain-lang-index-manager.js +5 -8
- package/out/lsp/domain-lang-index-manager.js.map +1 -1
- package/out/lsp/domain-lang-workspace-manager.d.ts +1 -1
- package/out/lsp/domain-lang-workspace-manager.js +2 -26
- package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
- package/out/lsp/explain.js +9 -3
- package/out/lsp/explain.js.map +1 -1
- package/out/lsp/hover/domain-lang-hover.js +13 -11
- package/out/lsp/hover/domain-lang-hover.js.map +1 -1
- package/out/lsp/hover/domain-lang-keywords.js +29 -26
- package/out/lsp/hover/domain-lang-keywords.js.map +1 -1
- package/out/sdk/ast-augmentation.d.ts +29 -21
- package/out/sdk/ast-augmentation.js +11 -7
- package/out/sdk/ast-augmentation.js.map +1 -1
- package/out/sdk/index.d.ts +2 -2
- package/out/sdk/index.js +1 -1
- package/out/sdk/index.js.map +1 -1
- package/out/sdk/loader-node.js +2 -2
- package/out/sdk/loader-node.js.map +1 -1
- package/out/sdk/patterns.d.ts +50 -61
- package/out/sdk/patterns.js +92 -62
- package/out/sdk/patterns.js.map +1 -1
- package/out/sdk/query.js +54 -43
- package/out/sdk/query.js.map +1 -1
- package/out/sdk/serializers.js +20 -7
- package/out/sdk/serializers.js.map +1 -1
- package/out/sdk/types.d.ts +87 -18
- package/out/sdk/types.js.map +1 -1
- package/out/sdk/validator.js +48 -64
- package/out/sdk/validator.js.map +1 -1
- package/out/services/performance-optimizer.d.ts +3 -3
- package/out/services/performance-optimizer.js +1 -3
- package/out/services/performance-optimizer.js.map +1 -1
- package/out/services/relationship-inference.d.ts +4 -4
- package/out/services/relationship-inference.js +34 -46
- package/out/services/relationship-inference.js.map +1 -1
- package/out/syntaxes/domain-lang.monarch.js +1 -1
- package/out/syntaxes/domain-lang.monarch.js.map +1 -1
- package/out/utils/import-utils.d.ts +6 -20
- package/out/utils/import-utils.js +3 -63
- package/out/utils/import-utils.js.map +1 -1
- package/out/validation/constants.d.ts +23 -6
- package/out/validation/constants.js +24 -7
- package/out/validation/constants.js.map +1 -1
- package/out/validation/maps.js +10 -4
- package/out/validation/maps.js.map +1 -1
- package/out/validation/relationships.d.ts +4 -8
- package/out/validation/relationships.js +96 -48
- package/out/validation/relationships.js.map +1 -1
- package/package.json +1 -1
- package/src/ast-augmentation.ts +7 -2
- package/src/diagram/context-map-diagram-generator.ts +132 -70
- package/src/domain-lang.langium +62 -26
- package/src/generated/ast.ts +413 -63
- package/src/generated/grammar.ts +418 -172
- package/src/lsp/domain-lang-completion.ts +42 -15
- package/src/lsp/domain-lang-formatter.ts +34 -0
- package/src/lsp/domain-lang-index-manager.ts +6 -9
- package/src/lsp/domain-lang-workspace-manager.ts +3 -29
- package/src/lsp/explain.ts +10 -2
- package/src/lsp/hover/domain-lang-hover.ts +10 -8
- package/src/lsp/hover/domain-lang-keywords.ts +27 -24
- package/src/sdk/ast-augmentation.ts +30 -21
- package/src/sdk/index.ts +11 -1
- package/src/sdk/loader-node.ts +2 -2
- package/src/sdk/patterns.ts +114 -76
- package/src/sdk/query.ts +57 -48
- package/src/sdk/serializers.ts +20 -7
- package/src/sdk/types.ts +92 -17
- package/src/sdk/validator.ts +52 -69
- package/src/services/performance-optimizer.ts +4 -6
- package/src/services/relationship-inference.ts +43 -54
- package/src/utils/import-utils.ts +9 -74
- package/src/validation/constants.ts +32 -9
- package/src/validation/maps.ts +12 -4
- package/src/validation/relationships.ts +150 -71
|
@@ -1193,11 +1193,20 @@ export class DomainLangCompletionProvider extends DefaultCompletionProvider {
|
|
|
1193
1193
|
acceptor(context, {
|
|
1194
1194
|
label: 'relationship (with patterns)',
|
|
1195
1195
|
kind: CompletionItemKind.Snippet,
|
|
1196
|
-
insertText: '[${
|
|
1196
|
+
insertText: '${1:Context1} [${2|OHS,PL,ACL,CF,S,BBoM|}] -> [${3|CF,ACL,C,BBoM|}] ${4:Context2}',
|
|
1197
1197
|
insertTextFormat: InsertTextFormat.Snippet,
|
|
1198
|
-
documentation: 'Add a relationship with
|
|
1198
|
+
documentation: 'Add a directional relationship with side patterns',
|
|
1199
1199
|
sortText: '1_relationship_patterns'
|
|
1200
1200
|
});
|
|
1201
|
+
|
|
1202
|
+
acceptor(context, {
|
|
1203
|
+
label: 'relationship (symmetric)',
|
|
1204
|
+
kind: CompletionItemKind.Snippet,
|
|
1205
|
+
insertText: '${1:Context1} [${2|SK,P,SW|}] ${3:Context2}',
|
|
1206
|
+
insertTextFormat: InsertTextFormat.Snippet,
|
|
1207
|
+
documentation: 'Add a symmetric relationship (Shared Kernel, Partnership, or Separate Ways)',
|
|
1208
|
+
sortText: '1_relationship_symmetric'
|
|
1209
|
+
});
|
|
1201
1210
|
}
|
|
1202
1211
|
|
|
1203
1212
|
/**
|
|
@@ -1230,32 +1239,50 @@ export class DomainLangCompletionProvider extends DefaultCompletionProvider {
|
|
|
1230
1239
|
acceptor: CompletionAcceptor,
|
|
1231
1240
|
context: CompletionContext
|
|
1232
1241
|
): void {
|
|
1233
|
-
//
|
|
1234
|
-
const
|
|
1235
|
-
{ label: 'OHS (Open Host Service)', insertText: '[OHS]', doc: 'Open Host Service pattern' },
|
|
1236
|
-
{ label: 'PL (Published Language)', insertText: '[PL]', doc: 'Published Language pattern' },
|
|
1237
|
-
{ label: '
|
|
1238
|
-
{ label: '
|
|
1239
|
-
{ label: '
|
|
1240
|
-
{ label: '
|
|
1242
|
+
// Side patterns (for directional relationships)
|
|
1243
|
+
const sidePatterns = [
|
|
1244
|
+
{ label: 'OHS (Open Host Service)', insertText: '[OHS]', doc: 'Open Host Service — upstream side pattern' },
|
|
1245
|
+
{ label: 'PL (Published Language)', insertText: '[PL]', doc: 'Published Language — upstream side pattern' },
|
|
1246
|
+
{ label: 'CF (Conformist)', insertText: '[CF]', doc: 'Conformist — downstream side pattern' },
|
|
1247
|
+
{ label: 'ACL (Anti-Corruption Layer)', insertText: '[ACL]', doc: 'Anti-Corruption Layer — downstream side pattern' },
|
|
1248
|
+
{ label: 'S (Supplier)', insertText: '[S]', doc: 'Supplier — upstream side (Customer/Supplier)' },
|
|
1249
|
+
{ label: 'C (Customer)', insertText: '[C]', doc: 'Customer — downstream side (Customer/Supplier)' },
|
|
1250
|
+
{ label: 'BBoM (Big Ball of Mud)', insertText: '[BBoM]', doc: 'Big Ball of Mud — either side' },
|
|
1251
|
+
];
|
|
1252
|
+
|
|
1253
|
+
for (const pattern of sidePatterns) {
|
|
1254
|
+
acceptor(context, {
|
|
1255
|
+
label: pattern.label,
|
|
1256
|
+
kind: CompletionItemKind.EnumMember,
|
|
1257
|
+
insertText: pattern.insertText,
|
|
1258
|
+
documentation: pattern.doc,
|
|
1259
|
+
sortText: `0_side_${pattern.label}`
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
// Symmetric patterns (for symmetric relationships)
|
|
1264
|
+
const symmetricPatterns = [
|
|
1265
|
+
{ label: 'SK (Shared Kernel)', insertText: '[SK]', doc: 'Shared Kernel — symmetric relationship' },
|
|
1266
|
+
{ label: 'P (Partnership)', insertText: '[P]', doc: 'Partnership — symmetric relationship' },
|
|
1267
|
+
{ label: 'SW (Separate Ways)', insertText: '[SW]', doc: 'Separate Ways — symmetric relationship' },
|
|
1241
1268
|
];
|
|
1242
1269
|
|
|
1243
|
-
for (const pattern of
|
|
1270
|
+
for (const pattern of symmetricPatterns) {
|
|
1244
1271
|
acceptor(context, {
|
|
1245
1272
|
label: pattern.label,
|
|
1246
1273
|
kind: CompletionItemKind.EnumMember,
|
|
1247
1274
|
insertText: pattern.insertText,
|
|
1248
1275
|
documentation: pattern.doc,
|
|
1249
|
-
sortText: `
|
|
1276
|
+
sortText: `0_sym_${pattern.label}`
|
|
1250
1277
|
});
|
|
1251
1278
|
}
|
|
1252
1279
|
|
|
1253
|
-
//
|
|
1280
|
+
// Directional arrows
|
|
1254
1281
|
const arrows = [
|
|
1255
1282
|
{ label: '->', doc: 'Upstream to downstream' },
|
|
1256
1283
|
{ label: '<-', doc: 'Downstream to upstream' },
|
|
1257
|
-
{ label: '<->', doc: 'Bidirectional
|
|
1258
|
-
{ label: '><', doc: 'Separate Ways' }
|
|
1284
|
+
{ label: '<->', doc: 'Bidirectional with patterns' },
|
|
1285
|
+
{ label: '><', doc: 'Separate Ways (arrow form)' },
|
|
1259
1286
|
];
|
|
1260
1287
|
|
|
1261
1288
|
for (const arrow of arrows) {
|
|
@@ -34,6 +34,40 @@ export class DomainLangFormatter extends AbstractFormatter {
|
|
|
34
34
|
if (ast.isDomainMap(node)) {
|
|
35
35
|
this.formatBlock(node);
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
// Directional relationships: A [OHS, PL] -> [CF, ACL] B
|
|
39
|
+
if (ast.isDirectionalRelationship(node)) {
|
|
40
|
+
const formatter = this.getNodeFormatter(node);
|
|
41
|
+
// No space inside bracket groups
|
|
42
|
+
formatter.keywords('[').append(Formatting.noSpace());
|
|
43
|
+
formatter.keywords(']').prepend(Formatting.noSpace());
|
|
44
|
+
formatter.keywords(',').append(Formatting.oneSpace());
|
|
45
|
+
// Space after left context name (before [ or ->)
|
|
46
|
+
formatter.property('left').append(Formatting.oneSpace());
|
|
47
|
+
// Space before right context name (after ] or ->)
|
|
48
|
+
formatter.property('right').prepend(Formatting.oneSpace());
|
|
49
|
+
// Arrow gets explicit surrounding space only from bracket-less sides
|
|
50
|
+
// to avoid double-spacing when bracket groups are present
|
|
51
|
+
if (node.leftPatterns.length > 0) {
|
|
52
|
+
formatter.property('arrow').prepend(Formatting.oneSpace());
|
|
53
|
+
}
|
|
54
|
+
if (node.rightPatterns.length > 0) {
|
|
55
|
+
formatter.property('arrow').append(Formatting.oneSpace());
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Symmetric relationships: A [SK] B OR A >< B
|
|
60
|
+
if (ast.isSymmetricRelationship(node)) {
|
|
61
|
+
const formatter = this.getNodeFormatter(node);
|
|
62
|
+
if (node.arrow === '><') {
|
|
63
|
+
formatter.property('arrow').surround(Formatting.oneSpace());
|
|
64
|
+
}
|
|
65
|
+
// [SK] form: space before [, no space inside brackets, space after ]
|
|
66
|
+
formatter.keywords('[').prepend(Formatting.oneSpace());
|
|
67
|
+
formatter.keywords('[').append(Formatting.noSpace());
|
|
68
|
+
formatter.keywords(']').prepend(Formatting.noSpace());
|
|
69
|
+
formatter.keywords(']').append(Formatting.oneSpace());
|
|
70
|
+
}
|
|
37
71
|
} catch (error) {
|
|
38
72
|
console.error('Error in format:', error);
|
|
39
73
|
// Continue - don't crash formatting
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { LangiumDocument, LangiumSharedCoreServices, URI } from 'langium';
|
|
2
2
|
import { DefaultIndexManager, DocumentState } from 'langium';
|
|
3
3
|
import { CancellationToken } from 'vscode-jsonrpc';
|
|
4
|
-
import { resolveImportPath } from '../utils/import-utils.js';
|
|
5
4
|
import type { Model } from '../generated/ast.js';
|
|
6
5
|
import type { ImportResolver } from '../services/import-resolver.js';
|
|
7
6
|
import type { DomainLangServices } from '../domain-lang-module.js';
|
|
@@ -96,7 +95,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
96
95
|
/**
|
|
97
96
|
* DI-injected import resolver. Set via late-binding because
|
|
98
97
|
* IndexManager (shared module) is created before ImportResolver (language module).
|
|
99
|
-
*
|
|
98
|
+
* Always set before any document indexing begins via `setLanguageServices()`.
|
|
100
99
|
*/
|
|
101
100
|
private importResolver: ImportResolver | undefined;
|
|
102
101
|
|
|
@@ -117,15 +116,13 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
/**
|
|
120
|
-
* Resolves an import path using the DI-injected ImportResolver
|
|
121
|
-
* falling back to the standalone resolver for backwards compatibility.
|
|
119
|
+
* Resolves an import path using the DI-injected ImportResolver.
|
|
122
120
|
*/
|
|
123
|
-
private
|
|
124
|
-
if (this.importResolver) {
|
|
125
|
-
|
|
121
|
+
private resolveImport(document: LangiumDocument, specifier: string): Promise<URI> {
|
|
122
|
+
if (!this.importResolver) {
|
|
123
|
+
throw new Error('ImportResolver not initialised — ensure setLanguageServices() was called');
|
|
126
124
|
}
|
|
127
|
-
|
|
128
|
-
return resolveImportPath(document, specifier);
|
|
125
|
+
return this.importResolver.resolveForDocument(document, specifier);
|
|
129
126
|
}
|
|
130
127
|
|
|
131
128
|
/**
|
|
@@ -66,7 +66,7 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
|
|
|
66
66
|
/**
|
|
67
67
|
* DI-injected import resolver. Set via late-binding because
|
|
68
68
|
* WorkspaceManager (shared module) is created before ImportResolver (language module).
|
|
69
|
-
*
|
|
69
|
+
* Always set before any workspace loading begins via `setLanguageServices()`.
|
|
70
70
|
*/
|
|
71
71
|
private importResolver: ImportResolver | undefined;
|
|
72
72
|
|
|
@@ -296,35 +296,9 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
|
|
|
296
296
|
*/
|
|
297
297
|
private async loadImportGraph(document: LangiumDocument): Promise<Set<string>> {
|
|
298
298
|
if (!this.importResolver) {
|
|
299
|
-
|
|
300
|
-
return ensureImportGraphFromDocument(document, this.langiumDocuments);
|
|
299
|
+
throw new Error('ImportResolver not initialised — ensure setLanguageServices() was called');
|
|
301
300
|
}
|
|
302
|
-
|
|
303
|
-
const resolver = this.importResolver;
|
|
304
|
-
const langiumDocuments = this.langiumDocuments;
|
|
305
|
-
const visited = new Set<string>();
|
|
306
|
-
|
|
307
|
-
async function visit(doc: LangiumDocument): Promise<void> {
|
|
308
|
-
const uriString = doc.uri.toString();
|
|
309
|
-
if (visited.has(uriString)) return;
|
|
310
|
-
visited.add(uriString);
|
|
311
|
-
|
|
312
|
-
const model = doc.parseResult.value as { imports?: Array<{ uri?: string }> };
|
|
313
|
-
for (const imp of model.imports ?? []) {
|
|
314
|
-
if (!imp.uri) continue;
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
const resolvedUri = await resolver.resolveForDocument(doc, imp.uri);
|
|
318
|
-
const childDoc = await langiumDocuments.getOrCreateDocument(resolvedUri);
|
|
319
|
-
await visit(childDoc);
|
|
320
|
-
} catch {
|
|
321
|
-
// Import resolution failed — validation will report the error
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
await visit(document);
|
|
327
|
-
return visited;
|
|
301
|
+
return ensureImportGraphFromDocument(document, this.langiumDocuments, this.importResolver);
|
|
328
302
|
}
|
|
329
303
|
|
|
330
304
|
// --- PRS-017 R7: Progress reporting ---
|
package/src/lsp/explain.ts
CHANGED
|
@@ -22,9 +22,11 @@ import {
|
|
|
22
22
|
isBoundedContext,
|
|
23
23
|
isClassification,
|
|
24
24
|
isContextMap,
|
|
25
|
+
isDirectionalRelationship,
|
|
25
26
|
isDomain,
|
|
26
27
|
isDomainMap,
|
|
27
28
|
isRelationship,
|
|
29
|
+
isSymmetricRelationship,
|
|
28
30
|
isTeam,
|
|
29
31
|
} from '../generated/ast.js';
|
|
30
32
|
import {
|
|
@@ -133,9 +135,15 @@ function explainClassification(classification: Classification): string {
|
|
|
133
135
|
function explainRelationship(relationship: Relationship): string {
|
|
134
136
|
const leftName = relationship.left.link?.ref?.name ?? 'unknown';
|
|
135
137
|
const rightName = relationship.right.link?.ref?.name ?? 'unknown';
|
|
136
|
-
const arrow = relationship.arrow;
|
|
137
138
|
|
|
138
|
-
|
|
139
|
+
let relationText = '↔';
|
|
140
|
+
if (isDirectionalRelationship(relationship)) {
|
|
141
|
+
relationText = relationship.arrow;
|
|
142
|
+
} else if (isSymmetricRelationship(relationship)) {
|
|
143
|
+
relationText = relationship.pattern ? `[${relationship.pattern.$type}]` : '><';
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const description = `Relationship from **${leftName}** ${relationText} **${rightName}**`;
|
|
139
147
|
return formatHoverContent('', '🔗', 'relationship', undefined, [description]);
|
|
140
148
|
}
|
|
141
149
|
|
|
@@ -385,14 +385,17 @@ export class DomainLangHoverProvider extends AstNodeHoverProvider {
|
|
|
385
385
|
private getRelationshipHover(node: AstNode, commentBlock: string, _importAlias?: string): string | undefined {
|
|
386
386
|
if (!ast.isRelationship(node)) return undefined;
|
|
387
387
|
|
|
388
|
-
const leftPatterns = node.leftPatterns.join(', ');
|
|
389
|
-
const rightPatterns = node.rightPatterns.join(', ');
|
|
390
388
|
const fields: string[] = [
|
|
391
|
-
`${this.refLink(node.left.link)} ${node.arrow} ${this.refLink(node.right.link)}`
|
|
389
|
+
`${this.refLink(node.left.link)} ${node.arrow ?? '↔'} ${this.refLink(node.right.link)}`
|
|
392
390
|
];
|
|
393
|
-
if (node
|
|
394
|
-
|
|
395
|
-
|
|
391
|
+
if (ast.isDirectionalRelationship(node)) {
|
|
392
|
+
const leftPatterns = node.leftPatterns.map(p => p.$type).join(', ');
|
|
393
|
+
const rightPatterns = node.rightPatterns.map(p => p.$type).join(', ');
|
|
394
|
+
if (leftPatterns) fields.push(`**Left patterns:** ${leftPatterns}`);
|
|
395
|
+
if (rightPatterns) fields.push(`**Right patterns:** ${rightPatterns}`);
|
|
396
|
+
} else if (ast.isSymmetricRelationship(node) && node.pattern) {
|
|
397
|
+
fields.push(`**Pattern:** ${node.pattern.$type}`);
|
|
398
|
+
}
|
|
396
399
|
|
|
397
400
|
return this.formatHover(commentBlock, '🔗', 'relationship', undefined, fields);
|
|
398
401
|
}
|
|
@@ -439,8 +442,7 @@ export class DomainLangHoverProvider extends AstNodeHoverProvider {
|
|
|
439
442
|
private formatRelationshipLine(rel: ast.Relationship): string {
|
|
440
443
|
const left = this.refLink(rel.left?.link);
|
|
441
444
|
const right = this.refLink(rel.right?.link);
|
|
442
|
-
|
|
443
|
-
return `- ${left} ${rel.arrow} ${right}${type}`;
|
|
445
|
+
return `- ${left} ${rel.arrow ?? '↔'} ${right}`;
|
|
444
446
|
}
|
|
445
447
|
|
|
446
448
|
/**
|
|
@@ -102,35 +102,38 @@ export const keywordExplanations: Record<string, string> = {
|
|
|
102
102
|
this: `**this** - References the current bounded context in relationships.${REL_LINK}`,
|
|
103
103
|
|
|
104
104
|
// ========================================================================
|
|
105
|
-
// DDD
|
|
106
|
-
// ========================================================================
|
|
107
|
-
acl: `**ACL** - Anti-Corruption Layer. Protects from external models by translating between domains.${REL_LINK}`,
|
|
108
|
-
anticorruptionlayer: `**AntiCorruptionLayer** - Protects from external models by translating between domains.${REL_LINK}`,
|
|
109
|
-
ohs: `**OHS** - Open Host Service. Provides a well-documented API for integration.${REL_LINK}`,
|
|
110
|
-
openhostservice: `**OpenHostService** - Provides a well-documented API for integration.${REL_LINK}`,
|
|
111
|
-
pl: `**PL** - Published Language. Documented language for inter-context communication.${REL_LINK}`,
|
|
112
|
-
publishedlanguage: `**PublishedLanguage** - Documented language for inter-context communication.${REL_LINK}`,
|
|
113
|
-
cf: `**CF** - Conformist. Adopts upstream model without translation.${REL_LINK}`,
|
|
114
|
-
conformist: `**Conformist** - Adopts upstream model without translation.${REL_LINK}`,
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
bbom: `**BBoM** - Big Ball of Mud. Legacy area without clear boundaries.${REL_LINK}`,
|
|
120
|
-
bigballofmud: `**BigBallOfMud** - Legacy area without clear boundaries.${REL_LINK}`,
|
|
105
|
+
// DDD Side Patterns (directional relationships)
|
|
106
|
+
// ========================================================================
|
|
107
|
+
acl: `**ACL** - Anti-Corruption Layer. Protects from external models by translating between domains. Used on the downstream side.${REL_LINK}`,
|
|
108
|
+
anticorruptionlayer: `**AntiCorruptionLayer** - Anti-Corruption Layer. Protects from external models by translating between domains. Used on the downstream side.${REL_LINK}`,
|
|
109
|
+
ohs: `**OHS** - Open Host Service. Provides a well-documented API for integration. Used on the upstream side.${REL_LINK}`,
|
|
110
|
+
openhostservice: `**OpenHostService** - Open Host Service. Provides a well-documented API for integration. Used on the upstream side.${REL_LINK}`,
|
|
111
|
+
pl: `**PL** - Published Language. Documented language for inter-context communication. Used on the upstream side.${REL_LINK}`,
|
|
112
|
+
publishedlanguage: `**PublishedLanguage** - Published Language. Documented language for inter-context communication. Used on the upstream side.${REL_LINK}`,
|
|
113
|
+
cf: `**CF** - Conformist. Adopts upstream model without translation. Used on the downstream side.${REL_LINK}`,
|
|
114
|
+
conformist: `**Conformist** - Conformist. Adopts upstream model without translation. Used on the downstream side.${REL_LINK}`,
|
|
115
|
+
s: `**S** - Supplier. Negotiated contract provider in a Customer/Supplier relationship. Must be on the upstream side.${REL_LINK}`,
|
|
116
|
+
supplier: `**Supplier** - Negotiated contract provider in a Customer/Supplier relationship. Must be on the upstream side.${REL_LINK}`,
|
|
117
|
+
c: `**C** - Customer. Negotiated contract consumer in a Customer/Supplier relationship. Must be on the downstream side.${REL_LINK}`,
|
|
118
|
+
customer: `**Customer** - Negotiated contract consumer in a Customer/Supplier relationship. Must be on the downstream side.${REL_LINK}`,
|
|
119
|
+
bbom: `**BBoM** - Big Ball of Mud. Legacy area without clear boundaries. Can appear on either side.${REL_LINK}`,
|
|
120
|
+
bigballofmud: `**BigBallOfMud** - Big Ball of Mud. Legacy area without clear boundaries. Can appear on either side.${REL_LINK}`,
|
|
121
121
|
|
|
122
122
|
// ========================================================================
|
|
123
|
-
//
|
|
123
|
+
// DDD Symmetric Patterns (symmetric relationships — entity [Pattern] entity)
|
|
124
124
|
// ========================================================================
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
p: `**P** - Partnership. Symmetric relationship: two teams with mutual dependency and shared goals. Usage: \`A [P] B\`${REL_LINK}`,
|
|
126
|
+
partnership: `**Partnership** - Symmetric relationship: two teams with mutual dependency and shared goals. Usage: \`A [Partnership] B\`${REL_LINK}`,
|
|
127
|
+
sk: `**SK** - Shared Kernel. Symmetric relationship: shared code/data requiring careful coordination between both contexts. Usage: \`A [SK] B\`${REL_LINK}`,
|
|
128
|
+
sharedkernel: `**SharedKernel** - Symmetric relationship: shared code/data requiring careful coordination between both contexts. Usage: \`A [SharedKernel] B\`${REL_LINK}`,
|
|
129
|
+
sw: `**SW** - Separate Ways. Symmetric relationship: contexts with no integration, solving problems independently. Usage: \`A [SW] B\` or \`A >< B\`${REL_LINK}`,
|
|
130
|
+
separateways: `**SeparateWays** - Symmetric relationship: contexts with no integration. Usage: \`A [SeparateWays] B\` or \`A >< B\`${REL_LINK}`,
|
|
128
131
|
|
|
129
132
|
// ========================================================================
|
|
130
133
|
// Relationship Arrows
|
|
131
134
|
// ========================================================================
|
|
132
|
-
'->': `**->** -
|
|
133
|
-
'<->': `**<->** - Bidirectional
|
|
134
|
-
'<-': `**<-** - Reverse
|
|
135
|
-
'><': `**><** - Separate Ways
|
|
135
|
+
'->': `**->** - Directional: upstream (left) to downstream (right). Example: \`Orders [OHS] -> [CF] Payments\`${REL_LINK}`,
|
|
136
|
+
'<->': `**<->** - Bidirectional: both sides have patterns, mutual data flow. Example: \`Orders [OHS] <-> [CF] Payments\`${REL_LINK}`,
|
|
137
|
+
'<-': `**<-** - Reverse directional: upstream (right) to downstream (left). Example: \`Payments [ACL] <- Orders\`${REL_LINK}`,
|
|
138
|
+
'><': `**><** - Separate Ways: no integration between contexts. Equivalent to \`[SW]\`. Example: \`Orders >< Legacy\`${REL_LINK}`,
|
|
136
139
|
};
|
|
@@ -46,15 +46,19 @@
|
|
|
46
46
|
* - `fqn` - Computed fully qualified name
|
|
47
47
|
* - `hasType(name)` - Check type matches
|
|
48
48
|
*
|
|
49
|
-
* **Properties added to
|
|
50
|
-
* - `
|
|
51
|
-
* - `
|
|
52
|
-
* - `
|
|
49
|
+
* **Properties added to DirectionalRelationship:**
|
|
50
|
+
* - `isBidirectional` - Check if relationship is bidirectional (`<->`)
|
|
51
|
+
* - `leftContextName` - Resolved name of left context (handles `this`)
|
|
52
|
+
* - `rightContextName` - Resolved name of right context (handles `this`)
|
|
53
|
+
* - `hasPattern(patternType)` - Check if pattern exists on either side
|
|
54
|
+
* - `hasLeftPattern(patternType)` - Check left patterns
|
|
55
|
+
* - `hasRightPattern(patternType)` - Check right patterns
|
|
53
56
|
* - `isUpstream(side)` - Check if side is upstream
|
|
54
57
|
* - `isDownstream(side)` - Check if side is downstream
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* - `
|
|
58
|
+
*
|
|
59
|
+
* **Properties added to SymmetricRelationship:**
|
|
60
|
+
* - `leftContextName` - Resolved name of left context (handles `this`)
|
|
61
|
+
* - `rightContextName` - Resolved name of right context (handles `this`)
|
|
58
62
|
*
|
|
59
63
|
* @module sdk/ast-augmentation
|
|
60
64
|
*/
|
|
@@ -109,9 +113,9 @@ declare module '../generated/ast.js' {
|
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
/**
|
|
112
|
-
* Augmented
|
|
116
|
+
* Augmented DirectionalRelationship with SDK helper methods.
|
|
113
117
|
*/
|
|
114
|
-
interface
|
|
118
|
+
interface DirectionalRelationship {
|
|
115
119
|
/** Resolved name of left context (handles 'this') */
|
|
116
120
|
readonly leftContextName: string;
|
|
117
121
|
/** Resolved name of right context (handles 'this') */
|
|
@@ -120,36 +124,41 @@ declare module '../generated/ast.js' {
|
|
|
120
124
|
readonly isBidirectional: boolean;
|
|
121
125
|
|
|
122
126
|
/**
|
|
123
|
-
* Checks if the relationship has a specific
|
|
124
|
-
* Accepts
|
|
125
|
-
* @param pattern - Pattern abbreviation or full name
|
|
127
|
+
* Checks if the relationship has a specific side pattern on either side.
|
|
128
|
+
* Accepts pattern $type names like 'OpenHostService', 'Conformist', etc.
|
|
126
129
|
*/
|
|
127
|
-
hasPattern(
|
|
130
|
+
hasPattern(patternType: string): boolean;
|
|
128
131
|
|
|
129
132
|
/**
|
|
130
|
-
* Checks if the left side has a specific
|
|
131
|
-
* @param pattern - Pattern abbreviation or full name
|
|
133
|
+
* Checks if the left side has a specific side pattern.
|
|
132
134
|
*/
|
|
133
|
-
hasLeftPattern(
|
|
135
|
+
hasLeftPattern(patternType: string): boolean;
|
|
134
136
|
|
|
135
137
|
/**
|
|
136
|
-
* Checks if the right side has a specific
|
|
137
|
-
* @param pattern - Pattern abbreviation or full name
|
|
138
|
+
* Checks if the right side has a specific side pattern.
|
|
138
139
|
*/
|
|
139
|
-
hasRightPattern(
|
|
140
|
+
hasRightPattern(patternType: string): boolean;
|
|
140
141
|
|
|
141
142
|
/**
|
|
142
143
|
* Checks if the specified side is upstream (provider) in this relationship.
|
|
143
|
-
* @param side - 'left' or 'right'
|
|
144
144
|
*/
|
|
145
145
|
isUpstream(side: 'left' | 'right'): boolean;
|
|
146
146
|
|
|
147
147
|
/**
|
|
148
148
|
* Checks if the specified side is downstream (consumer) in this relationship.
|
|
149
|
-
* @param side - 'left' or 'right'
|
|
150
149
|
*/
|
|
151
150
|
isDownstream(side: 'left' | 'right'): boolean;
|
|
152
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Augmented SymmetricRelationship with SDK helper methods.
|
|
155
|
+
*/
|
|
156
|
+
interface SymmetricRelationship {
|
|
157
|
+
/** Resolved name of left context (handles 'this') */
|
|
158
|
+
readonly leftContextName: string;
|
|
159
|
+
/** Resolved name of right context (handles 'this') */
|
|
160
|
+
readonly rightContextName: string;
|
|
161
|
+
}
|
|
153
162
|
}
|
|
154
163
|
|
|
155
164
|
// Export nothing - this file is purely for type augmentation
|
package/src/sdk/index.ts
CHANGED
|
@@ -116,14 +116,19 @@ export { fromModel, fromDocument, fromServices, augmentModel } from './query.js'
|
|
|
116
116
|
export {
|
|
117
117
|
Pattern,
|
|
118
118
|
PatternFullName,
|
|
119
|
+
PatternAbbreviation,
|
|
119
120
|
PatternAliases,
|
|
120
121
|
matchesPattern,
|
|
121
122
|
isUpstreamPattern,
|
|
122
123
|
isDownstreamPattern,
|
|
123
124
|
isMutualPattern,
|
|
125
|
+
isUpstreamSidePattern,
|
|
126
|
+
isDownstreamSidePattern,
|
|
127
|
+
isBBoMSidePattern,
|
|
128
|
+
getPatternAbbreviation,
|
|
124
129
|
UpstreamPatterns,
|
|
125
130
|
DownstreamPatterns,
|
|
126
|
-
|
|
131
|
+
SymmetricPatterns,
|
|
127
132
|
} from './patterns.js';
|
|
128
133
|
|
|
129
134
|
export type { IntegrationPattern } from './patterns.js';
|
|
@@ -140,6 +145,11 @@ export type {
|
|
|
140
145
|
LoadOptions,
|
|
141
146
|
BcQueryBuilder,
|
|
142
147
|
RelationshipView,
|
|
148
|
+
RelationshipSide,
|
|
149
|
+
DirectionalRelationshipView,
|
|
150
|
+
DirectionalKind,
|
|
151
|
+
SymmetricRelationshipView,
|
|
152
|
+
SymmetricKind,
|
|
143
153
|
} from './types.js';
|
|
144
154
|
|
|
145
155
|
// Serializers for tool responses (browser-safe)
|
package/src/sdk/loader-node.ts
CHANGED
|
@@ -62,7 +62,7 @@ export async function loadModel(
|
|
|
62
62
|
options?: LoadOptions
|
|
63
63
|
): Promise<QueryContext> {
|
|
64
64
|
// Resolve absolute path
|
|
65
|
-
const path = await import('path');
|
|
65
|
+
const path = await import('node:path');
|
|
66
66
|
const absolutePath = path.isAbsolute(entryFile)
|
|
67
67
|
? entryFile
|
|
68
68
|
: path.resolve(options?.workspaceDir ?? process.cwd(), entryFile);
|
|
@@ -82,7 +82,7 @@ export async function loadModel(
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
// Read file content and create document
|
|
85
|
-
const fs = await import('fs/promises');
|
|
85
|
+
const fs = await import('node:fs/promises');
|
|
86
86
|
const fileContent = await fs.readFile(absolutePath, 'utf-8');
|
|
87
87
|
const uri = URI.file(absolutePath);
|
|
88
88
|
|