@lssm-tech/lib.workflow-composer 3.7.29 → 5.0.1
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 +8 -8
- package/package.json +82 -19
- package/dist/browser/index.js +0 -1
- package/dist/composer.d.ts +0 -8
- package/dist/composer.test.d.ts +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -2
- package/dist/injector.d.ts +0 -3
- package/dist/merger.d.ts +0 -2
- package/dist/node/index.js +0 -1
- package/dist/templates.d.ts +0 -10
- package/dist/types.d.ts +0 -41
- package/dist/validator.d.ts +0 -7
- package/dist/workflow-composer.feature.d.ts +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @lssm-tech/lib.workflow-composer
|
|
2
2
|
|
|
3
3
|
Website: https://contractspec.io
|
|
4
4
|
|
|
@@ -8,20 +8,20 @@ Website: https://contractspec.io
|
|
|
8
8
|
|
|
9
9
|
- **Layer**: lib.
|
|
10
10
|
- **Consumers**: bundles.
|
|
11
|
-
- Related ContractSpec packages include `@
|
|
12
|
-
- Related ContractSpec packages include `@
|
|
11
|
+
- Related ContractSpec packages include `@lssm-tech/lib.ai-providers`, `@lssm-tech/lib.contracts-spec`, `@lssm-tech/tool.bun`, `@lssm-tech/tool.typescript`.
|
|
12
|
+
- Related ContractSpec packages include `@lssm-tech/lib.ai-providers`, `@lssm-tech/lib.contracts-spec`, `@lssm-tech/tool.bun`, `@lssm-tech/tool.typescript`.
|
|
13
13
|
|
|
14
14
|
## Installation
|
|
15
15
|
|
|
16
|
-
`npm install @
|
|
16
|
+
`npm install @lssm-tech/lib.workflow-composer`
|
|
17
17
|
|
|
18
18
|
or
|
|
19
19
|
|
|
20
|
-
`bun add @
|
|
20
|
+
`bun add @lssm-tech/lib.workflow-composer`
|
|
21
21
|
|
|
22
22
|
## Usage
|
|
23
23
|
|
|
24
|
-
Import the root entrypoint from `@
|
|
24
|
+
Import the root entrypoint from `@lssm-tech/lib.workflow-composer`, or choose a documented subpath when you only need one part of the package surface.
|
|
25
25
|
|
|
26
26
|
Workflow composition is deterministic by default:
|
|
27
27
|
|
|
@@ -47,12 +47,12 @@ Workflow composition is deterministic by default:
|
|
|
47
47
|
## Local Commands
|
|
48
48
|
|
|
49
49
|
- `bun run dev` — contractspec-bun-build dev
|
|
50
|
-
- `bun run build` — bun
|
|
50
|
+
- `bun run build` — contractspec-bun-build build
|
|
51
51
|
- `bun run test` — bun test --pass-with-no-tests
|
|
52
52
|
- `bun run lint` — bun lint:fix
|
|
53
53
|
- `bun run lint:check` — biome check .
|
|
54
54
|
- `bun run lint:fix` — biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .
|
|
55
|
-
- `bun run typecheck` —
|
|
55
|
+
- `bun run typecheck` — tsgo --noEmit
|
|
56
56
|
- `bun run publish:pkg` — bun publish --tolerate-republish --ignore-scripts --verbose
|
|
57
57
|
- `bun run publish:pkg:canary` — bun publish:pkg --tag canary
|
|
58
58
|
- `bun run clean` — rimraf dist .turbo
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lssm-tech/lib.workflow-composer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.1",
|
|
4
4
|
"description": "Tenant-aware workflow composition helpers for ContractSpec.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"contractspec",
|
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
"type": "module",
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
14
|
"files": [
|
|
15
|
-
"
|
|
16
|
-
"README.md"
|
|
15
|
+
"package.json"
|
|
17
16
|
],
|
|
18
17
|
"scripts": {
|
|
19
18
|
"publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
|
|
20
19
|
"publish:pkg:canary": "bun publish:pkg --tag canary",
|
|
21
|
-
"build": "bun
|
|
20
|
+
"build": "contractspec-bun-build build",
|
|
22
21
|
"build:bundle": "contractspec-bun-build transpile",
|
|
23
22
|
"build:types": "contractspec-bun-build types",
|
|
24
23
|
"dev": "contractspec-bun-build dev",
|
|
@@ -28,26 +27,20 @@
|
|
|
28
27
|
"lint:check": "node ../../../scripts/biome.cjs check .",
|
|
29
28
|
"test": "bun test --pass-with-no-tests",
|
|
30
29
|
"prebuild": "contractspec-bun-build prebuild",
|
|
31
|
-
"typecheck": "
|
|
30
|
+
"typecheck": "tsgo --noEmit"
|
|
32
31
|
},
|
|
33
32
|
"dependencies": {
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
36
|
-
"compare-versions": "
|
|
33
|
+
"@lssm-tech/lib.contracts-spec": "workspace:^",
|
|
34
|
+
"@lssm-tech/lib.ai-providers": "workspace:^",
|
|
35
|
+
"compare-versions": "catalog:data"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
|
-
"@
|
|
40
|
-
"typescript": "
|
|
41
|
-
"@
|
|
38
|
+
"@lssm-tech/tool.typescript": "workspace:*",
|
|
39
|
+
"typescript": "catalog:",
|
|
40
|
+
"@lssm-tech/tool.bun": "workspace:*"
|
|
42
41
|
},
|
|
43
42
|
"exports": {
|
|
44
|
-
".":
|
|
45
|
-
"types": "./dist/index.d.ts",
|
|
46
|
-
"browser": "./dist/browser/index.js",
|
|
47
|
-
"bun": "./dist/index.js",
|
|
48
|
-
"node": "./dist/node/index.js",
|
|
49
|
-
"default": "./dist/index.js"
|
|
50
|
-
}
|
|
43
|
+
".": "./src/index.ts"
|
|
51
44
|
},
|
|
52
45
|
"publishConfig": {
|
|
53
46
|
"access": "public",
|
|
@@ -68,5 +61,75 @@
|
|
|
68
61
|
"url": "https://github.com/lssm-tech/contractspec.git",
|
|
69
62
|
"directory": "packages/libs/workflow-composer"
|
|
70
63
|
},
|
|
71
|
-
"homepage": "https://contractspec.io"
|
|
64
|
+
"homepage": "https://contractspec.io",
|
|
65
|
+
"contractspec": {
|
|
66
|
+
"catalog": {
|
|
67
|
+
"family": "sharedLibs",
|
|
68
|
+
"kind": "library",
|
|
69
|
+
"status": "active",
|
|
70
|
+
"adoptionMode": "adoptable",
|
|
71
|
+
"stability": "stable",
|
|
72
|
+
"platforms": [
|
|
73
|
+
"server"
|
|
74
|
+
],
|
|
75
|
+
"runtimes": [
|
|
76
|
+
"node"
|
|
77
|
+
],
|
|
78
|
+
"entrypoints": [
|
|
79
|
+
"."
|
|
80
|
+
],
|
|
81
|
+
"documentation": [
|
|
82
|
+
{
|
|
83
|
+
"title": "Lib Workflow Composer documentation",
|
|
84
|
+
"url": "https://www.npmjs.com/package/%40lssm-tech%2Flib.workflow-composer",
|
|
85
|
+
"kind": "readme"
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"examples": [],
|
|
89
|
+
"replacements": [],
|
|
90
|
+
"capabilities": [
|
|
91
|
+
{
|
|
92
|
+
"id": "package.lssm.tech.lib.workflow.composer",
|
|
93
|
+
"title": "Lib Workflow Composer",
|
|
94
|
+
"description": "Tenant-aware workflow composition helpers for ContractSpec.",
|
|
95
|
+
"status": "active",
|
|
96
|
+
"useCases": [
|
|
97
|
+
"Adopt tenant-aware workflow composition helpers for contractspec"
|
|
98
|
+
],
|
|
99
|
+
"aliases": [
|
|
100
|
+
"contractspec",
|
|
101
|
+
"workflow",
|
|
102
|
+
"composer",
|
|
103
|
+
"multi-tenant",
|
|
104
|
+
"typescript",
|
|
105
|
+
"lib"
|
|
106
|
+
],
|
|
107
|
+
"pythonEquivalents": [],
|
|
108
|
+
"canonicalImports": [
|
|
109
|
+
{
|
|
110
|
+
"from": "@lssm-tech/lib.workflow-composer",
|
|
111
|
+
"symbols": []
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"constraints": {
|
|
115
|
+
"platforms": [
|
|
116
|
+
"server"
|
|
117
|
+
],
|
|
118
|
+
"runtimes": [
|
|
119
|
+
"node"
|
|
120
|
+
],
|
|
121
|
+
"avoidWhen": [
|
|
122
|
+
"The @lssm-tech/lib.workflow-composer package constraints do not match the target runtime or platform."
|
|
123
|
+
],
|
|
124
|
+
"requires": [
|
|
125
|
+
"TypeScript"
|
|
126
|
+
]
|
|
127
|
+
},
|
|
128
|
+
"alternatives": [],
|
|
129
|
+
"relationships": [],
|
|
130
|
+
"resolutionPriority": 50
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
72
135
|
}
|
package/dist/browser/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{satisfies as x}from"compare-versions";import{validateWorkflowSpec as i}from"@contractspec/lib.contracts-spec/workflow";function d(o,r){let e=[],s=new Set(r.definition.steps.map((t)=>t.id)),a=new Set(o.hiddenSteps??[]),f=new Set(s),m=r.definition.transitions.filter((t)=>f.has(t.from)&&f.has(t.to)).map((t)=>({...t}));if(!o.workflow.trim())e.push({code:"workflow.extension.workflow",message:"workflow is required"});if(o.workflow!==r.meta.key)e.push({code:"workflow.extension.workflow.mismatch",message:`extension targets "${o.workflow}" but base workflow is "${r.meta.key}"`});a.forEach((t)=>{if(!s.has(t)){e.push({code:"workflow.extension.hidden-step",message:`hidden step "${t}" does not exist`});return}f.delete(t)}),c(m,a);let w=new Set([...s].filter((t)=>!a.has(t)));o.customSteps?.forEach((t,p)=>{let u=t.inject.id?.trim();if(!u){e.push({code:"workflow.extension.step.id",message:`customSteps[${p}] is missing an id`});return}if(t.id&&t.id!==u)e.push({code:"workflow.extension.step.id-mismatch",message:`customSteps[${p}] has mismatched id (id="${t.id}", inject.id="${u}")`});if(w.has(u))e.push({code:"workflow.extension.step.id.duplicate",message:`customSteps[${p}] injects duplicate step id "${u}"`});if(t.after&&t.before)e.push({code:"workflow.extension.step.anchor.multiple",message:`customSteps[${p}] cannot set both after and before`});if(!t.after&&!t.before)e.push({code:"workflow.extension.step.anchor",message:`customSteps[${p}] must set after or before`});if(t.after&&!w.has(t.after))e.push({code:"workflow.extension.step.after",message:`customSteps[${p}] references unknown step "${t.after}"`});if(t.before&&!w.has(t.before))e.push({code:"workflow.extension.step.before",message:`customSteps[${p}] references unknown step "${t.before}"`});if(t.transitionFrom&&!w.has(t.transitionFrom))e.push({code:"workflow.extension.step.transition-from",message:`customSteps[${p}] references unknown transitionFrom step "${t.transitionFrom}"`});if(t.transitionTo&&!w.has(t.transitionTo))e.push({code:"workflow.extension.step.transition-to",message:`customSteps[${p}] references unknown transitionTo step "${t.transitionTo}"`});if(w.add(u),f.add(u),t.transitionFrom)m.push({from:t.transitionFrom,to:u,condition:t.when});if(t.transitionTo)m.push({from:u,to:t.transitionTo,condition:t.when})});let l=r.definition.entryStepId??r.definition.steps[0]?.id;if(l&&a.has(l))e.push({code:"workflow.extension.hidden-step.entry",message:`hiddenSteps removes the entry step "${l}"`});if(l&&!a.has(l)){let t=g(l,m);for(let p of f)if(!t.has(p))e.push({code:"workflow.extension.hidden-step.orphan",message:`extension leaves step "${p}" unreachable from entry step "${l}"`})}if(e.length){let t=e.map((p)=>`${p.code}: ${p.message}`).join("; ");throw Error(`Invalid workflow extension for ${o.workflow}: ${t}`)}}function c(o,r){for(let e=o.length-1;e>=0;e-=1){let s=o[e];if(!s)continue;if(r.has(s.from)||r.has(s.to))o.splice(e,1)}}function g(o,r){let e=new Map;for(let f of r){let m=e.get(f.from)??[];m.push(f.to),e.set(f.from,m)}let s=new Set,a=[o];while(a.length>0){let f=a.shift();if(!f||s.has(f))continue;s.add(f);for(let m of e.get(f)??[])a.push(m)}return s}function n(o,r){d(r,o);let e=v(o),s=[...e.definition.steps],a=[...e.definition.transitions],f=new Set(r.hiddenSteps??[]);if(f.forEach((l)=>{let t=s.findIndex((p)=>p.id===l);if(t!==-1)s.splice(t,1)}),f.size)a=a.filter((l)=>!f.has(l.from)&&!f.has(l.to));r.customSteps?.forEach((l)=>{S(s,l),$(a,l)}),e.definition.steps=s,e.definition.transitions=E(a),e.metadata=h(e.metadata,r.metadata),e.annotations=h(e.annotations,r.annotations);let w=i(e).filter((l)=>l.level==="error");if(w.length>0)throw Error(`Invalid composed workflow ${e.meta.key}.v${e.meta.version}: ${w.map((l)=>l.message).join("; ")}`);return e}function S(o,r){let e=y(o,r);if(e===-1)throw Error(`Unable to place injected step "${r.inject.id}"`);o.splice(e,0,{...r.inject})}function y(o,r){if(r.after){let e=o.findIndex((s)=>s.id===r.after);return e===-1?-1:e+1}if(r.before){let e=o.findIndex((s)=>s.id===r.before);return e===-1?-1:e}return o.length}function $(o,r){if(!r.inject.id)return;if(r.transitionFrom)o.push({from:r.transitionFrom,to:r.inject.id,condition:r.when});if(r.transitionTo)o.push({from:r.inject.id,to:r.transitionTo,condition:r.when})}function E(o){let r=new Set,e=[];return o.forEach((s)=>{let a=`${s.from}->${s.to}:${s.condition??""}`;if(r.has(a))return;r.add(a),e.push(s)}),e}function v(o){return JSON.parse(JSON.stringify(o))}function h(o,r){if(!o&&!r)return;return{...o??{},...r??{}}}function k(o){return[...o].sort((r,e)=>{let s=(r.priority??0)-(e.priority??0);if(s!==0)return s;let a=r.workflow.localeCompare(e.workflow);if(a!==0)return a;let f=(r.tenantId??"").localeCompare(e.tenantId??"");if(f!==0)return f;let m=(r.role??"").localeCompare(e.role??"");if(m!==0)return m;let w=(r.device??"").localeCompare(e.device??"");if(w!==0)return w;return(r.baseVersion??"").localeCompare(e.baseVersion??"")})}class W{extensions=[];register(o){return this.extensions.push(o),this}registerMany(o){return o.forEach((r)=>{this.register(r)}),this}compose(o){return k(this.extensions.filter((e)=>T(o,e))).reduce((e,s)=>n(e,s),o.base)}}function T(o,r){if(r.workflow!==o.base.meta.key)return!1;if(r.baseVersion&&!x(o.base.meta.version,r.baseVersion))return!1;if(r.tenantId&&r.tenantId!==o.tenantId)return!1;if(r.role&&r.role!==o.role)return!1;if(r.device&&r.device!==o.device)return!1;return!0}function M(o){return{id:o.id,label:o.label,type:o.type??"human",description:o.description??"Tenant-specific approval",action:o.action,guard:o.guardExpression?{type:"expression",value:o.guardExpression}:void 0}}import{defineFeature as b}from"@contractspec/lib.contracts-spec/features";var D=b({meta:{key:"libs.workflow-composer",version:"1.0.0",title:"Workflow Composer",description:"Tenant-aware workflow composition helpers for ContractSpec.",domain:"workflow-composer",owners:["@contractspec-core"],tags:["package","libs","workflow-composer"],stability:"experimental"}});export{d as validateExtension,k as mergeExtensions,M as approvalStepTemplate,n as applyWorkflowExtension,D as WorkflowComposerFeature,W as WorkflowComposer};
|
package/dist/composer.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow';
|
|
2
|
-
import type { ComposeParams, WorkflowExtension } from './types';
|
|
3
|
-
export declare class WorkflowComposer {
|
|
4
|
-
private readonly extensions;
|
|
5
|
-
register(extension: WorkflowExtension): this;
|
|
6
|
-
registerMany(extensions: WorkflowExtension[]): this;
|
|
7
|
-
compose(params: ComposeParams): WorkflowSpec;
|
|
8
|
-
}
|
package/dist/composer.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import{satisfies as x}from"compare-versions";import{validateWorkflowSpec as i}from"@contractspec/lib.contracts-spec/workflow";function d(o,r){let e=[],s=new Set(r.definition.steps.map((t)=>t.id)),a=new Set(o.hiddenSteps??[]),f=new Set(s),m=r.definition.transitions.filter((t)=>f.has(t.from)&&f.has(t.to)).map((t)=>({...t}));if(!o.workflow.trim())e.push({code:"workflow.extension.workflow",message:"workflow is required"});if(o.workflow!==r.meta.key)e.push({code:"workflow.extension.workflow.mismatch",message:`extension targets "${o.workflow}" but base workflow is "${r.meta.key}"`});a.forEach((t)=>{if(!s.has(t)){e.push({code:"workflow.extension.hidden-step",message:`hidden step "${t}" does not exist`});return}f.delete(t)}),c(m,a);let w=new Set([...s].filter((t)=>!a.has(t)));o.customSteps?.forEach((t,p)=>{let u=t.inject.id?.trim();if(!u){e.push({code:"workflow.extension.step.id",message:`customSteps[${p}] is missing an id`});return}if(t.id&&t.id!==u)e.push({code:"workflow.extension.step.id-mismatch",message:`customSteps[${p}] has mismatched id (id="${t.id}", inject.id="${u}")`});if(w.has(u))e.push({code:"workflow.extension.step.id.duplicate",message:`customSteps[${p}] injects duplicate step id "${u}"`});if(t.after&&t.before)e.push({code:"workflow.extension.step.anchor.multiple",message:`customSteps[${p}] cannot set both after and before`});if(!t.after&&!t.before)e.push({code:"workflow.extension.step.anchor",message:`customSteps[${p}] must set after or before`});if(t.after&&!w.has(t.after))e.push({code:"workflow.extension.step.after",message:`customSteps[${p}] references unknown step "${t.after}"`});if(t.before&&!w.has(t.before))e.push({code:"workflow.extension.step.before",message:`customSteps[${p}] references unknown step "${t.before}"`});if(t.transitionFrom&&!w.has(t.transitionFrom))e.push({code:"workflow.extension.step.transition-from",message:`customSteps[${p}] references unknown transitionFrom step "${t.transitionFrom}"`});if(t.transitionTo&&!w.has(t.transitionTo))e.push({code:"workflow.extension.step.transition-to",message:`customSteps[${p}] references unknown transitionTo step "${t.transitionTo}"`});if(w.add(u),f.add(u),t.transitionFrom)m.push({from:t.transitionFrom,to:u,condition:t.when});if(t.transitionTo)m.push({from:u,to:t.transitionTo,condition:t.when})});let l=r.definition.entryStepId??r.definition.steps[0]?.id;if(l&&a.has(l))e.push({code:"workflow.extension.hidden-step.entry",message:`hiddenSteps removes the entry step "${l}"`});if(l&&!a.has(l)){let t=g(l,m);for(let p of f)if(!t.has(p))e.push({code:"workflow.extension.hidden-step.orphan",message:`extension leaves step "${p}" unreachable from entry step "${l}"`})}if(e.length){let t=e.map((p)=>`${p.code}: ${p.message}`).join("; ");throw Error(`Invalid workflow extension for ${o.workflow}: ${t}`)}}function c(o,r){for(let e=o.length-1;e>=0;e-=1){let s=o[e];if(!s)continue;if(r.has(s.from)||r.has(s.to))o.splice(e,1)}}function g(o,r){let e=new Map;for(let f of r){let m=e.get(f.from)??[];m.push(f.to),e.set(f.from,m)}let s=new Set,a=[o];while(a.length>0){let f=a.shift();if(!f||s.has(f))continue;s.add(f);for(let m of e.get(f)??[])a.push(m)}return s}function n(o,r){d(r,o);let e=v(o),s=[...e.definition.steps],a=[...e.definition.transitions],f=new Set(r.hiddenSteps??[]);if(f.forEach((l)=>{let t=s.findIndex((p)=>p.id===l);if(t!==-1)s.splice(t,1)}),f.size)a=a.filter((l)=>!f.has(l.from)&&!f.has(l.to));r.customSteps?.forEach((l)=>{S(s,l),$(a,l)}),e.definition.steps=s,e.definition.transitions=E(a),e.metadata=h(e.metadata,r.metadata),e.annotations=h(e.annotations,r.annotations);let w=i(e).filter((l)=>l.level==="error");if(w.length>0)throw Error(`Invalid composed workflow ${e.meta.key}.v${e.meta.version}: ${w.map((l)=>l.message).join("; ")}`);return e}function S(o,r){let e=y(o,r);if(e===-1)throw Error(`Unable to place injected step "${r.inject.id}"`);o.splice(e,0,{...r.inject})}function y(o,r){if(r.after){let e=o.findIndex((s)=>s.id===r.after);return e===-1?-1:e+1}if(r.before){let e=o.findIndex((s)=>s.id===r.before);return e===-1?-1:e}return o.length}function $(o,r){if(!r.inject.id)return;if(r.transitionFrom)o.push({from:r.transitionFrom,to:r.inject.id,condition:r.when});if(r.transitionTo)o.push({from:r.inject.id,to:r.transitionTo,condition:r.when})}function E(o){let r=new Set,e=[];return o.forEach((s)=>{let a=`${s.from}->${s.to}:${s.condition??""}`;if(r.has(a))return;r.add(a),e.push(s)}),e}function v(o){return JSON.parse(JSON.stringify(o))}function h(o,r){if(!o&&!r)return;return{...o??{},...r??{}}}function k(o){return[...o].sort((r,e)=>{let s=(r.priority??0)-(e.priority??0);if(s!==0)return s;let a=r.workflow.localeCompare(e.workflow);if(a!==0)return a;let f=(r.tenantId??"").localeCompare(e.tenantId??"");if(f!==0)return f;let m=(r.role??"").localeCompare(e.role??"");if(m!==0)return m;let w=(r.device??"").localeCompare(e.device??"");if(w!==0)return w;return(r.baseVersion??"").localeCompare(e.baseVersion??"")})}class W{extensions=[];register(o){return this.extensions.push(o),this}registerMany(o){return o.forEach((r)=>{this.register(r)}),this}compose(o){return k(this.extensions.filter((e)=>T(o,e))).reduce((e,s)=>n(e,s),o.base)}}function T(o,r){if(r.workflow!==o.base.meta.key)return!1;if(r.baseVersion&&!x(o.base.meta.version,r.baseVersion))return!1;if(r.tenantId&&r.tenantId!==o.tenantId)return!1;if(r.role&&r.role!==o.role)return!1;if(r.device&&r.device!==o.device)return!1;return!0}function M(o){return{id:o.id,label:o.label,type:o.type??"human",description:o.description??"Tenant-specific approval",action:o.action,guard:o.guardExpression?{type:"expression",value:o.guardExpression}:void 0}}import{defineFeature as b}from"@contractspec/lib.contracts-spec/features";var D=b({meta:{key:"libs.workflow-composer",version:"1.0.0",title:"Workflow Composer",description:"Tenant-aware workflow composition helpers for ContractSpec.",domain:"workflow-composer",owners:["@contractspec-core"],tags:["package","libs","workflow-composer"],stability:"experimental"}});export{d as validateExtension,k as mergeExtensions,M as approvalStepTemplate,n as applyWorkflowExtension,D as WorkflowComposerFeature,W as WorkflowComposer};
|
package/dist/injector.d.ts
DELETED
package/dist/merger.d.ts
DELETED
package/dist/node/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{satisfies as x}from"compare-versions";import{validateWorkflowSpec as i}from"@contractspec/lib.contracts-spec/workflow";function d(o,r){let e=[],s=new Set(r.definition.steps.map((t)=>t.id)),a=new Set(o.hiddenSteps??[]),f=new Set(s),m=r.definition.transitions.filter((t)=>f.has(t.from)&&f.has(t.to)).map((t)=>({...t}));if(!o.workflow.trim())e.push({code:"workflow.extension.workflow",message:"workflow is required"});if(o.workflow!==r.meta.key)e.push({code:"workflow.extension.workflow.mismatch",message:`extension targets "${o.workflow}" but base workflow is "${r.meta.key}"`});a.forEach((t)=>{if(!s.has(t)){e.push({code:"workflow.extension.hidden-step",message:`hidden step "${t}" does not exist`});return}f.delete(t)}),c(m,a);let w=new Set([...s].filter((t)=>!a.has(t)));o.customSteps?.forEach((t,p)=>{let u=t.inject.id?.trim();if(!u){e.push({code:"workflow.extension.step.id",message:`customSteps[${p}] is missing an id`});return}if(t.id&&t.id!==u)e.push({code:"workflow.extension.step.id-mismatch",message:`customSteps[${p}] has mismatched id (id="${t.id}", inject.id="${u}")`});if(w.has(u))e.push({code:"workflow.extension.step.id.duplicate",message:`customSteps[${p}] injects duplicate step id "${u}"`});if(t.after&&t.before)e.push({code:"workflow.extension.step.anchor.multiple",message:`customSteps[${p}] cannot set both after and before`});if(!t.after&&!t.before)e.push({code:"workflow.extension.step.anchor",message:`customSteps[${p}] must set after or before`});if(t.after&&!w.has(t.after))e.push({code:"workflow.extension.step.after",message:`customSteps[${p}] references unknown step "${t.after}"`});if(t.before&&!w.has(t.before))e.push({code:"workflow.extension.step.before",message:`customSteps[${p}] references unknown step "${t.before}"`});if(t.transitionFrom&&!w.has(t.transitionFrom))e.push({code:"workflow.extension.step.transition-from",message:`customSteps[${p}] references unknown transitionFrom step "${t.transitionFrom}"`});if(t.transitionTo&&!w.has(t.transitionTo))e.push({code:"workflow.extension.step.transition-to",message:`customSteps[${p}] references unknown transitionTo step "${t.transitionTo}"`});if(w.add(u),f.add(u),t.transitionFrom)m.push({from:t.transitionFrom,to:u,condition:t.when});if(t.transitionTo)m.push({from:u,to:t.transitionTo,condition:t.when})});let l=r.definition.entryStepId??r.definition.steps[0]?.id;if(l&&a.has(l))e.push({code:"workflow.extension.hidden-step.entry",message:`hiddenSteps removes the entry step "${l}"`});if(l&&!a.has(l)){let t=g(l,m);for(let p of f)if(!t.has(p))e.push({code:"workflow.extension.hidden-step.orphan",message:`extension leaves step "${p}" unreachable from entry step "${l}"`})}if(e.length){let t=e.map((p)=>`${p.code}: ${p.message}`).join("; ");throw Error(`Invalid workflow extension for ${o.workflow}: ${t}`)}}function c(o,r){for(let e=o.length-1;e>=0;e-=1){let s=o[e];if(!s)continue;if(r.has(s.from)||r.has(s.to))o.splice(e,1)}}function g(o,r){let e=new Map;for(let f of r){let m=e.get(f.from)??[];m.push(f.to),e.set(f.from,m)}let s=new Set,a=[o];while(a.length>0){let f=a.shift();if(!f||s.has(f))continue;s.add(f);for(let m of e.get(f)??[])a.push(m)}return s}function n(o,r){d(r,o);let e=v(o),s=[...e.definition.steps],a=[...e.definition.transitions],f=new Set(r.hiddenSteps??[]);if(f.forEach((l)=>{let t=s.findIndex((p)=>p.id===l);if(t!==-1)s.splice(t,1)}),f.size)a=a.filter((l)=>!f.has(l.from)&&!f.has(l.to));r.customSteps?.forEach((l)=>{S(s,l),$(a,l)}),e.definition.steps=s,e.definition.transitions=E(a),e.metadata=h(e.metadata,r.metadata),e.annotations=h(e.annotations,r.annotations);let w=i(e).filter((l)=>l.level==="error");if(w.length>0)throw Error(`Invalid composed workflow ${e.meta.key}.v${e.meta.version}: ${w.map((l)=>l.message).join("; ")}`);return e}function S(o,r){let e=y(o,r);if(e===-1)throw Error(`Unable to place injected step "${r.inject.id}"`);o.splice(e,0,{...r.inject})}function y(o,r){if(r.after){let e=o.findIndex((s)=>s.id===r.after);return e===-1?-1:e+1}if(r.before){let e=o.findIndex((s)=>s.id===r.before);return e===-1?-1:e}return o.length}function $(o,r){if(!r.inject.id)return;if(r.transitionFrom)o.push({from:r.transitionFrom,to:r.inject.id,condition:r.when});if(r.transitionTo)o.push({from:r.inject.id,to:r.transitionTo,condition:r.when})}function E(o){let r=new Set,e=[];return o.forEach((s)=>{let a=`${s.from}->${s.to}:${s.condition??""}`;if(r.has(a))return;r.add(a),e.push(s)}),e}function v(o){return JSON.parse(JSON.stringify(o))}function h(o,r){if(!o&&!r)return;return{...o??{},...r??{}}}function k(o){return[...o].sort((r,e)=>{let s=(r.priority??0)-(e.priority??0);if(s!==0)return s;let a=r.workflow.localeCompare(e.workflow);if(a!==0)return a;let f=(r.tenantId??"").localeCompare(e.tenantId??"");if(f!==0)return f;let m=(r.role??"").localeCompare(e.role??"");if(m!==0)return m;let w=(r.device??"").localeCompare(e.device??"");if(w!==0)return w;return(r.baseVersion??"").localeCompare(e.baseVersion??"")})}class W{extensions=[];register(o){return this.extensions.push(o),this}registerMany(o){return o.forEach((r)=>{this.register(r)}),this}compose(o){return k(this.extensions.filter((e)=>T(o,e))).reduce((e,s)=>n(e,s),o.base)}}function T(o,r){if(r.workflow!==o.base.meta.key)return!1;if(r.baseVersion&&!x(o.base.meta.version,r.baseVersion))return!1;if(r.tenantId&&r.tenantId!==o.tenantId)return!1;if(r.role&&r.role!==o.role)return!1;if(r.device&&r.device!==o.device)return!1;return!0}function M(o){return{id:o.id,label:o.label,type:o.type??"human",description:o.description??"Tenant-specific approval",action:o.action,guard:o.guardExpression?{type:"expression",value:o.guardExpression}:void 0}}import{defineFeature as b}from"@contractspec/lib.contracts-spec/features";var D=b({meta:{key:"libs.workflow-composer",version:"1.0.0",title:"Workflow Composer",description:"Tenant-aware workflow composition helpers for ContractSpec.",domain:"workflow-composer",owners:["@contractspec-core"],tags:["package","libs","workflow-composer"],stability:"experimental"}});export{d as validateExtension,k as mergeExtensions,M as approvalStepTemplate,n as applyWorkflowExtension,D as WorkflowComposerFeature,W as WorkflowComposer};
|
package/dist/templates.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Step, StepAction, StepType } from '@contractspec/lib.contracts-spec/workflow';
|
|
2
|
-
export interface StepTemplateOptions {
|
|
3
|
-
id: string;
|
|
4
|
-
label: string;
|
|
5
|
-
type?: StepType;
|
|
6
|
-
description?: string;
|
|
7
|
-
action?: StepAction;
|
|
8
|
-
guardExpression?: string;
|
|
9
|
-
}
|
|
10
|
-
export declare function approvalStepTemplate(options: StepTemplateOptions): Step;
|
package/dist/types.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ModelSelector } from '@contractspec/lib.ai-providers/selector-types';
|
|
2
|
-
import type { Step, StepModelHints, WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow';
|
|
3
|
-
/**
|
|
4
|
-
* Context provided to operation executors during workflow step execution.
|
|
5
|
-
* Includes an optional ranking-driven model selector for AI-powered steps.
|
|
6
|
-
*/
|
|
7
|
-
export interface OperationExecutorContext {
|
|
8
|
-
tenantId?: string;
|
|
9
|
-
role?: string;
|
|
10
|
-
/** Ranking-driven model selector; executors should use this when selecting AI models. */
|
|
11
|
-
modelSelector?: ModelSelector;
|
|
12
|
-
/** Model hints from the current step, if any. */
|
|
13
|
-
stepModelHints?: StepModelHints;
|
|
14
|
-
metadata?: Record<string, unknown>;
|
|
15
|
-
}
|
|
16
|
-
export interface WorkflowExtensionScope {
|
|
17
|
-
tenantId?: string;
|
|
18
|
-
role?: string;
|
|
19
|
-
device?: string;
|
|
20
|
-
}
|
|
21
|
-
export interface StepInjection {
|
|
22
|
-
id?: string;
|
|
23
|
-
after?: string;
|
|
24
|
-
before?: string;
|
|
25
|
-
inject: Step;
|
|
26
|
-
when?: string;
|
|
27
|
-
transitionTo?: string;
|
|
28
|
-
transitionFrom?: string;
|
|
29
|
-
}
|
|
30
|
-
export interface WorkflowExtension extends WorkflowExtensionScope {
|
|
31
|
-
workflow: string;
|
|
32
|
-
baseVersion?: string;
|
|
33
|
-
priority?: number;
|
|
34
|
-
customSteps?: StepInjection[];
|
|
35
|
-
hiddenSteps?: string[];
|
|
36
|
-
metadata?: Record<string, unknown>;
|
|
37
|
-
annotations?: Record<string, unknown>;
|
|
38
|
-
}
|
|
39
|
-
export interface ComposeParams extends WorkflowExtensionScope {
|
|
40
|
-
base: WorkflowSpec;
|
|
41
|
-
}
|
package/dist/validator.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { WorkflowSpec } from '@contractspec/lib.contracts-spec/workflow';
|
|
2
|
-
import type { WorkflowExtension } from './types';
|
|
3
|
-
export interface WorkflowExtensionValidationIssue {
|
|
4
|
-
code: string;
|
|
5
|
-
message: string;
|
|
6
|
-
}
|
|
7
|
-
export declare function validateExtension(extension: WorkflowExtension, base: WorkflowSpec): void;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const WorkflowComposerFeature: import("@contractspec/lib.contracts-spec").FeatureModuleSpec;
|