@living-architecture/riviere-cli 0.9.3 → 0.9.5
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/dist/bin.js +167 -81
- package/dist/index.js +166 -80
- package/package.json +6 -6
package/dist/bin.js
CHANGED
|
@@ -6886,6 +6886,10 @@ var BuildValidationError = class extends Error {
|
|
|
6886
6886
|
}
|
|
6887
6887
|
};
|
|
6888
6888
|
|
|
6889
|
+
// ../riviere-schema/dist/schema.js
|
|
6890
|
+
var EVENT_NAME_FIELD = "eventName";
|
|
6891
|
+
var SUBSCRIBED_EVENTS_FIELD = "subscribedEvents";
|
|
6892
|
+
|
|
6889
6893
|
// ../riviere-schema/dist/validation.js
|
|
6890
6894
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
6891
6895
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
@@ -25532,7 +25536,6 @@ var COMPONENT_TYPES = [
|
|
|
25532
25536
|
"domainOp",
|
|
25533
25537
|
"event",
|
|
25534
25538
|
"eventHandler",
|
|
25535
|
-
"eventPublisher",
|
|
25536
25539
|
"ui"
|
|
25537
25540
|
];
|
|
25538
25541
|
function extractComponents(project, sourceFilePaths, config2, globMatcher, configDir) {
|
|
@@ -25691,7 +25694,6 @@ function resolveModule(moduleConfig, loader) {
|
|
|
25691
25694
|
domainOp: requireRule(moduleConfig.domainOp, "domainOp", moduleConfig.name),
|
|
25692
25695
|
event: requireRule(moduleConfig.event, "event", moduleConfig.name),
|
|
25693
25696
|
eventHandler: requireRule(moduleConfig.eventHandler, "eventHandler", moduleConfig.name),
|
|
25694
|
-
eventPublisher: requireRule(moduleConfig.eventPublisher, "eventPublisher", moduleConfig.name),
|
|
25695
25697
|
ui: requireRule(moduleConfig.ui, "ui", moduleConfig.name),
|
|
25696
25698
|
...moduleConfig.customTypes !== void 0 && { customTypes: moduleConfig.customTypes }
|
|
25697
25699
|
};
|
|
@@ -25711,7 +25713,6 @@ function resolveModuleWithExtends(moduleConfig, extendsSource, loader) {
|
|
|
25711
25713
|
domainOp: moduleConfig.domainOp ?? baseModule.domainOp,
|
|
25712
25714
|
event: moduleConfig.event ?? baseModule.event,
|
|
25713
25715
|
eventHandler: moduleConfig.eventHandler ?? baseModule.eventHandler,
|
|
25714
|
-
eventPublisher: moduleConfig.eventPublisher ?? baseModule.eventPublisher,
|
|
25715
25716
|
ui: moduleConfig.ui ?? baseModule.ui,
|
|
25716
25717
|
...mergedCustomTypes !== void 0 && { customTypes: mergedCustomTypes }
|
|
25717
25718
|
};
|
|
@@ -28171,90 +28172,104 @@ function traceNonComponent(project, componentIndex, source, typeName, calledMeth
|
|
|
28171
28172
|
}
|
|
28172
28173
|
}
|
|
28173
28174
|
|
|
28174
|
-
// ../riviere-extract-ts/dist/features/extraction/domain/connection-detection/async-detection/
|
|
28175
|
-
function
|
|
28176
|
-
|
|
28175
|
+
// ../riviere-extract-ts/dist/features/extraction/domain/connection-detection/async-detection/async-detection-types.js
|
|
28176
|
+
function toSourceLocation(component, repository) {
|
|
28177
|
+
return {
|
|
28178
|
+
repository,
|
|
28179
|
+
filePath: component.location.file,
|
|
28180
|
+
lineNumber: component.location.line
|
|
28181
|
+
};
|
|
28182
|
+
}
|
|
28183
|
+
|
|
28184
|
+
// ../riviere-extract-ts/dist/features/extraction/domain/connection-detection/async-detection/detect-event-publisher-connections.js
|
|
28185
|
+
function detectEventPublisherConnections(components, eventPublishers, options) {
|
|
28186
|
+
if (eventPublishers.length === 0) {
|
|
28187
|
+
return [];
|
|
28188
|
+
}
|
|
28177
28189
|
const events = components.filter((c) => c.type === "event");
|
|
28178
|
-
|
|
28179
|
-
|
|
28180
|
-
const
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
|
|
28184
|
-
|
|
28185
|
-
|
|
28186
|
-
|
|
28187
|
-
|
|
28188
|
-
|
|
28189
|
-
|
|
28190
|
+
return eventPublishers.flatMap((publisherConfig) => {
|
|
28191
|
+
const { fromType, metadataKey } = publisherConfig;
|
|
28192
|
+
const publishers = components.filter((c) => c.type === fromType);
|
|
28193
|
+
return publishers.flatMap((publisher) => {
|
|
28194
|
+
const publishedEventType = publisher.metadata[metadataKey];
|
|
28195
|
+
if (Array.isArray(publishedEventType)) {
|
|
28196
|
+
const validTypes = publishedEventType.filter((t) => typeof t === "string" && t.trim() !== "");
|
|
28197
|
+
if (validTypes.length === 0) {
|
|
28198
|
+
return [handleMissingMetadata(publisher, metadataKey, options)];
|
|
28199
|
+
}
|
|
28200
|
+
return validTypes.flatMap((t) => resolvePublishTarget(publisher, t, events, options));
|
|
28201
|
+
}
|
|
28202
|
+
if (typeof publishedEventType !== "string" || publishedEventType.trim() === "") {
|
|
28203
|
+
return [handleMissingMetadata(publisher, metadataKey, options)];
|
|
28204
|
+
}
|
|
28205
|
+
return resolvePublishTarget(publisher, publishedEventType, events, options);
|
|
28206
|
+
});
|
|
28190
28207
|
});
|
|
28191
28208
|
}
|
|
28192
|
-
function handleMissingMetadata(publisher,
|
|
28209
|
+
function handleMissingMetadata(publisher, metadataKey, options) {
|
|
28193
28210
|
if (options.strict) {
|
|
28194
28211
|
throw new ConnectionDetectionError({
|
|
28195
|
-
file:
|
|
28196
|
-
line:
|
|
28212
|
+
file: publisher.location.file,
|
|
28213
|
+
line: publisher.location.line,
|
|
28197
28214
|
typeName: publisher.name,
|
|
28198
|
-
reason:
|
|
28215
|
+
reason: `published event type in "${metadataKey}" metadata is missing or invalid`
|
|
28199
28216
|
});
|
|
28200
28217
|
}
|
|
28201
28218
|
return {
|
|
28202
28219
|
source: componentIdentity(publisher),
|
|
28203
28220
|
target: "_unresolved",
|
|
28204
28221
|
type: "async",
|
|
28205
|
-
sourceLocation,
|
|
28206
|
-
_uncertain: `
|
|
28222
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
28223
|
+
_uncertain: `event publisher "${publisher.name}" is missing required "${metadataKey}" metadata`
|
|
28207
28224
|
};
|
|
28208
28225
|
}
|
|
28209
|
-
function resolvePublishTarget(publisher, publishedEventType, events, options
|
|
28210
|
-
const matchingEvents = events.filter((e) => e.metadata[
|
|
28226
|
+
function resolvePublishTarget(publisher, publishedEventType, events, options) {
|
|
28227
|
+
const matchingEvents = events.filter((e) => e.metadata[EVENT_NAME_FIELD] === publishedEventType);
|
|
28211
28228
|
if (matchingEvents.length === 0) {
|
|
28212
|
-
return [handleNoMatch(publisher, publishedEventType, options
|
|
28229
|
+
return [handleNoMatch(publisher, publishedEventType, options)];
|
|
28213
28230
|
}
|
|
28214
28231
|
if (matchingEvents.length > 1) {
|
|
28215
|
-
return [
|
|
28216
|
-
handleAmbiguousMatch(publisher, publishedEventType, matchingEvents.length, options, sourceLocation)
|
|
28217
|
-
];
|
|
28232
|
+
return [handleAmbiguousMatch(publisher, publishedEventType, matchingEvents.length, options)];
|
|
28218
28233
|
}
|
|
28219
28234
|
return matchingEvents.map((event) => ({
|
|
28220
28235
|
source: componentIdentity(publisher),
|
|
28221
28236
|
target: componentIdentity(event),
|
|
28222
28237
|
type: "async",
|
|
28223
|
-
sourceLocation
|
|
28238
|
+
sourceLocation: toSourceLocation(publisher, options.repository)
|
|
28224
28239
|
}));
|
|
28225
28240
|
}
|
|
28226
|
-
function handleAmbiguousMatch(publisher, publishedEventType, matchCount, options
|
|
28241
|
+
function handleAmbiguousMatch(publisher, publishedEventType, matchCount, options) {
|
|
28227
28242
|
if (options.strict) {
|
|
28228
28243
|
throw new ConnectionDetectionError({
|
|
28229
|
-
file:
|
|
28230
|
-
line:
|
|
28244
|
+
file: publisher.location.file,
|
|
28245
|
+
line: publisher.location.line,
|
|
28231
28246
|
typeName: publisher.name,
|
|
28232
|
-
reason: `
|
|
28247
|
+
reason: `published event "${publishedEventType}" matches ${matchCount} Event components (ambiguous)`
|
|
28233
28248
|
});
|
|
28234
28249
|
}
|
|
28235
28250
|
return {
|
|
28236
28251
|
source: componentIdentity(publisher),
|
|
28237
28252
|
target: "_unresolved",
|
|
28238
28253
|
type: "async",
|
|
28239
|
-
sourceLocation,
|
|
28240
|
-
_uncertain: `ambiguous: ${matchCount} events match
|
|
28254
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
28255
|
+
_uncertain: `ambiguous: ${matchCount} events match published event type: ${publishedEventType}`
|
|
28241
28256
|
};
|
|
28242
28257
|
}
|
|
28243
|
-
function handleNoMatch(publisher, publishedEventType, options
|
|
28258
|
+
function handleNoMatch(publisher, publishedEventType, options) {
|
|
28244
28259
|
if (options.strict) {
|
|
28245
28260
|
throw new ConnectionDetectionError({
|
|
28246
|
-
file:
|
|
28247
|
-
line:
|
|
28261
|
+
file: publisher.location.file,
|
|
28262
|
+
line: publisher.location.line,
|
|
28248
28263
|
typeName: publisher.name,
|
|
28249
|
-
reason: `
|
|
28264
|
+
reason: `published event "${publishedEventType}" does not match any Event component`
|
|
28250
28265
|
});
|
|
28251
28266
|
}
|
|
28252
28267
|
return {
|
|
28253
28268
|
source: componentIdentity(publisher),
|
|
28254
28269
|
target: "_unresolved",
|
|
28255
28270
|
type: "async",
|
|
28256
|
-
sourceLocation,
|
|
28257
|
-
_uncertain: `no event found for
|
|
28271
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
28272
|
+
_uncertain: `no event found for published event type: ${publishedEventType}`
|
|
28258
28273
|
};
|
|
28259
28274
|
}
|
|
28260
28275
|
|
|
@@ -28265,15 +28280,8 @@ function detectSubscribeConnections(components, options) {
|
|
|
28265
28280
|
const repository = options.repository;
|
|
28266
28281
|
return eventHandlers.flatMap((handler) => getSubscribedEvents(handler).flatMap((eventName) => resolveSubscription(handler, eventName, events, options, repository)));
|
|
28267
28282
|
}
|
|
28268
|
-
function toSourceLocation(component, repository) {
|
|
28269
|
-
return {
|
|
28270
|
-
repository,
|
|
28271
|
-
filePath: component.location.file,
|
|
28272
|
-
lineNumber: component.location.line
|
|
28273
|
-
};
|
|
28274
|
-
}
|
|
28275
28283
|
function resolveSubscription(handler, eventName, events, options, repository) {
|
|
28276
|
-
const matchingEvents = events.filter((e) => e.metadata[
|
|
28284
|
+
const matchingEvents = events.filter((e) => e.metadata[EVENT_NAME_FIELD] === eventName);
|
|
28277
28285
|
if (matchingEvents.length === 0) {
|
|
28278
28286
|
return [handleNoMatch2(handler, eventName, options, repository)];
|
|
28279
28287
|
}
|
|
@@ -28322,7 +28330,7 @@ function handleNoMatch2(handler, eventName, options, repository) {
|
|
|
28322
28330
|
};
|
|
28323
28331
|
}
|
|
28324
28332
|
function getSubscribedEvents(handler) {
|
|
28325
|
-
const raw = handler.metadata[
|
|
28333
|
+
const raw = handler.metadata[SUBSCRIBED_EVENTS_FIELD];
|
|
28326
28334
|
if (!Array.isArray(raw)) {
|
|
28327
28335
|
return [];
|
|
28328
28336
|
}
|
|
@@ -28591,15 +28599,13 @@ function detectPerModuleConnections(project, components, options, globMatcher) {
|
|
|
28591
28599
|
function detectCrossModuleConnections(allComponents, options) {
|
|
28592
28600
|
const strict = options.allowIncomplete !== true;
|
|
28593
28601
|
const repository = options.repository;
|
|
28594
|
-
const
|
|
28595
|
-
const publishLinks = detectPublishConnections(allComponents, {
|
|
28596
|
-
strict,
|
|
28597
|
-
repository
|
|
28598
|
-
});
|
|
28599
|
-
const subscribeLinks = detectSubscribeConnections(allComponents, {
|
|
28602
|
+
const asyncOptions = {
|
|
28600
28603
|
strict,
|
|
28601
28604
|
repository
|
|
28602
|
-
}
|
|
28605
|
+
};
|
|
28606
|
+
const asyncStart = performance.now();
|
|
28607
|
+
const publishLinks = detectEventPublisherConnections(allComponents, options.eventPublishers ?? [], asyncOptions);
|
|
28608
|
+
const subscribeLinks = detectSubscribeConnections(allComponents, asyncOptions);
|
|
28603
28609
|
const asyncDetectionMs = performance.now() - asyncStart;
|
|
28604
28610
|
return {
|
|
28605
28611
|
links: [...publishLinks, ...subscribeLinks],
|
|
@@ -28638,7 +28644,6 @@ function getBuiltInRule(module, componentType) {
|
|
|
28638
28644
|
domainOp: module.domainOp,
|
|
28639
28645
|
event: module.event,
|
|
28640
28646
|
eventHandler: module.eventHandler,
|
|
28641
|
-
eventPublisher: module.eventPublisher,
|
|
28642
28647
|
ui: module.ui
|
|
28643
28648
|
};
|
|
28644
28649
|
const rule = ruleMap[componentType];
|
|
@@ -28654,7 +28659,6 @@ function findDetectionRule(module, componentType) {
|
|
|
28654
28659
|
"domainOp",
|
|
28655
28660
|
"event",
|
|
28656
28661
|
"eventHandler",
|
|
28657
|
-
"eventPublisher",
|
|
28658
28662
|
"ui"
|
|
28659
28663
|
];
|
|
28660
28664
|
if (builtInTypes.includes(componentType)) {
|
|
@@ -28705,10 +28709,7 @@ function evaluateClassRule(rule, classDecl) {
|
|
|
28705
28709
|
if ("fromClassName" in rule) {
|
|
28706
28710
|
return evaluateFromClassNameRule(rule, classDecl);
|
|
28707
28711
|
}
|
|
28708
|
-
|
|
28709
|
-
throw new ExtractionError("Unsupported extraction rule type for class-based component", classDecl.getSourceFile().getFilePath(), classDecl.getStartLineNumber());
|
|
28710
|
-
}
|
|
28711
|
-
return evaluateFromPropertyRule(rule, classDecl);
|
|
28712
|
+
throw new ExtractionError("Unsupported extraction rule type for class-based component", classDecl.getSourceFile().getFilePath(), classDecl.getStartLineNumber());
|
|
28712
28713
|
}
|
|
28713
28714
|
function evaluateRule2(rule, draft, project) {
|
|
28714
28715
|
if ("literal" in rule) {
|
|
@@ -28725,6 +28726,10 @@ function evaluateRule2(rule, draft, project) {
|
|
|
28725
28726
|
const classDecl2 = findContainingClass(project, draft);
|
|
28726
28727
|
return evaluateFromGenericArgRule(rule, classDecl2);
|
|
28727
28728
|
}
|
|
28729
|
+
if ("fromProperty" in rule) {
|
|
28730
|
+
const classDecl2 = findContainingClass(project, draft);
|
|
28731
|
+
return evaluateFromPropertyRule(rule, classDecl2);
|
|
28732
|
+
}
|
|
28728
28733
|
if ("fromParameterType" in rule) {
|
|
28729
28734
|
const methodDecl = findMethodAtLine(project, draft);
|
|
28730
28735
|
const params = methodDecl.getParameters();
|
|
@@ -28905,10 +28910,6 @@ var extraction_config_schema_default = {
|
|
|
28905
28910
|
$ref: "#/$defs/componentRule",
|
|
28906
28911
|
description: "Detection rule for EventHandler components"
|
|
28907
28912
|
},
|
|
28908
|
-
eventPublisher: {
|
|
28909
|
-
$ref: "#/$defs/componentRule",
|
|
28910
|
-
description: "Detection rule for EventPublisher components"
|
|
28911
|
-
},
|
|
28912
28913
|
ui: {
|
|
28913
28914
|
$ref: "#/$defs/componentRule",
|
|
28914
28915
|
description: "Detection rule for UI components"
|
|
@@ -28921,7 +28922,7 @@ var extraction_config_schema_default = {
|
|
|
28921
28922
|
}
|
|
28922
28923
|
},
|
|
28923
28924
|
connections: {
|
|
28924
|
-
$ref: "#/$defs/
|
|
28925
|
+
$ref: "#/$defs/moduleConnectionsConfig",
|
|
28925
28926
|
description: "Module-level connection detection patterns additive to global"
|
|
28926
28927
|
}
|
|
28927
28928
|
},
|
|
@@ -28931,7 +28932,7 @@ var extraction_config_schema_default = {
|
|
|
28931
28932
|
}
|
|
28932
28933
|
},
|
|
28933
28934
|
then: {
|
|
28934
|
-
required: ["api", "useCase", "domainOp", "event", "eventHandler", "
|
|
28935
|
+
required: ["api", "useCase", "domainOp", "event", "eventHandler", "ui"]
|
|
28935
28936
|
}
|
|
28936
28937
|
},
|
|
28937
28938
|
componentRule: {
|
|
@@ -29425,7 +29426,6 @@ var extraction_config_schema_default = {
|
|
|
29425
29426
|
connectionsConfig: {
|
|
29426
29427
|
type: "object",
|
|
29427
29428
|
description: "Connection detection configuration with pattern definitions",
|
|
29428
|
-
required: ["patterns"],
|
|
29429
29429
|
additionalProperties: false,
|
|
29430
29430
|
properties: {
|
|
29431
29431
|
patterns: {
|
|
@@ -29435,6 +29435,47 @@ var extraction_config_schema_default = {
|
|
|
29435
29435
|
items: {
|
|
29436
29436
|
$ref: "#/$defs/connectionPattern"
|
|
29437
29437
|
}
|
|
29438
|
+
},
|
|
29439
|
+
eventPublishers: {
|
|
29440
|
+
type: "array",
|
|
29441
|
+
description: "Declares which custom component types publish events and how to detect the connections",
|
|
29442
|
+
minItems: 1,
|
|
29443
|
+
items: {
|
|
29444
|
+
$ref: "#/$defs/eventPublisherConfig"
|
|
29445
|
+
}
|
|
29446
|
+
}
|
|
29447
|
+
}
|
|
29448
|
+
},
|
|
29449
|
+
moduleConnectionsConfig: {
|
|
29450
|
+
type: "object",
|
|
29451
|
+
description: "Module-level connection detection configuration (patterns only \u2014 eventPublishers is top-level only)",
|
|
29452
|
+
additionalProperties: false,
|
|
29453
|
+
properties: {
|
|
29454
|
+
patterns: {
|
|
29455
|
+
type: "array",
|
|
29456
|
+
description: "Connection detection patterns",
|
|
29457
|
+
minItems: 1,
|
|
29458
|
+
items: {
|
|
29459
|
+
$ref: "#/$defs/connectionPattern"
|
|
29460
|
+
}
|
|
29461
|
+
}
|
|
29462
|
+
}
|
|
29463
|
+
},
|
|
29464
|
+
eventPublisherConfig: {
|
|
29465
|
+
type: "object",
|
|
29466
|
+
description: "Declares a custom component type as an event publisher",
|
|
29467
|
+
required: ["fromType", "metadataKey"],
|
|
29468
|
+
additionalProperties: false,
|
|
29469
|
+
properties: {
|
|
29470
|
+
fromType: {
|
|
29471
|
+
type: "string",
|
|
29472
|
+
description: "The custom component type name \u2014 must be defined in customTypes in at least one module",
|
|
29473
|
+
minLength: 1
|
|
29474
|
+
},
|
|
29475
|
+
metadataKey: {
|
|
29476
|
+
type: "string",
|
|
29477
|
+
description: "The metadata key on this component type that holds the published event type name",
|
|
29478
|
+
minLength: 1
|
|
29438
29479
|
}
|
|
29439
29480
|
}
|
|
29440
29481
|
},
|
|
@@ -29570,7 +29611,6 @@ var REQUIRED_FIELDS = {
|
|
|
29570
29611
|
api: ["apiType"],
|
|
29571
29612
|
event: ["eventName"],
|
|
29572
29613
|
eventHandler: ["subscribedEvents"],
|
|
29573
|
-
eventPublisher: [],
|
|
29574
29614
|
domainOp: ["operationName"],
|
|
29575
29615
|
ui: ["route"],
|
|
29576
29616
|
useCase: []
|
|
@@ -29581,7 +29621,6 @@ var COMPONENT_TYPES2 = [
|
|
|
29581
29621
|
"domainOp",
|
|
29582
29622
|
"event",
|
|
29583
29623
|
"eventHandler",
|
|
29584
|
-
"eventPublisher",
|
|
29585
29624
|
"ui"
|
|
29586
29625
|
];
|
|
29587
29626
|
var ajv2 = new import_ajv2.default({ allErrors: true });
|
|
@@ -29660,6 +29699,54 @@ function validateAllExtractionRules(config2) {
|
|
|
29660
29699
|
return validateModuleExtractionRules(module, index);
|
|
29661
29700
|
});
|
|
29662
29701
|
}
|
|
29702
|
+
function collectCustomTypeExtractedFields(config2) {
|
|
29703
|
+
const fieldsByType = /* @__PURE__ */ new Map();
|
|
29704
|
+
for (const module of config2.modules) {
|
|
29705
|
+
if ("$ref" in module || module.customTypes === void 0) {
|
|
29706
|
+
continue;
|
|
29707
|
+
}
|
|
29708
|
+
for (const [typeName, rule] of Object.entries(module.customTypes)) {
|
|
29709
|
+
const existing = fieldsByType.get(typeName) ?? /* @__PURE__ */ new Set();
|
|
29710
|
+
for (const key of Object.keys(rule.extract ?? {})) {
|
|
29711
|
+
existing.add(key);
|
|
29712
|
+
}
|
|
29713
|
+
fieldsByType.set(typeName, existing);
|
|
29714
|
+
}
|
|
29715
|
+
}
|
|
29716
|
+
return fieldsByType;
|
|
29717
|
+
}
|
|
29718
|
+
function validateEventPublishers(connections, customTypeFields) {
|
|
29719
|
+
if (connections.eventPublishers === void 0) {
|
|
29720
|
+
return [];
|
|
29721
|
+
}
|
|
29722
|
+
return connections.eventPublishers.flatMap((publisher, index) => {
|
|
29723
|
+
const extractedFields = customTypeFields.get(publisher.fromType);
|
|
29724
|
+
if (extractedFields === void 0) {
|
|
29725
|
+
return [
|
|
29726
|
+
{
|
|
29727
|
+
path: `/connections/eventPublishers/${index}/fromType`,
|
|
29728
|
+
message: `"${publisher.fromType}" is not defined as a customType in any module. Add a customType named "${publisher.fromType}" to at least one module.`
|
|
29729
|
+
}
|
|
29730
|
+
];
|
|
29731
|
+
}
|
|
29732
|
+
if (!extractedFields.has(publisher.metadataKey)) {
|
|
29733
|
+
return [
|
|
29734
|
+
{
|
|
29735
|
+
path: `/connections/eventPublishers/${index}/fromType`,
|
|
29736
|
+
message: `customType "${publisher.fromType}" does not extract "${publisher.metadataKey}". Add extract["${publisher.metadataKey}"] to that custom type.`
|
|
29737
|
+
}
|
|
29738
|
+
];
|
|
29739
|
+
}
|
|
29740
|
+
return [];
|
|
29741
|
+
});
|
|
29742
|
+
}
|
|
29743
|
+
function validateConnectionsConfig(config2) {
|
|
29744
|
+
if (config2.connections === void 0) {
|
|
29745
|
+
return [];
|
|
29746
|
+
}
|
|
29747
|
+
const customTypeFields = collectCustomTypeExtractedFields(config2);
|
|
29748
|
+
return validateEventPublishers(config2.connections, customTypeFields);
|
|
29749
|
+
}
|
|
29663
29750
|
function validateExtractionConfigSchema(data) {
|
|
29664
29751
|
const schemaValid = validate2(data) === true;
|
|
29665
29752
|
if (!schemaValid) {
|
|
@@ -29677,7 +29764,7 @@ function validateExtractionConfig(data) {
|
|
|
29677
29764
|
if (!isValidExtractionConfig(data)) {
|
|
29678
29765
|
return validateExtractionConfigSchema(data);
|
|
29679
29766
|
}
|
|
29680
|
-
const semanticErrors = validateAllExtractionRules(data);
|
|
29767
|
+
const semanticErrors = [...validateAllExtractionRules(data), ...validateConnectionsConfig(data)];
|
|
29681
29768
|
if (semanticErrors.length > 0) {
|
|
29682
29769
|
return {
|
|
29683
29770
|
valid: false,
|
|
@@ -29693,10 +29780,10 @@ function formatValidationErrors2(errors) {
|
|
|
29693
29780
|
return formatValidationErrorsInternal2(errors);
|
|
29694
29781
|
}
|
|
29695
29782
|
function parseExtractionConfig(data) {
|
|
29696
|
-
|
|
29783
|
+
const result = validateExtractionConfig(data);
|
|
29784
|
+
if (result.valid && isValidExtractionConfig(data)) {
|
|
29697
29785
|
return data;
|
|
29698
29786
|
}
|
|
29699
|
-
const result = validateExtractionConfig(data);
|
|
29700
29787
|
throw new ExtractionConfigValidationError(result.errors);
|
|
29701
29788
|
}
|
|
29702
29789
|
|
|
@@ -30049,7 +30136,8 @@ var ExtractionProject = class {
|
|
|
30049
30136
|
}
|
|
30050
30137
|
const crossResult = detectCrossModuleConnections(enrichedComponents, {
|
|
30051
30138
|
allowIncomplete,
|
|
30052
|
-
repository: this.repositoryName
|
|
30139
|
+
repository: this.repositoryName,
|
|
30140
|
+
eventPublishers: this.resolvedConfig.connections?.eventPublishers
|
|
30053
30141
|
});
|
|
30054
30142
|
links.push(...crossResult.links);
|
|
30055
30143
|
timings.push({
|
|
@@ -30355,7 +30443,6 @@ ${formatValidationErrors2(validationResult.errors)}`
|
|
|
30355
30443
|
domainOp: parsed.domainOp ?? NOT_USED,
|
|
30356
30444
|
event: parsed.event ?? NOT_USED,
|
|
30357
30445
|
eventHandler: parsed.eventHandler ?? NOT_USED,
|
|
30358
|
-
eventPublisher: parsed.eventPublisher ?? NOT_USED,
|
|
30359
30446
|
ui: parsed.ui ?? NOT_USED
|
|
30360
30447
|
};
|
|
30361
30448
|
}
|
|
@@ -31120,7 +31207,7 @@ function parsePackageJson(pkg) {
|
|
|
31120
31207
|
}
|
|
31121
31208
|
function loadPackageJson() {
|
|
31122
31209
|
if (true) {
|
|
31123
|
-
return { version: "0.9.
|
|
31210
|
+
return { version: "0.9.4" };
|
|
31124
31211
|
}
|
|
31125
31212
|
const require2 = createRequire2(import.meta.url);
|
|
31126
31213
|
return parsePackageJson(require2("../../package.json"));
|
|
@@ -31214,7 +31301,6 @@ program.parseAsync().catch(handleGlobalError);
|
|
|
31214
31301
|
/* istanbul ignore else -- @preserve: false branch is unreachable; FindTarget is exhaustive */
|
|
31215
31302
|
/* istanbul ignore next -- @preserve: unreachable with valid FindTarget type; defensive fallback */
|
|
31216
31303
|
/* v8 ignore next -- @preserve: getExtends() !== undefined guarantees getBaseClass() returns a value */
|
|
31217
|
-
/* istanbul ignore next -- @preserve: only fromProperty reaches here; defensive guard */
|
|
31218
31304
|
/* istanbul ignore next -- @preserve: catch always receives Error instances from ExtractionError */
|
|
31219
31305
|
/* v8 ignore start -- @preserve: default executor delegates to execFileSync; tested via CLI integration */
|
|
31220
31306
|
/* v8 ignore next -- @preserve: defensive optional chain; property existence guaranteed by hasOwn check above */
|
package/dist/index.js
CHANGED
|
@@ -6885,6 +6885,10 @@ var BuildValidationError = class extends Error {
|
|
|
6885
6885
|
}
|
|
6886
6886
|
};
|
|
6887
6887
|
|
|
6888
|
+
// ../riviere-schema/dist/schema.js
|
|
6889
|
+
var EVENT_NAME_FIELD = "eventName";
|
|
6890
|
+
var SUBSCRIBED_EVENTS_FIELD = "subscribedEvents";
|
|
6891
|
+
|
|
6888
6892
|
// ../riviere-schema/dist/validation.js
|
|
6889
6893
|
var import_ajv = __toESM(require_ajv(), 1);
|
|
6890
6894
|
var import_ajv_formats = __toESM(require_dist(), 1);
|
|
@@ -25556,7 +25560,6 @@ var COMPONENT_TYPES = [
|
|
|
25556
25560
|
"domainOp",
|
|
25557
25561
|
"event",
|
|
25558
25562
|
"eventHandler",
|
|
25559
|
-
"eventPublisher",
|
|
25560
25563
|
"ui"
|
|
25561
25564
|
];
|
|
25562
25565
|
function extractComponents(project, sourceFilePaths, config2, globMatcher, configDir) {
|
|
@@ -25715,7 +25718,6 @@ function resolveModule(moduleConfig, loader) {
|
|
|
25715
25718
|
domainOp: requireRule(moduleConfig.domainOp, "domainOp", moduleConfig.name),
|
|
25716
25719
|
event: requireRule(moduleConfig.event, "event", moduleConfig.name),
|
|
25717
25720
|
eventHandler: requireRule(moduleConfig.eventHandler, "eventHandler", moduleConfig.name),
|
|
25718
|
-
eventPublisher: requireRule(moduleConfig.eventPublisher, "eventPublisher", moduleConfig.name),
|
|
25719
25721
|
ui: requireRule(moduleConfig.ui, "ui", moduleConfig.name),
|
|
25720
25722
|
...moduleConfig.customTypes !== void 0 && { customTypes: moduleConfig.customTypes }
|
|
25721
25723
|
};
|
|
@@ -25735,7 +25737,6 @@ function resolveModuleWithExtends(moduleConfig, extendsSource, loader) {
|
|
|
25735
25737
|
domainOp: moduleConfig.domainOp ?? baseModule.domainOp,
|
|
25736
25738
|
event: moduleConfig.event ?? baseModule.event,
|
|
25737
25739
|
eventHandler: moduleConfig.eventHandler ?? baseModule.eventHandler,
|
|
25738
|
-
eventPublisher: moduleConfig.eventPublisher ?? baseModule.eventPublisher,
|
|
25739
25740
|
ui: moduleConfig.ui ?? baseModule.ui,
|
|
25740
25741
|
...mergedCustomTypes !== void 0 && { customTypes: mergedCustomTypes }
|
|
25741
25742
|
};
|
|
@@ -28195,90 +28196,104 @@ function traceNonComponent(project, componentIndex, source, typeName, calledMeth
|
|
|
28195
28196
|
}
|
|
28196
28197
|
}
|
|
28197
28198
|
|
|
28198
|
-
// ../riviere-extract-ts/dist/features/extraction/domain/connection-detection/async-detection/
|
|
28199
|
-
function
|
|
28200
|
-
|
|
28199
|
+
// ../riviere-extract-ts/dist/features/extraction/domain/connection-detection/async-detection/async-detection-types.js
|
|
28200
|
+
function toSourceLocation(component, repository) {
|
|
28201
|
+
return {
|
|
28202
|
+
repository,
|
|
28203
|
+
filePath: component.location.file,
|
|
28204
|
+
lineNumber: component.location.line
|
|
28205
|
+
};
|
|
28206
|
+
}
|
|
28207
|
+
|
|
28208
|
+
// ../riviere-extract-ts/dist/features/extraction/domain/connection-detection/async-detection/detect-event-publisher-connections.js
|
|
28209
|
+
function detectEventPublisherConnections(components, eventPublishers, options) {
|
|
28210
|
+
if (eventPublishers.length === 0) {
|
|
28211
|
+
return [];
|
|
28212
|
+
}
|
|
28201
28213
|
const events = components.filter((c) => c.type === "event");
|
|
28202
|
-
|
|
28203
|
-
|
|
28204
|
-
const
|
|
28205
|
-
|
|
28206
|
-
|
|
28207
|
-
|
|
28208
|
-
|
|
28209
|
-
|
|
28210
|
-
|
|
28211
|
-
|
|
28212
|
-
|
|
28213
|
-
|
|
28214
|
+
return eventPublishers.flatMap((publisherConfig) => {
|
|
28215
|
+
const { fromType, metadataKey } = publisherConfig;
|
|
28216
|
+
const publishers = components.filter((c) => c.type === fromType);
|
|
28217
|
+
return publishers.flatMap((publisher) => {
|
|
28218
|
+
const publishedEventType = publisher.metadata[metadataKey];
|
|
28219
|
+
if (Array.isArray(publishedEventType)) {
|
|
28220
|
+
const validTypes = publishedEventType.filter((t) => typeof t === "string" && t.trim() !== "");
|
|
28221
|
+
if (validTypes.length === 0) {
|
|
28222
|
+
return [handleMissingMetadata(publisher, metadataKey, options)];
|
|
28223
|
+
}
|
|
28224
|
+
return validTypes.flatMap((t) => resolvePublishTarget(publisher, t, events, options));
|
|
28225
|
+
}
|
|
28226
|
+
if (typeof publishedEventType !== "string" || publishedEventType.trim() === "") {
|
|
28227
|
+
return [handleMissingMetadata(publisher, metadataKey, options)];
|
|
28228
|
+
}
|
|
28229
|
+
return resolvePublishTarget(publisher, publishedEventType, events, options);
|
|
28230
|
+
});
|
|
28214
28231
|
});
|
|
28215
28232
|
}
|
|
28216
|
-
function handleMissingMetadata(publisher,
|
|
28233
|
+
function handleMissingMetadata(publisher, metadataKey, options) {
|
|
28217
28234
|
if (options.strict) {
|
|
28218
28235
|
throw new ConnectionDetectionError({
|
|
28219
|
-
file:
|
|
28220
|
-
line:
|
|
28236
|
+
file: publisher.location.file,
|
|
28237
|
+
line: publisher.location.line,
|
|
28221
28238
|
typeName: publisher.name,
|
|
28222
|
-
reason:
|
|
28239
|
+
reason: `published event type in "${metadataKey}" metadata is missing or invalid`
|
|
28223
28240
|
});
|
|
28224
28241
|
}
|
|
28225
28242
|
return {
|
|
28226
28243
|
source: componentIdentity(publisher),
|
|
28227
28244
|
target: "_unresolved",
|
|
28228
28245
|
type: "async",
|
|
28229
|
-
sourceLocation,
|
|
28230
|
-
_uncertain: `
|
|
28246
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
28247
|
+
_uncertain: `event publisher "${publisher.name}" is missing required "${metadataKey}" metadata`
|
|
28231
28248
|
};
|
|
28232
28249
|
}
|
|
28233
|
-
function resolvePublishTarget(publisher, publishedEventType, events, options
|
|
28234
|
-
const matchingEvents = events.filter((e) => e.metadata[
|
|
28250
|
+
function resolvePublishTarget(publisher, publishedEventType, events, options) {
|
|
28251
|
+
const matchingEvents = events.filter((e) => e.metadata[EVENT_NAME_FIELD] === publishedEventType);
|
|
28235
28252
|
if (matchingEvents.length === 0) {
|
|
28236
|
-
return [handleNoMatch(publisher, publishedEventType, options
|
|
28253
|
+
return [handleNoMatch(publisher, publishedEventType, options)];
|
|
28237
28254
|
}
|
|
28238
28255
|
if (matchingEvents.length > 1) {
|
|
28239
|
-
return [
|
|
28240
|
-
handleAmbiguousMatch(publisher, publishedEventType, matchingEvents.length, options, sourceLocation)
|
|
28241
|
-
];
|
|
28256
|
+
return [handleAmbiguousMatch(publisher, publishedEventType, matchingEvents.length, options)];
|
|
28242
28257
|
}
|
|
28243
28258
|
return matchingEvents.map((event) => ({
|
|
28244
28259
|
source: componentIdentity(publisher),
|
|
28245
28260
|
target: componentIdentity(event),
|
|
28246
28261
|
type: "async",
|
|
28247
|
-
sourceLocation
|
|
28262
|
+
sourceLocation: toSourceLocation(publisher, options.repository)
|
|
28248
28263
|
}));
|
|
28249
28264
|
}
|
|
28250
|
-
function handleAmbiguousMatch(publisher, publishedEventType, matchCount, options
|
|
28265
|
+
function handleAmbiguousMatch(publisher, publishedEventType, matchCount, options) {
|
|
28251
28266
|
if (options.strict) {
|
|
28252
28267
|
throw new ConnectionDetectionError({
|
|
28253
|
-
file:
|
|
28254
|
-
line:
|
|
28268
|
+
file: publisher.location.file,
|
|
28269
|
+
line: publisher.location.line,
|
|
28255
28270
|
typeName: publisher.name,
|
|
28256
|
-
reason: `
|
|
28271
|
+
reason: `published event "${publishedEventType}" matches ${matchCount} Event components (ambiguous)`
|
|
28257
28272
|
});
|
|
28258
28273
|
}
|
|
28259
28274
|
return {
|
|
28260
28275
|
source: componentIdentity(publisher),
|
|
28261
28276
|
target: "_unresolved",
|
|
28262
28277
|
type: "async",
|
|
28263
|
-
sourceLocation,
|
|
28264
|
-
_uncertain: `ambiguous: ${matchCount} events match
|
|
28278
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
28279
|
+
_uncertain: `ambiguous: ${matchCount} events match published event type: ${publishedEventType}`
|
|
28265
28280
|
};
|
|
28266
28281
|
}
|
|
28267
|
-
function handleNoMatch(publisher, publishedEventType, options
|
|
28282
|
+
function handleNoMatch(publisher, publishedEventType, options) {
|
|
28268
28283
|
if (options.strict) {
|
|
28269
28284
|
throw new ConnectionDetectionError({
|
|
28270
|
-
file:
|
|
28271
|
-
line:
|
|
28285
|
+
file: publisher.location.file,
|
|
28286
|
+
line: publisher.location.line,
|
|
28272
28287
|
typeName: publisher.name,
|
|
28273
|
-
reason: `
|
|
28288
|
+
reason: `published event "${publishedEventType}" does not match any Event component`
|
|
28274
28289
|
});
|
|
28275
28290
|
}
|
|
28276
28291
|
return {
|
|
28277
28292
|
source: componentIdentity(publisher),
|
|
28278
28293
|
target: "_unresolved",
|
|
28279
28294
|
type: "async",
|
|
28280
|
-
sourceLocation,
|
|
28281
|
-
_uncertain: `no event found for
|
|
28295
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
28296
|
+
_uncertain: `no event found for published event type: ${publishedEventType}`
|
|
28282
28297
|
};
|
|
28283
28298
|
}
|
|
28284
28299
|
|
|
@@ -28289,15 +28304,8 @@ function detectSubscribeConnections(components, options) {
|
|
|
28289
28304
|
const repository = options.repository;
|
|
28290
28305
|
return eventHandlers.flatMap((handler) => getSubscribedEvents(handler).flatMap((eventName) => resolveSubscription(handler, eventName, events, options, repository)));
|
|
28291
28306
|
}
|
|
28292
|
-
function toSourceLocation(component, repository) {
|
|
28293
|
-
return {
|
|
28294
|
-
repository,
|
|
28295
|
-
filePath: component.location.file,
|
|
28296
|
-
lineNumber: component.location.line
|
|
28297
|
-
};
|
|
28298
|
-
}
|
|
28299
28307
|
function resolveSubscription(handler, eventName, events, options, repository) {
|
|
28300
|
-
const matchingEvents = events.filter((e) => e.metadata[
|
|
28308
|
+
const matchingEvents = events.filter((e) => e.metadata[EVENT_NAME_FIELD] === eventName);
|
|
28301
28309
|
if (matchingEvents.length === 0) {
|
|
28302
28310
|
return [handleNoMatch2(handler, eventName, options, repository)];
|
|
28303
28311
|
}
|
|
@@ -28346,7 +28354,7 @@ function handleNoMatch2(handler, eventName, options, repository) {
|
|
|
28346
28354
|
};
|
|
28347
28355
|
}
|
|
28348
28356
|
function getSubscribedEvents(handler) {
|
|
28349
|
-
const raw = handler.metadata[
|
|
28357
|
+
const raw = handler.metadata[SUBSCRIBED_EVENTS_FIELD];
|
|
28350
28358
|
if (!Array.isArray(raw)) {
|
|
28351
28359
|
return [];
|
|
28352
28360
|
}
|
|
@@ -28615,15 +28623,13 @@ function detectPerModuleConnections(project, components, options, globMatcher) {
|
|
|
28615
28623
|
function detectCrossModuleConnections(allComponents, options) {
|
|
28616
28624
|
const strict = options.allowIncomplete !== true;
|
|
28617
28625
|
const repository = options.repository;
|
|
28618
|
-
const
|
|
28619
|
-
const publishLinks = detectPublishConnections(allComponents, {
|
|
28620
|
-
strict,
|
|
28621
|
-
repository
|
|
28622
|
-
});
|
|
28623
|
-
const subscribeLinks = detectSubscribeConnections(allComponents, {
|
|
28626
|
+
const asyncOptions = {
|
|
28624
28627
|
strict,
|
|
28625
28628
|
repository
|
|
28626
|
-
}
|
|
28629
|
+
};
|
|
28630
|
+
const asyncStart = performance.now();
|
|
28631
|
+
const publishLinks = detectEventPublisherConnections(allComponents, options.eventPublishers ?? [], asyncOptions);
|
|
28632
|
+
const subscribeLinks = detectSubscribeConnections(allComponents, asyncOptions);
|
|
28627
28633
|
const asyncDetectionMs = performance.now() - asyncStart;
|
|
28628
28634
|
return {
|
|
28629
28635
|
links: [...publishLinks, ...subscribeLinks],
|
|
@@ -28662,7 +28668,6 @@ function getBuiltInRule(module, componentType) {
|
|
|
28662
28668
|
domainOp: module.domainOp,
|
|
28663
28669
|
event: module.event,
|
|
28664
28670
|
eventHandler: module.eventHandler,
|
|
28665
|
-
eventPublisher: module.eventPublisher,
|
|
28666
28671
|
ui: module.ui
|
|
28667
28672
|
};
|
|
28668
28673
|
const rule = ruleMap[componentType];
|
|
@@ -28678,7 +28683,6 @@ function findDetectionRule(module, componentType) {
|
|
|
28678
28683
|
"domainOp",
|
|
28679
28684
|
"event",
|
|
28680
28685
|
"eventHandler",
|
|
28681
|
-
"eventPublisher",
|
|
28682
28686
|
"ui"
|
|
28683
28687
|
];
|
|
28684
28688
|
if (builtInTypes.includes(componentType)) {
|
|
@@ -28729,10 +28733,7 @@ function evaluateClassRule(rule, classDecl) {
|
|
|
28729
28733
|
if ("fromClassName" in rule) {
|
|
28730
28734
|
return evaluateFromClassNameRule(rule, classDecl);
|
|
28731
28735
|
}
|
|
28732
|
-
|
|
28733
|
-
throw new ExtractionError("Unsupported extraction rule type for class-based component", classDecl.getSourceFile().getFilePath(), classDecl.getStartLineNumber());
|
|
28734
|
-
}
|
|
28735
|
-
return evaluateFromPropertyRule(rule, classDecl);
|
|
28736
|
+
throw new ExtractionError("Unsupported extraction rule type for class-based component", classDecl.getSourceFile().getFilePath(), classDecl.getStartLineNumber());
|
|
28736
28737
|
}
|
|
28737
28738
|
function evaluateRule2(rule, draft, project) {
|
|
28738
28739
|
if ("literal" in rule) {
|
|
@@ -28749,6 +28750,10 @@ function evaluateRule2(rule, draft, project) {
|
|
|
28749
28750
|
const classDecl2 = findContainingClass(project, draft);
|
|
28750
28751
|
return evaluateFromGenericArgRule(rule, classDecl2);
|
|
28751
28752
|
}
|
|
28753
|
+
if ("fromProperty" in rule) {
|
|
28754
|
+
const classDecl2 = findContainingClass(project, draft);
|
|
28755
|
+
return evaluateFromPropertyRule(rule, classDecl2);
|
|
28756
|
+
}
|
|
28752
28757
|
if ("fromParameterType" in rule) {
|
|
28753
28758
|
const methodDecl = findMethodAtLine(project, draft);
|
|
28754
28759
|
const params = methodDecl.getParameters();
|
|
@@ -28929,10 +28934,6 @@ var extraction_config_schema_default = {
|
|
|
28929
28934
|
$ref: "#/$defs/componentRule",
|
|
28930
28935
|
description: "Detection rule for EventHandler components"
|
|
28931
28936
|
},
|
|
28932
|
-
eventPublisher: {
|
|
28933
|
-
$ref: "#/$defs/componentRule",
|
|
28934
|
-
description: "Detection rule for EventPublisher components"
|
|
28935
|
-
},
|
|
28936
28937
|
ui: {
|
|
28937
28938
|
$ref: "#/$defs/componentRule",
|
|
28938
28939
|
description: "Detection rule for UI components"
|
|
@@ -28945,7 +28946,7 @@ var extraction_config_schema_default = {
|
|
|
28945
28946
|
}
|
|
28946
28947
|
},
|
|
28947
28948
|
connections: {
|
|
28948
|
-
$ref: "#/$defs/
|
|
28949
|
+
$ref: "#/$defs/moduleConnectionsConfig",
|
|
28949
28950
|
description: "Module-level connection detection patterns additive to global"
|
|
28950
28951
|
}
|
|
28951
28952
|
},
|
|
@@ -28955,7 +28956,7 @@ var extraction_config_schema_default = {
|
|
|
28955
28956
|
}
|
|
28956
28957
|
},
|
|
28957
28958
|
then: {
|
|
28958
|
-
required: ["api", "useCase", "domainOp", "event", "eventHandler", "
|
|
28959
|
+
required: ["api", "useCase", "domainOp", "event", "eventHandler", "ui"]
|
|
28959
28960
|
}
|
|
28960
28961
|
},
|
|
28961
28962
|
componentRule: {
|
|
@@ -29449,7 +29450,6 @@ var extraction_config_schema_default = {
|
|
|
29449
29450
|
connectionsConfig: {
|
|
29450
29451
|
type: "object",
|
|
29451
29452
|
description: "Connection detection configuration with pattern definitions",
|
|
29452
|
-
required: ["patterns"],
|
|
29453
29453
|
additionalProperties: false,
|
|
29454
29454
|
properties: {
|
|
29455
29455
|
patterns: {
|
|
@@ -29459,6 +29459,47 @@ var extraction_config_schema_default = {
|
|
|
29459
29459
|
items: {
|
|
29460
29460
|
$ref: "#/$defs/connectionPattern"
|
|
29461
29461
|
}
|
|
29462
|
+
},
|
|
29463
|
+
eventPublishers: {
|
|
29464
|
+
type: "array",
|
|
29465
|
+
description: "Declares which custom component types publish events and how to detect the connections",
|
|
29466
|
+
minItems: 1,
|
|
29467
|
+
items: {
|
|
29468
|
+
$ref: "#/$defs/eventPublisherConfig"
|
|
29469
|
+
}
|
|
29470
|
+
}
|
|
29471
|
+
}
|
|
29472
|
+
},
|
|
29473
|
+
moduleConnectionsConfig: {
|
|
29474
|
+
type: "object",
|
|
29475
|
+
description: "Module-level connection detection configuration (patterns only \u2014 eventPublishers is top-level only)",
|
|
29476
|
+
additionalProperties: false,
|
|
29477
|
+
properties: {
|
|
29478
|
+
patterns: {
|
|
29479
|
+
type: "array",
|
|
29480
|
+
description: "Connection detection patterns",
|
|
29481
|
+
minItems: 1,
|
|
29482
|
+
items: {
|
|
29483
|
+
$ref: "#/$defs/connectionPattern"
|
|
29484
|
+
}
|
|
29485
|
+
}
|
|
29486
|
+
}
|
|
29487
|
+
},
|
|
29488
|
+
eventPublisherConfig: {
|
|
29489
|
+
type: "object",
|
|
29490
|
+
description: "Declares a custom component type as an event publisher",
|
|
29491
|
+
required: ["fromType", "metadataKey"],
|
|
29492
|
+
additionalProperties: false,
|
|
29493
|
+
properties: {
|
|
29494
|
+
fromType: {
|
|
29495
|
+
type: "string",
|
|
29496
|
+
description: "The custom component type name \u2014 must be defined in customTypes in at least one module",
|
|
29497
|
+
minLength: 1
|
|
29498
|
+
},
|
|
29499
|
+
metadataKey: {
|
|
29500
|
+
type: "string",
|
|
29501
|
+
description: "The metadata key on this component type that holds the published event type name",
|
|
29502
|
+
minLength: 1
|
|
29462
29503
|
}
|
|
29463
29504
|
}
|
|
29464
29505
|
},
|
|
@@ -29594,7 +29635,6 @@ var REQUIRED_FIELDS = {
|
|
|
29594
29635
|
api: ["apiType"],
|
|
29595
29636
|
event: ["eventName"],
|
|
29596
29637
|
eventHandler: ["subscribedEvents"],
|
|
29597
|
-
eventPublisher: [],
|
|
29598
29638
|
domainOp: ["operationName"],
|
|
29599
29639
|
ui: ["route"],
|
|
29600
29640
|
useCase: []
|
|
@@ -29605,7 +29645,6 @@ var COMPONENT_TYPES2 = [
|
|
|
29605
29645
|
"domainOp",
|
|
29606
29646
|
"event",
|
|
29607
29647
|
"eventHandler",
|
|
29608
|
-
"eventPublisher",
|
|
29609
29648
|
"ui"
|
|
29610
29649
|
];
|
|
29611
29650
|
var ajv2 = new import_ajv2.default({ allErrors: true });
|
|
@@ -29684,6 +29723,54 @@ function validateAllExtractionRules(config2) {
|
|
|
29684
29723
|
return validateModuleExtractionRules(module, index);
|
|
29685
29724
|
});
|
|
29686
29725
|
}
|
|
29726
|
+
function collectCustomTypeExtractedFields(config2) {
|
|
29727
|
+
const fieldsByType = /* @__PURE__ */ new Map();
|
|
29728
|
+
for (const module of config2.modules) {
|
|
29729
|
+
if ("$ref" in module || module.customTypes === void 0) {
|
|
29730
|
+
continue;
|
|
29731
|
+
}
|
|
29732
|
+
for (const [typeName, rule] of Object.entries(module.customTypes)) {
|
|
29733
|
+
const existing = fieldsByType.get(typeName) ?? /* @__PURE__ */ new Set();
|
|
29734
|
+
for (const key of Object.keys(rule.extract ?? {})) {
|
|
29735
|
+
existing.add(key);
|
|
29736
|
+
}
|
|
29737
|
+
fieldsByType.set(typeName, existing);
|
|
29738
|
+
}
|
|
29739
|
+
}
|
|
29740
|
+
return fieldsByType;
|
|
29741
|
+
}
|
|
29742
|
+
function validateEventPublishers(connections, customTypeFields) {
|
|
29743
|
+
if (connections.eventPublishers === void 0) {
|
|
29744
|
+
return [];
|
|
29745
|
+
}
|
|
29746
|
+
return connections.eventPublishers.flatMap((publisher, index) => {
|
|
29747
|
+
const extractedFields = customTypeFields.get(publisher.fromType);
|
|
29748
|
+
if (extractedFields === void 0) {
|
|
29749
|
+
return [
|
|
29750
|
+
{
|
|
29751
|
+
path: `/connections/eventPublishers/${index}/fromType`,
|
|
29752
|
+
message: `"${publisher.fromType}" is not defined as a customType in any module. Add a customType named "${publisher.fromType}" to at least one module.`
|
|
29753
|
+
}
|
|
29754
|
+
];
|
|
29755
|
+
}
|
|
29756
|
+
if (!extractedFields.has(publisher.metadataKey)) {
|
|
29757
|
+
return [
|
|
29758
|
+
{
|
|
29759
|
+
path: `/connections/eventPublishers/${index}/fromType`,
|
|
29760
|
+
message: `customType "${publisher.fromType}" does not extract "${publisher.metadataKey}". Add extract["${publisher.metadataKey}"] to that custom type.`
|
|
29761
|
+
}
|
|
29762
|
+
];
|
|
29763
|
+
}
|
|
29764
|
+
return [];
|
|
29765
|
+
});
|
|
29766
|
+
}
|
|
29767
|
+
function validateConnectionsConfig(config2) {
|
|
29768
|
+
if (config2.connections === void 0) {
|
|
29769
|
+
return [];
|
|
29770
|
+
}
|
|
29771
|
+
const customTypeFields = collectCustomTypeExtractedFields(config2);
|
|
29772
|
+
return validateEventPublishers(config2.connections, customTypeFields);
|
|
29773
|
+
}
|
|
29687
29774
|
function validateExtractionConfigSchema(data) {
|
|
29688
29775
|
const schemaValid = validate2(data) === true;
|
|
29689
29776
|
if (!schemaValid) {
|
|
@@ -29701,7 +29788,7 @@ function validateExtractionConfig(data) {
|
|
|
29701
29788
|
if (!isValidExtractionConfig(data)) {
|
|
29702
29789
|
return validateExtractionConfigSchema(data);
|
|
29703
29790
|
}
|
|
29704
|
-
const semanticErrors = validateAllExtractionRules(data);
|
|
29791
|
+
const semanticErrors = [...validateAllExtractionRules(data), ...validateConnectionsConfig(data)];
|
|
29705
29792
|
if (semanticErrors.length > 0) {
|
|
29706
29793
|
return {
|
|
29707
29794
|
valid: false,
|
|
@@ -29717,10 +29804,10 @@ function formatValidationErrors2(errors) {
|
|
|
29717
29804
|
return formatValidationErrorsInternal2(errors);
|
|
29718
29805
|
}
|
|
29719
29806
|
function parseExtractionConfig(data) {
|
|
29720
|
-
|
|
29807
|
+
const result = validateExtractionConfig(data);
|
|
29808
|
+
if (result.valid && isValidExtractionConfig(data)) {
|
|
29721
29809
|
return data;
|
|
29722
29810
|
}
|
|
29723
|
-
const result = validateExtractionConfig(data);
|
|
29724
29811
|
throw new ExtractionConfigValidationError(result.errors);
|
|
29725
29812
|
}
|
|
29726
29813
|
|
|
@@ -30073,7 +30160,8 @@ var ExtractionProject = class {
|
|
|
30073
30160
|
}
|
|
30074
30161
|
const crossResult = detectCrossModuleConnections(enrichedComponents, {
|
|
30075
30162
|
allowIncomplete,
|
|
30076
|
-
repository: this.repositoryName
|
|
30163
|
+
repository: this.repositoryName,
|
|
30164
|
+
eventPublishers: this.resolvedConfig.connections?.eventPublishers
|
|
30077
30165
|
});
|
|
30078
30166
|
links.push(...crossResult.links);
|
|
30079
30167
|
timings.push({
|
|
@@ -30379,7 +30467,6 @@ ${formatValidationErrors2(validationResult.errors)}`
|
|
|
30379
30467
|
domainOp: parsed.domainOp ?? NOT_USED,
|
|
30380
30468
|
event: parsed.event ?? NOT_USED,
|
|
30381
30469
|
eventHandler: parsed.eventHandler ?? NOT_USED,
|
|
30382
|
-
eventPublisher: parsed.eventPublisher ?? NOT_USED,
|
|
30383
30470
|
ui: parsed.ui ?? NOT_USED
|
|
30384
30471
|
};
|
|
30385
30472
|
}
|
|
@@ -31202,7 +31289,6 @@ export {
|
|
|
31202
31289
|
/* istanbul ignore else -- @preserve: false branch is unreachable; FindTarget is exhaustive */
|
|
31203
31290
|
/* istanbul ignore next -- @preserve: unreachable with valid FindTarget type; defensive fallback */
|
|
31204
31291
|
/* v8 ignore next -- @preserve: getExtends() !== undefined guarantees getBaseClass() returns a value */
|
|
31205
|
-
/* istanbul ignore next -- @preserve: only fromProperty reaches here; defensive guard */
|
|
31206
31292
|
/* istanbul ignore next -- @preserve: catch always receives Error instances from ExtractionError */
|
|
31207
31293
|
/* v8 ignore start -- @preserve: default executor delegates to execFileSync; tested via CLI integration */
|
|
31208
31294
|
/* v8 ignore next -- @preserve: defensive optional chain; property existence guaranteed by hasOwn check above */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@living-architecture/riviere-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"glob": "^11.0.2",
|
|
33
33
|
"ts-morph": "^24.0.0",
|
|
34
34
|
"yaml": "^2.7.0",
|
|
35
|
-
"@living-architecture/riviere-builder": "0.7.
|
|
36
|
-
"@living-architecture/riviere-extract-ts": "0.4.
|
|
37
|
-
"@living-architecture/riviere-
|
|
38
|
-
"@living-architecture/riviere-schema": "0.6.
|
|
39
|
-
"@living-architecture/riviere-
|
|
35
|
+
"@living-architecture/riviere-builder": "0.7.4",
|
|
36
|
+
"@living-architecture/riviere-extract-ts": "0.4.4",
|
|
37
|
+
"@living-architecture/riviere-query": "0.6.4",
|
|
38
|
+
"@living-architecture/riviere-schema": "0.6.4",
|
|
39
|
+
"@living-architecture/riviere-extract-config": "0.5.4"
|
|
40
40
|
}
|
|
41
41
|
}
|