@hexabot-ai/api 3.2.2-alpha.10 → 3.2.2-alpha.12
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/actions/actions.service.d.ts +1 -0
- package/dist/actions/actions.service.js +19 -1
- package/dist/actions/actions.service.js.map +1 -1
- package/dist/app.module.js +2 -0
- package/dist/app.module.js.map +1 -1
- package/dist/extensions/actions/ai/mcp.binding.js +2 -0
- package/dist/extensions/actions/ai/mcp.binding.js.map +1 -1
- package/dist/extensions/actions/ai/memory.binding.js +2 -0
- package/dist/extensions/actions/ai/memory.binding.js.map +1 -1
- package/dist/extensions/actions/ai/retrieve-content-rag.action.js +2 -0
- package/dist/extensions/actions/ai/retrieve-content-rag.action.js.map +1 -1
- package/dist/extensions/actions/messaging/list.action.d.ts +2 -2
- package/dist/extensions/actions/messaging/list.action.js +7 -0
- package/dist/extensions/actions/messaging/list.action.js.map +1 -1
- package/dist/extensions/actions/subscriber/update-labels.action.js +3 -0
- package/dist/extensions/actions/subscriber/update-labels.action.js.map +1 -1
- package/dist/extensions/actions/workflow/call-workflow.action.d.ts +19 -0
- package/dist/extensions/actions/workflow/call-workflow.action.js +83 -0
- package/dist/extensions/actions/workflow/call-workflow.action.js.map +1 -0
- package/dist/extensions/actions/workflow/i18n/en.translations.json +9 -0
- package/dist/extensions/actions/workflow/i18n/fr.translations.json +9 -0
- package/dist/extensions/index.d.ts +1 -0
- package/dist/extensions/index.js +1 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/tools/hexabot-mcp.tools.d.ts +58 -0
- package/dist/static/assets/{browser-ponyfill-DN-Mu1Dr.js → browser-ponyfill-jlQAUd0m.js} +1 -1
- package/dist/static/assets/{cssMode-BCWxI_Ux.js → cssMode-CmMO_Mso.js} +1 -1
- package/dist/static/assets/{freemarker2-CFvevPey.js → freemarker2-DcQVPFyh.js} +1 -1
- package/dist/static/assets/{handlebars-BCStA9Eg.js → handlebars-DcnzpFQC.js} +1 -1
- package/dist/static/assets/{html-DkIwCA7q.js → html-BFzOjuas.js} +1 -1
- package/dist/static/assets/{htmlMode-DHeMkUp8.js → htmlMode-C-vRCUKF.js} +1 -1
- package/dist/static/assets/{index-C6VeVxYx.js → index-BKczCDFq.js} +2103 -2103
- package/dist/static/assets/{javascript-DLPKJzLc.js → javascript-Cw6lfMAI.js} +1 -1
- package/dist/static/assets/{jsonMode-BUIDFK3O.js → jsonMode-5xhIbw7r.js} +1 -1
- package/dist/static/assets/{liquid-B0XmwdKh.js → liquid-DRY_tZKy.js} +1 -1
- package/dist/static/assets/{lspLanguageFeatures-Fcpw3Ev_.js → lspLanguageFeatures-g0jq7rI8.js} +1 -1
- package/dist/static/assets/{mdx-DmJKi-dU.js → mdx-Cj1GGNiS.js} +1 -1
- package/dist/static/assets/{python-B1WnWY4I.js → python-Cx_web_-.js} +1 -1
- package/dist/static/assets/{razor-CL2s-6qt.js → razor-Bf3Htwpg.js} +1 -1
- package/dist/static/assets/{tsMode-DSFhDcf0.js → tsMode-DcrJAKHJ.js} +1 -1
- package/dist/static/assets/{typescript-CmHv7Jwl.js → typescript-D_NLpP2s.js} +1 -1
- package/dist/static/assets/{xml-Cyy6zXDM.js → xml-DX7g-Nrp.js} +1 -1
- package/dist/static/assets/{yaml-D_D6TAHE.js → yaml-BO2WdsT4.js} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/static/locales/en/translation.json +7 -1
- package/dist/static/locales/fr/translation.json +8 -2
- package/dist/transfer/adapters/content-type-transfer.adapter.d.ts +14 -0
- package/dist/transfer/adapters/content-type-transfer.adapter.js +102 -0
- package/dist/transfer/adapters/content-type-transfer.adapter.js.map +1 -0
- package/dist/transfer/adapters/credential-transfer.adapter.d.ts +13 -0
- package/dist/transfer/adapters/credential-transfer.adapter.js +110 -0
- package/dist/transfer/adapters/credential-transfer.adapter.js.map +1 -0
- package/dist/transfer/adapters/label-transfer.adapter.d.ts +15 -0
- package/dist/transfer/adapters/label-transfer.adapter.js +189 -0
- package/dist/transfer/adapters/label-transfer.adapter.js.map +1 -0
- package/dist/transfer/adapters/mcp-server-transfer.adapter.d.ts +16 -0
- package/dist/transfer/adapters/mcp-server-transfer.adapter.js +169 -0
- package/dist/transfer/adapters/mcp-server-transfer.adapter.js.map +1 -0
- package/dist/transfer/adapters/memory-definition-transfer.adapter.d.ts +14 -0
- package/dist/transfer/adapters/memory-definition-transfer.adapter.js +111 -0
- package/dist/transfer/adapters/memory-definition-transfer.adapter.js.map +1 -0
- package/dist/transfer/index.d.ts +7 -0
- package/dist/transfer/index.js +24 -0
- package/dist/transfer/index.js.map +1 -0
- package/dist/transfer/workflow-transfer-adapter.registry.d.ts +27 -0
- package/dist/transfer/workflow-transfer-adapter.registry.js +164 -0
- package/dist/transfer/workflow-transfer-adapter.registry.js.map +1 -0
- package/dist/transfer/workflow-transfer-definition.service.d.ts +40 -0
- package/dist/transfer/workflow-transfer-definition.service.js +353 -0
- package/dist/transfer/workflow-transfer-definition.service.js.map +1 -0
- package/dist/transfer/workflow-transfer-resource-adapter.d.ts +33 -0
- package/dist/transfer/workflow-transfer-resource-adapter.js +81 -0
- package/dist/transfer/workflow-transfer-resource-adapter.js.map +1 -0
- package/dist/transfer/workflow-transfer.controller.d.ts +9 -0
- package/dist/transfer/workflow-transfer.controller.js +63 -0
- package/dist/transfer/workflow-transfer.controller.js.map +1 -0
- package/dist/transfer/workflow-transfer.module.d.ts +2 -0
- package/dist/transfer/workflow-transfer.module.js +47 -0
- package/dist/transfer/workflow-transfer.module.js.map +1 -0
- package/dist/transfer/workflow-transfer.service.d.ts +51 -0
- package/dist/transfer/workflow-transfer.service.js +509 -0
- package/dist/transfer/workflow-transfer.service.js.map +1 -0
- package/dist/transfer/workflow-transfer.types.d.ts +31 -0
- package/dist/transfer/workflow-transfer.types.js +35 -0
- package/dist/transfer/workflow-transfer.types.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/user/dto/user.dto.d.ts +1 -1
- package/dist/utils/test/fixtures/label-group.d.ts +1 -1
- package/dist/utils/test/fixtures/label.d.ts +1 -1
- package/dist/utils/test/fixtures/subscriber.d.ts +1 -1
- package/dist/utils/test/fixtures/workflow-run.js +4 -1
- package/dist/utils/test/fixtures/workflow-run.js.map +1 -1
- package/dist/workflow/contexts/workflow-runtime.context.d.ts +3 -1
- package/dist/workflow/contexts/workflow-runtime.context.js +5 -0
- package/dist/workflow/contexts/workflow-runtime.context.js.map +1 -1
- package/dist/workflow/controllers/workflow-run.controller.js +2 -0
- package/dist/workflow/controllers/workflow-run.controller.js.map +1 -1
- package/dist/workflow/dto/workflow-run.dto.d.ts +1 -0
- package/dist/workflow/dto/workflow-run.dto.js +11 -0
- package/dist/workflow/dto/workflow-run.dto.js.map +1 -1
- package/dist/workflow/entities/memory-record.entity.d.ts +2 -0
- package/dist/workflow/entities/workflow-run.entity.d.ts +62 -0
- package/dist/workflow/entities/workflow-run.entity.js +15 -1
- package/dist/workflow/entities/workflow-run.entity.js.map +1 -1
- package/dist/workflow/index.d.ts +7 -0
- package/dist/workflow/index.js +7 -0
- package/dist/workflow/index.js.map +1 -1
- package/dist/workflow/repositories/workflow-run.repository.js +7 -1
- package/dist/workflow/repositories/workflow-run.repository.js.map +1 -1
- package/dist/workflow/resource-refs.d.ts +17 -0
- package/dist/workflow/resource-refs.js +15 -0
- package/dist/workflow/resource-refs.js.map +1 -0
- package/dist/workflow/services/agentic.service.d.ts +7 -1
- package/dist/workflow/services/agentic.service.js +134 -16
- package/dist/workflow/services/agentic.service.js.map +1 -1
- package/dist/workflow/services/workflow-run.service.d.ts +3 -0
- package/dist/workflow/services/workflow-run.service.js +75 -3
- package/dist/workflow/services/workflow-run.service.js.map +1 -1
- package/dist/workflow/services/workflow-version.service.d.ts +2 -0
- package/dist/workflow/services/workflow-version.service.js +19 -0
- package/dist/workflow/services/workflow-version.service.js.map +1 -1
- package/dist/workflow/services/workflow.service.d.ts +3 -1
- package/dist/workflow/services/workflow.service.js +5 -0
- package/dist/workflow/services/workflow.service.js.map +1 -1
- package/dist/workflow/types.d.ts +31 -0
- package/dist/workflow/types.js +2 -1
- package/dist/workflow/types.js.map +1 -1
- package/dist/workflow/workflow.module.js +3 -0
- package/dist/workflow/workflow.module.js.map +1 -1
- package/package.json +4 -4
- package/src/actions/actions.service.ts +34 -4
- package/src/app.module.ts +2 -0
- package/src/extensions/actions/ai/mcp.binding.ts +2 -0
- package/src/extensions/actions/ai/memory.binding.ts +2 -0
- package/src/extensions/actions/ai/retrieve-content-rag.action.ts +2 -0
- package/src/extensions/actions/messaging/list.action.ts +7 -0
- package/src/extensions/actions/subscriber/update-labels.action.ts +3 -0
- package/src/extensions/actions/workflow/call-workflow.action.ts +112 -0
- package/src/extensions/actions/workflow/i18n/en.translations.json +9 -0
- package/src/extensions/actions/workflow/i18n/fr.translations.json +9 -0
- package/src/extensions/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/transfer/adapters/content-type-transfer.adapter.ts +154 -0
- package/src/transfer/adapters/credential-transfer.adapter.ts +158 -0
- package/src/transfer/adapters/label-transfer.adapter.ts +291 -0
- package/src/transfer/adapters/mcp-server-transfer.adapter.ts +255 -0
- package/src/transfer/adapters/memory-definition-transfer.adapter.ts +167 -0
- package/src/transfer/index.ts +19 -0
- package/src/transfer/workflow-transfer-adapter.registry.ts +250 -0
- package/src/transfer/workflow-transfer-definition.service.ts +587 -0
- package/src/transfer/workflow-transfer-resource-adapter.ts +132 -0
- package/src/transfer/workflow-transfer.controller.ts +86 -0
- package/src/transfer/workflow-transfer.module.ts +46 -0
- package/src/transfer/workflow-transfer.service.ts +858 -0
- package/src/transfer/workflow-transfer.types.ts +98 -0
- package/src/utils/test/fixtures/workflow-run.ts +4 -1
- package/src/workflow/contexts/workflow-runtime.context.ts +12 -1
- package/src/workflow/controllers/workflow-run.controller.ts +2 -0
- package/src/workflow/dto/workflow-run.dto.ts +10 -0
- package/src/workflow/entities/workflow-run.entity.ts +22 -1
- package/src/workflow/index.ts +14 -0
- package/src/workflow/repositories/workflow-run.repository.ts +7 -1
- package/src/workflow/resource-refs.ts +44 -0
- package/src/workflow/services/agentic.service.ts +256 -26
- package/src/workflow/services/workflow-run.service.ts +120 -7
- package/src/workflow/services/workflow-version.service.ts +33 -0
- package/src/workflow/services/workflow.service.ts +21 -1
- package/src/workflow/types.ts +52 -0
- package/src/workflow/workflow.module.ts +3 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Hexabot — Fair Core License (FCL-1.0-ALv2)
|
|
3
|
+
* Copyright (c) 2026 Hexastack.
|
|
4
|
+
* Full terms: see LICENSE.md.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
type WorkflowExportBundle,
|
|
11
|
+
type WorkflowExportBundleMemoryDefinition,
|
|
12
|
+
type WorkflowImportResourceResult,
|
|
13
|
+
} from '@hexabot-ai/types';
|
|
14
|
+
import { ConflictException, Injectable } from '@nestjs/common';
|
|
15
|
+
import { In } from 'typeorm';
|
|
16
|
+
|
|
17
|
+
import { MemoryDefinitionOrmEntity } from '@/workflow/entities/memory-definition.entity';
|
|
18
|
+
import { MemoryDefinitionService } from '@/workflow/services/memory-definition.service';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
WorkflowTransferAdapter,
|
|
22
|
+
WorkflowTransferExportContext,
|
|
23
|
+
WorkflowTransferImportContext,
|
|
24
|
+
WorkflowTransferResourceAdapter,
|
|
25
|
+
} from '../workflow-transfer-resource-adapter';
|
|
26
|
+
import {
|
|
27
|
+
assertFoundAll,
|
|
28
|
+
buildPostCreateEvent,
|
|
29
|
+
buildResourceResult,
|
|
30
|
+
uniqueResourceIds,
|
|
31
|
+
type WorkflowTransferImportAdapterResult,
|
|
32
|
+
} from '../workflow-transfer.types';
|
|
33
|
+
|
|
34
|
+
@WorkflowTransferAdapter()
|
|
35
|
+
@Injectable()
|
|
36
|
+
export class MemoryDefinitionTransferAdapter extends WorkflowTransferResourceAdapter {
|
|
37
|
+
override readonly kind = 'memoryDefinition';
|
|
38
|
+
|
|
39
|
+
override readonly resourceKeys = ['memoryDefinitions'];
|
|
40
|
+
|
|
41
|
+
constructor(
|
|
42
|
+
private readonly memoryDefinitionService: MemoryDefinitionService,
|
|
43
|
+
) {
|
|
44
|
+
super();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
override async buildExportResources(
|
|
48
|
+
ctx: WorkflowTransferExportContext,
|
|
49
|
+
): Promise<Record<string, WorkflowExportBundleMemoryDefinition[]>> {
|
|
50
|
+
return {
|
|
51
|
+
memoryDefinitions: await this.buildMemoryDefinitionExportResources(
|
|
52
|
+
ctx.getRefs(this.kind),
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private async buildMemoryDefinitionExportResources(
|
|
58
|
+
ids: string[],
|
|
59
|
+
): Promise<WorkflowExportBundleMemoryDefinition[]> {
|
|
60
|
+
const uniqueIds = uniqueResourceIds(ids);
|
|
61
|
+
if (uniqueIds.length === 0) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const definitions = await this.memoryDefinitionService.find({
|
|
66
|
+
where: { id: In(uniqueIds) },
|
|
67
|
+
});
|
|
68
|
+
assertFoundAll(
|
|
69
|
+
'memory definition',
|
|
70
|
+
uniqueIds,
|
|
71
|
+
definitions.map((definition) => definition.id),
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return definitions.map((definition) => ({
|
|
75
|
+
exportId: definition.id,
|
|
76
|
+
name: definition.name,
|
|
77
|
+
slug: definition.slug,
|
|
78
|
+
scope: definition.scope,
|
|
79
|
+
schema: definition.schema,
|
|
80
|
+
ttlSeconds: definition.ttlSeconds ?? null,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
override async importResources(
|
|
85
|
+
ctx: WorkflowTransferImportContext,
|
|
86
|
+
): Promise<WorkflowTransferImportAdapterResult> {
|
|
87
|
+
const definitions =
|
|
88
|
+
ctx.getResources<
|
|
89
|
+
WorkflowExportBundle['resources']['memoryDefinitions'][number]
|
|
90
|
+
>('memoryDefinitions');
|
|
91
|
+
const idMap: Record<string, string> = {};
|
|
92
|
+
const resources: WorkflowImportResourceResult[] = [];
|
|
93
|
+
const postCreateEvents: WorkflowTransferImportAdapterResult['postCreateEvents'] =
|
|
94
|
+
[];
|
|
95
|
+
|
|
96
|
+
for (const definition of definitions) {
|
|
97
|
+
const existing = await ctx.manager.findOne(MemoryDefinitionOrmEntity, {
|
|
98
|
+
where: { slug: definition.slug },
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (existing) {
|
|
102
|
+
if (!this.isEquivalentMemoryDefinition(existing, definition)) {
|
|
103
|
+
throw new ConflictException(
|
|
104
|
+
`Memory definition "${definition.slug}" already exists with different configuration`,
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
idMap[definition.exportId] = existing.id;
|
|
109
|
+
resources.push(
|
|
110
|
+
buildResourceResult({
|
|
111
|
+
kind: 'memoryDefinition',
|
|
112
|
+
exportId: definition.exportId,
|
|
113
|
+
localId: existing.id,
|
|
114
|
+
name: definition.name,
|
|
115
|
+
action: 'reused',
|
|
116
|
+
}),
|
|
117
|
+
);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const payload = {
|
|
122
|
+
name: definition.name,
|
|
123
|
+
slug: definition.slug,
|
|
124
|
+
scope: definition.scope,
|
|
125
|
+
schema: definition.schema,
|
|
126
|
+
ttlSeconds: definition.ttlSeconds ?? null,
|
|
127
|
+
};
|
|
128
|
+
const created = await ctx.manager.save(
|
|
129
|
+
MemoryDefinitionOrmEntity,
|
|
130
|
+
ctx.manager.create(MemoryDefinitionOrmEntity, payload),
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
idMap[definition.exportId] = created.id;
|
|
134
|
+
resources.push(
|
|
135
|
+
buildResourceResult({
|
|
136
|
+
kind: 'memoryDefinition',
|
|
137
|
+
exportId: definition.exportId,
|
|
138
|
+
localId: created.id,
|
|
139
|
+
name: definition.name,
|
|
140
|
+
action: 'created',
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
143
|
+
postCreateEvents.push(
|
|
144
|
+
buildPostCreateEvent('memoryDefinition', created, payload),
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
idMap,
|
|
150
|
+
resources,
|
|
151
|
+
warnings: [],
|
|
152
|
+
postCreateEvents,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private isEquivalentMemoryDefinition(
|
|
157
|
+
existing: MemoryDefinitionOrmEntity,
|
|
158
|
+
imported: WorkflowExportBundle['resources']['memoryDefinitions'][number],
|
|
159
|
+
): boolean {
|
|
160
|
+
return (
|
|
161
|
+
existing.name === imported.name &&
|
|
162
|
+
existing.scope === imported.scope &&
|
|
163
|
+
(existing.ttlSeconds ?? null) === (imported.ttlSeconds ?? null) &&
|
|
164
|
+
isDeepStrictEqual(existing.schema, imported.schema)
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Hexabot — Fair Core License (FCL-1.0-ALv2)
|
|
3
|
+
* Copyright (c) 2026 Hexastack.
|
|
4
|
+
* Full terms: see LICENSE.md.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from './workflow-transfer.module';
|
|
8
|
+
|
|
9
|
+
export * from './workflow-transfer.controller';
|
|
10
|
+
|
|
11
|
+
export * from './workflow-transfer-definition.service';
|
|
12
|
+
|
|
13
|
+
export * from './workflow-transfer-resource-adapter';
|
|
14
|
+
|
|
15
|
+
export * from './workflow-transfer-adapter.registry';
|
|
16
|
+
|
|
17
|
+
export * from './workflow-transfer.types';
|
|
18
|
+
|
|
19
|
+
export * from './workflow-transfer.service';
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Hexabot — Fair Core License (FCL-1.0-ALv2)
|
|
3
|
+
* Copyright (c) 2026 Hexastack.
|
|
4
|
+
* Full terms: see LICENSE.md.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { WORKFLOW_TRANSFER_RESOURCE_KIND_PATTERN } from '@hexabot-ai/types';
|
|
8
|
+
import { Injectable, OnModuleInit } from '@nestjs/common';
|
|
9
|
+
import { DiscoveryService } from '@nestjs/core';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
WORKFLOW_TRANSFER_ADAPTER_METADATA_KEY,
|
|
13
|
+
WorkflowTransferResourceAdapter,
|
|
14
|
+
} from './workflow-transfer-resource-adapter';
|
|
15
|
+
|
|
16
|
+
type DiscoveredProvider = {
|
|
17
|
+
instance?: unknown;
|
|
18
|
+
metatype?: unknown;
|
|
19
|
+
name?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type VisitState = 'visiting' | 'visited';
|
|
23
|
+
|
|
24
|
+
@Injectable()
|
|
25
|
+
export class WorkflowTransferAdapterRegistry implements OnModuleInit {
|
|
26
|
+
private initialized = false;
|
|
27
|
+
|
|
28
|
+
private adaptersInDependencyOrder: WorkflowTransferResourceAdapter[] = [];
|
|
29
|
+
|
|
30
|
+
private adaptersByKind = new Map<string, WorkflowTransferResourceAdapter>();
|
|
31
|
+
|
|
32
|
+
private adaptersByResourceKey = new Map<
|
|
33
|
+
string,
|
|
34
|
+
WorkflowTransferResourceAdapter
|
|
35
|
+
>();
|
|
36
|
+
|
|
37
|
+
constructor(private readonly discoveryService: DiscoveryService) {}
|
|
38
|
+
|
|
39
|
+
onModuleInit(): void {
|
|
40
|
+
this.ensureInitialized();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
listInDependencyOrder(): WorkflowTransferResourceAdapter[] {
|
|
44
|
+
this.ensureInitialized();
|
|
45
|
+
|
|
46
|
+
return [...this.adaptersInDependencyOrder];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
listInReverseDependencyOrder(): WorkflowTransferResourceAdapter[] {
|
|
50
|
+
return [...this.listInDependencyOrder()].reverse();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get(kind: string): WorkflowTransferResourceAdapter | undefined {
|
|
54
|
+
this.ensureInitialized();
|
|
55
|
+
|
|
56
|
+
return this.adaptersByKind.get(kind);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getByResourceKey(key: string): WorkflowTransferResourceAdapter | undefined {
|
|
60
|
+
this.ensureInitialized();
|
|
61
|
+
|
|
62
|
+
return this.adaptersByResourceKey.get(key);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
getResourceKeys(): string[] {
|
|
66
|
+
this.ensureInitialized();
|
|
67
|
+
|
|
68
|
+
return Array.from(this.adaptersByResourceKey.keys());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private ensureInitialized(): void {
|
|
72
|
+
if (this.initialized) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const adapters = this.discoverAdapters();
|
|
77
|
+
this.adaptersByKind = this.buildKindMap(adapters);
|
|
78
|
+
this.adaptersByResourceKey = this.buildResourceKeyMap(adapters);
|
|
79
|
+
this.assertDependenciesExist(adapters);
|
|
80
|
+
this.adaptersInDependencyOrder = this.sortInDependencyOrder(adapters);
|
|
81
|
+
this.initialized = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private discoverAdapters(): WorkflowTransferResourceAdapter[] {
|
|
85
|
+
return this.discoveryService
|
|
86
|
+
.getProviders()
|
|
87
|
+
.flatMap((provider: DiscoveredProvider) => {
|
|
88
|
+
if (!this.hasAdapterMetadata(provider)) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!this.isAdapterInstance(provider.instance)) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`Workflow transfer adapter provider ${
|
|
95
|
+
provider.name ?? 'unknown'
|
|
96
|
+
} is missing a valid adapter instance`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return [provider.instance];
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private hasAdapterMetadata(provider: DiscoveredProvider): boolean {
|
|
105
|
+
const metatype =
|
|
106
|
+
typeof provider.metatype === 'function' ? provider.metatype : null;
|
|
107
|
+
const instanceConstructor =
|
|
108
|
+
provider.instance && typeof provider.instance === 'object'
|
|
109
|
+
? provider.instance.constructor
|
|
110
|
+
: null;
|
|
111
|
+
|
|
112
|
+
return [metatype, instanceConstructor].some(
|
|
113
|
+
(target) =>
|
|
114
|
+
!!target &&
|
|
115
|
+
Reflect.getMetadata(WORKFLOW_TRANSFER_ADAPTER_METADATA_KEY, target) ===
|
|
116
|
+
true,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
private isAdapterInstance(
|
|
121
|
+
value: unknown,
|
|
122
|
+
): value is WorkflowTransferResourceAdapter {
|
|
123
|
+
return (
|
|
124
|
+
typeof value === 'object' &&
|
|
125
|
+
value !== null &&
|
|
126
|
+
'kind' in value &&
|
|
127
|
+
'resourceKeys' in value &&
|
|
128
|
+
'buildExportResources' in value &&
|
|
129
|
+
'importResources' in value
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private buildKindMap(
|
|
134
|
+
adapters: WorkflowTransferResourceAdapter[],
|
|
135
|
+
): Map<string, WorkflowTransferResourceAdapter> {
|
|
136
|
+
const adaptersByKind = new Map<string, WorkflowTransferResourceAdapter>();
|
|
137
|
+
|
|
138
|
+
for (const adapter of adapters) {
|
|
139
|
+
this.assertValidName(adapter.kind, 'kind');
|
|
140
|
+
if (adaptersByKind.has(adapter.kind)) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Duplicate workflow transfer adapter kind "${adapter.kind}"`,
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
adaptersByKind.set(adapter.kind, adapter);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return adaptersByKind;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private buildResourceKeyMap(
|
|
153
|
+
adapters: WorkflowTransferResourceAdapter[],
|
|
154
|
+
): Map<string, WorkflowTransferResourceAdapter> {
|
|
155
|
+
const adaptersByResourceKey = new Map<
|
|
156
|
+
string,
|
|
157
|
+
WorkflowTransferResourceAdapter
|
|
158
|
+
>();
|
|
159
|
+
|
|
160
|
+
for (const adapter of adapters) {
|
|
161
|
+
if (adapter.resourceKeys.length === 0) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`Workflow transfer adapter "${adapter.kind}" must declare at least one resource key`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
for (const resourceKey of adapter.resourceKeys) {
|
|
168
|
+
this.assertValidName(resourceKey, 'resource key');
|
|
169
|
+
if (adaptersByResourceKey.has(resourceKey)) {
|
|
170
|
+
throw new Error(
|
|
171
|
+
`Duplicate workflow transfer resource key "${resourceKey}"`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
adaptersByResourceKey.set(resourceKey, adapter);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return adaptersByResourceKey;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private assertDependenciesExist(
|
|
183
|
+
adapters: WorkflowTransferResourceAdapter[],
|
|
184
|
+
): void {
|
|
185
|
+
for (const adapter of adapters) {
|
|
186
|
+
for (const dependency of adapter.dependsOn) {
|
|
187
|
+
this.assertValidName(dependency, 'dependency');
|
|
188
|
+
if (!this.adaptersByKind.has(dependency)) {
|
|
189
|
+
throw new Error(
|
|
190
|
+
`Workflow transfer adapter "${adapter.kind}" depends on unknown adapter "${dependency}"`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private sortInDependencyOrder(
|
|
198
|
+
adapters: WorkflowTransferResourceAdapter[],
|
|
199
|
+
): WorkflowTransferResourceAdapter[] {
|
|
200
|
+
const ordered: WorkflowTransferResourceAdapter[] = [];
|
|
201
|
+
const stateByKind = new Map<string, VisitState>();
|
|
202
|
+
|
|
203
|
+
for (const adapter of adapters) {
|
|
204
|
+
this.visitAdapter(adapter, [], stateByKind, ordered);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return ordered;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private visitAdapter(
|
|
211
|
+
adapter: WorkflowTransferResourceAdapter,
|
|
212
|
+
path: string[],
|
|
213
|
+
stateByKind: Map<string, VisitState>,
|
|
214
|
+
ordered: WorkflowTransferResourceAdapter[],
|
|
215
|
+
): void {
|
|
216
|
+
const state = stateByKind.get(adapter.kind);
|
|
217
|
+
if (state === 'visited') {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (state === 'visiting') {
|
|
222
|
+
const cycleStart = path.indexOf(adapter.kind);
|
|
223
|
+
const cyclePath = [
|
|
224
|
+
...(cycleStart >= 0 ? path.slice(cycleStart) : path),
|
|
225
|
+
adapter.kind,
|
|
226
|
+
];
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Workflow transfer adapter dependency cycle: ${cyclePath.join(' -> ')}`,
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
stateByKind.set(adapter.kind, 'visiting');
|
|
233
|
+
for (const dependency of adapter.dependsOn) {
|
|
234
|
+
this.visitAdapter(
|
|
235
|
+
this.adaptersByKind.get(dependency)!,
|
|
236
|
+
[...path, adapter.kind],
|
|
237
|
+
stateByKind,
|
|
238
|
+
ordered,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
stateByKind.set(adapter.kind, 'visited');
|
|
242
|
+
ordered.push(adapter);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private assertValidName(value: string, label: string): void {
|
|
246
|
+
if (!WORKFLOW_TRANSFER_RESOURCE_KIND_PATTERN.test(value)) {
|
|
247
|
+
throw new Error(`Invalid workflow transfer adapter ${label} "${value}"`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|