@codemation/host 0.1.6 → 0.1.7
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/CHANGELOG.md +9 -0
- package/dist/{AppConfigFactory-BiFHnorf.d.ts → AppConfigFactory-BBEn2B-i.d.ts} +3 -3
- package/dist/{AppContainerFactory-BRU02PTm.js → AppContainerFactory-CeKsjo8L.js} +79 -19
- package/dist/AppContainerFactory-CeKsjo8L.js.map +1 -0
- package/dist/{CodemationConfig-DuGk7uN5.d.ts → CodemationConfig-9PkOBCh-.d.ts} +2 -2
- package/dist/{CodemationConfigNormalizer-BP2-0ZDE.d.ts → CodemationConfigNormalizer-DIc-LYqW.d.ts} +2 -2
- package/dist/{CodemationConsumerConfigLoader-D5CSz3TQ.d.ts → CodemationConsumerConfigLoader-CeW4bnOg.d.ts} +3 -2
- package/dist/{CodemationConsumerConfigLoader-C_ISRrpI.js → CodemationConsumerConfigLoader-D6LFSlp5.js} +20 -7
- package/dist/CodemationConsumerConfigLoader-D6LFSlp5.js.map +1 -0
- package/dist/{CodemationPluginListMerger-DFzGgfyI.d.ts → CodemationPluginListMerger-Cv7CaM5_.d.ts} +5 -5
- package/dist/{CredentialServices-Bhejvys-.d.ts → CredentialServices-Dp_jXTJo.d.ts} +3 -3
- package/dist/{PublicFrontendBootstrapFactory-CSgWyTra.d.ts → PublicFrontendBootstrapFactory-SQVHMxLg.d.ts} +5 -2
- package/dist/consumer.d.ts +4 -4
- package/dist/consumer.js +1 -1
- package/dist/credentials.d.ts +3 -3
- package/dist/devServerSidecar.d.ts +1 -1
- package/dist/{index-BQaZZmOm.d.ts → index-CLRTQLAp.d.ts} +42 -60
- package/dist/index.d.ts +97 -12
- package/dist/index.js +3 -3
- package/dist/nextServer.d.ts +14 -7
- package/dist/nextServer.js +1 -1
- package/dist/{persistenceServer-fdldtXJH.d.ts → persistenceServer-Dv7fg_Jf.d.ts} +2 -2
- package/dist/persistenceServer.d.ts +5 -5
- package/dist/{server-Cpzpy1Ar.d.ts → server-C5oqDnZQ.d.ts} +5 -5
- package/dist/{server-ChTCEc6R.js → server-CioY8PP3.js} +4 -5
- package/dist/{server-ChTCEc6R.js.map → server-CioY8PP3.js.map} +1 -1
- package/dist/server.d.ts +8 -8
- package/dist/server.js +3 -3
- package/package.json +6 -5
- package/playwright.config.ts +10 -6
- package/src/application/contracts/WorkflowViewContracts.ts +3 -0
- package/src/application/mapping/WorkflowDefinitionMapper.ts +117 -19
- package/src/bootstrap/AppContainerFactory.ts +2 -0
- package/src/presentation/http/routeHandlers/CredentialHttpRouteHandler.ts +2 -1
- package/src/presentation/http/routeHandlers/WorkflowHttpRouteHandler.ts +4 -2
- package/src/presentation/server/CodemationConsumerConfigLoader.ts +28 -5
- package/src/presentation/server/CodemationPluginDiscovery.ts +4 -6
- package/dist/AppContainerFactory-BRU02PTm.js.map +0 -1
- package/dist/CodemationConsumerConfigLoader-C_ISRrpI.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { NodeDefinition, WorkflowActivationPolicy, WorkflowDefinition } from "@codemation/core";
|
|
2
2
|
import {
|
|
3
3
|
AgentConfigInspector,
|
|
4
4
|
AgentConnectionNodeCollector,
|
|
@@ -30,13 +30,14 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
mapSync(workflow: WorkflowDefinition): WorkflowDto {
|
|
33
|
+
const mapped = this.mapNodesAndEdges(workflow);
|
|
33
34
|
return {
|
|
34
35
|
id: workflow.id,
|
|
35
36
|
name: workflow.name,
|
|
36
37
|
active: this.workflowActivationPolicy.isActive(workflow.id),
|
|
37
38
|
hasWorkflowErrorHandler: this.policyUi.workflowHasErrorHandler(workflow),
|
|
38
|
-
nodes:
|
|
39
|
-
edges:
|
|
39
|
+
nodes: mapped.nodes,
|
|
40
|
+
edges: mapped.edges,
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -61,19 +62,54 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
61
62
|
return map;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
private
|
|
65
|
+
private mapNodesAndEdges(
|
|
66
|
+
workflow: WorkflowDefinition,
|
|
67
|
+
): Readonly<{ nodes: ReadonlyArray<WorkflowNodeDto>; edges: WorkflowDto["edges"] }> {
|
|
65
68
|
const connectionChildMeta = this.buildConnectionChildMeta(workflow);
|
|
66
69
|
const materializedConnectionNodeIds = new Set(connectionChildMeta.keys());
|
|
70
|
+
const nodesById = new Map(workflow.nodes.map((node) => [node.id, node] as const));
|
|
71
|
+
const agentConnectionDescriptors = this.buildAgentConnectionDescriptorIndex(workflow);
|
|
72
|
+
return {
|
|
73
|
+
nodes: this.toNodes({
|
|
74
|
+
workflow,
|
|
75
|
+
connectionChildMeta,
|
|
76
|
+
materializedConnectionNodeIds,
|
|
77
|
+
nodesById,
|
|
78
|
+
agentConnectionDescriptors,
|
|
79
|
+
}),
|
|
80
|
+
edges: this.toEdges({
|
|
81
|
+
workflow,
|
|
82
|
+
materializedConnectionNodeIds,
|
|
83
|
+
agentConnectionDescriptors,
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private toNodes(
|
|
89
|
+
args: Readonly<{
|
|
90
|
+
workflow: WorkflowDefinition;
|
|
91
|
+
connectionChildMeta: ReadonlyMap<string, Readonly<{ parentNodeId: string; connectionName: string }>>;
|
|
92
|
+
materializedConnectionNodeIds: ReadonlySet<string>;
|
|
93
|
+
nodesById: ReadonlyMap<string, WorkflowDefinition["nodes"][number]>;
|
|
94
|
+
agentConnectionDescriptors: Readonly<{
|
|
95
|
+
byAgentNodeId: ReadonlyMap<string, ReadonlyArray<AgentConnectionNodeDescriptor>>;
|
|
96
|
+
byChildNodeIdByAgentNodeId: ReadonlyMap<string, ReadonlyMap<string, AgentConnectionNodeDescriptor>>;
|
|
97
|
+
}>;
|
|
98
|
+
}>,
|
|
99
|
+
): ReadonlyArray<WorkflowNodeDto> {
|
|
100
|
+
const workflow = args.workflow;
|
|
101
|
+
const connectionChildMeta = args.connectionChildMeta;
|
|
102
|
+
const materializedConnectionNodeIds = args.materializedConnectionNodeIds;
|
|
103
|
+
const nodesById = args.nodesById;
|
|
104
|
+
const agentConnectionDescriptors = args.agentConnectionDescriptors;
|
|
67
105
|
const nodes: WorkflowNodeDto[] = [];
|
|
68
106
|
for (const node of workflow.nodes) {
|
|
69
107
|
const conn = connectionChildMeta.get(node.id);
|
|
70
108
|
if (conn) {
|
|
71
|
-
const parentNode =
|
|
109
|
+
const parentNode = nodesById.get(conn.parentNodeId);
|
|
72
110
|
let role: string = conn.connectionName === "llm" ? "languageModel" : "tool";
|
|
73
111
|
if (parentNode && AgentConfigInspector.isAgentNodeConfig(parentNode.config)) {
|
|
74
|
-
const descriptor =
|
|
75
|
-
(d) => d.nodeId === node.id,
|
|
76
|
-
);
|
|
112
|
+
const descriptor = agentConnectionDescriptors.byChildNodeIdByAgentNodeId.get(conn.parentNodeId)?.get(node.id);
|
|
77
113
|
if (descriptor) {
|
|
78
114
|
role = descriptor.role;
|
|
79
115
|
}
|
|
@@ -87,6 +123,7 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
87
123
|
icon: node.config?.icon,
|
|
88
124
|
retryPolicySummary: this.policyUi.nodeRetrySummary(node.config),
|
|
89
125
|
hasNodeErrorHandler: this.policyUi.nodeHasErrorHandler(node.config),
|
|
126
|
+
...this.nodePortFieldsFromConfig(node.config),
|
|
90
127
|
parentNodeId: conn.parentNodeId,
|
|
91
128
|
});
|
|
92
129
|
continue;
|
|
@@ -100,17 +137,32 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
100
137
|
icon: node.config?.icon,
|
|
101
138
|
retryPolicySummary: this.policyUi.nodeRetrySummary(node.config),
|
|
102
139
|
hasNodeErrorHandler: this.policyUi.nodeHasErrorHandler(node.config),
|
|
140
|
+
...this.nodePortFieldsFromConfig(node.config),
|
|
103
141
|
});
|
|
104
142
|
if (AgentConfigInspector.isAgentNodeConfig(node.config)) {
|
|
105
|
-
this.appendVirtualConnectionNodes(
|
|
143
|
+
this.appendVirtualConnectionNodes(
|
|
144
|
+
materializedConnectionNodeIds,
|
|
145
|
+
nodes,
|
|
146
|
+
agentConnectionDescriptors.byAgentNodeId.get(node.id) ?? [],
|
|
147
|
+
);
|
|
106
148
|
}
|
|
107
149
|
}
|
|
108
150
|
return nodes;
|
|
109
151
|
}
|
|
110
152
|
|
|
111
|
-
private toEdges(
|
|
112
|
-
|
|
113
|
-
|
|
153
|
+
private toEdges(
|
|
154
|
+
args: Readonly<{
|
|
155
|
+
workflow: WorkflowDefinition;
|
|
156
|
+
materializedConnectionNodeIds: ReadonlySet<string>;
|
|
157
|
+
agentConnectionDescriptors: Readonly<{
|
|
158
|
+
byAgentNodeId: ReadonlyMap<string, ReadonlyArray<AgentConnectionNodeDescriptor>>;
|
|
159
|
+
byChildNodeIdByAgentNodeId: ReadonlyMap<string, ReadonlyMap<string, AgentConnectionNodeDescriptor>>;
|
|
160
|
+
}>;
|
|
161
|
+
}>,
|
|
162
|
+
): WorkflowDto["edges"] {
|
|
163
|
+
const workflow = args.workflow;
|
|
164
|
+
const materializedConnectionNodeIds = args.materializedConnectionNodeIds;
|
|
165
|
+
const agentConnectionDescriptors = args.agentConnectionDescriptors;
|
|
114
166
|
const edges: WorkflowEdgeDto[] = [...workflow.edges];
|
|
115
167
|
const edgeKeys = new Set(edges.map((edge) => this.edgeKey(edge.from.nodeId, edge.to.nodeId, edge.to.input)));
|
|
116
168
|
this.appendMaterializedConnectionEdges(workflow, edgeKeys, edges);
|
|
@@ -118,7 +170,12 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
118
170
|
if (!AgentConfigInspector.isAgentNodeConfig(node.config)) {
|
|
119
171
|
continue;
|
|
120
172
|
}
|
|
121
|
-
this.appendVirtualConnectionEdges(
|
|
173
|
+
this.appendVirtualConnectionEdges(
|
|
174
|
+
materializedConnectionNodeIds,
|
|
175
|
+
edgeKeys,
|
|
176
|
+
edges,
|
|
177
|
+
agentConnectionDescriptors.byAgentNodeId.get(node.id) ?? [],
|
|
178
|
+
);
|
|
122
179
|
}
|
|
123
180
|
return edges;
|
|
124
181
|
}
|
|
@@ -143,13 +200,33 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
143
200
|
}
|
|
144
201
|
}
|
|
145
202
|
|
|
203
|
+
private buildAgentConnectionDescriptorIndex(workflow: WorkflowDefinition): Readonly<{
|
|
204
|
+
byAgentNodeId: ReadonlyMap<string, ReadonlyArray<AgentConnectionNodeDescriptor>>;
|
|
205
|
+
byChildNodeIdByAgentNodeId: ReadonlyMap<string, ReadonlyMap<string, AgentConnectionNodeDescriptor>>;
|
|
206
|
+
}> {
|
|
207
|
+
const byAgentNodeId = new Map<string, ReadonlyArray<AgentConnectionNodeDescriptor>>();
|
|
208
|
+
const byChildNodeIdByAgentNodeId = new Map<string, ReadonlyMap<string, AgentConnectionNodeDescriptor>>();
|
|
209
|
+
for (const node of workflow.nodes) {
|
|
210
|
+
if (!AgentConfigInspector.isAgentNodeConfig(node.config)) {
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const descriptors = AgentConnectionNodeCollector.collect(node.id, node.config);
|
|
214
|
+
byAgentNodeId.set(node.id, descriptors);
|
|
215
|
+
const byChildId = new Map<string, AgentConnectionNodeDescriptor>();
|
|
216
|
+
for (const descriptor of descriptors) {
|
|
217
|
+
byChildId.set(descriptor.nodeId, descriptor);
|
|
218
|
+
}
|
|
219
|
+
byChildNodeIdByAgentNodeId.set(node.id, byChildId);
|
|
220
|
+
}
|
|
221
|
+
return { byAgentNodeId, byChildNodeIdByAgentNodeId };
|
|
222
|
+
}
|
|
223
|
+
|
|
146
224
|
private appendVirtualConnectionNodes(
|
|
147
|
-
rootAgentNodeId: string,
|
|
148
|
-
agentConfig: AgentNodeConfig<any, any>,
|
|
149
225
|
materializedConnectionNodeIds: ReadonlySet<string>,
|
|
150
226
|
nodes: WorkflowNodeDto[],
|
|
227
|
+
descriptors: ReadonlyArray<AgentConnectionNodeDescriptor>,
|
|
151
228
|
): void {
|
|
152
|
-
for (const connectionNode of
|
|
229
|
+
for (const connectionNode of descriptors) {
|
|
153
230
|
if (materializedConnectionNodeIds.has(connectionNode.nodeId)) {
|
|
154
231
|
continue;
|
|
155
232
|
}
|
|
@@ -158,13 +235,12 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
158
235
|
}
|
|
159
236
|
|
|
160
237
|
private appendVirtualConnectionEdges(
|
|
161
|
-
rootAgentNodeId: string,
|
|
162
|
-
agentConfig: AgentNodeConfig<any, any>,
|
|
163
238
|
materializedConnectionNodeIds: ReadonlySet<string>,
|
|
164
239
|
edgeKeys: Set<string>,
|
|
165
240
|
edges: WorkflowEdgeDto[],
|
|
241
|
+
descriptors: ReadonlyArray<AgentConnectionNodeDescriptor>,
|
|
166
242
|
): void {
|
|
167
|
-
for (const connectionNode of
|
|
243
|
+
for (const connectionNode of descriptors) {
|
|
168
244
|
if (materializedConnectionNodeIds.has(connectionNode.nodeId)) {
|
|
169
245
|
continue;
|
|
170
246
|
}
|
|
@@ -196,6 +272,28 @@ export class WorkflowDefinitionMapper implements DataMapper<WorkflowDefinition,
|
|
|
196
272
|
};
|
|
197
273
|
}
|
|
198
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Omit optional port fields when undefined so persisted snapshot DTOs (which never serialize
|
|
277
|
+
* undefined keys) stay aligned with live workflow mapping.
|
|
278
|
+
*/
|
|
279
|
+
private nodePortFieldsFromConfig(
|
|
280
|
+
config: NodeDefinition["config"] | undefined,
|
|
281
|
+
): Pick<WorkflowNodeDto, "continueWhenEmptyOutput" | "declaredOutputPorts" | "declaredInputPorts"> {
|
|
282
|
+
if (!config || typeof config !== "object") {
|
|
283
|
+
return {};
|
|
284
|
+
}
|
|
285
|
+
const c = config as {
|
|
286
|
+
continueWhenEmptyOutput?: boolean;
|
|
287
|
+
declaredOutputPorts?: readonly string[];
|
|
288
|
+
declaredInputPorts?: readonly string[];
|
|
289
|
+
};
|
|
290
|
+
return {
|
|
291
|
+
...(c.continueWhenEmptyOutput !== undefined && { continueWhenEmptyOutput: c.continueWhenEmptyOutput }),
|
|
292
|
+
...(c.declaredOutputPorts !== undefined && { declaredOutputPorts: c.declaredOutputPorts }),
|
|
293
|
+
...(c.declaredInputPorts !== undefined && { declaredInputPorts: c.declaredInputPorts }),
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
199
297
|
private nodeTypeName(node: NodeDefinition): string {
|
|
200
298
|
const configToken = node.config?.type as Readonly<{ name?: unknown }> | undefined;
|
|
201
299
|
if (typeof configToken?.name === "string" && configToken.name) {
|
|
@@ -63,6 +63,7 @@ import {
|
|
|
63
63
|
GetRunStateQueryHandler,
|
|
64
64
|
GetWorkflowDebuggerOverlayQueryHandler,
|
|
65
65
|
GetWorkflowDetailQueryHandler,
|
|
66
|
+
GetWorkflowRunDetailQueryHandler,
|
|
66
67
|
GetWorkflowOverlayBinaryAttachmentQueryHandler,
|
|
67
68
|
GetWorkflowSummariesQueryHandler,
|
|
68
69
|
ListWorkflowRunsQueryHandler,
|
|
@@ -194,6 +195,7 @@ export class AppContainerFactory {
|
|
|
194
195
|
VerifyUserInviteQueryHandler,
|
|
195
196
|
GetRunBinaryAttachmentQueryHandler,
|
|
196
197
|
GetRunStateQueryHandler,
|
|
198
|
+
GetWorkflowRunDetailQueryHandler,
|
|
197
199
|
GetWorkflowDebuggerOverlayQueryHandler,
|
|
198
200
|
GetWorkflowDetailQueryHandler,
|
|
199
201
|
GetWorkflowOverlayBinaryAttachmentQueryHandler,
|
|
@@ -121,7 +121,8 @@ export class CredentialHttpRouteHandler {
|
|
|
121
121
|
|
|
122
122
|
async getWorkflowCredentialHealth(_: Request, params: ServerHttpRouteParams): Promise<Response> {
|
|
123
123
|
try {
|
|
124
|
-
|
|
124
|
+
const health = await this.queryBus.execute(new GetWorkflowCredentialHealthQuery(params.workflowId!));
|
|
125
|
+
return Response.json(health);
|
|
125
126
|
} catch (error) {
|
|
126
127
|
return ServerHttpErrorResponseFactory.fromUnknown(error);
|
|
127
128
|
}
|
|
@@ -66,7 +66,8 @@ export class WorkflowHttpRouteHandler {
|
|
|
66
66
|
|
|
67
67
|
async getWorkflowRuns(_: Request, params: ServerHttpRouteParams): Promise<Response> {
|
|
68
68
|
try {
|
|
69
|
-
|
|
69
|
+
const runs = await this.queryBus.execute(new ListWorkflowRunsQuery(params.workflowId!));
|
|
70
|
+
return Response.json(runs);
|
|
70
71
|
} catch (error) {
|
|
71
72
|
return ServerHttpErrorResponseFactory.fromUnknown(error);
|
|
72
73
|
}
|
|
@@ -74,7 +75,8 @@ export class WorkflowHttpRouteHandler {
|
|
|
74
75
|
|
|
75
76
|
async getWorkflowDebuggerOverlay(_: Request, params: ServerHttpRouteParams): Promise<Response> {
|
|
76
77
|
try {
|
|
77
|
-
|
|
78
|
+
const overlay = await this.queryBus.execute(new GetWorkflowDebuggerOverlayQuery(params.workflowId!));
|
|
79
|
+
return Response.json(overlay);
|
|
78
80
|
} catch (error) {
|
|
79
81
|
return ServerHttpErrorResponseFactory.fromUnknown(error);
|
|
80
82
|
}
|
|
@@ -20,6 +20,11 @@ export type CodemationConsumerConfigResolution = Readonly<{
|
|
|
20
20
|
workflowSources: ReadonlyArray<string>;
|
|
21
21
|
}>;
|
|
22
22
|
|
|
23
|
+
type ConsumerImportSession = Readonly<{
|
|
24
|
+
shouldResetImporter: boolean;
|
|
25
|
+
resetCacheKeys: Set<string>;
|
|
26
|
+
}>;
|
|
27
|
+
|
|
23
28
|
export class CodemationConsumerConfigLoader {
|
|
24
29
|
private static readonly importerRegistrationsByTsconfig = new Map<string, NamespacedUnregister>();
|
|
25
30
|
private static readonly importerNamespaceVersionByTsconfig = new Map<string, number>();
|
|
@@ -38,10 +43,13 @@ export class CodemationConsumerConfigLoader {
|
|
|
38
43
|
): Promise<CodemationConsumerConfigResolution> {
|
|
39
44
|
const loadStarted = performance.now();
|
|
40
45
|
let mark = loadStarted;
|
|
46
|
+
const importSession = this.createImportSession();
|
|
47
|
+
const phaseDurations = new Map<string, number>();
|
|
41
48
|
const phaseMs = (label: string): void => {
|
|
42
49
|
const now = performance.now();
|
|
43
50
|
const delta = now - mark;
|
|
44
51
|
mark = now;
|
|
52
|
+
phaseDurations.set(label, delta);
|
|
45
53
|
this.performanceDiagnosticsLogger.info(
|
|
46
54
|
`load.${label} +${delta.toFixed(1)}ms (cumulative ${(now - loadStarted).toFixed(1)}ms)`,
|
|
47
55
|
);
|
|
@@ -53,7 +61,7 @@ export class CodemationConsumerConfigLoader {
|
|
|
53
61
|
'Codemation config not found. Expected "codemation.config.ts" in the consumer project root or "src/".',
|
|
54
62
|
);
|
|
55
63
|
}
|
|
56
|
-
const moduleExports = await this.importModule(bootstrapSource);
|
|
64
|
+
const moduleExports = await this.importModule(bootstrapSource, importSession);
|
|
57
65
|
phaseMs("importConfigModule");
|
|
58
66
|
const rawConfig = this.configExportsResolver.resolveConfig(moduleExports);
|
|
59
67
|
if (!rawConfig) {
|
|
@@ -64,7 +72,7 @@ export class CodemationConsumerConfigLoader {
|
|
|
64
72
|
phaseMs("resolveWorkflowSources");
|
|
65
73
|
const workflows = this.mergeWorkflows(
|
|
66
74
|
config.workflows ?? [],
|
|
67
|
-
await this.loadDiscoveredWorkflows(args.consumerRoot, config, workflowSources),
|
|
75
|
+
await this.loadDiscoveredWorkflows(args.consumerRoot, config, workflowSources, importSession),
|
|
68
76
|
);
|
|
69
77
|
phaseMs("loadDiscoveredWorkflows");
|
|
70
78
|
const resolvedConfig: NormalizedCodemationConfig = {
|
|
@@ -125,6 +133,7 @@ export class CodemationConsumerConfigLoader {
|
|
|
125
133
|
consumerRoot: string,
|
|
126
134
|
config: CodemationConfig,
|
|
127
135
|
workflowSources: ReadonlyArray<string>,
|
|
136
|
+
importSession: ConsumerImportSession,
|
|
128
137
|
): Promise<ReadonlyArray<WorkflowDefinition>> {
|
|
129
138
|
const workflowDiscoveryDirectories = config.workflowDiscovery?.directories ?? [];
|
|
130
139
|
const workflowsById = new Map<string, WorkflowDefinition>();
|
|
@@ -136,7 +145,7 @@ export class CodemationConsumerConfigLoader {
|
|
|
136
145
|
workflowDiscoveryDirectories,
|
|
137
146
|
absoluteWorkflowModulePath: workflowSource,
|
|
138
147
|
}),
|
|
139
|
-
moduleExports: await this.importModule(workflowSource),
|
|
148
|
+
moduleExports: await this.importModule(workflowSource, importSession),
|
|
140
149
|
})),
|
|
141
150
|
);
|
|
142
151
|
for (const loadedWorkflowModule of loadedWorkflowModules) {
|
|
@@ -168,13 +177,20 @@ export class CodemationConsumerConfigLoader {
|
|
|
168
177
|
return [...workflowsById.values()];
|
|
169
178
|
}
|
|
170
179
|
|
|
171
|
-
private async importModule(
|
|
180
|
+
private async importModule(
|
|
181
|
+
modulePath: string,
|
|
182
|
+
importSession: ConsumerImportSession,
|
|
183
|
+
): Promise<Record<string, unknown>> {
|
|
172
184
|
if (this.shouldUseNativeRuntimeImport()) {
|
|
173
185
|
return await this.importModuleWithNativeRuntime(modulePath);
|
|
174
186
|
}
|
|
175
187
|
const tsconfigPath = await this.resolveTsconfigPath(modulePath);
|
|
176
|
-
|
|
188
|
+
const cacheKey = tsconfigPath || "default";
|
|
189
|
+
const shouldResetImporter = importSession.shouldResetImporter;
|
|
190
|
+
const didResetImporterForThisImport = shouldResetImporter && !importSession.resetCacheKeys.has(cacheKey);
|
|
191
|
+
if (didResetImporterForThisImport) {
|
|
177
192
|
await this.resetImporter(tsconfigPath);
|
|
193
|
+
importSession.resetCacheKeys.add(cacheKey);
|
|
178
194
|
}
|
|
179
195
|
const importSpecifier = await this.createImportSpecifier(modulePath);
|
|
180
196
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
@@ -278,6 +294,13 @@ export class CodemationConsumerConfigLoader {
|
|
|
278
294
|
return (process.env.CODEMATION_DEV_SERVER_TOKEN?.trim().length ?? 0) > 0;
|
|
279
295
|
}
|
|
280
296
|
|
|
297
|
+
private createImportSession(): ConsumerImportSession {
|
|
298
|
+
return {
|
|
299
|
+
resetCacheKeys: new Set<string>(),
|
|
300
|
+
shouldResetImporter: this.shouldResetImporterBeforeImport(),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
281
304
|
private isStoppedTransformServiceError(error: unknown): boolean {
|
|
282
305
|
return error instanceof Error && error.message.includes("The service is no longer running");
|
|
283
306
|
}
|
|
@@ -142,14 +142,12 @@ export class CodemationPluginDiscovery {
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
private resolvePluginEntry(discoveredPackage: CodemationDiscoveredPluginPackage): string {
|
|
145
|
-
|
|
145
|
+
const preferSource =
|
|
146
146
|
process.env.CODEMATION_PREFER_PLUGIN_SOURCE_ENTRY === "true" &&
|
|
147
147
|
typeof discoveredPackage.developmentEntry === "string" &&
|
|
148
|
-
discoveredPackage.developmentEntry.trim().length > 0
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
return discoveredPackage.pluginEntry;
|
|
148
|
+
discoveredPackage.developmentEntry.trim().length > 0;
|
|
149
|
+
const selectedEntry = preferSource ? discoveredPackage.developmentEntry : discoveredPackage.pluginEntry;
|
|
150
|
+
return selectedEntry;
|
|
153
151
|
}
|
|
154
152
|
|
|
155
153
|
private async resolveDevelopmentPluginEntry(packageRoot: string): Promise<string | undefined> {
|