@contractspec/example.workflow-system 3.8.9 → 3.8.11

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 (95) hide show
  1. package/dist/approval/approval.enum.js +1 -22
  2. package/dist/approval/approval.event.js +1 -112
  3. package/dist/approval/approval.operations.js +1 -369
  4. package/dist/approval/approval.schema.js +1 -73
  5. package/dist/approval/index.js +1 -484
  6. package/dist/browser/approval/approval.enum.js +1 -22
  7. package/dist/browser/approval/approval.event.js +1 -112
  8. package/dist/browser/approval/approval.operations.js +1 -369
  9. package/dist/browser/approval/approval.schema.js +1 -73
  10. package/dist/browser/approval/index.js +1 -484
  11. package/dist/browser/docs/index.js +5 -49
  12. package/dist/browser/docs/workflow-system.docblock.js +5 -49
  13. package/dist/browser/entities/approval.js +1 -119
  14. package/dist/browser/entities/index.js +1 -508
  15. package/dist/browser/entities/instance.js +1 -161
  16. package/dist/browser/entities/step.js +1 -124
  17. package/dist/browser/entities/workflow.js +1 -82
  18. package/dist/browser/example.js +1 -42
  19. package/dist/browser/handlers/index.js +8 -253
  20. package/dist/browser/handlers/workflow.handlers.js +8 -253
  21. package/dist/browser/index.js +13 -3524
  22. package/dist/browser/instance/index.js +1 -677
  23. package/dist/browser/instance/instance.enum.js +1 -15
  24. package/dist/browser/instance/instance.event.js +1 -164
  25. package/dist/browser/instance/instance.handler.js +1 -356
  26. package/dist/browser/instance/instance.operations.js +1 -9
  27. package/dist/browser/instance/instance.schema.js +1 -101
  28. package/dist/browser/presentations/index.js +1 -109
  29. package/dist/browser/seeders/index.js +1 -3
  30. package/dist/browser/shared/demo-scenario.js +1 -213
  31. package/dist/browser/shared/index.js +1 -3
  32. package/dist/browser/shared/mock-data.js +1 -11
  33. package/dist/browser/state-machine/index.js +1 -6
  34. package/dist/browser/tests/operations.test-spec.js +1 -6
  35. package/dist/browser/ui/WorkflowDashboard.js +1 -3
  36. package/dist/browser/ui/WorkflowDashboard.visualizations.js +1 -239
  37. package/dist/browser/ui/hooks/index.js +1 -3
  38. package/dist/browser/ui/hooks/useWorkflowList.js +1 -52
  39. package/dist/browser/ui/index.js +1 -56
  40. package/dist/browser/ui/renderers/index.js +5 -562
  41. package/dist/browser/ui/renderers/workflow.markdown.js +5 -562
  42. package/dist/browser/visualizations/catalog.js +1 -132
  43. package/dist/browser/visualizations/index.js +1 -133
  44. package/dist/browser/visualizations/selectors.js +1 -195
  45. package/dist/browser/workflow/index.js +1 -21
  46. package/dist/browser/workflow/workflow.enum.js +1 -36
  47. package/dist/browser/workflow/workflow.event.js +1 -6
  48. package/dist/browser/workflow/workflow.handler.js +1 -5
  49. package/dist/browser/workflow/workflow.operations.js +1 -8
  50. package/dist/browser/workflow/workflow.schema.js +1 -151
  51. package/dist/browser/workflow-system.capability.js +1 -5
  52. package/dist/browser/workflow-system.feature.js +1 -3
  53. package/dist/docs/index.js +5 -49
  54. package/dist/docs/workflow-system.docblock.js +5 -49
  55. package/dist/entities/approval.js +1 -119
  56. package/dist/entities/index.js +1 -508
  57. package/dist/entities/instance.js +1 -161
  58. package/dist/entities/step.js +1 -124
  59. package/dist/entities/workflow.js +1 -82
  60. package/dist/example.js +1 -42
  61. package/dist/handlers/index.js +8 -253
  62. package/dist/handlers/workflow.handlers.js +8 -253
  63. package/dist/index.js +13 -3524
  64. package/dist/instance/index.js +1 -677
  65. package/dist/instance/instance.enum.js +1 -15
  66. package/dist/instance/instance.event.js +1 -164
  67. package/dist/instance/instance.handler.js +1 -356
  68. package/dist/instance/instance.operations.js +1 -9
  69. package/dist/instance/instance.schema.js +1 -101
  70. package/dist/presentations/index.js +1 -109
  71. package/dist/seeders/index.js +1 -3
  72. package/dist/shared/demo-scenario.js +1 -213
  73. package/dist/shared/index.js +1 -3
  74. package/dist/shared/mock-data.js +1 -11
  75. package/dist/state-machine/index.js +1 -6
  76. package/dist/tests/operations.test-spec.js +1 -6
  77. package/dist/ui/WorkflowDashboard.js +1 -3
  78. package/dist/ui/WorkflowDashboard.visualizations.js +1 -239
  79. package/dist/ui/hooks/index.js +1 -3
  80. package/dist/ui/hooks/useWorkflowList.js +1 -52
  81. package/dist/ui/index.js +1 -56
  82. package/dist/ui/renderers/index.js +5 -562
  83. package/dist/ui/renderers/workflow.markdown.js +5 -562
  84. package/dist/visualizations/catalog.js +1 -132
  85. package/dist/visualizations/index.js +1 -133
  86. package/dist/visualizations/selectors.js +1 -195
  87. package/dist/workflow/index.js +1 -21
  88. package/dist/workflow/workflow.enum.js +1 -36
  89. package/dist/workflow/workflow.event.js +1 -6
  90. package/dist/workflow/workflow.handler.js +1 -5
  91. package/dist/workflow/workflow.operations.js +1 -8
  92. package/dist/workflow/workflow.schema.js +1 -151
  93. package/dist/workflow-system.capability.js +1 -5
  94. package/dist/workflow-system.feature.js +1 -3
  95. package/package.json +8 -8
@@ -1,254 +1,9 @@
1
1
  // @bun
2
- // src/handlers/workflow.handlers.ts
3
- import { web } from "@contractspec/lib.runtime-sandbox";
4
- var { generateId } = web;
5
- function rowToDefinition(row) {
6
- return {
7
- id: row.id,
8
- projectId: row.projectId,
9
- organizationId: row.organizationId,
10
- name: row.name,
11
- description: row.description ?? undefined,
12
- type: row.type,
13
- status: row.status,
14
- createdAt: new Date(row.createdAt),
15
- updatedAt: new Date(row.updatedAt)
16
- };
17
- }
18
- function rowToStep(row) {
19
- return {
20
- id: row.id,
21
- definitionId: row.definitionId,
22
- name: row.name,
23
- description: row.description ?? undefined,
24
- stepOrder: row.stepOrder,
25
- type: row.type,
26
- requiredRoles: row.requiredRoles ? JSON.parse(row.requiredRoles) : [],
27
- autoApproveCondition: row.autoApproveCondition ?? undefined,
28
- timeoutHours: row.timeoutHours ?? undefined,
29
- createdAt: new Date(row.createdAt)
30
- };
31
- }
32
- function rowToInstance(row) {
33
- return {
34
- id: row.id,
35
- projectId: row.projectId,
36
- definitionId: row.definitionId,
37
- status: row.status,
38
- currentStepId: row.currentStepId ?? undefined,
39
- data: row.data ? JSON.parse(row.data) : undefined,
40
- requestedBy: row.requestedBy,
41
- startedAt: new Date(row.startedAt),
42
- completedAt: row.completedAt ? new Date(row.completedAt) : undefined
43
- };
44
- }
45
- function rowToApproval(row) {
46
- return {
47
- id: row.id,
48
- instanceId: row.instanceId,
49
- stepId: row.stepId,
50
- status: row.status,
51
- actorId: row.actorId ?? undefined,
52
- comment: row.comment ?? undefined,
53
- decidedAt: row.decidedAt ? new Date(row.decidedAt) : undefined,
54
- createdAt: new Date(row.createdAt)
55
- };
56
- }
57
- function createWorkflowHandlers(db) {
58
- function normalizeSql(sql) {
59
- let placeholderIndex = 0;
60
- return sql.replace(/\?/g, () => `$${++placeholderIndex}`);
61
- }
62
- async function queryRows(sql, params = []) {
63
- return (await db.query(normalizeSql(sql), params)).rows;
64
- }
65
- async function execute(sql, params = []) {
66
- await db.execute(normalizeSql(sql), params);
67
- }
68
- async function listDefinitions(input) {
69
- const { projectId, status, search, limit = 20, offset = 0 } = input;
70
- let whereClause = 'WHERE "projectId" = ?';
71
- const params = [projectId];
72
- if (status && status !== "all") {
73
- whereClause += " AND status = ?";
74
- params.push(status);
75
- }
76
- if (search) {
77
- whereClause += " AND name LIKE ?";
78
- params.push(`%${search}%`);
79
- }
80
- const countResult = await queryRows(`SELECT COUNT(*) as count FROM workflow_definition ${whereClause}`, params);
81
- const total = countResult[0]?.count ?? 0;
82
- const rows = await queryRows(`SELECT * FROM workflow_definition ${whereClause} ORDER BY "updatedAt" DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
83
- return {
84
- definitions: rows.map(rowToDefinition),
85
- total
86
- };
87
- }
88
- async function createDefinition(input, context) {
89
- const id = generateId("wfdef");
90
- const now = new Date().toISOString();
91
- await execute(`INSERT INTO workflow_definition (id, "projectId", "organizationId", name, description, type, status, "createdAt", "updatedAt")
92
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
93
- id,
94
- context.projectId,
95
- context.organizationId,
96
- input.name,
97
- input.description ?? null,
98
- input.type ?? "APPROVAL",
99
- "DRAFT",
100
- now,
101
- now
102
- ]);
103
- const rows = await queryRows(`SELECT * FROM workflow_definition WHERE id = ?`, [id]);
104
- return rowToDefinition(rows[0]);
105
- }
106
- async function addStep(input) {
107
- const id = generateId("wfstep");
108
- const now = new Date().toISOString();
109
- const maxOrderResult = await queryRows(`SELECT MAX("stepOrder") as maxOrder FROM workflow_step WHERE "definitionId" = ?`, [input.definitionId]);
110
- const nextOrder = (maxOrderResult[0]?.maxOrder ?? 0) + 1;
111
- await execute(`INSERT INTO workflow_step (id, "definitionId", name, description, "stepOrder", type, "requiredRoles", "autoApproveCondition", "timeoutHours", "createdAt")
112
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
113
- id,
114
- input.definitionId,
115
- input.name,
116
- input.description ?? null,
117
- nextOrder,
118
- input.type ?? "APPROVAL",
119
- JSON.stringify(input.requiredRoles),
120
- input.autoApproveCondition ?? null,
121
- input.timeoutHours ?? null,
122
- now
123
- ]);
124
- const rows = await queryRows(`SELECT * FROM workflow_step WHERE id = ?`, [id]);
125
- return rowToStep(rows[0]);
126
- }
127
- async function getSteps(definitionId) {
128
- const rows = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder"`, [definitionId]);
129
- return rows.map(rowToStep);
130
- }
131
- async function listInstances(input) {
132
- const {
133
- projectId,
134
- definitionId,
135
- status,
136
- requestedBy,
137
- limit = 20,
138
- offset = 0
139
- } = input;
140
- let whereClause = 'WHERE "projectId" = ?';
141
- const params = [projectId];
142
- if (definitionId) {
143
- whereClause += ' AND "definitionId" = ?';
144
- params.push(definitionId);
145
- }
146
- if (status && status !== "all") {
147
- whereClause += " AND status = ?";
148
- params.push(status);
149
- }
150
- if (requestedBy) {
151
- whereClause += ' AND "requestedBy" = ?';
152
- params.push(requestedBy);
153
- }
154
- const countResult = await queryRows(`SELECT COUNT(*) as count FROM workflow_instance ${whereClause}`, params);
155
- const total = countResult[0]?.count ?? 0;
156
- const rows = await queryRows(`SELECT * FROM workflow_instance ${whereClause} ORDER BY "startedAt" DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
157
- return {
158
- instances: rows.map(rowToInstance),
159
- total
160
- };
161
- }
162
- async function startInstance(input, context) {
163
- const id = generateId("wfinst");
164
- const now = new Date().toISOString();
165
- const steps = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder" LIMIT 1`, [input.definitionId]);
166
- const firstStepId = steps[0]?.id ?? null;
167
- await execute(`INSERT INTO workflow_instance (id, "projectId", "definitionId", status, "currentStepId", data, "requestedBy", "startedAt")
168
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
169
- id,
170
- context.projectId,
171
- input.definitionId,
172
- firstStepId ? "IN_PROGRESS" : "PENDING",
173
- firstStepId,
174
- input.data ? JSON.stringify(input.data) : null,
175
- context.requestedBy,
176
- now
177
- ]);
178
- if (firstStepId) {
179
- await execute(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
180
- VALUES (?, ?, ?, ?, ?)`, [generateId("wfappr"), id, firstStepId, "PENDING", now]);
181
- }
182
- const rows = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [id]);
183
- return rowToInstance(rows[0]);
184
- }
185
- async function approveStep(input, context) {
186
- const now = new Date().toISOString();
187
- const instances = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
188
- if (!instances[0]) {
189
- throw new Error("NOT_FOUND");
190
- }
191
- const instance = instances[0];
192
- await execute(`UPDATE workflow_approval SET status = 'APPROVED', "actorId" = ?, comment = ?, "decidedAt" = ?
193
- WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`, [
194
- context.actorId,
195
- input.comment ?? null,
196
- now,
197
- input.instanceId,
198
- instance.currentStepId
199
- ]);
200
- const currentStep = await queryRows(`SELECT * FROM workflow_step WHERE id = ?`, [instance.currentStepId]);
201
- const nextSteps = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? AND "stepOrder" > ? ORDER BY "stepOrder" LIMIT 1`, [instance.definitionId, currentStep[0]?.stepOrder ?? 0]);
202
- if (nextSteps[0]) {
203
- await execute(`UPDATE workflow_instance SET "currentStepId" = ? WHERE id = ?`, [nextSteps[0].id, input.instanceId]);
204
- await execute(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
205
- VALUES (?, ?, ?, ?, ?)`, [
206
- generateId("wfappr"),
207
- input.instanceId,
208
- nextSteps[0].id,
209
- "PENDING",
210
- now
211
- ]);
212
- } else {
213
- await execute(`UPDATE workflow_instance SET status = 'COMPLETED', "currentStepId" = NULL, "completedAt" = ? WHERE id = ?`, [now, input.instanceId]);
214
- }
215
- const updated = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
216
- return rowToInstance(updated[0]);
217
- }
218
- async function rejectStep(input, context) {
219
- const now = new Date().toISOString();
220
- const instances = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
221
- if (!instances[0]) {
222
- throw new Error("NOT_FOUND");
223
- }
224
- await execute(`UPDATE workflow_approval SET status = 'REJECTED', "actorId" = ?, comment = ?, "decidedAt" = ?
225
- WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`, [
226
- context.actorId,
227
- input.reason,
228
- now,
229
- input.instanceId,
230
- instances[0].currentStepId
231
- ]);
232
- await execute(`UPDATE workflow_instance SET status = 'REJECTED', "completedAt" = ? WHERE id = ?`, [now, input.instanceId]);
233
- const updated = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
234
- return rowToInstance(updated[0]);
235
- }
236
- async function getApprovals(instanceId) {
237
- const rows = await queryRows(`SELECT * FROM workflow_approval WHERE "instanceId" = ? ORDER BY "createdAt"`, [instanceId]);
238
- return rows.map(rowToApproval);
239
- }
240
- return {
241
- listDefinitions,
242
- createDefinition,
243
- addStep,
244
- getSteps,
245
- listInstances,
246
- startInstance,
247
- approveStep,
248
- rejectStep,
249
- getApprovals
250
- };
251
- }
252
- export {
253
- createWorkflowHandlers
254
- };
2
+ import{web as g}from"@contractspec/lib.runtime-sandbox";var{generateId:U}=g;function Z(k){return{id:k.id,projectId:k.projectId,organizationId:k.organizationId,name:k.name,description:k.description??void 0,type:k.type,status:k.status,createdAt:new Date(k.createdAt),updatedAt:new Date(k.updatedAt)}}function _(k){return{id:k.id,definitionId:k.definitionId,name:k.name,description:k.description??void 0,stepOrder:k.stepOrder,type:k.type,requiredRoles:k.requiredRoles?JSON.parse(k.requiredRoles):[],autoApproveCondition:k.autoApproveCondition??void 0,timeoutHours:k.timeoutHours??void 0,createdAt:new Date(k.createdAt)}}function V(k){return{id:k.id,projectId:k.projectId,definitionId:k.definitionId,status:k.status,currentStepId:k.currentStepId??void 0,data:k.data?JSON.parse(k.data):void 0,requestedBy:k.requestedBy,startedAt:new Date(k.startedAt),completedAt:k.completedAt?new Date(k.completedAt):void 0}}function C(k){return{id:k.id,instanceId:k.instanceId,stepId:k.stepId,status:k.status,actorId:k.actorId??void 0,comment:k.comment??void 0,decidedAt:k.decidedAt?new Date(k.decidedAt):void 0,createdAt:new Date(k.createdAt)}}function f(k){function W(E){let F=0;return E.replace(/\?/g,()=>`$${++F}`)}async function J(E,F=[]){return(await k.query(W(E),F)).rows}async function P(E,F=[]){await k.execute(W(E),F)}async function $(E){let{projectId:F,status:G,search:H,limit:K=20,offset:L=0}=E,M='WHERE "projectId" = ?',N=[F];if(G&&G!=="all")M+=" AND status = ?",N.push(G);if(H)M+=" AND name LIKE ?",N.push(`%${H}%`);let X=(await J(`SELECT COUNT(*) as count FROM workflow_definition ${M}`,N))[0]?.count??0;return{definitions:(await J(`SELECT * FROM workflow_definition ${M} ORDER BY "updatedAt" DESC LIMIT ? OFFSET ?`,[...N,K,L])).map(Z),total:X}}async function O(E,F){let G=U("wfdef"),H=new Date().toISOString();await P(`INSERT INTO workflow_definition (id, "projectId", "organizationId", name, description, type, status, "createdAt", "updatedAt")
3
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[G,F.projectId,F.organizationId,E.name,E.description??null,E.type??"APPROVAL","DRAFT",H,H]);let K=await J("SELECT * FROM workflow_definition WHERE id = ?",[G]);return Z(K[0])}async function z(E){let F=U("wfstep"),G=new Date().toISOString(),K=((await J('SELECT MAX("stepOrder") as maxOrder FROM workflow_step WHERE "definitionId" = ?',[E.definitionId]))[0]?.maxOrder??0)+1;await P(`INSERT INTO workflow_step (id, "definitionId", name, description, "stepOrder", type, "requiredRoles", "autoApproveCondition", "timeoutHours", "createdAt")
4
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[F,E.definitionId,E.name,E.description??null,K,E.type??"APPROVAL",JSON.stringify(E.requiredRoles),E.autoApproveCondition??null,E.timeoutHours??null,G]);let L=await J("SELECT * FROM workflow_step WHERE id = ?",[F]);return _(L[0])}async function A(E){return(await J('SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder"',[E])).map(_)}async function B(E){let{projectId:F,definitionId:G,status:H,requestedBy:K,limit:L=20,offset:M=0}=E,N='WHERE "projectId" = ?',Q=[F];if(G)N+=' AND "definitionId" = ?',Q.push(G);if(H&&H!=="all")N+=" AND status = ?",Q.push(H);if(K)N+=' AND "requestedBy" = ?',Q.push(K);let Y=(await J(`SELECT COUNT(*) as count FROM workflow_instance ${N}`,Q))[0]?.count??0;return{instances:(await J(`SELECT * FROM workflow_instance ${N} ORDER BY "startedAt" DESC LIMIT ? OFFSET ?`,[...Q,L,M])).map(V),total:Y}}async function j(E,F){let G=U("wfinst"),H=new Date().toISOString(),L=(await J('SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder" LIMIT 1',[E.definitionId]))[0]?.id??null;if(await P(`INSERT INTO workflow_instance (id, "projectId", "definitionId", status, "currentStepId", data, "requestedBy", "startedAt")
5
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[G,F.projectId,E.definitionId,L?"IN_PROGRESS":"PENDING",L,E.data?JSON.stringify(E.data):null,F.requestedBy,H]),L)await P(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
6
+ VALUES (?, ?, ?, ?, ?)`,[U("wfappr"),G,L,"PENDING",H]);let M=await J("SELECT * FROM workflow_instance WHERE id = ?",[G]);return V(M[0])}async function v(E,F){let G=new Date().toISOString(),H=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);if(!H[0])throw Error("NOT_FOUND");let K=H[0];await P(`UPDATE workflow_approval SET status = 'APPROVED', "actorId" = ?, comment = ?, "decidedAt" = ?
7
+ WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`,[F.actorId,E.comment??null,G,E.instanceId,K.currentStepId]);let L=await J("SELECT * FROM workflow_step WHERE id = ?",[K.currentStepId]),M=await J('SELECT * FROM workflow_step WHERE "definitionId" = ? AND "stepOrder" > ? ORDER BY "stepOrder" LIMIT 1',[K.definitionId,L[0]?.stepOrder??0]);if(M[0])await P('UPDATE workflow_instance SET "currentStepId" = ? WHERE id = ?',[M[0].id,E.instanceId]),await P(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
8
+ VALUES (?, ?, ?, ?, ?)`,[U("wfappr"),E.instanceId,M[0].id,"PENDING",G]);else await P(`UPDATE workflow_instance SET status = 'COMPLETED', "currentStepId" = NULL, "completedAt" = ? WHERE id = ?`,[G,E.instanceId]);let N=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);return V(N[0])}async function D(E,F){let G=new Date().toISOString(),H=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);if(!H[0])throw Error("NOT_FOUND");await P(`UPDATE workflow_approval SET status = 'REJECTED', "actorId" = ?, comment = ?, "decidedAt" = ?
9
+ WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`,[F.actorId,E.reason,G,E.instanceId,H[0].currentStepId]),await P(`UPDATE workflow_instance SET status = 'REJECTED', "completedAt" = ? WHERE id = ?`,[G,E.instanceId]);let K=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);return V(K[0])}async function b(E){return(await J('SELECT * FROM workflow_approval WHERE "instanceId" = ? ORDER BY "createdAt"',[E])).map(C)}return{listDefinitions:$,createDefinition:O,addStep:z,getSteps:A,listInstances:B,startInstance:j,approveStep:v,rejectStep:D,getApprovals:b}}export{f as createWorkflowHandlers};
@@ -1,254 +1,9 @@
1
1
  // @bun
2
- // src/handlers/workflow.handlers.ts
3
- import { web } from "@contractspec/lib.runtime-sandbox";
4
- var { generateId } = web;
5
- function rowToDefinition(row) {
6
- return {
7
- id: row.id,
8
- projectId: row.projectId,
9
- organizationId: row.organizationId,
10
- name: row.name,
11
- description: row.description ?? undefined,
12
- type: row.type,
13
- status: row.status,
14
- createdAt: new Date(row.createdAt),
15
- updatedAt: new Date(row.updatedAt)
16
- };
17
- }
18
- function rowToStep(row) {
19
- return {
20
- id: row.id,
21
- definitionId: row.definitionId,
22
- name: row.name,
23
- description: row.description ?? undefined,
24
- stepOrder: row.stepOrder,
25
- type: row.type,
26
- requiredRoles: row.requiredRoles ? JSON.parse(row.requiredRoles) : [],
27
- autoApproveCondition: row.autoApproveCondition ?? undefined,
28
- timeoutHours: row.timeoutHours ?? undefined,
29
- createdAt: new Date(row.createdAt)
30
- };
31
- }
32
- function rowToInstance(row) {
33
- return {
34
- id: row.id,
35
- projectId: row.projectId,
36
- definitionId: row.definitionId,
37
- status: row.status,
38
- currentStepId: row.currentStepId ?? undefined,
39
- data: row.data ? JSON.parse(row.data) : undefined,
40
- requestedBy: row.requestedBy,
41
- startedAt: new Date(row.startedAt),
42
- completedAt: row.completedAt ? new Date(row.completedAt) : undefined
43
- };
44
- }
45
- function rowToApproval(row) {
46
- return {
47
- id: row.id,
48
- instanceId: row.instanceId,
49
- stepId: row.stepId,
50
- status: row.status,
51
- actorId: row.actorId ?? undefined,
52
- comment: row.comment ?? undefined,
53
- decidedAt: row.decidedAt ? new Date(row.decidedAt) : undefined,
54
- createdAt: new Date(row.createdAt)
55
- };
56
- }
57
- function createWorkflowHandlers(db) {
58
- function normalizeSql(sql) {
59
- let placeholderIndex = 0;
60
- return sql.replace(/\?/g, () => `$${++placeholderIndex}`);
61
- }
62
- async function queryRows(sql, params = []) {
63
- return (await db.query(normalizeSql(sql), params)).rows;
64
- }
65
- async function execute(sql, params = []) {
66
- await db.execute(normalizeSql(sql), params);
67
- }
68
- async function listDefinitions(input) {
69
- const { projectId, status, search, limit = 20, offset = 0 } = input;
70
- let whereClause = 'WHERE "projectId" = ?';
71
- const params = [projectId];
72
- if (status && status !== "all") {
73
- whereClause += " AND status = ?";
74
- params.push(status);
75
- }
76
- if (search) {
77
- whereClause += " AND name LIKE ?";
78
- params.push(`%${search}%`);
79
- }
80
- const countResult = await queryRows(`SELECT COUNT(*) as count FROM workflow_definition ${whereClause}`, params);
81
- const total = countResult[0]?.count ?? 0;
82
- const rows = await queryRows(`SELECT * FROM workflow_definition ${whereClause} ORDER BY "updatedAt" DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
83
- return {
84
- definitions: rows.map(rowToDefinition),
85
- total
86
- };
87
- }
88
- async function createDefinition(input, context) {
89
- const id = generateId("wfdef");
90
- const now = new Date().toISOString();
91
- await execute(`INSERT INTO workflow_definition (id, "projectId", "organizationId", name, description, type, status, "createdAt", "updatedAt")
92
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
93
- id,
94
- context.projectId,
95
- context.organizationId,
96
- input.name,
97
- input.description ?? null,
98
- input.type ?? "APPROVAL",
99
- "DRAFT",
100
- now,
101
- now
102
- ]);
103
- const rows = await queryRows(`SELECT * FROM workflow_definition WHERE id = ?`, [id]);
104
- return rowToDefinition(rows[0]);
105
- }
106
- async function addStep(input) {
107
- const id = generateId("wfstep");
108
- const now = new Date().toISOString();
109
- const maxOrderResult = await queryRows(`SELECT MAX("stepOrder") as maxOrder FROM workflow_step WHERE "definitionId" = ?`, [input.definitionId]);
110
- const nextOrder = (maxOrderResult[0]?.maxOrder ?? 0) + 1;
111
- await execute(`INSERT INTO workflow_step (id, "definitionId", name, description, "stepOrder", type, "requiredRoles", "autoApproveCondition", "timeoutHours", "createdAt")
112
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
113
- id,
114
- input.definitionId,
115
- input.name,
116
- input.description ?? null,
117
- nextOrder,
118
- input.type ?? "APPROVAL",
119
- JSON.stringify(input.requiredRoles),
120
- input.autoApproveCondition ?? null,
121
- input.timeoutHours ?? null,
122
- now
123
- ]);
124
- const rows = await queryRows(`SELECT * FROM workflow_step WHERE id = ?`, [id]);
125
- return rowToStep(rows[0]);
126
- }
127
- async function getSteps(definitionId) {
128
- const rows = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder"`, [definitionId]);
129
- return rows.map(rowToStep);
130
- }
131
- async function listInstances(input) {
132
- const {
133
- projectId,
134
- definitionId,
135
- status,
136
- requestedBy,
137
- limit = 20,
138
- offset = 0
139
- } = input;
140
- let whereClause = 'WHERE "projectId" = ?';
141
- const params = [projectId];
142
- if (definitionId) {
143
- whereClause += ' AND "definitionId" = ?';
144
- params.push(definitionId);
145
- }
146
- if (status && status !== "all") {
147
- whereClause += " AND status = ?";
148
- params.push(status);
149
- }
150
- if (requestedBy) {
151
- whereClause += ' AND "requestedBy" = ?';
152
- params.push(requestedBy);
153
- }
154
- const countResult = await queryRows(`SELECT COUNT(*) as count FROM workflow_instance ${whereClause}`, params);
155
- const total = countResult[0]?.count ?? 0;
156
- const rows = await queryRows(`SELECT * FROM workflow_instance ${whereClause} ORDER BY "startedAt" DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
157
- return {
158
- instances: rows.map(rowToInstance),
159
- total
160
- };
161
- }
162
- async function startInstance(input, context) {
163
- const id = generateId("wfinst");
164
- const now = new Date().toISOString();
165
- const steps = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder" LIMIT 1`, [input.definitionId]);
166
- const firstStepId = steps[0]?.id ?? null;
167
- await execute(`INSERT INTO workflow_instance (id, "projectId", "definitionId", status, "currentStepId", data, "requestedBy", "startedAt")
168
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
169
- id,
170
- context.projectId,
171
- input.definitionId,
172
- firstStepId ? "IN_PROGRESS" : "PENDING",
173
- firstStepId,
174
- input.data ? JSON.stringify(input.data) : null,
175
- context.requestedBy,
176
- now
177
- ]);
178
- if (firstStepId) {
179
- await execute(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
180
- VALUES (?, ?, ?, ?, ?)`, [generateId("wfappr"), id, firstStepId, "PENDING", now]);
181
- }
182
- const rows = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [id]);
183
- return rowToInstance(rows[0]);
184
- }
185
- async function approveStep(input, context) {
186
- const now = new Date().toISOString();
187
- const instances = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
188
- if (!instances[0]) {
189
- throw new Error("NOT_FOUND");
190
- }
191
- const instance = instances[0];
192
- await execute(`UPDATE workflow_approval SET status = 'APPROVED', "actorId" = ?, comment = ?, "decidedAt" = ?
193
- WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`, [
194
- context.actorId,
195
- input.comment ?? null,
196
- now,
197
- input.instanceId,
198
- instance.currentStepId
199
- ]);
200
- const currentStep = await queryRows(`SELECT * FROM workflow_step WHERE id = ?`, [instance.currentStepId]);
201
- const nextSteps = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? AND "stepOrder" > ? ORDER BY "stepOrder" LIMIT 1`, [instance.definitionId, currentStep[0]?.stepOrder ?? 0]);
202
- if (nextSteps[0]) {
203
- await execute(`UPDATE workflow_instance SET "currentStepId" = ? WHERE id = ?`, [nextSteps[0].id, input.instanceId]);
204
- await execute(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
205
- VALUES (?, ?, ?, ?, ?)`, [
206
- generateId("wfappr"),
207
- input.instanceId,
208
- nextSteps[0].id,
209
- "PENDING",
210
- now
211
- ]);
212
- } else {
213
- await execute(`UPDATE workflow_instance SET status = 'COMPLETED', "currentStepId" = NULL, "completedAt" = ? WHERE id = ?`, [now, input.instanceId]);
214
- }
215
- const updated = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
216
- return rowToInstance(updated[0]);
217
- }
218
- async function rejectStep(input, context) {
219
- const now = new Date().toISOString();
220
- const instances = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
221
- if (!instances[0]) {
222
- throw new Error("NOT_FOUND");
223
- }
224
- await execute(`UPDATE workflow_approval SET status = 'REJECTED', "actorId" = ?, comment = ?, "decidedAt" = ?
225
- WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`, [
226
- context.actorId,
227
- input.reason,
228
- now,
229
- input.instanceId,
230
- instances[0].currentStepId
231
- ]);
232
- await execute(`UPDATE workflow_instance SET status = 'REJECTED', "completedAt" = ? WHERE id = ?`, [now, input.instanceId]);
233
- const updated = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
234
- return rowToInstance(updated[0]);
235
- }
236
- async function getApprovals(instanceId) {
237
- const rows = await queryRows(`SELECT * FROM workflow_approval WHERE "instanceId" = ? ORDER BY "createdAt"`, [instanceId]);
238
- return rows.map(rowToApproval);
239
- }
240
- return {
241
- listDefinitions,
242
- createDefinition,
243
- addStep,
244
- getSteps,
245
- listInstances,
246
- startInstance,
247
- approveStep,
248
- rejectStep,
249
- getApprovals
250
- };
251
- }
252
- export {
253
- createWorkflowHandlers
254
- };
2
+ import{web as g}from"@contractspec/lib.runtime-sandbox";var{generateId:U}=g;function Z(k){return{id:k.id,projectId:k.projectId,organizationId:k.organizationId,name:k.name,description:k.description??void 0,type:k.type,status:k.status,createdAt:new Date(k.createdAt),updatedAt:new Date(k.updatedAt)}}function _(k){return{id:k.id,definitionId:k.definitionId,name:k.name,description:k.description??void 0,stepOrder:k.stepOrder,type:k.type,requiredRoles:k.requiredRoles?JSON.parse(k.requiredRoles):[],autoApproveCondition:k.autoApproveCondition??void 0,timeoutHours:k.timeoutHours??void 0,createdAt:new Date(k.createdAt)}}function V(k){return{id:k.id,projectId:k.projectId,definitionId:k.definitionId,status:k.status,currentStepId:k.currentStepId??void 0,data:k.data?JSON.parse(k.data):void 0,requestedBy:k.requestedBy,startedAt:new Date(k.startedAt),completedAt:k.completedAt?new Date(k.completedAt):void 0}}function C(k){return{id:k.id,instanceId:k.instanceId,stepId:k.stepId,status:k.status,actorId:k.actorId??void 0,comment:k.comment??void 0,decidedAt:k.decidedAt?new Date(k.decidedAt):void 0,createdAt:new Date(k.createdAt)}}function f(k){function W(E){let F=0;return E.replace(/\?/g,()=>`$${++F}`)}async function J(E,F=[]){return(await k.query(W(E),F)).rows}async function P(E,F=[]){await k.execute(W(E),F)}async function $(E){let{projectId:F,status:G,search:H,limit:K=20,offset:L=0}=E,M='WHERE "projectId" = ?',N=[F];if(G&&G!=="all")M+=" AND status = ?",N.push(G);if(H)M+=" AND name LIKE ?",N.push(`%${H}%`);let X=(await J(`SELECT COUNT(*) as count FROM workflow_definition ${M}`,N))[0]?.count??0;return{definitions:(await J(`SELECT * FROM workflow_definition ${M} ORDER BY "updatedAt" DESC LIMIT ? OFFSET ?`,[...N,K,L])).map(Z),total:X}}async function O(E,F){let G=U("wfdef"),H=new Date().toISOString();await P(`INSERT INTO workflow_definition (id, "projectId", "organizationId", name, description, type, status, "createdAt", "updatedAt")
3
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,[G,F.projectId,F.organizationId,E.name,E.description??null,E.type??"APPROVAL","DRAFT",H,H]);let K=await J("SELECT * FROM workflow_definition WHERE id = ?",[G]);return Z(K[0])}async function z(E){let F=U("wfstep"),G=new Date().toISOString(),K=((await J('SELECT MAX("stepOrder") as maxOrder FROM workflow_step WHERE "definitionId" = ?',[E.definitionId]))[0]?.maxOrder??0)+1;await P(`INSERT INTO workflow_step (id, "definitionId", name, description, "stepOrder", type, "requiredRoles", "autoApproveCondition", "timeoutHours", "createdAt")
4
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,[F,E.definitionId,E.name,E.description??null,K,E.type??"APPROVAL",JSON.stringify(E.requiredRoles),E.autoApproveCondition??null,E.timeoutHours??null,G]);let L=await J("SELECT * FROM workflow_step WHERE id = ?",[F]);return _(L[0])}async function A(E){return(await J('SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder"',[E])).map(_)}async function B(E){let{projectId:F,definitionId:G,status:H,requestedBy:K,limit:L=20,offset:M=0}=E,N='WHERE "projectId" = ?',Q=[F];if(G)N+=' AND "definitionId" = ?',Q.push(G);if(H&&H!=="all")N+=" AND status = ?",Q.push(H);if(K)N+=' AND "requestedBy" = ?',Q.push(K);let Y=(await J(`SELECT COUNT(*) as count FROM workflow_instance ${N}`,Q))[0]?.count??0;return{instances:(await J(`SELECT * FROM workflow_instance ${N} ORDER BY "startedAt" DESC LIMIT ? OFFSET ?`,[...Q,L,M])).map(V),total:Y}}async function j(E,F){let G=U("wfinst"),H=new Date().toISOString(),L=(await J('SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder" LIMIT 1',[E.definitionId]))[0]?.id??null;if(await P(`INSERT INTO workflow_instance (id, "projectId", "definitionId", status, "currentStepId", data, "requestedBy", "startedAt")
5
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,[G,F.projectId,E.definitionId,L?"IN_PROGRESS":"PENDING",L,E.data?JSON.stringify(E.data):null,F.requestedBy,H]),L)await P(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
6
+ VALUES (?, ?, ?, ?, ?)`,[U("wfappr"),G,L,"PENDING",H]);let M=await J("SELECT * FROM workflow_instance WHERE id = ?",[G]);return V(M[0])}async function v(E,F){let G=new Date().toISOString(),H=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);if(!H[0])throw Error("NOT_FOUND");let K=H[0];await P(`UPDATE workflow_approval SET status = 'APPROVED', "actorId" = ?, comment = ?, "decidedAt" = ?
7
+ WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`,[F.actorId,E.comment??null,G,E.instanceId,K.currentStepId]);let L=await J("SELECT * FROM workflow_step WHERE id = ?",[K.currentStepId]),M=await J('SELECT * FROM workflow_step WHERE "definitionId" = ? AND "stepOrder" > ? ORDER BY "stepOrder" LIMIT 1',[K.definitionId,L[0]?.stepOrder??0]);if(M[0])await P('UPDATE workflow_instance SET "currentStepId" = ? WHERE id = ?',[M[0].id,E.instanceId]),await P(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
8
+ VALUES (?, ?, ?, ?, ?)`,[U("wfappr"),E.instanceId,M[0].id,"PENDING",G]);else await P(`UPDATE workflow_instance SET status = 'COMPLETED', "currentStepId" = NULL, "completedAt" = ? WHERE id = ?`,[G,E.instanceId]);let N=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);return V(N[0])}async function D(E,F){let G=new Date().toISOString(),H=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);if(!H[0])throw Error("NOT_FOUND");await P(`UPDATE workflow_approval SET status = 'REJECTED', "actorId" = ?, comment = ?, "decidedAt" = ?
9
+ WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`,[F.actorId,E.reason,G,E.instanceId,H[0].currentStepId]),await P(`UPDATE workflow_instance SET status = 'REJECTED', "completedAt" = ? WHERE id = ?`,[G,E.instanceId]);let K=await J("SELECT * FROM workflow_instance WHERE id = ?",[E.instanceId]);return V(K[0])}async function b(E){return(await J('SELECT * FROM workflow_approval WHERE "instanceId" = ? ORDER BY "createdAt"',[E])).map(C)}return{listDefinitions:$,createDefinition:O,addStep:z,getSteps:A,listInstances:B,startInstance:j,approveStep:v,rejectStep:D,getApprovals:b}}export{f as createWorkflowHandlers};