@toolproof-core/lib 1.0.5 → 1.0.8

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.
Files changed (48) hide show
  1. package/dist/artifacts/artifacts.d.ts +1 -2
  2. package/dist/artifacts/artifacts.d.ts.map +1 -1
  3. package/dist/shared.d.ts +5 -5
  4. package/dist/shared.d.ts.map +1 -1
  5. package/dist/shared.js +5 -5
  6. package/dist/shared.js.map +1 -1
  7. package/dist/utils/bindInputRoleToResource.d.ts +5 -0
  8. package/dist/utils/bindInputRoleToResource.d.ts.map +1 -0
  9. package/dist/utils/bindInputRoleToResource.js +75 -0
  10. package/dist/utils/bindInputRoleToResource.js.map +1 -0
  11. package/dist/utils/createResource.d.ts +9 -0
  12. package/dist/utils/createResource.d.ts.map +1 -0
  13. package/dist/utils/createResource.js +62 -0
  14. package/dist/utils/createResource.js.map +1 -0
  15. package/dist/utils/createRunnableStrategy.d.ts +3 -0
  16. package/dist/utils/createRunnableStrategy.d.ts.map +1 -0
  17. package/dist/utils/createRunnableStrategy.js +23 -0
  18. package/dist/utils/createRunnableStrategy.js.map +1 -0
  19. package/dist/utils/createStep.d.ts +11 -0
  20. package/dist/utils/createStep.d.ts.map +1 -0
  21. package/dist/utils/createStep.js +81 -0
  22. package/dist/utils/createStep.js.map +1 -0
  23. package/dist/utils/extractData.d.ts +11 -0
  24. package/dist/utils/extractData.d.ts.map +1 -0
  25. package/dist/utils/extractData.js +102 -0
  26. package/dist/utils/extractData.js.map +1 -0
  27. package/dist/utils/parallelizeSteps.d.ts +3 -0
  28. package/dist/utils/parallelizeSteps.d.ts.map +1 -0
  29. package/dist/utils/parallelizeSteps.js +137 -0
  30. package/dist/utils/parallelizeSteps.js.map +1 -0
  31. package/dist/utils/resolveResourceChain.d.ts +23 -0
  32. package/dist/utils/resolveResourceChain.d.ts.map +1 -0
  33. package/dist/utils/resolveResourceChain.js +39 -0
  34. package/dist/utils/resolveResourceChain.js.map +1 -0
  35. package/package.json +23 -11
  36. package/src/utils/{roleResourceBinding.ts → bindInputRoleToResource.ts} +8 -6
  37. package/src/utils/createResource.ts +105 -0
  38. package/src/utils/createRunnableStrategy.ts +31 -0
  39. package/src/utils/createStep.ts +111 -0
  40. package/src/utils/{extractFrom.ts → extractData.ts} +54 -2
  41. package/src/utils/{parallelization.ts → parallelizeSteps.ts} +5 -4
  42. package/src/utils/{resourceChain.ts → resolveResourceChain.ts} +11 -10
  43. package/tsconfig.tsbuildinfo +1 -1
  44. package/src/shared.ts +0 -126
  45. package/src/utils/extractFromResourcesByResourceTypeHandle.ts +0 -55
  46. package/src/utils/generateFrom.ts +0 -27
  47. package/src/utils/runnableStrategyCreation.ts +0 -47
  48. package/src/utils/stepCreation.ts +0 -112
@@ -0,0 +1,137 @@
1
+ import { CONSTANTS } from '../artifacts/artifacts.js';
2
+ export function getIndependentThreads(steps, strategyState) {
3
+ const getOwnerLabel = (ownerIndex) => {
4
+ const step = steps[ownerIndex];
5
+ return `steps[${ownerIndex}] stepKind=${step?.stepKind ?? 'unknown'}`;
6
+ };
7
+ // Map each jobStep.identity (including macro-nested job steps) to owning top-level step index.
8
+ const jobStepIdToOwner = new Map();
9
+ const ownerToJobStepIds = new Map();
10
+ const jobStepById = new Map();
11
+ const addJobStep = (jobStep, ownerIndex) => {
12
+ if (!jobStep?.identity)
13
+ return;
14
+ const existingOwner = jobStepIdToOwner.get(jobStep.identity);
15
+ if (existingOwner !== undefined) {
16
+ throw new Error(`Duplicate jobStep.identity '${jobStep.identity}' found in ${getOwnerLabel(ownerIndex)} and ${getOwnerLabel(existingOwner)}`);
17
+ }
18
+ jobStepIdToOwner.set(jobStep.identity, ownerIndex);
19
+ jobStepById.set(jobStep.identity, jobStep);
20
+ const bucket = ownerToJobStepIds.get(ownerIndex) ?? [];
21
+ bucket.push(jobStep.identity);
22
+ ownerToJobStepIds.set(ownerIndex, bucket);
23
+ };
24
+ steps.forEach((step, ownerIndex) => {
25
+ if (step.stepKind === CONSTANTS.Enums.StepKind.job) {
26
+ addJobStep(step, ownerIndex);
27
+ return;
28
+ }
29
+ if (step.stepKind === CONSTANTS.Enums.StepKind.for) {
30
+ const loop = step;
31
+ addJobStep(loop.case?.what, ownerIndex);
32
+ addJobStep(loop.case?.when, ownerIndex);
33
+ return;
34
+ }
35
+ if (step.stepKind === CONSTANTS.Enums.StepKind.while) {
36
+ const loop = step;
37
+ addJobStep(loop.case?.what, ownerIndex);
38
+ addJobStep(loop.case?.when, ownerIndex);
39
+ return;
40
+ }
41
+ if (step.stepKind === CONSTANTS.Enums.StepKind.branch) {
42
+ const branch = step;
43
+ for (const caseItem of branch.cases ?? []) {
44
+ addJobStep(caseItem?.what, ownerIndex);
45
+ addJobStep(caseItem?.when, ownerIndex);
46
+ }
47
+ return;
48
+ }
49
+ });
50
+ // Undirected adjacency used for connected components (thread groups).
51
+ const ownerAdj = new Map();
52
+ // Directed dependencies used for strict ordering validation: owner -> producers it depends on.
53
+ const ownerDeps = new Map();
54
+ const ensureOwner = (ownerIndex) => {
55
+ if (!ownerAdj.has(ownerIndex))
56
+ ownerAdj.set(ownerIndex, new Set());
57
+ if (!ownerDeps.has(ownerIndex))
58
+ ownerDeps.set(ownerIndex, new Set());
59
+ };
60
+ for (let i = 0; i < steps.length; i++) {
61
+ ensureOwner(i);
62
+ }
63
+ // Discover dependencies from strategyState.
64
+ for (const [jobStepId, ownerIndex] of jobStepIdToOwner) {
65
+ ensureOwner(ownerIndex);
66
+ const jobStep = jobStepById.get(jobStepId);
67
+ const inputBindings = jobStep?.roleBindings?.inputBindings ?? [];
68
+ const bucket = strategyState?.[jobStepId] ?? {};
69
+ for (const inputRoleHandle of inputBindings) {
70
+ const entry = bucket?.[inputRoleHandle];
71
+ if (!entry || entry.resourceShellKind !== 'inputPotential')
72
+ continue;
73
+ const creatorJobStepHandle = entry?.creationContext?.jobStepHandle;
74
+ if (!creatorJobStepHandle) {
75
+ throw new Error(`Unresolvable inputPotential in jobStep '${jobStepId}' (${getOwnerLabel(ownerIndex)}): missing creationContext.jobStepHandle for role '${inputRoleHandle}'`);
76
+ }
77
+ const producerOwner = jobStepIdToOwner.get(creatorJobStepHandle);
78
+ if (producerOwner === undefined) {
79
+ throw new Error(`Unresolvable inputPotential in jobStep '${jobStepId}' (${getOwnerLabel(ownerIndex)}): creator jobStepHandle '${creatorJobStepHandle}' not found in strategy steps`);
80
+ }
81
+ ensureOwner(producerOwner);
82
+ ownerAdj.get(ownerIndex).add(producerOwner);
83
+ ownerAdj.get(producerOwner).add(ownerIndex);
84
+ ownerDeps.get(ownerIndex).add(producerOwner);
85
+ }
86
+ }
87
+ // Connected components over owners.
88
+ const visited = new Set();
89
+ const components = [];
90
+ for (let ownerIndex = 0; ownerIndex < steps.length; ownerIndex++) {
91
+ if (visited.has(ownerIndex))
92
+ continue;
93
+ const component = [];
94
+ const queue = [ownerIndex];
95
+ visited.add(ownerIndex);
96
+ while (queue.length > 0) {
97
+ const node = queue.shift();
98
+ component.push(node);
99
+ for (const neighbor of ownerAdj.get(node) ?? []) {
100
+ if (!visited.has(neighbor)) {
101
+ visited.add(neighbor);
102
+ queue.push(neighbor);
103
+ }
104
+ }
105
+ }
106
+ components.push(component);
107
+ }
108
+ // Strict validation: within a thread, the linear order must not contain forward refs.
109
+ for (const comp of components) {
110
+ const compSet = new Set(comp);
111
+ const ownersInOrder = steps.map((_, i) => i).filter((i) => compSet.has(i));
112
+ const position = new Map();
113
+ ownersInOrder.forEach((owner, idx) => position.set(owner, idx));
114
+ for (const consumerOwner of ownersInOrder) {
115
+ const deps = ownerDeps.get(consumerOwner);
116
+ if (!deps || deps.size === 0)
117
+ continue;
118
+ const consumerPos = position.get(consumerOwner);
119
+ for (const producerOwner of deps) {
120
+ const producerPos = position.get(producerOwner);
121
+ if (producerPos === undefined) {
122
+ throw new Error(`Internal error: dependency producer ${getOwnerLabel(producerOwner)} missing from computed thread for ${getOwnerLabel(consumerOwner)}`);
123
+ }
124
+ if (producerPos >= consumerPos) {
125
+ throw new Error(`Invalid step order in thread: ${getOwnerLabel(consumerOwner)} depends on ${getOwnerLabel(producerOwner)}, but producer is not scheduled before consumer`);
126
+ }
127
+ }
128
+ }
129
+ }
130
+ return components
131
+ .map((compOwners) => {
132
+ const ownerSet = new Set(compOwners);
133
+ return steps.filter((_, i) => ownerSet.has(i));
134
+ })
135
+ .filter((group) => group.length > 0);
136
+ }
137
+ //# sourceMappingURL=parallelizeSteps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallelizeSteps.js","sourceRoot":"","sources":["../../src/utils/parallelizeSteps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { CreationContextJson, ResourceJson, ResourceMissingJson, ResourceOutputPotentialJson, StrategyStateJson } from '@toolproof-core/schema';
2
+ import { CONSTANTS } from '../artifacts/artifacts.js';
3
+ export type ResolveResult = {
4
+ status: typeof CONSTANTS.Enums.ResourceShellKind.materialized;
5
+ entry: ResourceJson;
6
+ path: CreationContextJson[];
7
+ } | {
8
+ status: typeof CONSTANTS.Enums.ResourceShellKind.missing;
9
+ entry: ResourceMissingJson;
10
+ path: CreationContextJson[];
11
+ } | {
12
+ status: typeof CONSTANTS.Enums.ResourceShellKind.outputPotential;
13
+ entry: ResourceOutputPotentialJson;
14
+ path: CreationContextJson[];
15
+ } | {
16
+ status: 'unresolved';
17
+ reason: 'not-found' | 'cycle' | 'depth-exceeded';
18
+ path: CreationContextJson[];
19
+ };
20
+ export declare function resolveResourceChain(strategyState: StrategyStateJson, start: CreationContextJson, opts?: {
21
+ maxDepth?: number;
22
+ }): ResolveResult;
23
+ //# sourceMappingURL=resolveResourceChain.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveResourceChain.d.ts","sourceRoot":"","sources":["../../src/utils/resolveResourceChain.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,EAEnB,2BAA2B,EAC3B,iBAAiB,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAEtD,MAAM,MAAM,aAAa,GACnB;IAAE,MAAM,EAAE,OAAO,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,YAAY,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,mBAAmB,EAAE,CAAA;CAAE,GACnH;IAAE,MAAM,EAAE,OAAO,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,mBAAmB,EAAE,CAAA;CAAE,GACrH;IAAE,MAAM,EAAE,OAAO,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,eAAe,CAAC;IAAC,KAAK,EAAE,2BAA2B,CAAC;IAAC,IAAI,EAAE,mBAAmB,EAAE,CAAA;CAAE,GACrI;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,OAAO,GAAG,gBAAgB,CAAC;IAAC,IAAI,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC;AAE9G,wBAAgB,oBAAoB,CAChC,aAAa,EAAE,iBAAiB,EAChC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,aAAa,CA8Cf"}
@@ -0,0 +1,39 @@
1
+ import { CONSTANTS } from '../artifacts/artifacts.js';
2
+ export function resolveResourceChain(strategyState, start, opts) {
3
+ const maxDepth = opts?.maxDepth ?? 50;
4
+ const visited = new Set();
5
+ const path = [];
6
+ let current = start;
7
+ for (let depth = 0; depth <= maxDepth; depth++) {
8
+ path.push(current);
9
+ const visitKey = `${current.jobStepHandle}::${current.resourceRoleHandle}`;
10
+ if (visited.has(visitKey)) {
11
+ return { status: 'unresolved', reason: 'cycle', path };
12
+ }
13
+ visited.add(visitKey);
14
+ const bucket = strategyState[current.jobStepHandle];
15
+ if (!bucket)
16
+ return { status: 'unresolved', reason: 'not-found', path };
17
+ const entry = bucket[current.resourceRoleHandle];
18
+ if (!entry)
19
+ return { status: 'unresolved', reason: 'not-found', path };
20
+ if (entry.resourceShellKind === CONSTANTS.Enums.ResourceShellKind.materialized) {
21
+ return { status: CONSTANTS.Enums.ResourceShellKind.materialized, entry: entry, path };
22
+ }
23
+ if (entry.resourceShellKind === CONSTANTS.Enums.ResourceShellKind.missing) {
24
+ return { status: CONSTANTS.Enums.ResourceShellKind.missing, entry: entry, path };
25
+ }
26
+ if (entry.resourceShellKind === CONSTANTS.Enums.ResourceShellKind.outputPotential) {
27
+ return { status: CONSTANTS.Enums.ResourceShellKind.outputPotential, entry: entry, path };
28
+ }
29
+ // inputPotential: follow ref backwards
30
+ if (entry.resourceShellKind === CONSTANTS.Enums.ResourceShellKind.inputPotential) {
31
+ current = entry.creationContext;
32
+ continue;
33
+ }
34
+ // Unknown case
35
+ return { status: 'unresolved', reason: 'not-found', path };
36
+ }
37
+ return { status: 'unresolved', reason: 'depth-exceeded', path };
38
+ }
39
+ //# sourceMappingURL=resolveResourceChain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveResourceChain.js","sourceRoot":"","sources":["../../src/utils/resolveResourceChain.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAQtD,MAAM,UAAU,oBAAoB,CAChC,aAAgC,EAChC,KAA0B,EAC1B,IAA4B;IAE5B,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,IAAI,GAA0B,EAAE,CAAC;IACvC,IAAI,OAAO,GAAwB,KAAK,CAAC;IAEzC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnB,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,aAAa,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxB,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3D,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEtB,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM;YAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QACxE,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAM9C,CAAC;QACF,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAEvE,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,YAAY,EAAE,CAAC;YAC7E,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,YAAY,EAAE,KAAK,EAAE,KAAqB,EAAE,IAAI,EAAE,CAAC;QAC1G,CAAC;QACD,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACxE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAAE,KAA4B,EAAE,IAAI,EAAE,CAAC;QAC5G,CAAC;QACD,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,eAAe,EAAE,CAAC;YAChF,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,eAAe,EAAE,KAAK,EAAE,KAAoC,EAAE,IAAI,EAAE,CAAC;QAC5H,CAAC;QAED,uCAAuC;QACvC,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,KAAK,CAAC,iBAAiB,CAAC,cAAc,EAAE,CAAC;YAC/E,OAAO,GAAI,KAAoC,CAAC,eAAe,CAAC;YAChE,SAAS;QACb,CAAC;QAED,eAAe;QACf,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;AACpE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolproof-core/lib",
3
- "version": "1.0.5",
3
+ "version": "1.0.8",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -15,17 +15,29 @@
15
15
  "types": "./dist/types/types.d.ts",
16
16
  "import": "./dist/types/types.js"
17
17
  },
18
- "./extract-from": {
19
- "types": "./dist/utils/extractFrom.d.ts",
20
- "import": "./dist/utils/extractFrom.js"
18
+ "./extract-data": {
19
+ "types": "./dist/utils/extractData.d.ts",
20
+ "import": "./dist/utils/extractData.js"
21
21
  },
22
- "./extract-from-resources-by-resource-type-handle": {
23
- "types": "./dist/utils/extractFromResourcesByResourceTypeHandle.d.ts",
24
- "import": "./dist/utils/extractFromResourcesByResourceTypeHandle.js"
22
+ "./create-resource": {
23
+ "types": "./dist/utils/createResource.d.ts",
24
+ "import": "./dist/utils/createResource.js"
25
25
  },
26
- "./generate-from": {
27
- "types": "./dist/utils/generateFrom.d.ts",
28
- "import": "./dist/utils/generateFrom.js"
26
+ "./create-step": {
27
+ "types": "./dist/utils/createStep.d.ts",
28
+ "import": "./dist/utils/createStep.js"
29
+ },
30
+ "./create-runnable-strategy": {
31
+ "types": "./dist/utils/createRunnableStrategy.d.ts",
32
+ "import": "./dist/utils/createRunnableStrategy.js"
33
+ },
34
+ "./resolve-resource-chain": {
35
+ "types": "./dist/utils/resolveResourceChain.d.ts",
36
+ "import": "./dist/utils/resolveResourceChain.js"
37
+ },
38
+ "./bind-input-role-to-resource": {
39
+ "types": "./dist/utils/bindInputRoleToResource.d.ts",
40
+ "import": "./dist/utils/bindInputRoleToResource.js"
29
41
  },
30
42
  "./firebase-admin-init": {
31
43
  "types": "./dist/_lib/setup/firebaseAdminInit.d.ts",
@@ -44,7 +56,7 @@
44
56
  "@types/node": "^22.0.0"
45
57
  },
46
58
  "dependencies": {
47
- "@toolproof-core/schema": "^1.0.11",
59
+ "@toolproof-core/schema": "^1.0.16",
48
60
  "firebase-admin": "^13.7.0"
49
61
  },
50
62
  "scripts": {
@@ -6,7 +6,9 @@ import type {
6
6
  CreationContextJson,
7
7
  StrategyStateJson,
8
8
  } from '@toolproof-core/schema';
9
- import { resolveResourceChain } from './resourceChain.js';
9
+ import { CONSTANTS } from '../artifacts/artifacts.js';
10
+ import { resolveResourceChain } from './resolveResourceChain.js';
11
+
10
12
 
11
13
  export function bindInputResInStrategyState(
12
14
  strategyState: StrategyStateJson,
@@ -42,7 +44,7 @@ export function bindInputRefInStrategyState(
42
44
  const result = resolveResourceChain(strategyState, source);
43
45
  const bucket = strategyState[target.jobStepHandle] ?? {};
44
46
 
45
- if (result.status === 'materialized') {
47
+ if (result.status === CONSTANTS.Enums.ResourceShellKind.materialized) {
46
48
  return {
47
49
  ...strategyState,
48
50
  [target.jobStepHandle]: {
@@ -52,12 +54,12 @@ export function bindInputRefInStrategyState(
52
54
  };
53
55
  }
54
56
 
55
- if (result.status === 'missing') {
57
+ if (result.status === CONSTANTS.Enums.ResourceShellKind.missing) {
56
58
  const missing = result.entry;
57
59
  const reusedMissing: ResourceMissingJson = {
58
60
  identity: missing.identity,
59
61
  resourceTypeHandle: missing.resourceTypeHandle,
60
- resourceShellKind: 'missing',
62
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.missing,
61
63
  };
62
64
 
63
65
  return {
@@ -69,7 +71,7 @@ export function bindInputRefInStrategyState(
69
71
  };
70
72
  }
71
73
 
72
- if (result.status === 'outputPotential') {
74
+ if (result.status === CONSTANTS.Enums.ResourceShellKind.outputPotential) {
73
75
  const potentialInput: ResourceInputPotentialJson = {
74
76
  identity: sourceEntry.identity,
75
77
  resourceTypeHandle: sourceEntry.resourceTypeHandle,
@@ -77,7 +79,7 @@ export function bindInputRefInStrategyState(
77
79
  jobStepHandle: source.jobStepHandle,
78
80
  resourceRoleHandle: source.resourceRoleHandle,
79
81
  },
80
- resourceShellKind: 'inputPotential',
82
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.inputPotential,
81
83
  };
82
84
 
83
85
  return {
@@ -0,0 +1,105 @@
1
+ import type {
2
+ CreationContextJson,
3
+ ResourceIdentityJson,
4
+ ResourceInputPotentialJson,
5
+ ResourceJson,
6
+ ResourceMissingJson,
7
+ ResourceOutputPotentialJson,
8
+ ResourceTypeIdentityJson,
9
+ } from '@toolproof-core/schema';
10
+ import { CONSTANTS } from '../artifacts/artifacts.js';
11
+
12
+
13
+ export function generatePath(resourceTypeHandle: ResourceTypeIdentityJson, identity: ResourceIdentityJson): string {
14
+ return `${resourceTypeHandle}/${identity}.json`;
15
+ }
16
+
17
+ export function createMaterializedFromOutputPotential(
18
+ outputPotential: ResourceOutputPotentialJson,
19
+ nucleus: unknown,
20
+ timestamp?: string
21
+ ): ResourceJson {
22
+ const { identity, resourceTypeHandle, creationContext } = outputPotential;
23
+
24
+ const path = generatePath(resourceTypeHandle, identity);
25
+
26
+ return {
27
+ identity,
28
+ resourceTypeHandle,
29
+ creationContext,
30
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.materialized,
31
+ version: 1,
32
+ timestamp: timestamp ?? new Date().toISOString(), // Preserve original timestamp when copying
33
+ path,
34
+ nucleus,
35
+ };
36
+ }
37
+
38
+ export function createMaterializedFromInputPotential(
39
+ inputPotential: ResourceInputPotentialJson,
40
+ nucleus: unknown,
41
+ timestamp?: string
42
+ ): ResourceJson {
43
+ const { identity, resourceTypeHandle, creationContext } = inputPotential;
44
+
45
+ const path = generatePath(resourceTypeHandle, identity);
46
+
47
+ return {
48
+ identity,
49
+ resourceTypeHandle,
50
+ creationContext,
51
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.materialized,
52
+ version: 1,
53
+ timestamp: timestamp ?? new Date().toISOString(),
54
+ path,
55
+ nucleus,
56
+ };
57
+ }
58
+
59
+ export function createMaterializedFromPotential(
60
+ potential: ResourceInputPotentialJson | ResourceOutputPotentialJson,
61
+ nucleus: unknown,
62
+ timestamp?: string
63
+ ): ResourceJson {
64
+ if (potential.resourceShellKind === CONSTANTS.Enums.ResourceShellKind.inputPotential) {
65
+ return createMaterializedFromInputPotential(potential, nucleus, timestamp);
66
+ }
67
+ return createMaterializedFromOutputPotential(potential, nucleus, timestamp);
68
+ }
69
+
70
+ export function createMissing(
71
+ identity: ResourceIdentityJson,
72
+ resourceTypeHandle: ResourceTypeIdentityJson
73
+ ): ResourceMissingJson {
74
+ return {
75
+ identity,
76
+ resourceTypeHandle,
77
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.missing,
78
+ };
79
+ }
80
+
81
+ export function createInputPotential(
82
+ identity: ResourceIdentityJson,
83
+ resourceTypeHandle: ResourceTypeIdentityJson,
84
+ creationContext: CreationContextJson
85
+ ): ResourceInputPotentialJson {
86
+ return {
87
+ identity,
88
+ resourceTypeHandle,
89
+ creationContext,
90
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.inputPotential,
91
+ };
92
+ }
93
+
94
+ export function createOutputPotential(
95
+ identity: ResourceIdentityJson,
96
+ resourceTypeHandle: ResourceTypeIdentityJson,
97
+ creationContext: CreationContextJson
98
+ ): ResourceOutputPotentialJson {
99
+ return {
100
+ identity,
101
+ resourceTypeHandle,
102
+ creationContext,
103
+ resourceShellKind: CONSTANTS.Enums.ResourceShellKind.outputPotential,
104
+ };
105
+ }
@@ -0,0 +1,31 @@
1
+ import type {
2
+ RawStrategyJson,
3
+ RunnableStrategyJson,
4
+ StrategyThreadDictJson
5
+ } from '@toolproof-core/schema';
6
+ import { CONSTANTS } from '../artifacts/artifacts.js';
7
+ import { getNewIdentity } from '../firebase/firebaseAdminHelpers.js';
8
+ import { getIndependentThreads } from './parallelizeSteps.js';
9
+
10
+ export function createRunnableStrategy(rawStrategy: RawStrategyJson): RunnableStrategyJson {
11
+ const runnableStrategyIdentity = getNewIdentity(CONSTANTS.Names.RunnableStrategyIdentity);
12
+ const steps = rawStrategy.steps;
13
+ const strategyState = rawStrategy.strategyState;
14
+
15
+ const threadStepGroups = getIndependentThreads(steps, strategyState);
16
+ const strategyThreadDict: StrategyThreadDictJson = {};
17
+
18
+ for (const group of threadStepGroups) {
19
+ const threadIdentity = getNewIdentity(CONSTANTS.Names.StrategyThreadIdentity);
20
+ strategyThreadDict[threadIdentity] = group;
21
+ }
22
+
23
+ return {
24
+ identity: runnableStrategyIdentity,
25
+ runnableStrategyContext: {
26
+ status: CONSTANTS.Enums.RunnableStrategyStatus.pending,
27
+ },
28
+ strategyThreadDict,
29
+ strategyState,
30
+ };
31
+ }
@@ -0,0 +1,111 @@
1
+ import type {
2
+ BranchStepJson,
3
+ CaseJson,
4
+ ForStepJson,
5
+ JobJson,
6
+ JobStepJson,
7
+ ResourceRoleIdentityJson,
8
+ WhileStepJson,
9
+ } from '@toolproof-core/schema';
10
+ import { CONSTANTS } from '../artifacts/artifacts.js';
11
+ import { getNewStepIdentity } from '../firebase/firebaseAdminHelpers.js';
12
+
13
+
14
+ function assertNonEmpty<T>(arr: T[], msg: string): asserts arr is [T, ...T[]] {
15
+ if (arr.length === 0) throw new Error(msg);
16
+ }
17
+
18
+
19
+ export function createJobStepFromJob(job: JobJson): JobStepJson {
20
+ const inputBindings = Object.keys(job.roles.inputDict) as ResourceRoleIdentityJson[];
21
+ const outputBindings = Object.keys(job.roles.outputDict) as ResourceRoleIdentityJson[];
22
+
23
+ return {
24
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.job),
25
+ stepKind: CONSTANTS.Enums.StepKind.job,
26
+ jobHandle: job.identity,
27
+ roleBindings: {
28
+ inputBindings,
29
+ outputBindings,
30
+ },
31
+ };
32
+ }
33
+
34
+
35
+ export function createLoopStepFromJobPair(
36
+ whatJob: JobJson,
37
+ whenJob: JobJson,
38
+ stepKind: typeof CONSTANTS.Enums.StepKind.for | typeof CONSTANTS.Enums.StepKind.while
39
+ ): ForStepJson | WhileStepJson {
40
+ const what = createJobStepFromJob(whatJob);
41
+ const when = createJobStepFromJob(whenJob);
42
+
43
+ if (stepKind === CONSTANTS.Enums.StepKind.for) {
44
+ return {
45
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.for),
46
+ stepKind: CONSTANTS.Enums.StepKind.for,
47
+ case: { what, when },
48
+ };
49
+ }
50
+
51
+ return {
52
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.while),
53
+ stepKind: CONSTANTS.Enums.StepKind.while,
54
+ case: { what, when },
55
+ };
56
+ }
57
+
58
+
59
+ export function createBranchStepFromJobPairs(
60
+ cases: Array<{ whatJob: JobJson; whenJob: JobJson }>
61
+ ): BranchStepJson {
62
+ const resolved = cases.map(({ whatJob, whenJob }) => {
63
+ const what = createJobStepFromJob(whatJob);
64
+ const when = createJobStepFromJob(whenJob);
65
+ return { what, when } satisfies CaseJson;
66
+ });
67
+
68
+ assertNonEmpty(resolved, 'createBranchStepFromJobPairs requires at least one case'); // ATTENTION_IMPURE
69
+
70
+ return {
71
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.branch),
72
+ stepKind: CONSTANTS.Enums.StepKind.branch,
73
+ cases: resolved,
74
+ };
75
+ }
76
+
77
+
78
+ export function cloneForStep(forStep: ForStepJson): ForStepJson {
79
+ return {
80
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.for),
81
+ stepKind: CONSTANTS.Enums.StepKind.for,
82
+ case: {
83
+ what: {
84
+ ...forStep.case.what,
85
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.job),
86
+ },
87
+ when: {
88
+ ...forStep.case.when,
89
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.job),
90
+ },
91
+ },
92
+ };
93
+ }
94
+
95
+
96
+ export function cloneWhileStep(whileStep: WhileStepJson): WhileStepJson {
97
+ return {
98
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.while),
99
+ stepKind: CONSTANTS.Enums.StepKind.while,
100
+ case: {
101
+ what: {
102
+ ...whileStep.case.what,
103
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.job),
104
+ },
105
+ when: {
106
+ ...whileStep.case.when,
107
+ identity: getNewStepIdentity(CONSTANTS.Enums.StepKind.job),
108
+ },
109
+ },
110
+ };
111
+ }
@@ -7,7 +7,9 @@ import type {
7
7
  StepJson,
8
8
  ResourceRoleIdentityJson,
9
9
  ResourceRoleJson,
10
- ErrorJson
10
+ ResourceIdentityJson,
11
+ ResourceTypeIdentityJson,
12
+ ResourceJson,
11
13
  } from '@toolproof-core/schema';
12
14
  import { CONSTANTS } from '../artifacts/artifacts.js';
13
15
 
@@ -90,4 +92,54 @@ export function extractResourceRolesFromRawStrategy(rawStrategy: RawStrategyJson
90
92
  }
91
93
 
92
94
  return Array.from(map.values());
93
- }
95
+ }
96
+
97
+
98
+ export function extractResourceMapForResourceType<TResource extends ResourceJson = ResourceJson>(
99
+ resourcesByResourceTypeHandle: Partial<Record<ResourceTypeIdentityJson, TResource[]>>,
100
+ resourceTypeHandle: ResourceTypeIdentityJson
101
+ ): Map<ResourceIdentityJson, TResource> {
102
+ const resources = resourcesByResourceTypeHandle[resourceTypeHandle] ?? [];
103
+ const map = new Map<ResourceIdentityJson, TResource>();
104
+
105
+ for (const resource of resources) {
106
+ map.set(resource.identity, resource);
107
+ }
108
+
109
+ return map;
110
+ }
111
+
112
+ // ATTENTION: should only need standalone type as type parameter, then we could extract the nuclueus type and identity type
113
+ export function extractNucleusMapForResourceType<
114
+ TKey extends string = string,
115
+ TNucleus extends { identity: string | number | boolean } = { identity: string | number | boolean },
116
+ TResource extends ResourceJson = ResourceJson
117
+ >(
118
+ resourcesByResourceTypeHandle: Partial<Record<ResourceTypeIdentityJson, TResource[]>>,
119
+ resourceTypeHandle: ResourceTypeIdentityJson,
120
+ ): Map<TKey, TNucleus> {
121
+ const resourceMap = extractResourceMapForResourceType<TResource>(resourcesByResourceTypeHandle, resourceTypeHandle);
122
+ const out = new Map<TKey, TNucleus>();
123
+
124
+ for (const resource of resourceMap.values()) {
125
+ const data = (resource as any).nucleus as unknown;
126
+ if (data === null || data === undefined) {
127
+ continue;
128
+ }
129
+ if (typeof data !== 'object') {
130
+ continue;
131
+ }
132
+
133
+ const maybeIdentity = (data as any).identity as unknown;
134
+ if (maybeIdentity === null || maybeIdentity === undefined) {
135
+ continue;
136
+ }
137
+
138
+ const value = data as TNucleus;
139
+ const key = String(maybeIdentity) as TKey;
140
+
141
+ out.set(key, value);
142
+ }
143
+
144
+ return out;
145
+ }