@living-architecture/riviere-extract-ts 0.4.3 → 0.4.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/features/extraction/domain/component-extraction/extractor.d.ts.map +1 -1
- package/dist/features/extraction/domain/component-extraction/extractor.js +0 -1
- package/dist/features/extraction/domain/config-resolution/resolve-config.js +0 -2
- package/dist/features/extraction/domain/connection-detection/async-detection/async-detection-types.d.ts +10 -0
- package/dist/features/extraction/domain/connection-detection/async-detection/async-detection-types.d.ts.map +1 -0
- package/dist/features/extraction/domain/connection-detection/async-detection/async-detection-types.js +8 -0
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-event-publisher-connections.d.ts +7 -0
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-event-publisher-connections.d.ts.map +1 -0
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-event-publisher-connections.js +95 -0
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-subscribe-connections.d.ts +1 -5
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-subscribe-connections.d.ts.map +1 -1
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-subscribe-connections.js +4 -9
- package/dist/features/extraction/domain/connection-detection/detect-connections.d.ts +3 -1
- package/dist/features/extraction/domain/connection-detection/detect-connections.d.ts.map +1 -1
- package/dist/features/extraction/domain/connection-detection/detect-connections.js +11 -15
- package/dist/features/extraction/domain/value-extraction/enrich-components.d.ts.map +1 -1
- package/dist/features/extraction/domain/value-extraction/enrich-components.js +0 -2
- package/dist/test-fixtures.d.ts.map +1 -1
- package/dist/test-fixtures.js +0 -1
- package/package.json +3 -3
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-publish-connections.d.ts +0 -6
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-publish-connections.d.ts.map +0 -1
- package/dist/features/extraction/domain/connection-detection/async-detection/detect-publish-connections.js +0 -88
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../../../../src/features/extraction/domain/component-extraction/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,OAAO,EAEb,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EACV,wBAAwB,EAIzB,MAAM,6CAA6C,CAAA;AAGpD,iCAAiC;AACjC,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;AAEpE,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;CACf;
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../../../../src/features/extraction/domain/component-extraction/extractor.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,OAAO,EAEb,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EACV,wBAAwB,EAIzB,MAAM,6CAA6C,CAAA;AAGpD,iCAAiC;AACjC,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAA;AAEpE,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;CACf;AAWD,mCAAmC;AACnC,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,eAAe,EAAE,MAAM,EAAE,EACzB,MAAM,EAAE,wBAAwB,EAChC,WAAW,EAAE,WAAW,EACxB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,EAAE,CAIlB"}
|
|
@@ -20,7 +20,6 @@ function resolveModule(moduleConfig, loader) {
|
|
|
20
20
|
domainOp: requireRule(moduleConfig.domainOp, 'domainOp', moduleConfig.name),
|
|
21
21
|
event: requireRule(moduleConfig.event, 'event', moduleConfig.name),
|
|
22
22
|
eventHandler: requireRule(moduleConfig.eventHandler, 'eventHandler', moduleConfig.name),
|
|
23
|
-
eventPublisher: requireRule(moduleConfig.eventPublisher, 'eventPublisher', moduleConfig.name),
|
|
24
23
|
ui: requireRule(moduleConfig.ui, 'ui', moduleConfig.name),
|
|
25
24
|
...(moduleConfig.customTypes !== undefined && { customTypes: moduleConfig.customTypes }),
|
|
26
25
|
};
|
|
@@ -40,7 +39,6 @@ function resolveModuleWithExtends(moduleConfig, extendsSource, loader) {
|
|
|
40
39
|
domainOp: moduleConfig.domainOp ?? baseModule.domainOp,
|
|
41
40
|
event: moduleConfig.event ?? baseModule.event,
|
|
42
41
|
eventHandler: moduleConfig.eventHandler ?? baseModule.eventHandler,
|
|
43
|
-
eventPublisher: moduleConfig.eventPublisher ?? baseModule.eventPublisher,
|
|
44
42
|
ui: moduleConfig.ui ?? baseModule.ui,
|
|
45
43
|
...(mergedCustomTypes !== undefined && { customTypes: mergedCustomTypes }),
|
|
46
44
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SourceLocation } from '@living-architecture/riviere-schema';
|
|
2
|
+
import type { EnrichedComponent } from '../../value-extraction/enrich-components';
|
|
3
|
+
/** @riviere-role value-object */
|
|
4
|
+
export interface AsyncDetectionOptions {
|
|
5
|
+
strict: boolean;
|
|
6
|
+
repository: string;
|
|
7
|
+
}
|
|
8
|
+
/** @riviere-role domain-service */
|
|
9
|
+
export declare function toSourceLocation(component: EnrichedComponent, repository: string): SourceLocation;
|
|
10
|
+
//# sourceMappingURL=async-detection-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-detection-types.d.ts","sourceRoot":"","sources":["../../../../../../src/features/extraction/domain/connection-detection/async-detection/async-detection-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AACzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAEjF,iCAAiC;AACjC,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,mCAAmC;AACnC,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc,CAMjG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { EventPublisherConfig } from '@living-architecture/riviere-extract-config';
|
|
2
|
+
import type { EnrichedComponent } from '../../value-extraction/enrich-components';
|
|
3
|
+
import type { ExtractedLink } from '../extracted-link';
|
|
4
|
+
import type { AsyncDetectionOptions } from './async-detection-types';
|
|
5
|
+
/** @riviere-role domain-service */
|
|
6
|
+
export declare function detectEventPublisherConnections(components: readonly EnrichedComponent[], eventPublishers: readonly EventPublisherConfig[], options: AsyncDetectionOptions): ExtractedLink[];
|
|
7
|
+
//# sourceMappingURL=detect-event-publisher-connections.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-event-publisher-connections.d.ts","sourceRoot":"","sources":["../../../../../../src/features/extraction/domain/connection-detection/async-detection/detect-event-publisher-connections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAA;AAEvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAGpE,mCAAmC;AACnC,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,eAAe,EAAE,SAAS,oBAAoB,EAAE,EAChD,OAAO,EAAE,qBAAqB,GAC7B,aAAa,EAAE,CAgCjB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { EVENT_NAME_FIELD } from '@living-architecture/riviere-schema';
|
|
2
|
+
import { ConnectionDetectionError } from '../connection-detection-error';
|
|
3
|
+
import { componentIdentity } from '../call-graph/call-graph-types';
|
|
4
|
+
import { toSourceLocation } from './async-detection-types';
|
|
5
|
+
/** @riviere-role domain-service */
|
|
6
|
+
export function detectEventPublisherConnections(components, eventPublishers, options) {
|
|
7
|
+
if (eventPublishers.length === 0) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const events = components.filter((c) => c.type === 'event');
|
|
11
|
+
return eventPublishers.flatMap((publisherConfig) => {
|
|
12
|
+
const { fromType, metadataKey } = publisherConfig;
|
|
13
|
+
const publishers = components.filter((c) => c.type === fromType);
|
|
14
|
+
return publishers.flatMap((publisher) => {
|
|
15
|
+
const publishedEventType = publisher.metadata[metadataKey];
|
|
16
|
+
if (Array.isArray(publishedEventType)) {
|
|
17
|
+
const validTypes = publishedEventType.filter((t) => typeof t === 'string' && t.trim() !== '');
|
|
18
|
+
if (validTypes.length === 0) {
|
|
19
|
+
return [handleMissingMetadata(publisher, metadataKey, options)];
|
|
20
|
+
}
|
|
21
|
+
return validTypes.flatMap((t) => resolvePublishTarget(publisher, t, events, options));
|
|
22
|
+
}
|
|
23
|
+
if (typeof publishedEventType !== 'string' || publishedEventType.trim() === '') {
|
|
24
|
+
return [handleMissingMetadata(publisher, metadataKey, options)];
|
|
25
|
+
}
|
|
26
|
+
return resolvePublishTarget(publisher, publishedEventType, events, options);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function handleMissingMetadata(publisher, metadataKey, options) {
|
|
31
|
+
if (options.strict) {
|
|
32
|
+
throw new ConnectionDetectionError({
|
|
33
|
+
file: publisher.location.file,
|
|
34
|
+
line: publisher.location.line,
|
|
35
|
+
typeName: publisher.name,
|
|
36
|
+
reason: `published event type in "${metadataKey}" metadata is missing or invalid`,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
source: componentIdentity(publisher),
|
|
41
|
+
target: '_unresolved',
|
|
42
|
+
type: 'async',
|
|
43
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
44
|
+
_uncertain: `event publisher "${publisher.name}" is missing required "${metadataKey}" metadata`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function resolvePublishTarget(publisher, publishedEventType, events, options) {
|
|
48
|
+
const matchingEvents = events.filter((e) => e.metadata[EVENT_NAME_FIELD] === publishedEventType);
|
|
49
|
+
if (matchingEvents.length === 0) {
|
|
50
|
+
return [handleNoMatch(publisher, publishedEventType, options)];
|
|
51
|
+
}
|
|
52
|
+
if (matchingEvents.length > 1) {
|
|
53
|
+
return [handleAmbiguousMatch(publisher, publishedEventType, matchingEvents.length, options)];
|
|
54
|
+
}
|
|
55
|
+
return matchingEvents.map((event) => ({
|
|
56
|
+
source: componentIdentity(publisher),
|
|
57
|
+
target: componentIdentity(event),
|
|
58
|
+
type: 'async',
|
|
59
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
function handleAmbiguousMatch(publisher, publishedEventType, matchCount, options) {
|
|
63
|
+
if (options.strict) {
|
|
64
|
+
throw new ConnectionDetectionError({
|
|
65
|
+
file: publisher.location.file,
|
|
66
|
+
line: publisher.location.line,
|
|
67
|
+
typeName: publisher.name,
|
|
68
|
+
reason: `published event "${publishedEventType}" matches ${matchCount} Event components (ambiguous)`,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
source: componentIdentity(publisher),
|
|
73
|
+
target: '_unresolved',
|
|
74
|
+
type: 'async',
|
|
75
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
76
|
+
_uncertain: `ambiguous: ${matchCount} events match published event type: ${publishedEventType}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function handleNoMatch(publisher, publishedEventType, options) {
|
|
80
|
+
if (options.strict) {
|
|
81
|
+
throw new ConnectionDetectionError({
|
|
82
|
+
file: publisher.location.file,
|
|
83
|
+
line: publisher.location.line,
|
|
84
|
+
typeName: publisher.name,
|
|
85
|
+
reason: `published event "${publishedEventType}" does not match any Event component`,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
source: componentIdentity(publisher),
|
|
90
|
+
target: '_unresolved',
|
|
91
|
+
type: 'async',
|
|
92
|
+
sourceLocation: toSourceLocation(publisher, options.repository),
|
|
93
|
+
_uncertain: `no event found for published event type: ${publishedEventType}`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import type { EnrichedComponent } from '../../value-extraction/enrich-components';
|
|
2
2
|
import type { ExtractedLink } from '../extracted-link';
|
|
3
|
-
|
|
4
|
-
export interface AsyncDetectionOptions {
|
|
5
|
-
strict: boolean;
|
|
6
|
-
repository: string;
|
|
7
|
-
}
|
|
3
|
+
import type { AsyncDetectionOptions } from './async-detection-types';
|
|
8
4
|
/** @riviere-role domain-service */
|
|
9
5
|
export declare function detectSubscribeConnections(components: readonly EnrichedComponent[], options: AsyncDetectionOptions): ExtractedLink[];
|
|
10
6
|
//# sourceMappingURL=detect-subscribe-connections.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-subscribe-connections.d.ts","sourceRoot":"","sources":["../../../../../../src/features/extraction/domain/connection-detection/async-detection/detect-subscribe-connections.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"detect-subscribe-connections.d.ts","sourceRoot":"","sources":["../../../../../../src/features/extraction/domain/connection-detection/async-detection/detect-subscribe-connections.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAGpE,mCAAmC;AACnC,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,OAAO,EAAE,qBAAqB,GAC7B,aAAa,EAAE,CAUjB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { EVENT_NAME_FIELD, SUBSCRIBED_EVENTS_FIELD } from '@living-architecture/riviere-schema';
|
|
1
2
|
import { ConnectionDetectionError } from '../connection-detection-error';
|
|
2
3
|
import { componentIdentity } from '../call-graph/call-graph-types';
|
|
4
|
+
import { toSourceLocation } from './async-detection-types';
|
|
3
5
|
/** @riviere-role domain-service */
|
|
4
6
|
export function detectSubscribeConnections(components, options) {
|
|
5
7
|
const eventHandlers = components.filter((c) => c.type === 'eventHandler');
|
|
@@ -7,15 +9,8 @@ export function detectSubscribeConnections(components, options) {
|
|
|
7
9
|
const repository = options.repository;
|
|
8
10
|
return eventHandlers.flatMap((handler) => getSubscribedEvents(handler).flatMap((eventName) => resolveSubscription(handler, eventName, events, options, repository)));
|
|
9
11
|
}
|
|
10
|
-
function toSourceLocation(component, repository) {
|
|
11
|
-
return {
|
|
12
|
-
repository,
|
|
13
|
-
filePath: component.location.file,
|
|
14
|
-
lineNumber: component.location.line,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
12
|
function resolveSubscription(handler, eventName, events, options, repository) {
|
|
18
|
-
const matchingEvents = events.filter((e) => e.metadata[
|
|
13
|
+
const matchingEvents = events.filter((e) => e.metadata[EVENT_NAME_FIELD] === eventName);
|
|
19
14
|
if (matchingEvents.length === 0) {
|
|
20
15
|
return [handleNoMatch(handler, eventName, options, repository)];
|
|
21
16
|
}
|
|
@@ -64,7 +59,7 @@ function handleNoMatch(handler, eventName, options, repository) {
|
|
|
64
59
|
};
|
|
65
60
|
}
|
|
66
61
|
function getSubscribedEvents(handler) {
|
|
67
|
-
const raw = handler.metadata[
|
|
62
|
+
const raw = handler.metadata[SUBSCRIBED_EVENTS_FIELD];
|
|
68
63
|
if (!Array.isArray(raw)) {
|
|
69
64
|
return [];
|
|
70
65
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Project } from 'ts-morph';
|
|
2
|
-
import type { ConnectionPattern } from '@living-architecture/riviere-extract-config';
|
|
2
|
+
import type { ConnectionPattern, EventPublisherConfig } from '@living-architecture/riviere-extract-config';
|
|
3
3
|
import type { EnrichedComponent } from '../value-extraction/enrich-components';
|
|
4
4
|
import type { GlobMatcher } from '../component-extraction/extractor';
|
|
5
5
|
import type { ExtractedLink } from './extracted-link';
|
|
@@ -8,6 +8,7 @@ export interface ConnectionDetectionOptions {
|
|
|
8
8
|
allowIncomplete?: boolean;
|
|
9
9
|
moduleGlobs: string[];
|
|
10
10
|
patterns?: ConnectionPattern[];
|
|
11
|
+
eventPublishers?: EventPublisherConfig[];
|
|
11
12
|
repository: string;
|
|
12
13
|
}
|
|
13
14
|
/** @riviere-role value-object */
|
|
@@ -48,6 +49,7 @@ export declare function detectPerModuleConnections(project: Project, components:
|
|
|
48
49
|
/** @riviere-role value-object */
|
|
49
50
|
export interface CrossModuleConnectionOptions {
|
|
50
51
|
allowIncomplete?: boolean;
|
|
52
|
+
eventPublishers?: EventPublisherConfig[];
|
|
51
53
|
repository: string;
|
|
52
54
|
}
|
|
53
55
|
/** @riviere-role value-object */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-connections.d.ts","sourceRoot":"","sources":["../../../../../src/features/extraction/domain/connection-detection/detect-connections.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"detect-connections.d.ts","sourceRoot":"","sources":["../../../../../src/features/extraction/domain/connection-detection/detect-connections.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EACrB,MAAM,6CAA6C,CAAA;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;AACpE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAOrD,iCAAiC;AACjC,MAAM,WAAW,0BAA0B;IACzC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC9B,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACxC,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,iCAAiC;AACjC,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,OAAO,EAAE,iBAAiB,CAAA;CAC3B;AAaD,mCAAmC;AACnC,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAchF;AAED,iCAAiC;AACjC,MAAM,WAAW,0BAA0B;IACzC,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC9B,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,iCAAiC;AACjC,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,OAAO,EAAE,gBAAgB,CAAA;CAC1B;AAED,mCAAmC;AACnC,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,OAAO,EAAE,0BAA0B,EACnC,WAAW,EAAE,WAAW,GACvB,wBAAwB,CAqC1B;AAED,iCAAiC;AACjC,MAAM,WAAW,4BAA4B;IAC3C,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,eAAe,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACxC,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,iCAAiC;AACjC,MAAM,WAAW,kBAAkB;IAAE,gBAAgB,EAAE,MAAM,CAAA;CAAC;AAE9D,iCAAiC;AACjC,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,aAAa,EAAE,CAAA;IACtB,OAAO,EAAE,kBAAkB,CAAA;CAC5B;AAED,mCAAmC;AACnC,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,OAAO,EAAE,4BAA4B,GACpC,0BAA0B,CAqB5B;AA8BD,mCAAmC;AACnC,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,OAAO,EAAE,0BAA0B,EACnC,WAAW,EAAE,WAAW,GACvB,yBAAyB,CA2D3B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { performance } from 'node:perf_hooks';
|
|
2
2
|
import { ComponentIndex } from './component-index';
|
|
3
3
|
import { buildCallGraph } from './call-graph/build-call-graph';
|
|
4
|
-
import {
|
|
4
|
+
import { detectEventPublisherConnections } from './async-detection/detect-event-publisher-connections';
|
|
5
5
|
import { detectSubscribeConnections } from './async-detection/detect-subscribe-connections';
|
|
6
6
|
import { detectConfigurableConnections } from './configurable/detect-configurable-connections';
|
|
7
7
|
function computeFilteredFilePaths(project, moduleGlobs, globMatcher) {
|
|
@@ -56,15 +56,13 @@ export function detectPerModuleConnections(project, components, options, globMat
|
|
|
56
56
|
export function detectCrossModuleConnections(allComponents, options) {
|
|
57
57
|
const strict = options.allowIncomplete !== true;
|
|
58
58
|
const repository = options.repository;
|
|
59
|
-
const
|
|
60
|
-
const publishLinks = detectPublishConnections(allComponents, {
|
|
61
|
-
strict,
|
|
62
|
-
repository,
|
|
63
|
-
});
|
|
64
|
-
const subscribeLinks = detectSubscribeConnections(allComponents, {
|
|
59
|
+
const asyncOptions = {
|
|
65
60
|
strict,
|
|
66
61
|
repository,
|
|
67
|
-
}
|
|
62
|
+
};
|
|
63
|
+
const asyncStart = performance.now();
|
|
64
|
+
const publishLinks = detectEventPublisherConnections(allComponents, options.eventPublishers ?? [], asyncOptions);
|
|
65
|
+
const subscribeLinks = detectSubscribeConnections(allComponents, asyncOptions);
|
|
68
66
|
const asyncDetectionMs = performance.now() - asyncStart;
|
|
69
67
|
return {
|
|
70
68
|
links: [...publishLinks, ...subscribeLinks],
|
|
@@ -104,15 +102,13 @@ export function detectConnections(project, components, options, globMatcher) {
|
|
|
104
102
|
repository,
|
|
105
103
|
});
|
|
106
104
|
const callGraphMs = performance.now() - callGraphStart;
|
|
107
|
-
const
|
|
108
|
-
const publishLinks = detectPublishConnections(components, {
|
|
109
|
-
strict,
|
|
110
|
-
repository,
|
|
111
|
-
});
|
|
112
|
-
const subscribeLinks = detectSubscribeConnections(components, {
|
|
105
|
+
const asyncOptions = {
|
|
113
106
|
strict,
|
|
114
107
|
repository,
|
|
115
|
-
}
|
|
108
|
+
};
|
|
109
|
+
const asyncStart = performance.now();
|
|
110
|
+
const publishLinks = detectEventPublisherConnections(components, options.eventPublishers ?? [], asyncOptions);
|
|
111
|
+
const subscribeLinks = detectSubscribeConnections(components, asyncOptions);
|
|
116
112
|
const asyncDetectionMs = performance.now() - asyncStart;
|
|
117
113
|
const patterns = options.patterns ?? [];
|
|
118
114
|
const { configurableLinks, configurableMs } = runConfigurableDetection(project, patterns, components, componentIndex, strict, repository);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enrich-components.d.ts","sourceRoot":"","sources":["../../../../../src/features/extraction/domain/value-extraction/enrich-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAC2B,OAAO,EAC7C,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EACV,wBAAwB,EAKzB,MAAM,6CAA6C,CAAA;AACpD,OAAO,KAAK,EACV,cAAc,EAAE,WAAW,EAC5B,MAAM,mCAAmC,CAAA;AAa1C,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAA;AAEzD,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACvC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,cAAc,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,iBAAiB,EAAE,CAAA;IAC/B,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAC9B;
|
|
1
|
+
{"version":3,"file":"enrich-components.d.ts","sourceRoot":"","sources":["../../../../../src/features/extraction/domain/value-extraction/enrich-components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAC2B,OAAO,EAC7C,MAAM,UAAU,CAAA;AAEjB,OAAO,KAAK,EACV,wBAAwB,EAKzB,MAAM,6CAA6C,CAAA;AACpD,OAAO,KAAK,EACV,cAAc,EAAE,WAAW,EAC5B,MAAM,mCAAmC,CAAA;AAa1C,KAAK,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAA;AAEzD,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACvC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,iCAAiC;AACjC,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,cAAc,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED,iCAAiC;AACjC,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,iBAAiB,EAAE,CAAA;IAC/B,QAAQ,EAAE,iBAAiB,EAAE,CAAA;CAC9B;AAiRD,mCAAmC;AACnC,wBAAgB,gBAAgB,CAC9B,eAAe,EAAE,cAAc,EAAE,EACjC,MAAM,EAAE,wBAAwB,EAChC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,GAChB,gBAAgB,CAclB"}
|
|
@@ -15,7 +15,6 @@ function getBuiltInRule(module, componentType) {
|
|
|
15
15
|
domainOp: module.domainOp,
|
|
16
16
|
event: module.event,
|
|
17
17
|
eventHandler: module.eventHandler,
|
|
18
|
-
eventPublisher: module.eventPublisher,
|
|
19
18
|
ui: module.ui,
|
|
20
19
|
};
|
|
21
20
|
const rule = ruleMap[componentType];
|
|
@@ -31,7 +30,6 @@ function findDetectionRule(module, componentType) {
|
|
|
31
30
|
'domainOp',
|
|
32
31
|
'event',
|
|
33
32
|
'eventHandler',
|
|
34
|
-
'eventPublisher',
|
|
35
33
|
'ui',
|
|
36
34
|
];
|
|
37
35
|
if (builtInTypes.includes(componentType)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-fixtures.d.ts","sourceRoot":"","sources":["../src/test-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EAExB,aAAa,EACb,WAAW,EACX,aAAa,EACd,MAAM,6CAA6C,CAAA;
|
|
1
|
+
{"version":3,"file":"test-fixtures.d.ts","sourceRoot":"","sources":["../src/test-fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EAExB,aAAa,EACb,WAAW,EACX,aAAa,EACd,MAAM,6CAA6C,CAAA;AAmBpD,wBAAgB,oBAAoB,IAAI,wBAAwB,CAE/D;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,UAAU,SAAO,GAChB,wBAAwB,CAW1B;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,aAAa,EACnB,UAAU,SAAO,GAChB,wBAAwB,CAW1B;AAED,wBAAgB,yBAAyB,CACvC,UAAU,SAAW,EACrB,UAAU,SAAO,GAChB,wBAAwB,CAW1B"}
|
package/dist/test-fixtures.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@living-architecture/riviere-extract-ts",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"minimatch": "^10.0.1",
|
|
26
26
|
"ts-morph": "^24.0.0",
|
|
27
|
-
"@living-architecture/riviere-extract-config": "0.5.
|
|
28
|
-
"@living-architecture/riviere-schema": "0.6.
|
|
27
|
+
"@living-architecture/riviere-extract-config": "0.5.5",
|
|
28
|
+
"@living-architecture/riviere-schema": "0.6.5"
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { EnrichedComponent } from '../../value-extraction/enrich-components';
|
|
2
|
-
import type { ExtractedLink } from '../extracted-link';
|
|
3
|
-
import type { AsyncDetectionOptions } from './detect-subscribe-connections';
|
|
4
|
-
/** @riviere-role domain-service */
|
|
5
|
-
export declare function detectPublishConnections(components: readonly EnrichedComponent[], options: AsyncDetectionOptions): ExtractedLink[];
|
|
6
|
-
//# sourceMappingURL=detect-publish-connections.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"detect-publish-connections.d.ts","sourceRoot":"","sources":["../../../../../../src/features/extraction/domain/connection-detection/async-detection/detect-publish-connections.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAA;AAI3E,mCAAmC;AACnC,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,OAAO,EAAE,qBAAqB,GAC7B,aAAa,EAAE,CAmBjB"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { ConnectionDetectionError } from '../connection-detection-error';
|
|
2
|
-
import { componentIdentity } from '../call-graph/call-graph-types';
|
|
3
|
-
/** @riviere-role domain-service */
|
|
4
|
-
export function detectPublishConnections(components, options) {
|
|
5
|
-
const publishers = components.filter((c) => c.type === 'eventPublisher');
|
|
6
|
-
const events = components.filter((c) => c.type === 'event');
|
|
7
|
-
const repository = options.repository;
|
|
8
|
-
return publishers.flatMap((publisher) => {
|
|
9
|
-
const publishedEventType = publisher.metadata['publishedEventType'];
|
|
10
|
-
const sourceLocation = {
|
|
11
|
-
repository,
|
|
12
|
-
filePath: publisher.location.file,
|
|
13
|
-
lineNumber: publisher.location.line,
|
|
14
|
-
};
|
|
15
|
-
if (typeof publishedEventType !== 'string') {
|
|
16
|
-
return [handleMissingMetadata(publisher, options, sourceLocation)];
|
|
17
|
-
}
|
|
18
|
-
return resolvePublishTarget(publisher, publishedEventType, events, options, sourceLocation);
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
function handleMissingMetadata(publisher, options, sourceLocation) {
|
|
22
|
-
if (options.strict) {
|
|
23
|
-
throw new ConnectionDetectionError({
|
|
24
|
-
file: sourceLocation.filePath,
|
|
25
|
-
line: sourceLocation.lineNumber,
|
|
26
|
-
typeName: publisher.name,
|
|
27
|
-
reason: 'eventPublisher is missing required "publishedEventType" metadata',
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
source: componentIdentity(publisher),
|
|
32
|
-
target: '_unresolved',
|
|
33
|
-
type: 'async',
|
|
34
|
-
sourceLocation,
|
|
35
|
-
_uncertain: `eventPublisher "${publisher.name}" is missing required "publishedEventType" metadata`,
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function resolvePublishTarget(publisher, publishedEventType, events, options, sourceLocation) {
|
|
39
|
-
const matchingEvents = events.filter((e) => e.metadata['eventName'] === publishedEventType);
|
|
40
|
-
if (matchingEvents.length === 0) {
|
|
41
|
-
return [handleNoMatch(publisher, publishedEventType, options, sourceLocation)];
|
|
42
|
-
}
|
|
43
|
-
if (matchingEvents.length > 1) {
|
|
44
|
-
return [
|
|
45
|
-
handleAmbiguousMatch(publisher, publishedEventType, matchingEvents.length, options, sourceLocation),
|
|
46
|
-
];
|
|
47
|
-
}
|
|
48
|
-
return matchingEvents.map((event) => ({
|
|
49
|
-
source: componentIdentity(publisher),
|
|
50
|
-
target: componentIdentity(event),
|
|
51
|
-
type: 'async',
|
|
52
|
-
sourceLocation,
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
function handleAmbiguousMatch(publisher, publishedEventType, matchCount, options, sourceLocation) {
|
|
56
|
-
if (options.strict) {
|
|
57
|
-
throw new ConnectionDetectionError({
|
|
58
|
-
file: sourceLocation.filePath,
|
|
59
|
-
line: sourceLocation.lineNumber,
|
|
60
|
-
typeName: publisher.name,
|
|
61
|
-
reason: `publishedEventType "${publishedEventType}" matches ${matchCount} Event components (ambiguous)`,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
source: componentIdentity(publisher),
|
|
66
|
-
target: '_unresolved',
|
|
67
|
-
type: 'async',
|
|
68
|
-
sourceLocation,
|
|
69
|
-
_uncertain: `ambiguous: ${matchCount} events match publishedEventType: ${publishedEventType}`,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
function handleNoMatch(publisher, publishedEventType, options, sourceLocation) {
|
|
73
|
-
if (options.strict) {
|
|
74
|
-
throw new ConnectionDetectionError({
|
|
75
|
-
file: sourceLocation.filePath,
|
|
76
|
-
line: sourceLocation.lineNumber,
|
|
77
|
-
typeName: publisher.name,
|
|
78
|
-
reason: `publishedEventType "${publishedEventType}" does not match any Event component`,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
source: componentIdentity(publisher),
|
|
83
|
-
target: '_unresolved',
|
|
84
|
-
type: 'async',
|
|
85
|
-
sourceLocation,
|
|
86
|
-
_uncertain: `no event found for publishedEventType: ${publishedEventType}`,
|
|
87
|
-
};
|
|
88
|
-
}
|