@notmrabhi/flowforge 0.1.35 → 0.1.36
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/README.md +52 -0
- package/dist/canvas.d.ts +77 -0
- package/dist/core.d.ts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/nodeRegistry.d.ts +6 -0
- package/dist/templateRegistry.cjs +1 -1
- package/dist/templateRegistry.cjs.map +1 -1
- package/dist/templateRegistry.d.ts +49 -0
- package/dist/templateRegistry.js +63 -20
- package/dist/templateRegistry.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,6 +46,58 @@ export function Builder() {
|
|
|
46
46
|
}
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
## Loading templates from a backend
|
|
50
|
+
|
|
51
|
+
Instead of hardcoding `templateRegistry.register({...})` calls, fetch templates
|
|
52
|
+
from your API and bulk-register them. The package accepts the backend wire
|
|
53
|
+
shape directly via `registerFromApi`:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { templateRegistry } from '@miniorange/flowforge/templates';
|
|
57
|
+
import type { ApiWorkflowTemplate } from '@miniorange/flowforge/canvas';
|
|
58
|
+
|
|
59
|
+
async function loadTemplates() {
|
|
60
|
+
const res = await fetch('/api/v1/workflow-template');
|
|
61
|
+
const list: ApiWorkflowTemplate[] = await res.json();
|
|
62
|
+
templateRegistry.clear().registerFromApi(list);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Expected payload shape per row (the backend's persistence model + a `templateUI`
|
|
67
|
+
JSON column for UI fields):
|
|
68
|
+
|
|
69
|
+
```jsonc
|
|
70
|
+
{
|
|
71
|
+
"key": "END_USER_CREATION",
|
|
72
|
+
"name": "New User Registration",
|
|
73
|
+
"description": "…",
|
|
74
|
+
"state": "PUBLISHED",
|
|
75
|
+
"allowedTasks": ["USER_CREATION", "USER_GROUP_ASSIGNMENT", "USER_ROLE_ASSIGNMENT"],
|
|
76
|
+
"allowedSources": ["SIGNUP_FLOW", "ADMIN_CREATION_FLOW"],
|
|
77
|
+
"configuration": { /* runtime BPMN — ignored by the canvas */ },
|
|
78
|
+
"templateUI": {
|
|
79
|
+
"triggerCategory": "event",
|
|
80
|
+
"icon": "user-plus",
|
|
81
|
+
"tags": ["onboarding"],
|
|
82
|
+
"category": "User Lifecycle",
|
|
83
|
+
"author": "miniOrange",
|
|
84
|
+
"popularity": 100,
|
|
85
|
+
"source": "system",
|
|
86
|
+
"product": "IAM",
|
|
87
|
+
"maxTasks": 10,
|
|
88
|
+
"taskLabels": { "USER_GROUP_ASSIGNMENT": "Assign Groups" },
|
|
89
|
+
"skeletonState": {
|
|
90
|
+
"slots": [ /* CanvasSlot[] — pre-seeded canvas chain */ ],
|
|
91
|
+
"branches": {}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`registerFromApi` normalises `allowedTasks → availableTasks` automatically.
|
|
98
|
+
Bad rows (missing `key`) are skipped with a DEV-mode warning, so a single
|
|
99
|
+
malformed template doesn't blank the picker.
|
|
100
|
+
|
|
49
101
|
## Entry points
|
|
50
102
|
|
|
51
103
|
| Import | Contents |
|
package/dist/canvas.d.ts
CHANGED
|
@@ -24,6 +24,38 @@ export declare interface AddStepContext {
|
|
|
24
24
|
branch?: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Wire shape the backend `/api/v1/workflow-template` endpoint is expected
|
|
29
|
+
* to return. Top-level fields mirror the persistence model; everything
|
|
30
|
+
* UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
|
|
31
|
+
*/
|
|
32
|
+
export declare interface ApiWorkflowTemplate {
|
|
33
|
+
key: string;
|
|
34
|
+
name: string;
|
|
35
|
+
state?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
allowedTasks?: string[];
|
|
38
|
+
allowedSources?: string[];
|
|
39
|
+
configuration?: Record<string, unknown>;
|
|
40
|
+
templateUI?: Partial<Omit<WorkflowTemplate, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Wire shape the backend `/api/v1/workflow-template` endpoint is expected
|
|
45
|
+
* to return. Top-level fields mirror the persistence model; everything
|
|
46
|
+
* UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
|
|
47
|
+
*/
|
|
48
|
+
declare interface ApiWorkflowTemplate_2 {
|
|
49
|
+
key: string;
|
|
50
|
+
name: string;
|
|
51
|
+
state?: string;
|
|
52
|
+
description?: string;
|
|
53
|
+
allowedTasks?: string[];
|
|
54
|
+
allowedSources?: string[];
|
|
55
|
+
configuration?: Record<string, unknown>;
|
|
56
|
+
templateUI?: Partial<Omit<WorkflowTemplate_3, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
|
|
57
|
+
}
|
|
58
|
+
|
|
27
59
|
export declare const ApprovalNode: ({ id, data }: NodeProps) => JSX_2.Element;
|
|
28
60
|
|
|
29
61
|
export declare interface BpmnElement {
|
|
@@ -727,13 +759,40 @@ declare interface SubWorkflowPreviewDrawerProps {
|
|
|
727
759
|
|
|
728
760
|
declare class TemplateRegistry {
|
|
729
761
|
private templates;
|
|
762
|
+
/**
|
|
763
|
+
* Register a template. Normalises `allowedTasks` (the backend's name) →
|
|
764
|
+
* `availableTasks` (FlowForge's canonical name) so consumers can pass
|
|
765
|
+
* either without rewriting.
|
|
766
|
+
*/
|
|
730
767
|
register(template: WorkflowTemplate_3): this;
|
|
768
|
+
/**
|
|
769
|
+
* Register a list of templates fetched from `GET /api/v1/workflow-template`.
|
|
770
|
+
*
|
|
771
|
+
* The API shape is:
|
|
772
|
+
* {
|
|
773
|
+
* key, name, description, allowedTasks, allowedSources,
|
|
774
|
+
* configuration, // runtime BPMN — ignored by the canvas
|
|
775
|
+
* templateUI: { // ← UI bag, spread onto the template
|
|
776
|
+
* triggerCategory, icon, tags, category, author, popularity,
|
|
777
|
+
* source, product, taskLabels, maxTasks, skeletonState, …
|
|
778
|
+
* }
|
|
779
|
+
* }
|
|
780
|
+
*
|
|
781
|
+
* Anything in `templateUI` overrides the top-level shorthand where there's
|
|
782
|
+
* an overlap. Bad rows (missing `key`) are skipped with a DEV warning
|
|
783
|
+
* rather than throwing, so one broken template doesn't blank the picker.
|
|
784
|
+
*
|
|
785
|
+
* Returns `this` for chaining and the count of templates registered.
|
|
786
|
+
*/
|
|
787
|
+
registerFromApi(list: ApiWorkflowTemplate_2[]): this;
|
|
731
788
|
lookup(triggerKey: string): WorkflowTemplate_3 | undefined;
|
|
732
789
|
list(): WorkflowTemplate_3[];
|
|
733
790
|
listByCategory(category: string): WorkflowTemplate_3[];
|
|
734
791
|
listByTag(tag: string): WorkflowTemplate_3[];
|
|
735
792
|
search(query: string): WorkflowTemplate_3[];
|
|
736
793
|
categories(): string[];
|
|
794
|
+
/** Remove every template — useful before re-loading from backend. */
|
|
795
|
+
clear(): this;
|
|
737
796
|
}
|
|
738
797
|
|
|
739
798
|
export declare const TriggerNode: ({ data }: NodeProps) => JSX_2.Element;
|
|
@@ -776,7 +835,13 @@ export declare interface WorkflowTemplate {
|
|
|
776
835
|
description?: string;
|
|
777
836
|
icon?: ReactNode;
|
|
778
837
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
838
|
+
/**
|
|
839
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
840
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
841
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
842
|
+
*/
|
|
779
843
|
availableTasks?: string[];
|
|
844
|
+
allowedTasks?: string[];
|
|
780
845
|
maxTasks?: number;
|
|
781
846
|
taskLabels?: Record<string, string>;
|
|
782
847
|
fixedNodes?: FixedNode_3[];
|
|
@@ -802,7 +867,13 @@ declare interface WorkflowTemplate_2 {
|
|
|
802
867
|
description?: string;
|
|
803
868
|
icon?: ReactNode;
|
|
804
869
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
870
|
+
/**
|
|
871
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
872
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
873
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
874
|
+
*/
|
|
805
875
|
availableTasks?: string[];
|
|
876
|
+
allowedTasks?: string[];
|
|
806
877
|
maxTasks?: number;
|
|
807
878
|
taskLabels?: Record<string, string>;
|
|
808
879
|
fixedNodes?: FixedNode[];
|
|
@@ -828,7 +899,13 @@ declare interface WorkflowTemplate_3 {
|
|
|
828
899
|
description?: string;
|
|
829
900
|
icon?: ReactNode;
|
|
830
901
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
902
|
+
/**
|
|
903
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
904
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
905
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
906
|
+
*/
|
|
831
907
|
availableTasks?: string[];
|
|
908
|
+
allowedTasks?: string[];
|
|
832
909
|
maxTasks?: number;
|
|
833
910
|
taskLabels?: Record<string, string>;
|
|
834
911
|
fixedNodes?: FixedNode_2[];
|
package/dist/core.d.ts
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { AnySchema } from 'yup';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Wire shape the backend `/api/v1/workflow-template` endpoint is expected
|
|
6
|
+
* to return. Top-level fields mirror the persistence model; everything
|
|
7
|
+
* UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
|
|
8
|
+
*/
|
|
9
|
+
export declare interface ApiWorkflowTemplate {
|
|
10
|
+
key: string;
|
|
11
|
+
name: string;
|
|
12
|
+
state?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
allowedTasks?: string[];
|
|
15
|
+
allowedSources?: string[];
|
|
16
|
+
configuration?: Record<string, unknown>;
|
|
17
|
+
templateUI?: Partial<Omit<WorkflowTemplate, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
|
|
18
|
+
}
|
|
19
|
+
|
|
4
20
|
/**
|
|
5
21
|
* Base defaults shared by every node descriptor. A new node only has to specify
|
|
6
22
|
* what makes it different — these fill in the rest.
|
|
@@ -350,13 +366,40 @@ export declare interface SubWorkflowDescriptorOptions {
|
|
|
350
366
|
|
|
351
367
|
export declare class TemplateRegistry {
|
|
352
368
|
private templates;
|
|
369
|
+
/**
|
|
370
|
+
* Register a template. Normalises `allowedTasks` (the backend's name) →
|
|
371
|
+
* `availableTasks` (FlowForge's canonical name) so consumers can pass
|
|
372
|
+
* either without rewriting.
|
|
373
|
+
*/
|
|
353
374
|
register(template: WorkflowTemplate): this;
|
|
375
|
+
/**
|
|
376
|
+
* Register a list of templates fetched from `GET /api/v1/workflow-template`.
|
|
377
|
+
*
|
|
378
|
+
* The API shape is:
|
|
379
|
+
* {
|
|
380
|
+
* key, name, description, allowedTasks, allowedSources,
|
|
381
|
+
* configuration, // runtime BPMN — ignored by the canvas
|
|
382
|
+
* templateUI: { // ← UI bag, spread onto the template
|
|
383
|
+
* triggerCategory, icon, tags, category, author, popularity,
|
|
384
|
+
* source, product, taskLabels, maxTasks, skeletonState, …
|
|
385
|
+
* }
|
|
386
|
+
* }
|
|
387
|
+
*
|
|
388
|
+
* Anything in `templateUI` overrides the top-level shorthand where there's
|
|
389
|
+
* an overlap. Bad rows (missing `key`) are skipped with a DEV warning
|
|
390
|
+
* rather than throwing, so one broken template doesn't blank the picker.
|
|
391
|
+
*
|
|
392
|
+
* Returns `this` for chaining and the count of templates registered.
|
|
393
|
+
*/
|
|
394
|
+
registerFromApi(list: ApiWorkflowTemplate[]): this;
|
|
354
395
|
lookup(triggerKey: string): WorkflowTemplate | undefined;
|
|
355
396
|
list(): WorkflowTemplate[];
|
|
356
397
|
listByCategory(category: string): WorkflowTemplate[];
|
|
357
398
|
listByTag(tag: string): WorkflowTemplate[];
|
|
358
399
|
search(query: string): WorkflowTemplate[];
|
|
359
400
|
categories(): string[];
|
|
401
|
+
/** Remove every template — useful before re-loading from backend. */
|
|
402
|
+
clear(): this;
|
|
360
403
|
}
|
|
361
404
|
|
|
362
405
|
export declare const templateRegistry: TemplateRegistry;
|
|
@@ -376,7 +419,13 @@ export declare interface WorkflowTemplate {
|
|
|
376
419
|
description?: string;
|
|
377
420
|
icon?: ReactNode;
|
|
378
421
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
422
|
+
/**
|
|
423
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
424
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
425
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
426
|
+
*/
|
|
379
427
|
availableTasks?: string[];
|
|
428
|
+
allowedTasks?: string[];
|
|
380
429
|
maxTasks?: number;
|
|
381
430
|
taskLabels?: Record<string, string>;
|
|
382
431
|
fixedNodes?: FixedNode[];
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,22 @@ export declare interface AddStepContext {
|
|
|
41
41
|
branch?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Wire shape the backend `/api/v1/workflow-template` endpoint is expected
|
|
46
|
+
* to return. Top-level fields mirror the persistence model; everything
|
|
47
|
+
* UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
|
|
48
|
+
*/
|
|
49
|
+
export declare interface ApiWorkflowTemplate {
|
|
50
|
+
key: string;
|
|
51
|
+
name: string;
|
|
52
|
+
state?: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
allowedTasks?: string[];
|
|
55
|
+
allowedSources?: string[];
|
|
56
|
+
configuration?: Record<string, unknown>;
|
|
57
|
+
templateUI?: Partial<Omit<WorkflowTemplate, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
|
|
58
|
+
}
|
|
59
|
+
|
|
44
60
|
export declare const ApprovalNode: ({ id, data }: NodeProps) => JSX_2.Element;
|
|
45
61
|
|
|
46
62
|
/** True if the AST contains at least one non-text node. */
|
|
@@ -1290,13 +1306,40 @@ export declare interface TabsFieldDescriptor extends FieldDescriptor {
|
|
|
1290
1306
|
|
|
1291
1307
|
export declare class TemplateRegistry {
|
|
1292
1308
|
private templates;
|
|
1309
|
+
/**
|
|
1310
|
+
* Register a template. Normalises `allowedTasks` (the backend's name) →
|
|
1311
|
+
* `availableTasks` (FlowForge's canonical name) so consumers can pass
|
|
1312
|
+
* either without rewriting.
|
|
1313
|
+
*/
|
|
1293
1314
|
register(template: WorkflowTemplate): this;
|
|
1315
|
+
/**
|
|
1316
|
+
* Register a list of templates fetched from `GET /api/v1/workflow-template`.
|
|
1317
|
+
*
|
|
1318
|
+
* The API shape is:
|
|
1319
|
+
* {
|
|
1320
|
+
* key, name, description, allowedTasks, allowedSources,
|
|
1321
|
+
* configuration, // runtime BPMN — ignored by the canvas
|
|
1322
|
+
* templateUI: { // ← UI bag, spread onto the template
|
|
1323
|
+
* triggerCategory, icon, tags, category, author, popularity,
|
|
1324
|
+
* source, product, taskLabels, maxTasks, skeletonState, …
|
|
1325
|
+
* }
|
|
1326
|
+
* }
|
|
1327
|
+
*
|
|
1328
|
+
* Anything in `templateUI` overrides the top-level shorthand where there's
|
|
1329
|
+
* an overlap. Bad rows (missing `key`) are skipped with a DEV warning
|
|
1330
|
+
* rather than throwing, so one broken template doesn't blank the picker.
|
|
1331
|
+
*
|
|
1332
|
+
* Returns `this` for chaining and the count of templates registered.
|
|
1333
|
+
*/
|
|
1334
|
+
registerFromApi(list: ApiWorkflowTemplate[]): this;
|
|
1294
1335
|
lookup(triggerKey: string): WorkflowTemplate | undefined;
|
|
1295
1336
|
list(): WorkflowTemplate[];
|
|
1296
1337
|
listByCategory(category: string): WorkflowTemplate[];
|
|
1297
1338
|
listByTag(tag: string): WorkflowTemplate[];
|
|
1298
1339
|
search(query: string): WorkflowTemplate[];
|
|
1299
1340
|
categories(): string[];
|
|
1341
|
+
/** Remove every template — useful before re-loading from backend. */
|
|
1342
|
+
clear(): this;
|
|
1300
1343
|
}
|
|
1301
1344
|
|
|
1302
1345
|
export declare const templateRegistry: TemplateRegistry;
|
|
@@ -1468,7 +1511,13 @@ export declare interface WorkflowTemplate {
|
|
|
1468
1511
|
description?: string;
|
|
1469
1512
|
icon?: ReactNode;
|
|
1470
1513
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
1514
|
+
/**
|
|
1515
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
1516
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
1517
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
1518
|
+
*/
|
|
1471
1519
|
availableTasks?: string[];
|
|
1520
|
+
allowedTasks?: string[];
|
|
1472
1521
|
maxTasks?: number;
|
|
1473
1522
|
taskLabels?: Record<string, string>;
|
|
1474
1523
|
fixedNodes?: FixedNode[];
|
package/dist/nodeRegistry.d.ts
CHANGED
|
@@ -336,7 +336,13 @@ declare interface WorkflowTemplate {
|
|
|
336
336
|
description?: string;
|
|
337
337
|
icon?: ReactNode;
|
|
338
338
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
339
|
+
/**
|
|
340
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
341
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
342
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
343
|
+
*/
|
|
339
344
|
availableTasks?: string[];
|
|
345
|
+
allowedTasks?: string[];
|
|
340
346
|
maxTasks?: number;
|
|
341
347
|
taskLabels?: Record<string, string>;
|
|
342
348
|
fixedNodes?: FixedNode[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class l{constructor(){this.templates=new Map}register(t){const e={...t,availableTasks:t.availableTasks??t.allowedTasks};return this.templates.set(e.triggerKey,e),this}registerFromApi(t){for(const e of t??[])e!=null&&e.key&&this.register({triggerKey:e.key,label:e.name??e.key,description:e.description,availableTasks:e.allowedTasks,...e.templateUI??{}});return this}lookup(t){return this.templates.get(t)}list(){return[...this.templates.values()]}listByCategory(t){return this.list().filter(e=>e.category===t)}listByTag(t){return this.list().filter(e=>{var s;return(s=e.tags)==null?void 0:s.includes(t)})}search(t){const e=t.toLowerCase();return this.list().filter(s=>{var r,i,a;return s.label.toLowerCase().includes(e)||((r=s.description)==null?void 0:r.toLowerCase().includes(e))||((i=s.tags)==null?void 0:i.some(o=>o.toLowerCase().includes(e)))||((a=s.category)==null?void 0:a.toLowerCase().includes(e))})}categories(){const t=new Set;return this.list().forEach(e=>{e.category&&t.add(e.category)}),Array.from(t)}clear(){return this.templates.clear(),this}}const n=new l;exports.TemplateRegistry=l;exports.templateRegistry=n;
|
|
2
2
|
//# sourceMappingURL=templateRegistry.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templateRegistry.cjs","sources":["../src/templateRegistry/index.ts"],"sourcesContent":["import { WorkflowTemplate } from '../WorkflowCanvas/types';\
|
|
1
|
+
{"version":3,"file":"templateRegistry.cjs","sources":["../src/templateRegistry/index.ts"],"sourcesContent":["import type { WorkflowTemplate, ApiWorkflowTemplate } from '../WorkflowCanvas/types';\n\nexport class TemplateRegistry {\n private templates = new Map<string, WorkflowTemplate>();\n\n /**\n * Register a template. Normalises `allowedTasks` (the backend's name) →\n * `availableTasks` (FlowForge's canonical name) so consumers can pass\n * either without rewriting.\n */\n register(template: WorkflowTemplate): this {\n const normalised: WorkflowTemplate = {\n ...template,\n availableTasks: template.availableTasks ?? template.allowedTasks,\n };\n this.templates.set(normalised.triggerKey, normalised);\n return this;\n }\n\n /**\n * Register a list of templates fetched from `GET /api/v1/workflow-template`.\n *\n * The API shape is:\n * {\n * key, name, description, allowedTasks, allowedSources,\n * configuration, // runtime BPMN — ignored by the canvas\n * templateUI: { // ← UI bag, spread onto the template\n * triggerCategory, icon, tags, category, author, popularity,\n * source, product, taskLabels, maxTasks, skeletonState, …\n * }\n * }\n *\n * Anything in `templateUI` overrides the top-level shorthand where there's\n * an overlap. Bad rows (missing `key`) are skipped with a DEV warning\n * rather than throwing, so one broken template doesn't blank the picker.\n *\n * Returns `this` for chaining and the count of templates registered.\n */\n registerFromApi(list: ApiWorkflowTemplate[]): this {\n for (const t of list ?? []) {\n if (!t?.key) {\n if (import.meta.env?.DEV) {\n // eslint-disable-next-line no-console\n console.warn('[FlowForge] templateRegistry.registerFromApi: skipped row without `key`', t);\n }\n continue;\n }\n this.register({\n triggerKey: t.key,\n label: t.name ?? t.key,\n description: t.description,\n availableTasks: t.allowedTasks,\n ...(t.templateUI ?? {}),\n } as WorkflowTemplate);\n }\n return this;\n }\n\n lookup(triggerKey: string): WorkflowTemplate | undefined {\n return this.templates.get(triggerKey);\n }\n\n list(): WorkflowTemplate[] {\n return [...this.templates.values()];\n }\n\n listByCategory(category: string): WorkflowTemplate[] {\n return this.list().filter((t) => t.category === category);\n }\n\n listByTag(tag: string): WorkflowTemplate[] {\n return this.list().filter((t) => t.tags?.includes(tag));\n }\n\n search(query: string): WorkflowTemplate[] {\n const q = query.toLowerCase();\n return this.list().filter(\n (t) =>\n t.label.toLowerCase().includes(q) ||\n t.description?.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q)) ||\n t.category?.toLowerCase().includes(q),\n );\n }\n\n categories(): string[] {\n const cats = new Set<string>();\n this.list().forEach((t) => { if (t.category) cats.add(t.category); });\n return Array.from(cats);\n }\n\n /** Remove every template — useful before re-loading from backend. */\n clear(): this {\n this.templates.clear();\n return this;\n }\n}\n\nexport const templateRegistry = new TemplateRegistry();\nexport type { WorkflowTemplate, ApiWorkflowTemplate };\n"],"names":["TemplateRegistry","template","normalised","list","t","triggerKey","category","tag","_a","query","q","_b","_c","cats","templateRegistry"],"mappings":"gFAEO,MAAMA,CAAiB,CAAvB,aAAA,CACL,KAAQ,cAAgB,GAA8B,CAOtD,SAASC,EAAkC,CACzC,MAAMC,EAA+B,CACnC,GAAGD,EACH,eAAgBA,EAAS,gBAAkBA,EAAS,YAAA,EAEtD,YAAK,UAAU,IAAIC,EAAW,WAAYA,CAAU,EAC7C,IACT,CAqBA,gBAAgBC,EAAmC,CACjD,UAAWC,KAAKD,GAAQ,GACjBC,GAAA,MAAAA,EAAG,KAOR,KAAK,SAAS,CACZ,WAAYA,EAAE,IACd,MAAOA,EAAE,MAAQA,EAAE,IACnB,YAAaA,EAAE,YACf,eAAgBA,EAAE,aAClB,GAAIA,EAAE,YAAc,CAAA,CAAC,CACF,EAEvB,OAAO,IACT,CAEA,OAAOC,EAAkD,CACvD,OAAO,KAAK,UAAU,IAAIA,CAAU,CACtC,CAEA,MAA2B,CACzB,MAAO,CAAC,GAAG,KAAK,UAAU,QAAQ,CACpC,CAEA,eAAeC,EAAsC,CACnD,OAAO,KAAK,OAAO,OAAQF,GAAMA,EAAE,WAAaE,CAAQ,CAC1D,CAEA,UAAUC,EAAiC,CACzC,OAAO,KAAK,KAAA,EAAO,OAAQH,UAAM,OAAAI,EAAAJ,EAAE,OAAF,YAAAI,EAAQ,SAASD,GAAI,CACxD,CAEA,OAAOE,EAAmC,CACxC,MAAMC,EAAID,EAAM,YAAA,EAChB,OAAO,KAAK,OAAO,OAChBL,GAAA,WACC,OAAAA,EAAE,MAAM,cAAc,SAASM,CAAC,KAChCF,EAAAJ,EAAE,cAAF,YAAAI,EAAe,cAAc,SAASE,OACtCC,EAAAP,EAAE,OAAF,YAAAO,EAAQ,KAAMJ,GAAQA,EAAI,cAAc,SAASG,CAAC,OAClDE,EAAAR,EAAE,WAAF,YAAAQ,EAAY,cAAc,SAASF,IAAC,CAE1C,CAEA,YAAuB,CACrB,MAAMG,MAAW,IACjB,YAAK,KAAA,EAAO,QAAST,GAAM,CAAMA,EAAE,UAAUS,EAAK,IAAIT,EAAE,QAAQ,CAAG,CAAC,EAC7D,MAAM,KAAKS,CAAI,CACxB,CAGA,OAAc,CACZ,YAAK,UAAU,MAAA,EACR,IACT,CACF,CAEO,MAAMC,EAAmB,IAAId"}
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Wire shape the backend `/api/v1/workflow-template` endpoint is expected
|
|
5
|
+
* to return. Top-level fields mirror the persistence model; everything
|
|
6
|
+
* UI-related lives under `templateUI`. Use with `templateRegistry.registerFromApi(list)`.
|
|
7
|
+
*/
|
|
8
|
+
export declare interface ApiWorkflowTemplate {
|
|
9
|
+
key: string;
|
|
10
|
+
name: string;
|
|
11
|
+
state?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
allowedTasks?: string[];
|
|
14
|
+
allowedSources?: string[];
|
|
15
|
+
configuration?: Record<string, unknown>;
|
|
16
|
+
templateUI?: Partial<Omit<WorkflowTemplate, 'triggerKey' | 'label' | 'description' | 'availableTasks'>>;
|
|
17
|
+
}
|
|
18
|
+
|
|
3
19
|
declare type BranchChain = CanvasSlot[];
|
|
4
20
|
|
|
5
21
|
declare interface BranchMap {
|
|
@@ -38,13 +54,40 @@ declare type SlotKind = 'start' | 'end' | 'addTrigger' | 'triggerFixed' | 'userT
|
|
|
38
54
|
|
|
39
55
|
export declare class TemplateRegistry {
|
|
40
56
|
private templates;
|
|
57
|
+
/**
|
|
58
|
+
* Register a template. Normalises `allowedTasks` (the backend's name) →
|
|
59
|
+
* `availableTasks` (FlowForge's canonical name) so consumers can pass
|
|
60
|
+
* either without rewriting.
|
|
61
|
+
*/
|
|
41
62
|
register(template: WorkflowTemplate): this;
|
|
63
|
+
/**
|
|
64
|
+
* Register a list of templates fetched from `GET /api/v1/workflow-template`.
|
|
65
|
+
*
|
|
66
|
+
* The API shape is:
|
|
67
|
+
* {
|
|
68
|
+
* key, name, description, allowedTasks, allowedSources,
|
|
69
|
+
* configuration, // runtime BPMN — ignored by the canvas
|
|
70
|
+
* templateUI: { // ← UI bag, spread onto the template
|
|
71
|
+
* triggerCategory, icon, tags, category, author, popularity,
|
|
72
|
+
* source, product, taskLabels, maxTasks, skeletonState, …
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
*
|
|
76
|
+
* Anything in `templateUI` overrides the top-level shorthand where there's
|
|
77
|
+
* an overlap. Bad rows (missing `key`) are skipped with a DEV warning
|
|
78
|
+
* rather than throwing, so one broken template doesn't blank the picker.
|
|
79
|
+
*
|
|
80
|
+
* Returns `this` for chaining and the count of templates registered.
|
|
81
|
+
*/
|
|
82
|
+
registerFromApi(list: ApiWorkflowTemplate[]): this;
|
|
42
83
|
lookup(triggerKey: string): WorkflowTemplate | undefined;
|
|
43
84
|
list(): WorkflowTemplate[];
|
|
44
85
|
listByCategory(category: string): WorkflowTemplate[];
|
|
45
86
|
listByTag(tag: string): WorkflowTemplate[];
|
|
46
87
|
search(query: string): WorkflowTemplate[];
|
|
47
88
|
categories(): string[];
|
|
89
|
+
/** Remove every template — useful before re-loading from backend. */
|
|
90
|
+
clear(): this;
|
|
48
91
|
}
|
|
49
92
|
|
|
50
93
|
export declare const templateRegistry: TemplateRegistry;
|
|
@@ -60,7 +103,13 @@ export declare interface WorkflowTemplate {
|
|
|
60
103
|
description?: string;
|
|
61
104
|
icon?: ReactNode;
|
|
62
105
|
triggerCategory?: 'event' | 'scheduler' | 'webhook' | string;
|
|
106
|
+
/**
|
|
107
|
+
* Task IDs (descriptor types) that can be inserted into this workflow.
|
|
108
|
+
* `allowedTasks` is accepted as an alias for backend payloads that use
|
|
109
|
+
* that name — TemplateRegistry.register() normalises them.
|
|
110
|
+
*/
|
|
63
111
|
availableTasks?: string[];
|
|
112
|
+
allowedTasks?: string[];
|
|
64
113
|
maxTasks?: number;
|
|
65
114
|
taskLabels?: Record<string, string>;
|
|
66
115
|
fixedNodes?: FixedNode[];
|
package/dist/templateRegistry.js
CHANGED
|
@@ -1,44 +1,87 @@
|
|
|
1
|
-
class
|
|
1
|
+
class o {
|
|
2
2
|
constructor() {
|
|
3
3
|
this.templates = /* @__PURE__ */ new Map();
|
|
4
4
|
}
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Register a template. Normalises `allowedTasks` (the backend's name) →
|
|
7
|
+
* `availableTasks` (FlowForge's canonical name) so consumers can pass
|
|
8
|
+
* either without rewriting.
|
|
9
|
+
*/
|
|
10
|
+
register(t) {
|
|
11
|
+
const e = {
|
|
12
|
+
...t,
|
|
13
|
+
availableTasks: t.availableTasks ?? t.allowedTasks
|
|
14
|
+
};
|
|
6
15
|
return this.templates.set(e.triggerKey, e), this;
|
|
7
16
|
}
|
|
8
|
-
|
|
9
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Register a list of templates fetched from `GET /api/v1/workflow-template`.
|
|
19
|
+
*
|
|
20
|
+
* The API shape is:
|
|
21
|
+
* {
|
|
22
|
+
* key, name, description, allowedTasks, allowedSources,
|
|
23
|
+
* configuration, // runtime BPMN — ignored by the canvas
|
|
24
|
+
* templateUI: { // ← UI bag, spread onto the template
|
|
25
|
+
* triggerCategory, icon, tags, category, author, popularity,
|
|
26
|
+
* source, product, taskLabels, maxTasks, skeletonState, …
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* Anything in `templateUI` overrides the top-level shorthand where there's
|
|
31
|
+
* an overlap. Bad rows (missing `key`) are skipped with a DEV warning
|
|
32
|
+
* rather than throwing, so one broken template doesn't blank the picker.
|
|
33
|
+
*
|
|
34
|
+
* Returns `this` for chaining and the count of templates registered.
|
|
35
|
+
*/
|
|
36
|
+
registerFromApi(t) {
|
|
37
|
+
for (const e of t ?? [])
|
|
38
|
+
e != null && e.key && this.register({
|
|
39
|
+
triggerKey: e.key,
|
|
40
|
+
label: e.name ?? e.key,
|
|
41
|
+
description: e.description,
|
|
42
|
+
availableTasks: e.allowedTasks,
|
|
43
|
+
...e.templateUI ?? {}
|
|
44
|
+
});
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
lookup(t) {
|
|
48
|
+
return this.templates.get(t);
|
|
10
49
|
}
|
|
11
50
|
list() {
|
|
12
51
|
return [...this.templates.values()];
|
|
13
52
|
}
|
|
14
|
-
listByCategory(
|
|
15
|
-
return this.list().filter((
|
|
53
|
+
listByCategory(t) {
|
|
54
|
+
return this.list().filter((e) => e.category === t);
|
|
16
55
|
}
|
|
17
|
-
listByTag(
|
|
18
|
-
return this.list().filter((
|
|
56
|
+
listByTag(t) {
|
|
57
|
+
return this.list().filter((e) => {
|
|
19
58
|
var s;
|
|
20
|
-
return (s =
|
|
59
|
+
return (s = e.tags) == null ? void 0 : s.includes(t);
|
|
21
60
|
});
|
|
22
61
|
}
|
|
23
|
-
search(
|
|
24
|
-
const
|
|
62
|
+
search(t) {
|
|
63
|
+
const e = t.toLowerCase();
|
|
25
64
|
return this.list().filter(
|
|
26
65
|
(s) => {
|
|
27
|
-
var r,
|
|
28
|
-
return s.label.toLowerCase().includes(
|
|
66
|
+
var r, a, i;
|
|
67
|
+
return s.label.toLowerCase().includes(e) || ((r = s.description) == null ? void 0 : r.toLowerCase().includes(e)) || ((a = s.tags) == null ? void 0 : a.some((l) => l.toLowerCase().includes(e))) || ((i = s.category) == null ? void 0 : i.toLowerCase().includes(e));
|
|
29
68
|
}
|
|
30
69
|
);
|
|
31
70
|
}
|
|
32
71
|
categories() {
|
|
33
|
-
const
|
|
34
|
-
return this.list().forEach((
|
|
35
|
-
|
|
36
|
-
}), Array.from(
|
|
72
|
+
const t = /* @__PURE__ */ new Set();
|
|
73
|
+
return this.list().forEach((e) => {
|
|
74
|
+
e.category && t.add(e.category);
|
|
75
|
+
}), Array.from(t);
|
|
76
|
+
}
|
|
77
|
+
/** Remove every template — useful before re-loading from backend. */
|
|
78
|
+
clear() {
|
|
79
|
+
return this.templates.clear(), this;
|
|
37
80
|
}
|
|
38
81
|
}
|
|
39
|
-
const
|
|
82
|
+
const c = new o();
|
|
40
83
|
export {
|
|
41
|
-
|
|
42
|
-
|
|
84
|
+
o as TemplateRegistry,
|
|
85
|
+
c as templateRegistry
|
|
43
86
|
};
|
|
44
87
|
//# sourceMappingURL=templateRegistry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templateRegistry.js","sources":["../src/templateRegistry/index.ts"],"sourcesContent":["import { WorkflowTemplate } from '../WorkflowCanvas/types';\
|
|
1
|
+
{"version":3,"file":"templateRegistry.js","sources":["../src/templateRegistry/index.ts"],"sourcesContent":["import type { WorkflowTemplate, ApiWorkflowTemplate } from '../WorkflowCanvas/types';\n\nexport class TemplateRegistry {\n private templates = new Map<string, WorkflowTemplate>();\n\n /**\n * Register a template. Normalises `allowedTasks` (the backend's name) →\n * `availableTasks` (FlowForge's canonical name) so consumers can pass\n * either without rewriting.\n */\n register(template: WorkflowTemplate): this {\n const normalised: WorkflowTemplate = {\n ...template,\n availableTasks: template.availableTasks ?? template.allowedTasks,\n };\n this.templates.set(normalised.triggerKey, normalised);\n return this;\n }\n\n /**\n * Register a list of templates fetched from `GET /api/v1/workflow-template`.\n *\n * The API shape is:\n * {\n * key, name, description, allowedTasks, allowedSources,\n * configuration, // runtime BPMN — ignored by the canvas\n * templateUI: { // ← UI bag, spread onto the template\n * triggerCategory, icon, tags, category, author, popularity,\n * source, product, taskLabels, maxTasks, skeletonState, …\n * }\n * }\n *\n * Anything in `templateUI` overrides the top-level shorthand where there's\n * an overlap. Bad rows (missing `key`) are skipped with a DEV warning\n * rather than throwing, so one broken template doesn't blank the picker.\n *\n * Returns `this` for chaining and the count of templates registered.\n */\n registerFromApi(list: ApiWorkflowTemplate[]): this {\n for (const t of list ?? []) {\n if (!t?.key) {\n if (import.meta.env?.DEV) {\n // eslint-disable-next-line no-console\n console.warn('[FlowForge] templateRegistry.registerFromApi: skipped row without `key`', t);\n }\n continue;\n }\n this.register({\n triggerKey: t.key,\n label: t.name ?? t.key,\n description: t.description,\n availableTasks: t.allowedTasks,\n ...(t.templateUI ?? {}),\n } as WorkflowTemplate);\n }\n return this;\n }\n\n lookup(triggerKey: string): WorkflowTemplate | undefined {\n return this.templates.get(triggerKey);\n }\n\n list(): WorkflowTemplate[] {\n return [...this.templates.values()];\n }\n\n listByCategory(category: string): WorkflowTemplate[] {\n return this.list().filter((t) => t.category === category);\n }\n\n listByTag(tag: string): WorkflowTemplate[] {\n return this.list().filter((t) => t.tags?.includes(tag));\n }\n\n search(query: string): WorkflowTemplate[] {\n const q = query.toLowerCase();\n return this.list().filter(\n (t) =>\n t.label.toLowerCase().includes(q) ||\n t.description?.toLowerCase().includes(q) ||\n t.tags?.some((tag) => tag.toLowerCase().includes(q)) ||\n t.category?.toLowerCase().includes(q),\n );\n }\n\n categories(): string[] {\n const cats = new Set<string>();\n this.list().forEach((t) => { if (t.category) cats.add(t.category); });\n return Array.from(cats);\n }\n\n /** Remove every template — useful before re-loading from backend. */\n clear(): this {\n this.templates.clear();\n return this;\n }\n}\n\nexport const templateRegistry = new TemplateRegistry();\nexport type { WorkflowTemplate, ApiWorkflowTemplate };\n"],"names":["TemplateRegistry","template","normalised","list","t","triggerKey","category","tag","_a","query","q","_b","_c","cats","templateRegistry"],"mappings":"AAEO,MAAMA,EAAiB;AAAA,EAAvB,cAAA;AACL,SAAQ,gCAAgB,IAAA;AAAA,EAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtD,SAASC,GAAkC;AACzC,UAAMC,IAA+B;AAAA,MACnC,GAAGD;AAAA,MACH,gBAAgBA,EAAS,kBAAkBA,EAAS;AAAA,IAAA;AAEtD,gBAAK,UAAU,IAAIC,EAAW,YAAYA,CAAU,GAC7C;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,gBAAgBC,GAAmC;AACjD,eAAWC,KAAKD,KAAQ;AACtB,MAAKC,KAAA,QAAAA,EAAG,OAOR,KAAK,SAAS;AAAA,QACZ,YAAYA,EAAE;AAAA,QACd,OAAOA,EAAE,QAAQA,EAAE;AAAA,QACnB,aAAaA,EAAE;AAAA,QACf,gBAAgBA,EAAE;AAAA,QAClB,GAAIA,EAAE,cAAc,CAAA;AAAA,MAAC,CACF;AAEvB,WAAO;AAAA,EACT;AAAA,EAEA,OAAOC,GAAkD;AACvD,WAAO,KAAK,UAAU,IAAIA,CAAU;AAAA,EACtC;AAAA,EAEA,OAA2B;AACzB,WAAO,CAAC,GAAG,KAAK,UAAU,QAAQ;AAAA,EACpC;AAAA,EAEA,eAAeC,GAAsC;AACnD,WAAO,KAAK,OAAO,OAAO,CAACF,MAAMA,EAAE,aAAaE,CAAQ;AAAA,EAC1D;AAAA,EAEA,UAAUC,GAAiC;AACzC,WAAO,KAAK,KAAA,EAAO,OAAO,CAACH;AArExB,UAAAI;AAqE8B,cAAAA,IAAAJ,EAAE,SAAF,gBAAAI,EAAQ,SAASD;AAAA,KAAI;AAAA,EACxD;AAAA,EAEA,OAAOE,GAAmC;AACxC,UAAMC,IAAID,EAAM,YAAA;AAChB,WAAO,KAAK,OAAO;AAAA,MACjB,CAACL,MAAA;AA3EA,YAAAI,GAAAG,GAAAC;AA4EC,eAAAR,EAAE,MAAM,cAAc,SAASM,CAAC,OAChCF,IAAAJ,EAAE,gBAAF,gBAAAI,EAAe,cAAc,SAASE,SACtCC,IAAAP,EAAE,SAAF,gBAAAO,EAAQ,KAAK,CAACJ,MAAQA,EAAI,cAAc,SAASG,CAAC,SAClDE,IAAAR,EAAE,aAAF,gBAAAQ,EAAY,cAAc,SAASF;AAAA;AAAA,IAAC;AAAA,EAE1C;AAAA,EAEA,aAAuB;AACrB,UAAMG,wBAAW,IAAA;AACjB,gBAAK,KAAA,EAAO,QAAQ,CAACT,MAAM;AAAE,MAAIA,EAAE,YAAUS,EAAK,IAAIT,EAAE,QAAQ;AAAA,IAAG,CAAC,GAC7D,MAAM,KAAKS,CAAI;AAAA,EACxB;AAAA;AAAA,EAGA,QAAc;AACZ,gBAAK,UAAU,MAAA,GACR;AAAA,EACT;AACF;AAEO,MAAMC,IAAmB,IAAId,EAAA;"}
|