@contractspec/example.workflow-system 3.7.6 → 3.8.2
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 +72 -119
- package/dist/approval/approval.event.js +1 -1
- package/dist/approval/approval.handler.d.ts +1 -1
- package/dist/approval/index.d.ts +4 -4
- package/dist/approval/index.js +1 -1
- package/dist/browser/approval/approval.event.js +1 -1
- package/dist/browser/approval/index.js +1 -1
- package/dist/browser/entities/index.js +166 -166
- package/dist/browser/handlers/index.js +43 -43
- package/dist/browser/handlers/workflow.handlers.js +43 -43
- package/dist/browser/index.js +1935 -1548
- package/dist/browser/instance/index.js +210 -210
- package/dist/browser/instance/instance.event.js +1 -1
- package/dist/browser/shared/demo-scenario.js +213 -0
- package/dist/browser/ui/WorkflowDashboard.visualizations.js +239 -0
- package/dist/browser/ui/hooks/index.js +0 -47
- package/dist/browser/ui/hooks/useWorkflowList.js +6 -4
- package/dist/browser/ui/index.js +6 -4
- package/dist/browser/ui/renderers/index.js +409 -73
- package/dist/browser/ui/renderers/workflow.markdown.js +409 -73
- package/dist/browser/visualizations/catalog.js +132 -0
- package/dist/browser/visualizations/index.js +133 -0
- package/dist/browser/visualizations/selectors.js +195 -0
- package/dist/entities/index.d.ts +53 -53
- package/dist/entities/index.js +166 -166
- package/dist/example.test.d.ts +1 -0
- package/dist/handlers/index.js +43 -43
- package/dist/handlers/workflow.handlers.js +43 -43
- package/dist/index.d.ts +6 -5
- package/dist/index.js +1935 -1548
- package/dist/instance/index.d.ts +3 -3
- package/dist/instance/index.js +210 -210
- package/dist/instance/instance.event.js +1 -1
- package/dist/instance/instance.handler.d.ts +1 -1
- package/dist/shared/demo-scenario.d.ts +43 -0
- package/dist/shared/demo-scenario.js +214 -0
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/mock-data.d.ts +1 -1
- package/dist/ui/WorkflowDashboard.visualizations.d.ts +4 -0
- package/dist/ui/WorkflowDashboard.visualizations.js +240 -0
- package/dist/ui/hooks/index.js +0 -47
- package/dist/ui/hooks/useWorkflowList.d.ts +2 -1
- package/dist/ui/hooks/useWorkflowList.js +6 -4
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +6 -4
- package/dist/ui/renderers/index.js +409 -73
- package/dist/ui/renderers/workflow.markdown.js +409 -73
- package/dist/visualizations/catalog.d.ts +11 -0
- package/dist/visualizations/catalog.js +133 -0
- package/dist/visualizations/index.d.ts +2 -0
- package/dist/visualizations/index.js +134 -0
- package/dist/visualizations/selectors.d.ts +11 -0
- package/dist/visualizations/selectors.js +196 -0
- package/dist/visualizations/selectors.test.d.ts +1 -0
- package/dist/workflow/index.d.ts +4 -4
- package/dist/workflow/workflow.handler.d.ts +1 -1
- package/package.json +71 -10
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ var ApprovalDecisionEnum = defineEnum("ApprovalDecision", [
|
|
|
20
20
|
|
|
21
21
|
// src/approval/approval.event.ts
|
|
22
22
|
import { defineEvent } from "@contractspec/lib.contracts-spec";
|
|
23
|
-
import {
|
|
23
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
24
24
|
var ApprovalRequestedPayload = defineSchemaModel({
|
|
25
25
|
name: "ApprovalRequestedEventPayload",
|
|
26
26
|
description: "Payload when approval is requested",
|
|
@@ -716,9 +716,19 @@ function rowToApproval(row) {
|
|
|
716
716
|
};
|
|
717
717
|
}
|
|
718
718
|
function createWorkflowHandlers(db) {
|
|
719
|
+
function normalizeSql(sql) {
|
|
720
|
+
let placeholderIndex = 0;
|
|
721
|
+
return sql.replace(/\?/g, () => `$${++placeholderIndex}`);
|
|
722
|
+
}
|
|
723
|
+
async function queryRows(sql, params = []) {
|
|
724
|
+
return (await db.query(normalizeSql(sql), params)).rows;
|
|
725
|
+
}
|
|
726
|
+
async function execute(sql, params = []) {
|
|
727
|
+
await db.execute(normalizeSql(sql), params);
|
|
728
|
+
}
|
|
719
729
|
async function listDefinitions(input) {
|
|
720
730
|
const { projectId, status, search, limit = 20, offset = 0 } = input;
|
|
721
|
-
let whereClause =
|
|
731
|
+
let whereClause = 'WHERE "projectId" = ?';
|
|
722
732
|
const params = [projectId];
|
|
723
733
|
if (status && status !== "all") {
|
|
724
734
|
whereClause += " AND status = ?";
|
|
@@ -728,9 +738,9 @@ function createWorkflowHandlers(db) {
|
|
|
728
738
|
whereClause += " AND name LIKE ?";
|
|
729
739
|
params.push(`%${search}%`);
|
|
730
740
|
}
|
|
731
|
-
const countResult =
|
|
741
|
+
const countResult = await queryRows(`SELECT COUNT(*) as count FROM workflow_definition ${whereClause}`, params);
|
|
732
742
|
const total = countResult[0]?.count ?? 0;
|
|
733
|
-
const rows =
|
|
743
|
+
const rows = await queryRows(`SELECT * FROM workflow_definition ${whereClause} ORDER BY "updatedAt" DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
|
|
734
744
|
return {
|
|
735
745
|
definitions: rows.map(rowToDefinition),
|
|
736
746
|
total
|
|
@@ -739,7 +749,7 @@ function createWorkflowHandlers(db) {
|
|
|
739
749
|
async function createDefinition(input, context) {
|
|
740
750
|
const id = generateId("wfdef");
|
|
741
751
|
const now = new Date().toISOString();
|
|
742
|
-
await
|
|
752
|
+
await execute(`INSERT INTO workflow_definition (id, "projectId", "organizationId", name, description, type, status, "createdAt", "updatedAt")
|
|
743
753
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
744
754
|
id,
|
|
745
755
|
context.projectId,
|
|
@@ -751,15 +761,15 @@ function createWorkflowHandlers(db) {
|
|
|
751
761
|
now,
|
|
752
762
|
now
|
|
753
763
|
]);
|
|
754
|
-
const rows =
|
|
764
|
+
const rows = await queryRows(`SELECT * FROM workflow_definition WHERE id = ?`, [id]);
|
|
755
765
|
return rowToDefinition(rows[0]);
|
|
756
766
|
}
|
|
757
767
|
async function addStep(input) {
|
|
758
768
|
const id = generateId("wfstep");
|
|
759
769
|
const now = new Date().toISOString();
|
|
760
|
-
const maxOrderResult =
|
|
770
|
+
const maxOrderResult = await queryRows(`SELECT MAX("stepOrder") as maxOrder FROM workflow_step WHERE "definitionId" = ?`, [input.definitionId]);
|
|
761
771
|
const nextOrder = (maxOrderResult[0]?.maxOrder ?? 0) + 1;
|
|
762
|
-
await
|
|
772
|
+
await execute(`INSERT INTO workflow_step (id, "definitionId", name, description, "stepOrder", type, "requiredRoles", "autoApproveCondition", "timeoutHours", "createdAt")
|
|
763
773
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
764
774
|
id,
|
|
765
775
|
input.definitionId,
|
|
@@ -772,11 +782,11 @@ function createWorkflowHandlers(db) {
|
|
|
772
782
|
input.timeoutHours ?? null,
|
|
773
783
|
now
|
|
774
784
|
]);
|
|
775
|
-
const rows =
|
|
785
|
+
const rows = await queryRows(`SELECT * FROM workflow_step WHERE id = ?`, [id]);
|
|
776
786
|
return rowToStep(rows[0]);
|
|
777
787
|
}
|
|
778
788
|
async function getSteps(definitionId) {
|
|
779
|
-
const rows =
|
|
789
|
+
const rows = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder"`, [definitionId]);
|
|
780
790
|
return rows.map(rowToStep);
|
|
781
791
|
}
|
|
782
792
|
async function listInstances(input) {
|
|
@@ -788,10 +798,10 @@ function createWorkflowHandlers(db) {
|
|
|
788
798
|
limit = 20,
|
|
789
799
|
offset = 0
|
|
790
800
|
} = input;
|
|
791
|
-
let whereClause =
|
|
801
|
+
let whereClause = 'WHERE "projectId" = ?';
|
|
792
802
|
const params = [projectId];
|
|
793
803
|
if (definitionId) {
|
|
794
|
-
whereClause +=
|
|
804
|
+
whereClause += ' AND "definitionId" = ?';
|
|
795
805
|
params.push(definitionId);
|
|
796
806
|
}
|
|
797
807
|
if (status && status !== "all") {
|
|
@@ -799,12 +809,12 @@ function createWorkflowHandlers(db) {
|
|
|
799
809
|
params.push(status);
|
|
800
810
|
}
|
|
801
811
|
if (requestedBy) {
|
|
802
|
-
whereClause +=
|
|
812
|
+
whereClause += ' AND "requestedBy" = ?';
|
|
803
813
|
params.push(requestedBy);
|
|
804
814
|
}
|
|
805
|
-
const countResult =
|
|
815
|
+
const countResult = await queryRows(`SELECT COUNT(*) as count FROM workflow_instance ${whereClause}`, params);
|
|
806
816
|
const total = countResult[0]?.count ?? 0;
|
|
807
|
-
const rows =
|
|
817
|
+
const rows = await queryRows(`SELECT * FROM workflow_instance ${whereClause} ORDER BY "startedAt" DESC LIMIT ? OFFSET ?`, [...params, limit, offset]);
|
|
808
818
|
return {
|
|
809
819
|
instances: rows.map(rowToInstance),
|
|
810
820
|
total
|
|
@@ -813,9 +823,9 @@ function createWorkflowHandlers(db) {
|
|
|
813
823
|
async function startInstance(input, context) {
|
|
814
824
|
const id = generateId("wfinst");
|
|
815
825
|
const now = new Date().toISOString();
|
|
816
|
-
const steps =
|
|
826
|
+
const steps = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? ORDER BY "stepOrder" LIMIT 1`, [input.definitionId]);
|
|
817
827
|
const firstStepId = steps[0]?.id ?? null;
|
|
818
|
-
await
|
|
828
|
+
await execute(`INSERT INTO workflow_instance (id, "projectId", "definitionId", status, "currentStepId", data, "requestedBy", "startedAt")
|
|
819
829
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
820
830
|
id,
|
|
821
831
|
context.projectId,
|
|
@@ -827,36 +837,32 @@ function createWorkflowHandlers(db) {
|
|
|
827
837
|
now
|
|
828
838
|
]);
|
|
829
839
|
if (firstStepId) {
|
|
830
|
-
await
|
|
840
|
+
await execute(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
|
|
831
841
|
VALUES (?, ?, ?, ?, ?)`, [generateId("wfappr"), id, firstStepId, "PENDING", now]);
|
|
832
842
|
}
|
|
833
|
-
const rows =
|
|
843
|
+
const rows = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [id]);
|
|
834
844
|
return rowToInstance(rows[0]);
|
|
835
845
|
}
|
|
836
846
|
async function approveStep(input, context) {
|
|
837
847
|
const now = new Date().toISOString();
|
|
838
|
-
const instances =
|
|
839
|
-
input.instanceId
|
|
840
|
-
])).rows;
|
|
848
|
+
const instances = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
|
|
841
849
|
if (!instances[0]) {
|
|
842
850
|
throw new Error("NOT_FOUND");
|
|
843
851
|
}
|
|
844
852
|
const instance = instances[0];
|
|
845
|
-
await
|
|
846
|
-
WHERE instanceId = ? AND stepId = ? AND status = 'PENDING'`, [
|
|
853
|
+
await execute(`UPDATE workflow_approval SET status = 'APPROVED', "actorId" = ?, comment = ?, "decidedAt" = ?
|
|
854
|
+
WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`, [
|
|
847
855
|
context.actorId,
|
|
848
856
|
input.comment ?? null,
|
|
849
857
|
now,
|
|
850
858
|
input.instanceId,
|
|
851
859
|
instance.currentStepId
|
|
852
860
|
]);
|
|
853
|
-
const currentStep =
|
|
854
|
-
|
|
855
|
-
])).rows;
|
|
856
|
-
const nextSteps = (await db.query(`SELECT * FROM workflow_step WHERE definitionId = ? AND stepOrder > ? ORDER BY stepOrder LIMIT 1`, [instance.definitionId, currentStep[0]?.stepOrder ?? 0])).rows;
|
|
861
|
+
const currentStep = await queryRows(`SELECT * FROM workflow_step WHERE id = ?`, [instance.currentStepId]);
|
|
862
|
+
const nextSteps = await queryRows(`SELECT * FROM workflow_step WHERE "definitionId" = ? AND "stepOrder" > ? ORDER BY "stepOrder" LIMIT 1`, [instance.definitionId, currentStep[0]?.stepOrder ?? 0]);
|
|
857
863
|
if (nextSteps[0]) {
|
|
858
|
-
await
|
|
859
|
-
await
|
|
864
|
+
await execute(`UPDATE workflow_instance SET "currentStepId" = ? WHERE id = ?`, [nextSteps[0].id, input.instanceId]);
|
|
865
|
+
await execute(`INSERT INTO workflow_approval (id, "instanceId", "stepId", status, "createdAt")
|
|
860
866
|
VALUES (?, ?, ?, ?, ?)`, [
|
|
861
867
|
generateId("wfappr"),
|
|
862
868
|
input.instanceId,
|
|
@@ -865,37 +871,31 @@ function createWorkflowHandlers(db) {
|
|
|
865
871
|
now
|
|
866
872
|
]);
|
|
867
873
|
} else {
|
|
868
|
-
await
|
|
874
|
+
await execute(`UPDATE workflow_instance SET status = 'COMPLETED', "currentStepId" = NULL, "completedAt" = ? WHERE id = ?`, [now, input.instanceId]);
|
|
869
875
|
}
|
|
870
|
-
const updated =
|
|
871
|
-
input.instanceId
|
|
872
|
-
])).rows;
|
|
876
|
+
const updated = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
|
|
873
877
|
return rowToInstance(updated[0]);
|
|
874
878
|
}
|
|
875
879
|
async function rejectStep(input, context) {
|
|
876
880
|
const now = new Date().toISOString();
|
|
877
|
-
const instances =
|
|
878
|
-
input.instanceId
|
|
879
|
-
])).rows;
|
|
881
|
+
const instances = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
|
|
880
882
|
if (!instances[0]) {
|
|
881
883
|
throw new Error("NOT_FOUND");
|
|
882
884
|
}
|
|
883
|
-
await
|
|
884
|
-
WHERE instanceId = ? AND stepId = ? AND status = 'PENDING'`, [
|
|
885
|
+
await execute(`UPDATE workflow_approval SET status = 'REJECTED', "actorId" = ?, comment = ?, "decidedAt" = ?
|
|
886
|
+
WHERE "instanceId" = ? AND "stepId" = ? AND status = 'PENDING'`, [
|
|
885
887
|
context.actorId,
|
|
886
888
|
input.reason,
|
|
887
889
|
now,
|
|
888
890
|
input.instanceId,
|
|
889
891
|
instances[0].currentStepId
|
|
890
892
|
]);
|
|
891
|
-
await
|
|
892
|
-
const updated =
|
|
893
|
-
input.instanceId
|
|
894
|
-
])).rows;
|
|
893
|
+
await execute(`UPDATE workflow_instance SET status = 'REJECTED', "completedAt" = ? WHERE id = ?`, [now, input.instanceId]);
|
|
894
|
+
const updated = await queryRows(`SELECT * FROM workflow_instance WHERE id = ?`, [input.instanceId]);
|
|
895
895
|
return rowToInstance(updated[0]);
|
|
896
896
|
}
|
|
897
897
|
async function getApprovals(instanceId) {
|
|
898
|
-
const rows =
|
|
898
|
+
const rows = await queryRows(`SELECT * FROM workflow_approval WHERE "instanceId" = ? ORDER BY "createdAt"`, [instanceId]);
|
|
899
899
|
return rows.map(rowToApproval);
|
|
900
900
|
}
|
|
901
901
|
return {
|
|
@@ -911,398 +911,596 @@ function createWorkflowHandlers(db) {
|
|
|
911
911
|
};
|
|
912
912
|
}
|
|
913
913
|
|
|
914
|
-
// src/
|
|
914
|
+
// src/instance/instance.enum.ts
|
|
915
915
|
import { defineEnum as defineEnum2 } from "@contractspec/lib.schema";
|
|
916
|
-
var
|
|
917
|
-
"
|
|
918
|
-
"
|
|
919
|
-
"
|
|
920
|
-
"
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
"
|
|
924
|
-
"
|
|
925
|
-
"SCHEDULED",
|
|
926
|
-
"API"
|
|
927
|
-
]);
|
|
928
|
-
var StepTypeEnum = defineEnum2("StepType", [
|
|
929
|
-
"START",
|
|
930
|
-
"APPROVAL",
|
|
931
|
-
"TASK",
|
|
932
|
-
"CONDITION",
|
|
933
|
-
"PARALLEL",
|
|
934
|
-
"WAIT",
|
|
935
|
-
"ACTION",
|
|
936
|
-
"END"
|
|
937
|
-
]);
|
|
938
|
-
var ApprovalModeEnum = defineEnum2("ApprovalMode", [
|
|
939
|
-
"ANY",
|
|
940
|
-
"ALL",
|
|
941
|
-
"MAJORITY",
|
|
942
|
-
"SEQUENTIAL"
|
|
916
|
+
var InstanceStatusEnum = defineEnum2("InstanceStatus", [
|
|
917
|
+
"PENDING",
|
|
918
|
+
"RUNNING",
|
|
919
|
+
"WAITING",
|
|
920
|
+
"PAUSED",
|
|
921
|
+
"COMPLETED",
|
|
922
|
+
"CANCELLED",
|
|
923
|
+
"FAILED",
|
|
924
|
+
"TIMEOUT"
|
|
943
925
|
]);
|
|
944
926
|
|
|
945
|
-
// src/
|
|
927
|
+
// src/instance/instance.event.ts
|
|
928
|
+
import { defineEvent as defineEvent2 } from "@contractspec/lib.contracts-spec";
|
|
946
929
|
import { defineSchemaModel as defineSchemaModel4, ScalarTypeEnum as ScalarTypeEnum4 } from "@contractspec/lib.schema";
|
|
947
|
-
var
|
|
948
|
-
name: "
|
|
949
|
-
description: "
|
|
950
|
-
fields: {
|
|
951
|
-
id: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
952
|
-
key: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
953
|
-
name: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
954
|
-
description: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
|
|
955
|
-
type: { type: StepTypeEnum, isOptional: false },
|
|
956
|
-
position: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: false },
|
|
957
|
-
transitions: { type: ScalarTypeEnum4.JSON(), isOptional: false },
|
|
958
|
-
approvalMode: { type: ApprovalModeEnum, isOptional: true },
|
|
959
|
-
approverRoles: {
|
|
960
|
-
type: ScalarTypeEnum4.String_unsecure(),
|
|
961
|
-
isArray: true,
|
|
962
|
-
isOptional: true
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
});
|
|
966
|
-
var WorkflowDefinitionModel = defineSchemaModel4({
|
|
967
|
-
name: "WorkflowDefinitionModel",
|
|
968
|
-
description: "A workflow definition",
|
|
930
|
+
var InstanceEventPayload = defineSchemaModel4({
|
|
931
|
+
name: "InstanceEventPayload",
|
|
932
|
+
description: "Base payload for instance events",
|
|
969
933
|
fields: {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
triggerType: { type: TriggerTypeEnum, isOptional: false },
|
|
977
|
-
initialStepId: {
|
|
978
|
-
type: ScalarTypeEnum4.String_unsecure(),
|
|
979
|
-
isOptional: true
|
|
980
|
-
},
|
|
981
|
-
featureFlagKey: {
|
|
934
|
+
instanceId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
935
|
+
workflowId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
936
|
+
workflowKey: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
937
|
+
status: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
938
|
+
referenceId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
|
|
939
|
+
referenceType: {
|
|
982
940
|
type: ScalarTypeEnum4.String_unsecure(),
|
|
983
941
|
isOptional: true
|
|
984
942
|
},
|
|
943
|
+
triggeredBy: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
985
944
|
organizationId: {
|
|
986
945
|
type: ScalarTypeEnum4.String_unsecure(),
|
|
987
946
|
isOptional: false
|
|
988
947
|
},
|
|
989
|
-
|
|
990
|
-
updatedAt: { type: ScalarTypeEnum4.DateTime(), isOptional: false },
|
|
991
|
-
steps: { type: WorkflowStepModel, isArray: true, isOptional: true }
|
|
948
|
+
timestamp: { type: ScalarTypeEnum4.DateTime(), isOptional: false }
|
|
992
949
|
}
|
|
993
950
|
});
|
|
994
|
-
var
|
|
995
|
-
name: "
|
|
996
|
-
description: "
|
|
951
|
+
var StepTransitionPayload = defineSchemaModel4({
|
|
952
|
+
name: "StepTransitionEventPayload",
|
|
953
|
+
description: "Payload for step transition events",
|
|
997
954
|
fields: {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
955
|
+
instanceId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
956
|
+
workflowId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
957
|
+
fromStepKey: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
|
|
958
|
+
toStepKey: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
959
|
+
action: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
|
|
960
|
+
executedBy: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
961
|
+
timestamp: { type: ScalarTypeEnum4.DateTime(), isOptional: false }
|
|
962
|
+
}
|
|
963
|
+
});
|
|
964
|
+
var InstanceCompletedPayload = defineSchemaModel4({
|
|
965
|
+
name: "InstanceCompletedEventPayload",
|
|
966
|
+
description: "Payload when instance completes",
|
|
967
|
+
fields: {
|
|
968
|
+
instanceId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
969
|
+
workflowId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
970
|
+
workflowKey: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
971
|
+
outcome: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false },
|
|
972
|
+
referenceId: { type: ScalarTypeEnum4.String_unsecure(), isOptional: true },
|
|
973
|
+
referenceType: {
|
|
1004
974
|
type: ScalarTypeEnum4.String_unsecure(),
|
|
1005
975
|
isOptional: true
|
|
1006
976
|
},
|
|
1007
|
-
|
|
977
|
+
duration: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: false },
|
|
978
|
+
timestamp: { type: ScalarTypeEnum4.DateTime(), isOptional: false }
|
|
1008
979
|
}
|
|
1009
980
|
});
|
|
1010
|
-
var
|
|
1011
|
-
|
|
1012
|
-
|
|
981
|
+
var InstanceStartedEvent = defineEvent2({
|
|
982
|
+
meta: {
|
|
983
|
+
key: "workflow.instance.started",
|
|
984
|
+
version: "1.0.0",
|
|
985
|
+
description: "A new workflow instance has been started.",
|
|
986
|
+
stability: "stable",
|
|
987
|
+
owners: ["@workflow-team"],
|
|
988
|
+
tags: ["workflow", "instance", "started"]
|
|
989
|
+
},
|
|
990
|
+
payload: InstanceEventPayload
|
|
991
|
+
});
|
|
992
|
+
var StepEnteredEvent = defineEvent2({
|
|
993
|
+
meta: {
|
|
994
|
+
key: "workflow.step.entered",
|
|
995
|
+
version: "1.0.0",
|
|
996
|
+
description: "A workflow instance has entered a new step.",
|
|
997
|
+
stability: "stable",
|
|
998
|
+
owners: ["@workflow-team"],
|
|
999
|
+
tags: ["workflow", "step", "entered"]
|
|
1000
|
+
},
|
|
1001
|
+
payload: StepTransitionPayload
|
|
1002
|
+
});
|
|
1003
|
+
var StepExitedEvent = defineEvent2({
|
|
1004
|
+
meta: {
|
|
1005
|
+
key: "workflow.step.exited",
|
|
1006
|
+
version: "1.0.0",
|
|
1007
|
+
description: "A workflow instance has exited a step.",
|
|
1008
|
+
stability: "stable",
|
|
1009
|
+
owners: ["@workflow-team"],
|
|
1010
|
+
tags: ["workflow", "step", "exited"]
|
|
1011
|
+
},
|
|
1012
|
+
payload: StepTransitionPayload
|
|
1013
|
+
});
|
|
1014
|
+
var InstanceCompletedEvent = defineEvent2({
|
|
1015
|
+
meta: {
|
|
1016
|
+
key: "workflow.instance.completed",
|
|
1017
|
+
version: "1.0.0",
|
|
1018
|
+
description: "A workflow instance has completed.",
|
|
1019
|
+
stability: "stable",
|
|
1020
|
+
owners: ["@workflow-team"],
|
|
1021
|
+
tags: ["workflow", "instance", "completed"]
|
|
1022
|
+
},
|
|
1023
|
+
payload: InstanceCompletedPayload
|
|
1024
|
+
});
|
|
1025
|
+
var InstanceCancelledEvent = defineEvent2({
|
|
1026
|
+
meta: {
|
|
1027
|
+
key: "workflow.instance.cancelled",
|
|
1028
|
+
version: "1.0.0",
|
|
1029
|
+
description: "A workflow instance has been cancelled.",
|
|
1030
|
+
stability: "stable",
|
|
1031
|
+
owners: ["@workflow-team"],
|
|
1032
|
+
tags: ["workflow", "instance", "cancelled"]
|
|
1033
|
+
},
|
|
1034
|
+
payload: InstanceEventPayload
|
|
1035
|
+
});
|
|
1036
|
+
var InstancePausedEvent = defineEvent2({
|
|
1037
|
+
meta: {
|
|
1038
|
+
key: "workflow.instance.paused",
|
|
1039
|
+
version: "1.0.0",
|
|
1040
|
+
description: "A workflow instance has been paused.",
|
|
1041
|
+
stability: "stable",
|
|
1042
|
+
owners: ["@workflow-team"],
|
|
1043
|
+
tags: ["workflow", "instance", "paused"]
|
|
1044
|
+
},
|
|
1045
|
+
payload: InstanceEventPayload
|
|
1046
|
+
});
|
|
1047
|
+
var InstanceResumedEvent = defineEvent2({
|
|
1048
|
+
meta: {
|
|
1049
|
+
key: "workflow.instance.resumed",
|
|
1050
|
+
version: "1.0.0",
|
|
1051
|
+
description: "A workflow instance has been resumed.",
|
|
1052
|
+
stability: "stable",
|
|
1053
|
+
owners: ["@workflow-team"],
|
|
1054
|
+
tags: ["workflow", "instance", "resumed"]
|
|
1055
|
+
},
|
|
1056
|
+
payload: InstanceEventPayload
|
|
1057
|
+
});
|
|
1058
|
+
var InstanceFailedEvent = defineEvent2({
|
|
1059
|
+
meta: {
|
|
1060
|
+
key: "workflow.instance.failed",
|
|
1061
|
+
version: "1.0.0",
|
|
1062
|
+
description: "A workflow instance has failed.",
|
|
1063
|
+
stability: "stable",
|
|
1064
|
+
owners: ["@workflow-team"],
|
|
1065
|
+
tags: ["workflow", "instance", "failed"]
|
|
1066
|
+
},
|
|
1067
|
+
payload: InstanceEventPayload
|
|
1068
|
+
});
|
|
1069
|
+
var InstanceTimedOutEvent = defineEvent2({
|
|
1070
|
+
meta: {
|
|
1071
|
+
key: "workflow.instance.timedOut",
|
|
1072
|
+
version: "1.0.0",
|
|
1073
|
+
description: "A workflow instance has timed out.",
|
|
1074
|
+
stability: "stable",
|
|
1075
|
+
owners: ["@workflow-team"],
|
|
1076
|
+
tags: ["workflow", "instance", "timeout"]
|
|
1077
|
+
},
|
|
1078
|
+
payload: InstanceEventPayload
|
|
1079
|
+
});
|
|
1080
|
+
|
|
1081
|
+
// src/instance/instance.schema.ts
|
|
1082
|
+
import { defineSchemaModel as defineSchemaModel5, ScalarTypeEnum as ScalarTypeEnum5 } from "@contractspec/lib.schema";
|
|
1083
|
+
var WorkflowInstanceModel = defineSchemaModel5({
|
|
1084
|
+
name: "WorkflowInstanceModel",
|
|
1085
|
+
description: "A running workflow instance",
|
|
1013
1086
|
fields: {
|
|
1014
|
-
|
|
1015
|
-
|
|
1087
|
+
id: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
|
|
1088
|
+
workflowDefinitionId: {
|
|
1089
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1016
1090
|
isOptional: false
|
|
1017
1091
|
},
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1092
|
+
referenceId: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true },
|
|
1093
|
+
referenceType: {
|
|
1094
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1095
|
+
isOptional: true
|
|
1096
|
+
},
|
|
1097
|
+
status: { type: InstanceStatusEnum, isOptional: false },
|
|
1098
|
+
currentStepId: {
|
|
1099
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1100
|
+
isOptional: true
|
|
1101
|
+
},
|
|
1102
|
+
contextData: { type: ScalarTypeEnum5.JSON(), isOptional: true },
|
|
1103
|
+
triggeredBy: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
|
|
1104
|
+
organizationId: {
|
|
1105
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1106
|
+
isOptional: false
|
|
1107
|
+
},
|
|
1108
|
+
priority: { type: ScalarTypeEnum5.Int_unsecure(), isOptional: false },
|
|
1109
|
+
dueAt: { type: ScalarTypeEnum5.DateTime(), isOptional: true },
|
|
1110
|
+
outcome: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true },
|
|
1111
|
+
resultData: { type: ScalarTypeEnum5.JSON(), isOptional: true },
|
|
1112
|
+
errorMessage: {
|
|
1113
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1024
1114
|
isOptional: true
|
|
1025
1115
|
},
|
|
1026
|
-
|
|
1116
|
+
createdAt: { type: ScalarTypeEnum5.DateTime(), isOptional: false },
|
|
1117
|
+
startedAt: { type: ScalarTypeEnum5.DateTime(), isOptional: true },
|
|
1118
|
+
completedAt: { type: ScalarTypeEnum5.DateTime(), isOptional: true }
|
|
1027
1119
|
}
|
|
1028
1120
|
});
|
|
1029
|
-
var
|
|
1030
|
-
name: "
|
|
1031
|
-
description: "Input for
|
|
1121
|
+
var StartWorkflowInputModel = defineSchemaModel5({
|
|
1122
|
+
name: "StartWorkflowInput",
|
|
1123
|
+
description: "Input for starting a workflow",
|
|
1032
1124
|
fields: {
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1125
|
+
workflowKey: { type: ScalarTypeEnum5.NonEmptyString(), isOptional: false },
|
|
1126
|
+
contextData: { type: ScalarTypeEnum5.JSON(), isOptional: true },
|
|
1127
|
+
referenceId: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true },
|
|
1128
|
+
referenceType: {
|
|
1129
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1130
|
+
isOptional: true
|
|
1036
1131
|
},
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1132
|
+
priority: { type: ScalarTypeEnum5.Int_unsecure(), isOptional: true },
|
|
1133
|
+
dueAt: { type: ScalarTypeEnum5.DateTime(), isOptional: true }
|
|
1134
|
+
}
|
|
1135
|
+
});
|
|
1136
|
+
var TransitionInputModel = defineSchemaModel5({
|
|
1137
|
+
name: "TransitionInput",
|
|
1138
|
+
description: "Input for transitioning a workflow",
|
|
1139
|
+
fields: {
|
|
1140
|
+
instanceId: { type: ScalarTypeEnum5.String_unsecure(), isOptional: false },
|
|
1141
|
+
action: { type: ScalarTypeEnum5.NonEmptyString(), isOptional: false },
|
|
1142
|
+
data: { type: ScalarTypeEnum5.JSON(), isOptional: true },
|
|
1143
|
+
comment: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true }
|
|
1144
|
+
}
|
|
1145
|
+
});
|
|
1146
|
+
var TransitionResultModel = defineSchemaModel5({
|
|
1147
|
+
name: "TransitionResult",
|
|
1148
|
+
description: "Result of a workflow transition",
|
|
1149
|
+
fields: {
|
|
1150
|
+
success: { type: ScalarTypeEnum5.Boolean(), isOptional: false },
|
|
1151
|
+
instance: { type: WorkflowInstanceModel, isOptional: false },
|
|
1152
|
+
previousStepKey: {
|
|
1153
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1047
1154
|
isOptional: true
|
|
1048
1155
|
},
|
|
1049
|
-
|
|
1050
|
-
type:
|
|
1051
|
-
isArray: true,
|
|
1156
|
+
currentStepKey: {
|
|
1157
|
+
type: ScalarTypeEnum5.String_unsecure(),
|
|
1052
1158
|
isOptional: true
|
|
1053
1159
|
},
|
|
1054
|
-
|
|
1055
|
-
slaSeconds: { type: ScalarTypeEnum4.Int_unsecure(), isOptional: true }
|
|
1160
|
+
message: { type: ScalarTypeEnum5.String_unsecure(), isOptional: true }
|
|
1056
1161
|
}
|
|
1057
1162
|
});
|
|
1058
1163
|
|
|
1059
|
-
// src/
|
|
1164
|
+
// src/instance/instance.operations.ts
|
|
1060
1165
|
import {
|
|
1061
1166
|
defineCommand as defineCommand2,
|
|
1062
1167
|
defineQuery as defineQuery2
|
|
1063
1168
|
} from "@contractspec/lib.contracts-spec/operations";
|
|
1064
|
-
import { defineSchemaModel as
|
|
1169
|
+
import { defineSchemaModel as defineSchemaModel6, ScalarTypeEnum as ScalarTypeEnum6 } from "@contractspec/lib.schema";
|
|
1065
1170
|
var OWNERS2 = ["@example.workflow-system"];
|
|
1066
|
-
var
|
|
1171
|
+
var StartWorkflowContract = defineCommand2({
|
|
1067
1172
|
meta: {
|
|
1068
|
-
key: "workflow.
|
|
1173
|
+
key: "workflow.instance.start",
|
|
1069
1174
|
version: "1.0.0",
|
|
1070
1175
|
stability: "stable",
|
|
1071
1176
|
owners: [...OWNERS2],
|
|
1072
|
-
tags: ["workflow", "
|
|
1073
|
-
description: "
|
|
1074
|
-
goal: "
|
|
1075
|
-
context: "
|
|
1177
|
+
tags: ["workflow", "instance", "start"],
|
|
1178
|
+
description: "Start a new workflow instance.",
|
|
1179
|
+
goal: "Initiate a workflow for a business process.",
|
|
1180
|
+
context: "Order creation, request submission, etc."
|
|
1076
1181
|
},
|
|
1077
1182
|
io: {
|
|
1078
|
-
input:
|
|
1079
|
-
output:
|
|
1183
|
+
input: StartWorkflowInputModel,
|
|
1184
|
+
output: WorkflowInstanceModel
|
|
1080
1185
|
},
|
|
1081
1186
|
policy: { auth: "user" },
|
|
1082
1187
|
sideEffects: {
|
|
1083
1188
|
emits: [
|
|
1084
1189
|
{
|
|
1085
|
-
key: "workflow.
|
|
1190
|
+
key: "workflow.instance.started",
|
|
1086
1191
|
version: "1.0.0",
|
|
1087
|
-
when: "Workflow
|
|
1088
|
-
payload:
|
|
1192
|
+
when: "Workflow starts",
|
|
1193
|
+
payload: WorkflowInstanceModel
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
key: "workflow.step.entered",
|
|
1197
|
+
version: "1.0.0",
|
|
1198
|
+
when: "First step entered",
|
|
1199
|
+
payload: WorkflowInstanceModel
|
|
1089
1200
|
}
|
|
1090
1201
|
],
|
|
1091
|
-
audit: ["workflow.
|
|
1202
|
+
audit: ["workflow.instance.started"]
|
|
1092
1203
|
},
|
|
1093
1204
|
acceptance: {
|
|
1094
1205
|
scenarios: [
|
|
1095
1206
|
{
|
|
1096
|
-
key: "
|
|
1097
|
-
given: ["
|
|
1098
|
-
when: ["User
|
|
1099
|
-
then: [
|
|
1100
|
-
"Definition is created",
|
|
1101
|
-
"WorkflowDefinitionCreated event is emitted"
|
|
1102
|
-
]
|
|
1207
|
+
key: "start-workflow-happy-path",
|
|
1208
|
+
given: ["Workflow definition exists"],
|
|
1209
|
+
when: ["User starts workflow"],
|
|
1210
|
+
then: ["Instance is created and started"]
|
|
1103
1211
|
}
|
|
1104
1212
|
],
|
|
1105
1213
|
examples: [
|
|
1106
1214
|
{
|
|
1107
|
-
key: "
|
|
1215
|
+
key: "start-onboarding",
|
|
1108
1216
|
input: {
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
version: "1.0.0"
|
|
1217
|
+
workflowKey: "onboarding-v1",
|
|
1218
|
+
context: { employeeId: "emp-123" }
|
|
1112
1219
|
},
|
|
1113
|
-
output: { id: "
|
|
1220
|
+
output: { id: "inst-456", status: "running" }
|
|
1114
1221
|
}
|
|
1115
1222
|
]
|
|
1116
1223
|
}
|
|
1117
1224
|
});
|
|
1118
|
-
var
|
|
1225
|
+
var TransitionWorkflowContract = defineCommand2({
|
|
1119
1226
|
meta: {
|
|
1120
|
-
key: "workflow.
|
|
1227
|
+
key: "workflow.instance.transition",
|
|
1121
1228
|
version: "1.0.0",
|
|
1122
1229
|
stability: "stable",
|
|
1123
1230
|
owners: [...OWNERS2],
|
|
1124
|
-
tags: ["workflow", "
|
|
1125
|
-
description: "
|
|
1126
|
-
goal: "
|
|
1127
|
-
context: "
|
|
1231
|
+
tags: ["workflow", "instance", "transition", "state-machine"],
|
|
1232
|
+
description: "Transition a workflow instance to the next step.",
|
|
1233
|
+
goal: "Move workflow forward based on action.",
|
|
1234
|
+
context: "Task completion, approval decisions."
|
|
1128
1235
|
},
|
|
1129
1236
|
io: {
|
|
1130
|
-
input:
|
|
1131
|
-
output:
|
|
1237
|
+
input: TransitionInputModel,
|
|
1238
|
+
output: TransitionResultModel
|
|
1132
1239
|
},
|
|
1133
1240
|
policy: { auth: "user" },
|
|
1134
1241
|
sideEffects: {
|
|
1135
1242
|
emits: [
|
|
1136
1243
|
{
|
|
1137
|
-
key: "workflow.
|
|
1244
|
+
key: "workflow.step.exited",
|
|
1138
1245
|
version: "1.0.0",
|
|
1139
|
-
when: "
|
|
1140
|
-
payload:
|
|
1246
|
+
when: "Step is exited",
|
|
1247
|
+
payload: WorkflowInstanceModel
|
|
1248
|
+
},
|
|
1249
|
+
{
|
|
1250
|
+
key: "workflow.step.entered",
|
|
1251
|
+
version: "1.0.0",
|
|
1252
|
+
when: "New step is entered",
|
|
1253
|
+
payload: WorkflowInstanceModel
|
|
1254
|
+
},
|
|
1255
|
+
{
|
|
1256
|
+
key: "workflow.instance.completed",
|
|
1257
|
+
version: "1.0.0",
|
|
1258
|
+
when: "Workflow reaches end",
|
|
1259
|
+
payload: WorkflowInstanceModel
|
|
1141
1260
|
}
|
|
1142
1261
|
],
|
|
1143
|
-
audit: ["workflow.
|
|
1262
|
+
audit: ["workflow.instance.transitioned"]
|
|
1144
1263
|
},
|
|
1145
1264
|
acceptance: {
|
|
1146
1265
|
scenarios: [
|
|
1147
1266
|
{
|
|
1148
|
-
key: "
|
|
1149
|
-
given: ["Workflow
|
|
1150
|
-
when: ["User
|
|
1151
|
-
then: [
|
|
1152
|
-
"Definition is updated",
|
|
1153
|
-
"WorkflowDefinitionUpdated event is emitted"
|
|
1154
|
-
]
|
|
1267
|
+
key: "transition-workflow-happy-path",
|
|
1268
|
+
given: ["Workflow instance is waiting at step"],
|
|
1269
|
+
when: ["User provides input"],
|
|
1270
|
+
then: ["Instance moves to next step"]
|
|
1155
1271
|
}
|
|
1156
1272
|
],
|
|
1157
1273
|
examples: [
|
|
1158
1274
|
{
|
|
1159
|
-
key: "
|
|
1160
|
-
input: {
|
|
1161
|
-
|
|
1275
|
+
key: "complete-task",
|
|
1276
|
+
input: {
|
|
1277
|
+
instanceId: "inst-456",
|
|
1278
|
+
action: "complete",
|
|
1279
|
+
data: { approved: true }
|
|
1280
|
+
},
|
|
1281
|
+
output: { success: true, nextStep: "notify-hr" }
|
|
1162
1282
|
}
|
|
1163
1283
|
]
|
|
1164
1284
|
}
|
|
1165
1285
|
});
|
|
1166
|
-
var
|
|
1286
|
+
var PauseWorkflowContract = defineCommand2({
|
|
1167
1287
|
meta: {
|
|
1168
|
-
key: "workflow.
|
|
1288
|
+
key: "workflow.instance.pause",
|
|
1169
1289
|
version: "1.0.0",
|
|
1170
1290
|
stability: "stable",
|
|
1171
1291
|
owners: [...OWNERS2],
|
|
1172
|
-
tags: ["workflow", "
|
|
1173
|
-
description: "
|
|
1174
|
-
goal: "
|
|
1175
|
-
context: "
|
|
1292
|
+
tags: ["workflow", "instance", "pause"],
|
|
1293
|
+
description: "Pause a running workflow instance.",
|
|
1294
|
+
goal: "Temporarily halt workflow execution.",
|
|
1295
|
+
context: "Administrative action, emergency stop."
|
|
1176
1296
|
},
|
|
1177
1297
|
io: {
|
|
1178
|
-
input:
|
|
1179
|
-
|
|
1298
|
+
input: defineSchemaModel6({
|
|
1299
|
+
name: "PauseResumeInput",
|
|
1300
|
+
fields: {
|
|
1301
|
+
instanceId: {
|
|
1302
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1303
|
+
isOptional: false
|
|
1304
|
+
},
|
|
1305
|
+
reason: { type: ScalarTypeEnum6.String_unsecure(), isOptional: true }
|
|
1306
|
+
}
|
|
1307
|
+
}),
|
|
1308
|
+
output: WorkflowInstanceModel
|
|
1180
1309
|
},
|
|
1181
1310
|
policy: { auth: "user" },
|
|
1182
1311
|
sideEffects: {
|
|
1183
1312
|
emits: [
|
|
1184
1313
|
{
|
|
1185
|
-
key: "workflow.
|
|
1314
|
+
key: "workflow.instance.paused",
|
|
1186
1315
|
version: "1.0.0",
|
|
1187
|
-
when: "
|
|
1188
|
-
payload:
|
|
1316
|
+
when: "Workflow is paused",
|
|
1317
|
+
payload: WorkflowInstanceModel
|
|
1189
1318
|
}
|
|
1190
1319
|
],
|
|
1191
|
-
audit: ["workflow.
|
|
1320
|
+
audit: ["workflow.instance.paused"]
|
|
1192
1321
|
},
|
|
1193
1322
|
acceptance: {
|
|
1194
1323
|
scenarios: [
|
|
1195
1324
|
{
|
|
1196
|
-
key: "
|
|
1197
|
-
given: ["Workflow
|
|
1198
|
-
when: ["
|
|
1199
|
-
then: ["
|
|
1325
|
+
key: "pause-workflow-happy-path",
|
|
1326
|
+
given: ["Workflow is running"],
|
|
1327
|
+
when: ["Admin pauses workflow"],
|
|
1328
|
+
then: ["Instance status becomes PAUSED"]
|
|
1200
1329
|
}
|
|
1201
1330
|
],
|
|
1202
1331
|
examples: [
|
|
1203
1332
|
{
|
|
1204
|
-
key: "
|
|
1205
|
-
input: {
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1333
|
+
key: "pause-maintenance",
|
|
1334
|
+
input: { instanceId: "inst-456", reason: "System maintenance" },
|
|
1335
|
+
output: { id: "inst-456", status: "paused" }
|
|
1336
|
+
}
|
|
1337
|
+
]
|
|
1338
|
+
}
|
|
1339
|
+
});
|
|
1340
|
+
var ResumeWorkflowContract = defineCommand2({
|
|
1341
|
+
meta: {
|
|
1342
|
+
key: "workflow.instance.resume",
|
|
1343
|
+
version: "1.0.0",
|
|
1344
|
+
stability: "stable",
|
|
1345
|
+
owners: [...OWNERS2],
|
|
1346
|
+
tags: ["workflow", "instance", "resume"],
|
|
1347
|
+
description: "Resume a paused workflow instance.",
|
|
1348
|
+
goal: "Continue workflow execution.",
|
|
1349
|
+
context: "Administrative action."
|
|
1350
|
+
},
|
|
1351
|
+
io: {
|
|
1352
|
+
input: defineSchemaModel6({
|
|
1353
|
+
name: "PauseResumeInput",
|
|
1354
|
+
fields: {
|
|
1355
|
+
instanceId: {
|
|
1356
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1357
|
+
isOptional: false
|
|
1209
1358
|
},
|
|
1210
|
-
|
|
1359
|
+
reason: { type: ScalarTypeEnum6.String_unsecure(), isOptional: true }
|
|
1360
|
+
}
|
|
1361
|
+
}),
|
|
1362
|
+
output: WorkflowInstanceModel
|
|
1363
|
+
},
|
|
1364
|
+
policy: { auth: "user" },
|
|
1365
|
+
sideEffects: {
|
|
1366
|
+
emits: [
|
|
1367
|
+
{
|
|
1368
|
+
key: "workflow.instance.resumed",
|
|
1369
|
+
version: "1.0.0",
|
|
1370
|
+
when: "Workflow is resumed",
|
|
1371
|
+
payload: WorkflowInstanceModel
|
|
1372
|
+
}
|
|
1373
|
+
],
|
|
1374
|
+
audit: ["workflow.instance.resumed"]
|
|
1375
|
+
},
|
|
1376
|
+
acceptance: {
|
|
1377
|
+
scenarios: [
|
|
1378
|
+
{
|
|
1379
|
+
key: "resume-workflow-happy-path",
|
|
1380
|
+
given: ["Workflow is paused"],
|
|
1381
|
+
when: ["Admin resumes workflow"],
|
|
1382
|
+
then: ["Instance status becomes RUNNING"]
|
|
1383
|
+
}
|
|
1384
|
+
],
|
|
1385
|
+
examples: [
|
|
1386
|
+
{
|
|
1387
|
+
key: "resume-normal",
|
|
1388
|
+
input: { instanceId: "inst-456", reason: "Issue resolved" },
|
|
1389
|
+
output: { id: "inst-456", status: "running" }
|
|
1211
1390
|
}
|
|
1212
1391
|
]
|
|
1213
1392
|
}
|
|
1214
1393
|
});
|
|
1215
|
-
var
|
|
1394
|
+
var CancelWorkflowContract = defineCommand2({
|
|
1216
1395
|
meta: {
|
|
1217
|
-
key: "workflow.
|
|
1396
|
+
key: "workflow.instance.cancel",
|
|
1218
1397
|
version: "1.0.0",
|
|
1219
1398
|
stability: "stable",
|
|
1220
1399
|
owners: [...OWNERS2],
|
|
1221
|
-
tags: ["workflow", "
|
|
1222
|
-
description: "
|
|
1223
|
-
goal: "
|
|
1224
|
-
context: "
|
|
1400
|
+
tags: ["workflow", "instance", "cancel"],
|
|
1401
|
+
description: "Cancel a workflow instance.",
|
|
1402
|
+
goal: "Terminate workflow without completion.",
|
|
1403
|
+
context: "User request, system cancellation."
|
|
1225
1404
|
},
|
|
1226
1405
|
io: {
|
|
1227
|
-
input:
|
|
1228
|
-
name: "
|
|
1406
|
+
input: defineSchemaModel6({
|
|
1407
|
+
name: "CancelWorkflowInput",
|
|
1229
1408
|
fields: {
|
|
1230
|
-
|
|
1231
|
-
type:
|
|
1409
|
+
instanceId: {
|
|
1410
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1411
|
+
isOptional: false
|
|
1412
|
+
},
|
|
1413
|
+
reason: {
|
|
1414
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1232
1415
|
isOptional: false
|
|
1233
1416
|
}
|
|
1234
1417
|
}
|
|
1235
1418
|
}),
|
|
1236
|
-
output:
|
|
1419
|
+
output: WorkflowInstanceModel
|
|
1237
1420
|
},
|
|
1238
1421
|
policy: { auth: "user" },
|
|
1239
1422
|
sideEffects: {
|
|
1240
1423
|
emits: [
|
|
1241
1424
|
{
|
|
1242
|
-
key: "workflow.
|
|
1425
|
+
key: "workflow.instance.cancelled",
|
|
1243
1426
|
version: "1.0.0",
|
|
1244
|
-
when: "Workflow is
|
|
1245
|
-
payload:
|
|
1427
|
+
when: "Workflow is cancelled",
|
|
1428
|
+
payload: WorkflowInstanceModel
|
|
1246
1429
|
}
|
|
1247
1430
|
],
|
|
1248
|
-
audit: ["workflow.
|
|
1431
|
+
audit: ["workflow.instance.cancelled"]
|
|
1249
1432
|
},
|
|
1250
1433
|
acceptance: {
|
|
1251
1434
|
scenarios: [
|
|
1252
1435
|
{
|
|
1253
|
-
key: "
|
|
1254
|
-
given: ["Workflow
|
|
1255
|
-
when: ["User
|
|
1256
|
-
then: ["
|
|
1436
|
+
key: "cancel-workflow-happy-path",
|
|
1437
|
+
given: ["Workflow is running"],
|
|
1438
|
+
when: ["User cancels workflow"],
|
|
1439
|
+
then: ["Instance status becomes CANCELLED"]
|
|
1257
1440
|
}
|
|
1258
1441
|
],
|
|
1259
1442
|
examples: [
|
|
1260
1443
|
{
|
|
1261
|
-
key: "
|
|
1262
|
-
input: {
|
|
1263
|
-
output: { id: "
|
|
1444
|
+
key: "cancel-mistake",
|
|
1445
|
+
input: { instanceId: "inst-456", reason: "Created by mistake" },
|
|
1446
|
+
output: { id: "inst-456", status: "cancelled" }
|
|
1264
1447
|
}
|
|
1265
1448
|
]
|
|
1266
1449
|
}
|
|
1267
1450
|
});
|
|
1268
|
-
var
|
|
1451
|
+
var ListInstancesContract = defineQuery2({
|
|
1269
1452
|
meta: {
|
|
1270
|
-
key: "workflow.
|
|
1453
|
+
key: "workflow.instance.list",
|
|
1271
1454
|
version: "1.0.0",
|
|
1272
1455
|
stability: "stable",
|
|
1273
1456
|
owners: [...OWNERS2],
|
|
1274
|
-
tags: ["workflow", "
|
|
1275
|
-
description: "List workflow
|
|
1276
|
-
goal: "Browse and search
|
|
1277
|
-
context: "
|
|
1457
|
+
tags: ["workflow", "instance", "list"],
|
|
1458
|
+
description: "List workflow instances with filtering.",
|
|
1459
|
+
goal: "Browse and search running workflows.",
|
|
1460
|
+
context: "Dashboard, monitoring."
|
|
1278
1461
|
},
|
|
1279
1462
|
io: {
|
|
1280
|
-
input:
|
|
1281
|
-
name: "
|
|
1463
|
+
input: defineSchemaModel6({
|
|
1464
|
+
name: "ListInstancesInput",
|
|
1282
1465
|
fields: {
|
|
1283
|
-
|
|
1284
|
-
|
|
1466
|
+
workflowKey: {
|
|
1467
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1468
|
+
isOptional: true
|
|
1469
|
+
},
|
|
1470
|
+
status: { type: InstanceStatusEnum, isOptional: true },
|
|
1471
|
+
referenceType: {
|
|
1472
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1473
|
+
isOptional: true
|
|
1474
|
+
},
|
|
1475
|
+
referenceId: {
|
|
1476
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1477
|
+
isOptional: true
|
|
1478
|
+
},
|
|
1479
|
+
triggeredBy: {
|
|
1480
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1481
|
+
isOptional: true
|
|
1482
|
+
},
|
|
1285
1483
|
limit: {
|
|
1286
|
-
type:
|
|
1484
|
+
type: ScalarTypeEnum6.Int_unsecure(),
|
|
1287
1485
|
isOptional: true,
|
|
1288
1486
|
defaultValue: 20
|
|
1289
1487
|
},
|
|
1290
1488
|
offset: {
|
|
1291
|
-
type:
|
|
1489
|
+
type: ScalarTypeEnum6.Int_unsecure(),
|
|
1292
1490
|
isOptional: true,
|
|
1293
1491
|
defaultValue: 0
|
|
1294
1492
|
}
|
|
1295
1493
|
}
|
|
1296
1494
|
}),
|
|
1297
|
-
output:
|
|
1298
|
-
name: "
|
|
1495
|
+
output: defineSchemaModel6({
|
|
1496
|
+
name: "ListInstancesOutput",
|
|
1299
1497
|
fields: {
|
|
1300
|
-
|
|
1301
|
-
type:
|
|
1498
|
+
instances: {
|
|
1499
|
+
type: WorkflowInstanceModel,
|
|
1302
1500
|
isArray: true,
|
|
1303
1501
|
isOptional: false
|
|
1304
1502
|
},
|
|
1305
|
-
total: { type:
|
|
1503
|
+
total: { type: ScalarTypeEnum6.Int_unsecure(), isOptional: false }
|
|
1306
1504
|
}
|
|
1307
1505
|
})
|
|
1308
1506
|
},
|
|
@@ -1310,1333 +1508,984 @@ var ListWorkflowsContract = defineQuery2({
|
|
|
1310
1508
|
acceptance: {
|
|
1311
1509
|
scenarios: [
|
|
1312
1510
|
{
|
|
1313
|
-
key: "list-
|
|
1314
|
-
given: ["Workflow
|
|
1315
|
-
when: ["User lists
|
|
1316
|
-
then: ["List of
|
|
1511
|
+
key: "list-instances-happy-path",
|
|
1512
|
+
given: ["Workflow instances exist"],
|
|
1513
|
+
when: ["User lists instances"],
|
|
1514
|
+
then: ["List of instances is returned"]
|
|
1317
1515
|
}
|
|
1318
1516
|
],
|
|
1319
1517
|
examples: [
|
|
1320
1518
|
{
|
|
1321
|
-
key: "list-
|
|
1322
|
-
input: { limit: 10 },
|
|
1323
|
-
output: {
|
|
1519
|
+
key: "list-running",
|
|
1520
|
+
input: { status: "running", limit: 10 },
|
|
1521
|
+
output: { instances: [], total: 5 }
|
|
1324
1522
|
}
|
|
1325
1523
|
]
|
|
1326
1524
|
}
|
|
1327
1525
|
});
|
|
1328
|
-
var
|
|
1526
|
+
var GetInstanceContract = defineQuery2({
|
|
1329
1527
|
meta: {
|
|
1330
|
-
key: "workflow.
|
|
1528
|
+
key: "workflow.instance.get",
|
|
1331
1529
|
version: "1.0.0",
|
|
1332
1530
|
stability: "stable",
|
|
1333
1531
|
owners: [...OWNERS2],
|
|
1334
|
-
tags: ["workflow", "
|
|
1335
|
-
description: "Get a workflow
|
|
1336
|
-
goal: "View workflow details.",
|
|
1337
|
-
context: "
|
|
1532
|
+
tags: ["workflow", "instance", "get"],
|
|
1533
|
+
description: "Get a workflow instance with details.",
|
|
1534
|
+
goal: "View workflow instance details.",
|
|
1535
|
+
context: "Instance detail view."
|
|
1338
1536
|
},
|
|
1339
1537
|
io: {
|
|
1340
|
-
input:
|
|
1341
|
-
name: "
|
|
1538
|
+
input: defineSchemaModel6({
|
|
1539
|
+
name: "GetInstanceInput",
|
|
1342
1540
|
fields: {
|
|
1343
|
-
|
|
1344
|
-
type:
|
|
1541
|
+
instanceId: {
|
|
1542
|
+
type: ScalarTypeEnum6.String_unsecure(),
|
|
1345
1543
|
isOptional: false
|
|
1346
1544
|
}
|
|
1347
1545
|
}
|
|
1348
1546
|
}),
|
|
1349
|
-
output:
|
|
1547
|
+
output: WorkflowInstanceModel
|
|
1350
1548
|
},
|
|
1351
1549
|
policy: { auth: "user" },
|
|
1352
1550
|
acceptance: {
|
|
1353
1551
|
scenarios: [
|
|
1354
1552
|
{
|
|
1355
|
-
key: "get-
|
|
1356
|
-
given: ["
|
|
1357
|
-
when: ["User requests
|
|
1358
|
-
then: ["
|
|
1553
|
+
key: "get-instance-happy-path",
|
|
1554
|
+
given: ["Instance exists"],
|
|
1555
|
+
when: ["User requests instance details"],
|
|
1556
|
+
then: ["Instance details are returned"]
|
|
1359
1557
|
}
|
|
1360
1558
|
],
|
|
1361
1559
|
examples: [
|
|
1362
1560
|
{
|
|
1363
1561
|
key: "get-details",
|
|
1364
|
-
input: {
|
|
1365
|
-
output: { id: "
|
|
1562
|
+
input: { instanceId: "inst-456" },
|
|
1563
|
+
output: { id: "inst-456", workflowKey: "onboarding-v1" }
|
|
1366
1564
|
}
|
|
1367
1565
|
]
|
|
1368
1566
|
}
|
|
1369
1567
|
});
|
|
1370
|
-
|
|
1371
|
-
// src/workflow/workflow.event.ts
|
|
1372
|
-
import { defineEvent as defineEvent2 } from "@contractspec/lib.contracts-spec";
|
|
1373
|
-
import { ScalarTypeEnum as ScalarTypeEnum6, defineSchemaModel as defineSchemaModel6 } from "@contractspec/lib.schema";
|
|
1374
|
-
var WorkflowDefinitionPayload = defineSchemaModel6({
|
|
1375
|
-
name: "WorkflowDefinitionEventPayload",
|
|
1376
|
-
description: "Payload for workflow definition events",
|
|
1377
|
-
fields: {
|
|
1378
|
-
workflowId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1379
|
-
key: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1380
|
-
name: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1381
|
-
version: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1382
|
-
organizationId: {
|
|
1383
|
-
type: ScalarTypeEnum6.String_unsecure(),
|
|
1384
|
-
isOptional: false
|
|
1385
|
-
},
|
|
1386
|
-
createdBy: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1387
|
-
timestamp: { type: ScalarTypeEnum6.DateTime(), isOptional: false }
|
|
1388
|
-
}
|
|
1389
|
-
});
|
|
1390
|
-
var StepAddedPayload = defineSchemaModel6({
|
|
1391
|
-
name: "StepAddedEventPayload",
|
|
1392
|
-
description: "Payload when a step is added",
|
|
1393
|
-
fields: {
|
|
1394
|
-
stepId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1395
|
-
workflowId: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1396
|
-
stepKey: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1397
|
-
stepType: { type: ScalarTypeEnum6.String_unsecure(), isOptional: false },
|
|
1398
|
-
position: { type: ScalarTypeEnum6.Int_unsecure(), isOptional: false },
|
|
1399
|
-
timestamp: { type: ScalarTypeEnum6.DateTime(), isOptional: false }
|
|
1400
|
-
}
|
|
1401
|
-
});
|
|
1402
|
-
var WorkflowCreatedEvent = defineEvent2({
|
|
1403
|
-
meta: {
|
|
1404
|
-
key: "workflow.definition.created",
|
|
1405
|
-
version: "1.0.0",
|
|
1406
|
-
description: "A new workflow definition has been created.",
|
|
1407
|
-
stability: "stable",
|
|
1408
|
-
owners: ["@workflow-team"],
|
|
1409
|
-
tags: ["workflow", "definition", "created"]
|
|
1410
|
-
},
|
|
1411
|
-
payload: WorkflowDefinitionPayload
|
|
1412
|
-
});
|
|
1413
|
-
var WorkflowUpdatedEvent = defineEvent2({
|
|
1414
|
-
meta: {
|
|
1415
|
-
key: "workflow.definition.updated",
|
|
1416
|
-
version: "1.0.0",
|
|
1417
|
-
description: "A workflow definition has been updated.",
|
|
1418
|
-
stability: "stable",
|
|
1419
|
-
owners: ["@workflow-team"],
|
|
1420
|
-
tags: ["workflow", "definition", "updated"]
|
|
1421
|
-
},
|
|
1422
|
-
payload: WorkflowDefinitionPayload
|
|
1423
|
-
});
|
|
1424
|
-
var WorkflowPublishedEvent = defineEvent2({
|
|
1425
|
-
meta: {
|
|
1426
|
-
key: "workflow.definition.published",
|
|
1427
|
-
version: "1.0.0",
|
|
1428
|
-
description: "A workflow definition has been published and is now active.",
|
|
1429
|
-
stability: "stable",
|
|
1430
|
-
owners: ["@workflow-team"],
|
|
1431
|
-
tags: ["workflow", "definition", "published"]
|
|
1432
|
-
},
|
|
1433
|
-
payload: WorkflowDefinitionPayload
|
|
1434
|
-
});
|
|
1435
|
-
var StepAddedEvent = defineEvent2({
|
|
1436
|
-
meta: {
|
|
1437
|
-
key: "workflow.step.added",
|
|
1438
|
-
version: "1.0.0",
|
|
1439
|
-
description: "A step has been added to a workflow definition.",
|
|
1440
|
-
stability: "stable",
|
|
1441
|
-
owners: ["@workflow-team"],
|
|
1442
|
-
tags: ["workflow", "step", "added"]
|
|
1443
|
-
},
|
|
1444
|
-
payload: StepAddedPayload
|
|
1445
|
-
});
|
|
1446
|
-
// src/instance/instance.enum.ts
|
|
1568
|
+
// src/workflow/workflow.enum.ts
|
|
1447
1569
|
import { defineEnum as defineEnum3 } from "@contractspec/lib.schema";
|
|
1448
|
-
var
|
|
1449
|
-
"
|
|
1450
|
-
"
|
|
1451
|
-
"
|
|
1452
|
-
"
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
"
|
|
1456
|
-
"
|
|
1570
|
+
var WorkflowStatusEnum = defineEnum3("WorkflowStatus", [
|
|
1571
|
+
"DRAFT",
|
|
1572
|
+
"ACTIVE",
|
|
1573
|
+
"DEPRECATED",
|
|
1574
|
+
"ARCHIVED"
|
|
1575
|
+
]);
|
|
1576
|
+
var TriggerTypeEnum = defineEnum3("WorkflowTriggerType", [
|
|
1577
|
+
"MANUAL",
|
|
1578
|
+
"EVENT",
|
|
1579
|
+
"SCHEDULED",
|
|
1580
|
+
"API"
|
|
1581
|
+
]);
|
|
1582
|
+
var StepTypeEnum = defineEnum3("StepType", [
|
|
1583
|
+
"START",
|
|
1584
|
+
"APPROVAL",
|
|
1585
|
+
"TASK",
|
|
1586
|
+
"CONDITION",
|
|
1587
|
+
"PARALLEL",
|
|
1588
|
+
"WAIT",
|
|
1589
|
+
"ACTION",
|
|
1590
|
+
"END"
|
|
1591
|
+
]);
|
|
1592
|
+
var ApprovalModeEnum = defineEnum3("ApprovalMode", [
|
|
1593
|
+
"ANY",
|
|
1594
|
+
"ALL",
|
|
1595
|
+
"MAJORITY",
|
|
1596
|
+
"SEQUENTIAL"
|
|
1457
1597
|
]);
|
|
1458
1598
|
|
|
1459
|
-
// src/
|
|
1599
|
+
// src/workflow/workflow.schema.ts
|
|
1460
1600
|
import { defineSchemaModel as defineSchemaModel7, ScalarTypeEnum as ScalarTypeEnum7 } from "@contractspec/lib.schema";
|
|
1461
|
-
var
|
|
1462
|
-
name: "
|
|
1463
|
-
description: "A
|
|
1601
|
+
var WorkflowStepModel = defineSchemaModel7({
|
|
1602
|
+
name: "WorkflowStepModel",
|
|
1603
|
+
description: "A step in a workflow definition",
|
|
1464
1604
|
fields: {
|
|
1465
1605
|
id: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1466
|
-
|
|
1606
|
+
key: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1607
|
+
name: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1608
|
+
description: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1609
|
+
type: { type: StepTypeEnum, isOptional: false },
|
|
1610
|
+
position: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: false },
|
|
1611
|
+
transitions: { type: ScalarTypeEnum7.JSON(), isOptional: false },
|
|
1612
|
+
approvalMode: { type: ApprovalModeEnum, isOptional: true },
|
|
1613
|
+
approverRoles: {
|
|
1467
1614
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1615
|
+
isArray: true,
|
|
1616
|
+
isOptional: true
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
var WorkflowDefinitionModel = defineSchemaModel7({
|
|
1621
|
+
name: "WorkflowDefinitionModel",
|
|
1622
|
+
description: "A workflow definition",
|
|
1623
|
+
fields: {
|
|
1624
|
+
id: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1625
|
+
name: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1626
|
+
key: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1627
|
+
description: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1628
|
+
version: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1629
|
+
status: { type: WorkflowStatusEnum, isOptional: false },
|
|
1630
|
+
triggerType: { type: TriggerTypeEnum, isOptional: false },
|
|
1631
|
+
initialStepId: {
|
|
1472
1632
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1473
1633
|
isOptional: true
|
|
1474
1634
|
},
|
|
1475
|
-
|
|
1476
|
-
currentStepId: {
|
|
1635
|
+
featureFlagKey: {
|
|
1477
1636
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1478
1637
|
isOptional: true
|
|
1479
1638
|
},
|
|
1480
|
-
contextData: { type: ScalarTypeEnum7.JSON(), isOptional: true },
|
|
1481
|
-
triggeredBy: { type: ScalarTypeEnum7.String_unsecure(), isOptional: false },
|
|
1482
1639
|
organizationId: {
|
|
1483
1640
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1484
1641
|
isOptional: false
|
|
1485
1642
|
},
|
|
1486
|
-
priority: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: false },
|
|
1487
|
-
dueAt: { type: ScalarTypeEnum7.DateTime(), isOptional: true },
|
|
1488
|
-
outcome: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1489
|
-
resultData: { type: ScalarTypeEnum7.JSON(), isOptional: true },
|
|
1490
|
-
errorMessage: {
|
|
1491
|
-
type: ScalarTypeEnum7.String_unsecure(),
|
|
1492
|
-
isOptional: true
|
|
1493
|
-
},
|
|
1494
1643
|
createdAt: { type: ScalarTypeEnum7.DateTime(), isOptional: false },
|
|
1495
|
-
|
|
1496
|
-
|
|
1644
|
+
updatedAt: { type: ScalarTypeEnum7.DateTime(), isOptional: false },
|
|
1645
|
+
steps: { type: WorkflowStepModel, isArray: true, isOptional: true }
|
|
1497
1646
|
}
|
|
1498
1647
|
});
|
|
1499
|
-
var
|
|
1500
|
-
name: "
|
|
1501
|
-
description: "Input for
|
|
1648
|
+
var CreateWorkflowInputModel = defineSchemaModel7({
|
|
1649
|
+
name: "CreateWorkflowInput",
|
|
1650
|
+
description: "Input for creating a workflow definition",
|
|
1502
1651
|
fields: {
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1652
|
+
name: { type: ScalarTypeEnum7.NonEmptyString(), isOptional: false },
|
|
1653
|
+
key: { type: ScalarTypeEnum7.NonEmptyString(), isOptional: false },
|
|
1654
|
+
description: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1655
|
+
triggerType: { type: TriggerTypeEnum, isOptional: true },
|
|
1656
|
+
triggerConfig: { type: ScalarTypeEnum7.JSON(), isOptional: true },
|
|
1657
|
+
featureFlagKey: {
|
|
1507
1658
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1508
1659
|
isOptional: true
|
|
1509
1660
|
},
|
|
1510
|
-
|
|
1511
|
-
dueAt: { type: ScalarTypeEnum7.DateTime(), isOptional: true }
|
|
1661
|
+
settings: { type: ScalarTypeEnum7.JSON(), isOptional: true }
|
|
1512
1662
|
}
|
|
1513
1663
|
});
|
|
1514
|
-
var
|
|
1515
|
-
name: "
|
|
1516
|
-
description: "Input for
|
|
1664
|
+
var UpdateWorkflowInputModel = defineSchemaModel7({
|
|
1665
|
+
name: "UpdateWorkflowInput",
|
|
1666
|
+
description: "Input for updating a workflow definition",
|
|
1517
1667
|
fields: {
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1668
|
+
workflowId: {
|
|
1669
|
+
type: ScalarTypeEnum7.String_unsecure(),
|
|
1670
|
+
isOptional: false
|
|
1671
|
+
},
|
|
1672
|
+
name: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1673
|
+
description: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1674
|
+
triggerType: { type: TriggerTypeEnum, isOptional: true },
|
|
1675
|
+
triggerConfig: { type: ScalarTypeEnum7.JSON(), isOptional: true },
|
|
1676
|
+
featureFlagKey: {
|
|
1677
|
+
type: ScalarTypeEnum7.String_unsecure(),
|
|
1678
|
+
isOptional: true
|
|
1679
|
+
},
|
|
1680
|
+
settings: { type: ScalarTypeEnum7.JSON(), isOptional: true }
|
|
1522
1681
|
}
|
|
1523
1682
|
});
|
|
1524
|
-
var
|
|
1525
|
-
name: "
|
|
1526
|
-
description: "
|
|
1683
|
+
var AddStepInputModel = defineSchemaModel7({
|
|
1684
|
+
name: "AddStepInput",
|
|
1685
|
+
description: "Input for adding a step to a workflow",
|
|
1527
1686
|
fields: {
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1687
|
+
workflowId: {
|
|
1688
|
+
type: ScalarTypeEnum7.String_unsecure(),
|
|
1689
|
+
isOptional: false
|
|
1690
|
+
},
|
|
1691
|
+
key: { type: ScalarTypeEnum7.NonEmptyString(), isOptional: false },
|
|
1692
|
+
name: { type: ScalarTypeEnum7.NonEmptyString(), isOptional: false },
|
|
1693
|
+
description: { type: ScalarTypeEnum7.String_unsecure(), isOptional: true },
|
|
1694
|
+
type: { type: StepTypeEnum, isOptional: false },
|
|
1695
|
+
position: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: true },
|
|
1696
|
+
transitions: { type: ScalarTypeEnum7.JSON(), isOptional: false },
|
|
1697
|
+
approvalMode: { type: ApprovalModeEnum, isOptional: true },
|
|
1698
|
+
approverRoles: {
|
|
1531
1699
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1700
|
+
isArray: true,
|
|
1532
1701
|
isOptional: true
|
|
1533
1702
|
},
|
|
1534
|
-
|
|
1703
|
+
approverUserIds: {
|
|
1535
1704
|
type: ScalarTypeEnum7.String_unsecure(),
|
|
1705
|
+
isArray: true,
|
|
1536
1706
|
isOptional: true
|
|
1537
1707
|
},
|
|
1538
|
-
|
|
1708
|
+
timeoutSeconds: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: true },
|
|
1709
|
+
slaSeconds: { type: ScalarTypeEnum7.Int_unsecure(), isOptional: true }
|
|
1539
1710
|
}
|
|
1540
1711
|
});
|
|
1541
1712
|
|
|
1542
|
-
// src/
|
|
1713
|
+
// src/presentations/index.ts
|
|
1543
1714
|
import {
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
} from "@contractspec/lib.contracts-spec
|
|
1547
|
-
|
|
1548
|
-
var OWNERS3 = ["@example.workflow-system"];
|
|
1549
|
-
var StartWorkflowContract = defineCommand3({
|
|
1715
|
+
definePresentation,
|
|
1716
|
+
StabilityEnum
|
|
1717
|
+
} from "@contractspec/lib.contracts-spec";
|
|
1718
|
+
var WorkflowDesignerPresentation = definePresentation({
|
|
1550
1719
|
meta: {
|
|
1551
|
-
key: "workflow.
|
|
1720
|
+
key: "workflow.designer",
|
|
1552
1721
|
version: "1.0.0",
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1722
|
+
title: "Workflow Designer",
|
|
1723
|
+
description: "Visual workflow designer with drag-and-drop steps",
|
|
1724
|
+
domain: "workflow-system",
|
|
1725
|
+
owners: ["@workflow-team"],
|
|
1726
|
+
tags: ["workflow", "designer", "admin"],
|
|
1727
|
+
stability: StabilityEnum.Experimental,
|
|
1728
|
+
goal: "Building and modifying workflow definitions",
|
|
1729
|
+
context: "Workflow administration and setup"
|
|
1559
1730
|
},
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1731
|
+
source: {
|
|
1732
|
+
type: "component",
|
|
1733
|
+
framework: "react",
|
|
1734
|
+
componentKey: "WorkflowDesigner",
|
|
1735
|
+
props: WorkflowDefinitionModel
|
|
1563
1736
|
},
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1737
|
+
targets: ["react"],
|
|
1738
|
+
policy: {
|
|
1739
|
+
flags: ["workflow.designer.enabled"]
|
|
1740
|
+
}
|
|
1741
|
+
});
|
|
1742
|
+
var WorkflowListPresentation = definePresentation({
|
|
1743
|
+
meta: {
|
|
1744
|
+
key: "workflow.definition.viewList",
|
|
1745
|
+
version: "1.0.0",
|
|
1746
|
+
title: "Workflow List",
|
|
1747
|
+
description: "List of workflow definitions with status and actions",
|
|
1748
|
+
domain: "workflow-system",
|
|
1749
|
+
owners: ["@workflow-team"],
|
|
1750
|
+
tags: ["workflow", "list", "admin"],
|
|
1751
|
+
stability: StabilityEnum.Experimental,
|
|
1752
|
+
goal: "Overview of all defined workflows",
|
|
1753
|
+
context: "Workflow management dashboard"
|
|
1581
1754
|
},
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
]
|
|
1591
|
-
examples: [
|
|
1592
|
-
{
|
|
1593
|
-
key: "start-onboarding",
|
|
1594
|
-
input: {
|
|
1595
|
-
workflowKey: "onboarding-v1",
|
|
1596
|
-
context: { employeeId: "emp-123" }
|
|
1597
|
-
},
|
|
1598
|
-
output: { id: "inst-456", status: "running" }
|
|
1599
|
-
}
|
|
1600
|
-
]
|
|
1755
|
+
source: {
|
|
1756
|
+
type: "component",
|
|
1757
|
+
framework: "react",
|
|
1758
|
+
componentKey: "WorkflowDefinitionList",
|
|
1759
|
+
props: WorkflowDefinitionModel
|
|
1760
|
+
},
|
|
1761
|
+
targets: ["react", "markdown"],
|
|
1762
|
+
policy: {
|
|
1763
|
+
flags: ["workflow.enabled"]
|
|
1601
1764
|
}
|
|
1602
1765
|
});
|
|
1603
|
-
var
|
|
1766
|
+
var WorkflowDetailPresentation = definePresentation({
|
|
1604
1767
|
meta: {
|
|
1605
|
-
key: "workflow.
|
|
1768
|
+
key: "workflow.definition.detail",
|
|
1606
1769
|
version: "1.0.0",
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
input: TransitionInputModel,
|
|
1616
|
-
output: TransitionResultModel
|
|
1770
|
+
title: "Workflow Details",
|
|
1771
|
+
description: "Detailed view of a workflow definition with steps",
|
|
1772
|
+
domain: "workflow-system",
|
|
1773
|
+
owners: ["@workflow-team"],
|
|
1774
|
+
tags: ["workflow", "detail"],
|
|
1775
|
+
stability: StabilityEnum.Experimental,
|
|
1776
|
+
goal: "Viewing technical details of a workflow definition",
|
|
1777
|
+
context: "Workflow inspection and debugging"
|
|
1617
1778
|
},
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
version: "1.0.0",
|
|
1624
|
-
when: "Step is exited",
|
|
1625
|
-
payload: WorkflowInstanceModel
|
|
1626
|
-
},
|
|
1627
|
-
{
|
|
1628
|
-
key: "workflow.step.entered",
|
|
1629
|
-
version: "1.0.0",
|
|
1630
|
-
when: "New step is entered",
|
|
1631
|
-
payload: WorkflowInstanceModel
|
|
1632
|
-
},
|
|
1633
|
-
{
|
|
1634
|
-
key: "workflow.instance.completed",
|
|
1635
|
-
version: "1.0.0",
|
|
1636
|
-
when: "Workflow reaches end",
|
|
1637
|
-
payload: WorkflowInstanceModel
|
|
1638
|
-
}
|
|
1639
|
-
],
|
|
1640
|
-
audit: ["workflow.instance.transitioned"]
|
|
1779
|
+
source: {
|
|
1780
|
+
type: "component",
|
|
1781
|
+
framework: "react",
|
|
1782
|
+
componentKey: "WorkflowDefinitionDetail",
|
|
1783
|
+
props: WorkflowDefinitionModel
|
|
1641
1784
|
},
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
key: "transition-workflow-happy-path",
|
|
1646
|
-
given: ["Workflow instance is waiting at step"],
|
|
1647
|
-
when: ["User provides input"],
|
|
1648
|
-
then: ["Instance moves to next step"]
|
|
1649
|
-
}
|
|
1650
|
-
],
|
|
1651
|
-
examples: [
|
|
1652
|
-
{
|
|
1653
|
-
key: "complete-task",
|
|
1654
|
-
input: {
|
|
1655
|
-
instanceId: "inst-456",
|
|
1656
|
-
action: "complete",
|
|
1657
|
-
data: { approved: true }
|
|
1658
|
-
},
|
|
1659
|
-
output: { success: true, nextStep: "notify-hr" }
|
|
1660
|
-
}
|
|
1661
|
-
]
|
|
1785
|
+
targets: ["react", "markdown"],
|
|
1786
|
+
policy: {
|
|
1787
|
+
flags: ["workflow.enabled"]
|
|
1662
1788
|
}
|
|
1663
1789
|
});
|
|
1664
|
-
var
|
|
1790
|
+
var InstanceListPresentation = definePresentation({
|
|
1665
1791
|
meta: {
|
|
1666
|
-
key: "workflow.instance.
|
|
1792
|
+
key: "workflow.instance.viewList",
|
|
1667
1793
|
version: "1.0.0",
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
input: defineSchemaModel8({
|
|
1677
|
-
name: "PauseResumeInput",
|
|
1678
|
-
fields: {
|
|
1679
|
-
instanceId: {
|
|
1680
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1681
|
-
isOptional: false
|
|
1682
|
-
},
|
|
1683
|
-
reason: { type: ScalarTypeEnum8.String_unsecure(), isOptional: true }
|
|
1684
|
-
}
|
|
1685
|
-
}),
|
|
1686
|
-
output: WorkflowInstanceModel
|
|
1794
|
+
title: "Instance List",
|
|
1795
|
+
description: "List of workflow instances with status and progress",
|
|
1796
|
+
domain: "workflow-system",
|
|
1797
|
+
owners: ["@workflow-team"],
|
|
1798
|
+
tags: ["workflow", "instance", "list"],
|
|
1799
|
+
stability: StabilityEnum.Experimental,
|
|
1800
|
+
goal: "Monitoring active and past workflow executions",
|
|
1801
|
+
context: "Operations monitoring"
|
|
1687
1802
|
},
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
version: "1.0.0",
|
|
1694
|
-
when: "Workflow is paused",
|
|
1695
|
-
payload: WorkflowInstanceModel
|
|
1696
|
-
}
|
|
1697
|
-
],
|
|
1698
|
-
audit: ["workflow.instance.paused"]
|
|
1803
|
+
source: {
|
|
1804
|
+
type: "component",
|
|
1805
|
+
framework: "react",
|
|
1806
|
+
componentKey: "WorkflowInstanceList",
|
|
1807
|
+
props: WorkflowInstanceModel
|
|
1699
1808
|
},
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
key: "pause-workflow-happy-path",
|
|
1704
|
-
given: ["Workflow is running"],
|
|
1705
|
-
when: ["Admin pauses workflow"],
|
|
1706
|
-
then: ["Instance status becomes PAUSED"]
|
|
1707
|
-
}
|
|
1708
|
-
],
|
|
1709
|
-
examples: [
|
|
1710
|
-
{
|
|
1711
|
-
key: "pause-maintenance",
|
|
1712
|
-
input: { instanceId: "inst-456", reason: "System maintenance" },
|
|
1713
|
-
output: { id: "inst-456", status: "paused" }
|
|
1714
|
-
}
|
|
1715
|
-
]
|
|
1809
|
+
targets: ["react", "markdown"],
|
|
1810
|
+
policy: {
|
|
1811
|
+
flags: ["workflow.enabled"]
|
|
1716
1812
|
}
|
|
1717
1813
|
});
|
|
1718
|
-
var
|
|
1814
|
+
var InstanceDetailPresentation = definePresentation({
|
|
1719
1815
|
meta: {
|
|
1720
|
-
key: "workflow.instance.
|
|
1816
|
+
key: "workflow.instance.detail",
|
|
1721
1817
|
version: "1.0.0",
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
input: defineSchemaModel8({
|
|
1731
|
-
name: "PauseResumeInput",
|
|
1732
|
-
fields: {
|
|
1733
|
-
instanceId: {
|
|
1734
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1735
|
-
isOptional: false
|
|
1736
|
-
},
|
|
1737
|
-
reason: { type: ScalarTypeEnum8.String_unsecure(), isOptional: true }
|
|
1738
|
-
}
|
|
1739
|
-
}),
|
|
1740
|
-
output: WorkflowInstanceModel
|
|
1818
|
+
title: "Instance Details",
|
|
1819
|
+
description: "Detailed view of a workflow instance with step timeline",
|
|
1820
|
+
domain: "workflow-system",
|
|
1821
|
+
owners: ["@workflow-team"],
|
|
1822
|
+
tags: ["workflow", "instance", "detail", "timeline"],
|
|
1823
|
+
stability: StabilityEnum.Experimental,
|
|
1824
|
+
goal: "Detailed inspection of a specific workflow instance",
|
|
1825
|
+
context: "Case management and troubleshooting"
|
|
1741
1826
|
},
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
version: "1.0.0",
|
|
1748
|
-
when: "Workflow is resumed",
|
|
1749
|
-
payload: WorkflowInstanceModel
|
|
1750
|
-
}
|
|
1751
|
-
],
|
|
1752
|
-
audit: ["workflow.instance.resumed"]
|
|
1827
|
+
source: {
|
|
1828
|
+
type: "component",
|
|
1829
|
+
framework: "react",
|
|
1830
|
+
componentKey: "WorkflowInstanceDetail",
|
|
1831
|
+
props: WorkflowInstanceModel
|
|
1753
1832
|
},
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
key: "resume-workflow-happy-path",
|
|
1758
|
-
given: ["Workflow is paused"],
|
|
1759
|
-
when: ["Admin resumes workflow"],
|
|
1760
|
-
then: ["Instance status becomes RUNNING"]
|
|
1761
|
-
}
|
|
1762
|
-
],
|
|
1763
|
-
examples: [
|
|
1764
|
-
{
|
|
1765
|
-
key: "resume-normal",
|
|
1766
|
-
input: { instanceId: "inst-456", reason: "Issue resolved" },
|
|
1767
|
-
output: { id: "inst-456", status: "running" }
|
|
1768
|
-
}
|
|
1769
|
-
]
|
|
1833
|
+
targets: ["react", "markdown"],
|
|
1834
|
+
policy: {
|
|
1835
|
+
flags: ["workflow.enabled"]
|
|
1770
1836
|
}
|
|
1771
1837
|
});
|
|
1772
|
-
var
|
|
1838
|
+
var ProgressTrackerPresentation = definePresentation({
|
|
1773
1839
|
meta: {
|
|
1774
|
-
key: "workflow.instance.
|
|
1840
|
+
key: "workflow.instance.progress",
|
|
1775
1841
|
version: "1.0.0",
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1842
|
+
title: "Progress Tracker",
|
|
1843
|
+
description: "Visual progress tracker showing current step in workflow",
|
|
1844
|
+
domain: "workflow-system",
|
|
1845
|
+
owners: ["@workflow-team"],
|
|
1846
|
+
tags: ["workflow", "progress", "widget"],
|
|
1847
|
+
stability: StabilityEnum.Experimental,
|
|
1848
|
+
goal: "Quick view of current progress for a workflow",
|
|
1849
|
+
context: "Embedded progress indicator in entity views"
|
|
1782
1850
|
},
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1789
|
-
isOptional: false
|
|
1790
|
-
},
|
|
1791
|
-
reason: {
|
|
1792
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1793
|
-
isOptional: false
|
|
1794
|
-
}
|
|
1795
|
-
}
|
|
1796
|
-
}),
|
|
1797
|
-
output: WorkflowInstanceModel
|
|
1851
|
+
source: {
|
|
1852
|
+
type: "component",
|
|
1853
|
+
framework: "react",
|
|
1854
|
+
componentKey: "WorkflowProgressTracker",
|
|
1855
|
+
props: WorkflowInstanceModel
|
|
1798
1856
|
},
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
{
|
|
1803
|
-
key: "workflow.instance.cancelled",
|
|
1804
|
-
version: "1.0.0",
|
|
1805
|
-
when: "Workflow is cancelled",
|
|
1806
|
-
payload: WorkflowInstanceModel
|
|
1807
|
-
}
|
|
1808
|
-
],
|
|
1809
|
-
audit: ["workflow.instance.cancelled"]
|
|
1810
|
-
},
|
|
1811
|
-
acceptance: {
|
|
1812
|
-
scenarios: [
|
|
1813
|
-
{
|
|
1814
|
-
key: "cancel-workflow-happy-path",
|
|
1815
|
-
given: ["Workflow is running"],
|
|
1816
|
-
when: ["User cancels workflow"],
|
|
1817
|
-
then: ["Instance status becomes CANCELLED"]
|
|
1818
|
-
}
|
|
1819
|
-
],
|
|
1820
|
-
examples: [
|
|
1821
|
-
{
|
|
1822
|
-
key: "cancel-mistake",
|
|
1823
|
-
input: { instanceId: "inst-456", reason: "Created by mistake" },
|
|
1824
|
-
output: { id: "inst-456", status: "cancelled" }
|
|
1825
|
-
}
|
|
1826
|
-
]
|
|
1857
|
+
targets: ["react"],
|
|
1858
|
+
policy: {
|
|
1859
|
+
flags: ["workflow.enabled"]
|
|
1827
1860
|
}
|
|
1828
1861
|
});
|
|
1829
|
-
var
|
|
1862
|
+
var ApprovalInboxPresentation = definePresentation({
|
|
1830
1863
|
meta: {
|
|
1831
|
-
key: "workflow.
|
|
1864
|
+
key: "workflow.approval.inbox",
|
|
1832
1865
|
version: "1.0.0",
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1866
|
+
title: "Approval Inbox",
|
|
1867
|
+
description: "Inbox showing pending approval requests for current user",
|
|
1868
|
+
domain: "workflow-system",
|
|
1869
|
+
owners: ["@workflow-team"],
|
|
1870
|
+
tags: ["workflow", "approval", "inbox"],
|
|
1871
|
+
stability: StabilityEnum.Experimental,
|
|
1872
|
+
goal: "Managing personal workload of approval requests",
|
|
1873
|
+
context: "Personal task management"
|
|
1839
1874
|
},
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1846
|
-
isOptional: true
|
|
1847
|
-
},
|
|
1848
|
-
status: { type: InstanceStatusEnum, isOptional: true },
|
|
1849
|
-
referenceType: {
|
|
1850
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1851
|
-
isOptional: true
|
|
1852
|
-
},
|
|
1853
|
-
referenceId: {
|
|
1854
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1855
|
-
isOptional: true
|
|
1856
|
-
},
|
|
1857
|
-
triggeredBy: {
|
|
1858
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1859
|
-
isOptional: true
|
|
1860
|
-
},
|
|
1861
|
-
limit: {
|
|
1862
|
-
type: ScalarTypeEnum8.Int_unsecure(),
|
|
1863
|
-
isOptional: true,
|
|
1864
|
-
defaultValue: 20
|
|
1865
|
-
},
|
|
1866
|
-
offset: {
|
|
1867
|
-
type: ScalarTypeEnum8.Int_unsecure(),
|
|
1868
|
-
isOptional: true,
|
|
1869
|
-
defaultValue: 0
|
|
1870
|
-
}
|
|
1871
|
-
}
|
|
1872
|
-
}),
|
|
1873
|
-
output: defineSchemaModel8({
|
|
1874
|
-
name: "ListInstancesOutput",
|
|
1875
|
-
fields: {
|
|
1876
|
-
instances: {
|
|
1877
|
-
type: WorkflowInstanceModel,
|
|
1878
|
-
isArray: true,
|
|
1879
|
-
isOptional: false
|
|
1880
|
-
},
|
|
1881
|
-
total: { type: ScalarTypeEnum8.Int_unsecure(), isOptional: false }
|
|
1882
|
-
}
|
|
1883
|
-
})
|
|
1875
|
+
source: {
|
|
1876
|
+
type: "component",
|
|
1877
|
+
framework: "react",
|
|
1878
|
+
componentKey: "ApprovalInbox",
|
|
1879
|
+
props: ApprovalRequestModel
|
|
1884
1880
|
},
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
{
|
|
1889
|
-
key: "list-instances-happy-path",
|
|
1890
|
-
given: ["Workflow instances exist"],
|
|
1891
|
-
when: ["User lists instances"],
|
|
1892
|
-
then: ["List of instances is returned"]
|
|
1893
|
-
}
|
|
1894
|
-
],
|
|
1895
|
-
examples: [
|
|
1896
|
-
{
|
|
1897
|
-
key: "list-running",
|
|
1898
|
-
input: { status: "running", limit: 10 },
|
|
1899
|
-
output: { instances: [], total: 5 }
|
|
1900
|
-
}
|
|
1901
|
-
]
|
|
1881
|
+
targets: ["react", "markdown"],
|
|
1882
|
+
policy: {
|
|
1883
|
+
flags: ["workflow.approvals.enabled"]
|
|
1902
1884
|
}
|
|
1903
1885
|
});
|
|
1904
|
-
var
|
|
1886
|
+
var ApprovalDetailPresentation = definePresentation({
|
|
1905
1887
|
meta: {
|
|
1906
|
-
key: "workflow.
|
|
1888
|
+
key: "workflow.approval.detail",
|
|
1907
1889
|
version: "1.0.0",
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1890
|
+
title: "Approval Details",
|
|
1891
|
+
description: "Detailed approval request view with context and actions",
|
|
1892
|
+
domain: "workflow-system",
|
|
1893
|
+
owners: ["@workflow-team"],
|
|
1894
|
+
tags: ["workflow", "approval", "detail"],
|
|
1895
|
+
stability: StabilityEnum.Experimental,
|
|
1896
|
+
goal: "Decision support for an approval request",
|
|
1897
|
+
context: "Specific approval action"
|
|
1914
1898
|
},
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
type: ScalarTypeEnum8.String_unsecure(),
|
|
1921
|
-
isOptional: false
|
|
1922
|
-
}
|
|
1923
|
-
}
|
|
1924
|
-
}),
|
|
1925
|
-
output: WorkflowInstanceModel
|
|
1899
|
+
source: {
|
|
1900
|
+
type: "component",
|
|
1901
|
+
framework: "react",
|
|
1902
|
+
componentKey: "ApprovalRequestDetail",
|
|
1903
|
+
props: ApprovalRequestModel
|
|
1926
1904
|
},
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
{
|
|
1931
|
-
key: "get-instance-happy-path",
|
|
1932
|
-
given: ["Instance exists"],
|
|
1933
|
-
when: ["User requests instance details"],
|
|
1934
|
-
then: ["Instance details are returned"]
|
|
1935
|
-
}
|
|
1936
|
-
],
|
|
1937
|
-
examples: [
|
|
1938
|
-
{
|
|
1939
|
-
key: "get-details",
|
|
1940
|
-
input: { instanceId: "inst-456" },
|
|
1941
|
-
output: { id: "inst-456", workflowKey: "onboarding-v1" }
|
|
1942
|
-
}
|
|
1943
|
-
]
|
|
1944
|
-
}
|
|
1945
|
-
});
|
|
1946
|
-
|
|
1947
|
-
// src/instance/instance.event.ts
|
|
1948
|
-
import { defineEvent as defineEvent3 } from "@contractspec/lib.contracts-spec";
|
|
1949
|
-
import { ScalarTypeEnum as ScalarTypeEnum9, defineSchemaModel as defineSchemaModel9 } from "@contractspec/lib.schema";
|
|
1950
|
-
var InstanceEventPayload = defineSchemaModel9({
|
|
1951
|
-
name: "InstanceEventPayload",
|
|
1952
|
-
description: "Base payload for instance events",
|
|
1953
|
-
fields: {
|
|
1954
|
-
instanceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1955
|
-
workflowId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1956
|
-
workflowKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1957
|
-
status: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1958
|
-
referenceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
|
|
1959
|
-
referenceType: {
|
|
1960
|
-
type: ScalarTypeEnum9.String_unsecure(),
|
|
1961
|
-
isOptional: true
|
|
1962
|
-
},
|
|
1963
|
-
triggeredBy: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1964
|
-
organizationId: {
|
|
1965
|
-
type: ScalarTypeEnum9.String_unsecure(),
|
|
1966
|
-
isOptional: false
|
|
1967
|
-
},
|
|
1968
|
-
timestamp: { type: ScalarTypeEnum9.DateTime(), isOptional: false }
|
|
1969
|
-
}
|
|
1970
|
-
});
|
|
1971
|
-
var StepTransitionPayload = defineSchemaModel9({
|
|
1972
|
-
name: "StepTransitionEventPayload",
|
|
1973
|
-
description: "Payload for step transition events",
|
|
1974
|
-
fields: {
|
|
1975
|
-
instanceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1976
|
-
workflowId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1977
|
-
fromStepKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
|
|
1978
|
-
toStepKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1979
|
-
action: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
|
|
1980
|
-
executedBy: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1981
|
-
timestamp: { type: ScalarTypeEnum9.DateTime(), isOptional: false }
|
|
1982
|
-
}
|
|
1983
|
-
});
|
|
1984
|
-
var InstanceCompletedPayload = defineSchemaModel9({
|
|
1985
|
-
name: "InstanceCompletedEventPayload",
|
|
1986
|
-
description: "Payload when instance completes",
|
|
1987
|
-
fields: {
|
|
1988
|
-
instanceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1989
|
-
workflowId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1990
|
-
workflowKey: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1991
|
-
outcome: { type: ScalarTypeEnum9.String_unsecure(), isOptional: false },
|
|
1992
|
-
referenceId: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
|
|
1993
|
-
referenceType: {
|
|
1994
|
-
type: ScalarTypeEnum9.String_unsecure(),
|
|
1995
|
-
isOptional: true
|
|
1996
|
-
},
|
|
1997
|
-
duration: { type: ScalarTypeEnum9.Int_unsecure(), isOptional: false },
|
|
1998
|
-
timestamp: { type: ScalarTypeEnum9.DateTime(), isOptional: false }
|
|
1905
|
+
targets: ["react", "markdown"],
|
|
1906
|
+
policy: {
|
|
1907
|
+
flags: ["workflow.approvals.enabled"]
|
|
1999
1908
|
}
|
|
2000
1909
|
});
|
|
2001
|
-
var
|
|
1910
|
+
var ApprovalFormPresentation = definePresentation({
|
|
2002
1911
|
meta: {
|
|
2003
|
-
key: "workflow.
|
|
1912
|
+
key: "workflow.approval.form",
|
|
2004
1913
|
version: "1.0.0",
|
|
2005
|
-
|
|
2006
|
-
|
|
1914
|
+
title: "Approval Form",
|
|
1915
|
+
description: "Form for submitting approval decisions",
|
|
1916
|
+
domain: "workflow-system",
|
|
2007
1917
|
owners: ["@workflow-team"],
|
|
2008
|
-
tags: ["workflow", "
|
|
1918
|
+
tags: ["workflow", "approval", "form"],
|
|
1919
|
+
stability: StabilityEnum.Experimental,
|
|
1920
|
+
goal: "Submitting a decision on an approval request",
|
|
1921
|
+
context: "Approval decision dialog"
|
|
2009
1922
|
},
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
key: "workflow.step.entered",
|
|
2015
|
-
version: "1.0.0",
|
|
2016
|
-
description: "A workflow instance has entered a new step.",
|
|
2017
|
-
stability: "stable",
|
|
2018
|
-
owners: ["@workflow-team"],
|
|
2019
|
-
tags: ["workflow", "step", "entered"]
|
|
1923
|
+
source: {
|
|
1924
|
+
type: "component",
|
|
1925
|
+
framework: "react",
|
|
1926
|
+
componentKey: "ApprovalDecisionForm"
|
|
2020
1927
|
},
|
|
2021
|
-
|
|
1928
|
+
targets: ["react"],
|
|
1929
|
+
policy: {
|
|
1930
|
+
flags: ["workflow.approvals.enabled"]
|
|
1931
|
+
}
|
|
2022
1932
|
});
|
|
2023
|
-
var
|
|
1933
|
+
var PendingApprovalsBadgePresentation = definePresentation({
|
|
2024
1934
|
meta: {
|
|
2025
|
-
key: "workflow.
|
|
1935
|
+
key: "workflow.approval.badge",
|
|
2026
1936
|
version: "1.0.0",
|
|
2027
|
-
|
|
2028
|
-
|
|
1937
|
+
title: "Pending Approvals Badge",
|
|
1938
|
+
description: "Badge showing count of pending approvals",
|
|
1939
|
+
domain: "workflow-system",
|
|
2029
1940
|
owners: ["@workflow-team"],
|
|
2030
|
-
tags: ["workflow", "
|
|
1941
|
+
tags: ["workflow", "approval", "badge", "widget"],
|
|
1942
|
+
stability: StabilityEnum.Experimental,
|
|
1943
|
+
goal: "Visual notification of pending approvals",
|
|
1944
|
+
context: "Global navigation or sidebar"
|
|
2031
1945
|
},
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
key: "workflow.instance.completed",
|
|
2037
|
-
version: "1.0.0",
|
|
2038
|
-
description: "A workflow instance has completed.",
|
|
2039
|
-
stability: "stable",
|
|
2040
|
-
owners: ["@workflow-team"],
|
|
2041
|
-
tags: ["workflow", "instance", "completed"]
|
|
1946
|
+
source: {
|
|
1947
|
+
type: "component",
|
|
1948
|
+
framework: "react",
|
|
1949
|
+
componentKey: "PendingApprovalsBadge"
|
|
2042
1950
|
},
|
|
2043
|
-
|
|
1951
|
+
targets: ["react"],
|
|
1952
|
+
policy: {
|
|
1953
|
+
flags: ["workflow.approvals.enabled"]
|
|
1954
|
+
}
|
|
2044
1955
|
});
|
|
2045
|
-
var
|
|
1956
|
+
var WorkflowMetricsPresentation = definePresentation({
|
|
2046
1957
|
meta: {
|
|
2047
|
-
key: "workflow.
|
|
1958
|
+
key: "workflow.metrics",
|
|
2048
1959
|
version: "1.0.0",
|
|
2049
|
-
|
|
2050
|
-
|
|
1960
|
+
title: "Workflow Metrics",
|
|
1961
|
+
description: "Dashboard widget showing workflow metrics and statistics",
|
|
1962
|
+
domain: "workflow-system",
|
|
2051
1963
|
owners: ["@workflow-team"],
|
|
2052
|
-
tags: ["workflow", "
|
|
2053
|
-
},
|
|
2054
|
-
payload: InstanceEventPayload
|
|
2055
|
-
});
|
|
2056
|
-
var InstancePausedEvent = defineEvent3({
|
|
2057
|
-
meta: {
|
|
2058
|
-
key: "workflow.instance.paused",
|
|
2059
|
-
version: "1.0.0",
|
|
2060
|
-
description: "A workflow instance has been paused.",
|
|
2061
|
-
stability: "stable",
|
|
2062
|
-
owners: ["@workflow-team"],
|
|
2063
|
-
tags: ["workflow", "instance", "paused"]
|
|
2064
|
-
},
|
|
2065
|
-
payload: InstanceEventPayload
|
|
2066
|
-
});
|
|
2067
|
-
var InstanceResumedEvent = defineEvent3({
|
|
2068
|
-
meta: {
|
|
2069
|
-
key: "workflow.instance.resumed",
|
|
2070
|
-
version: "1.0.0",
|
|
2071
|
-
description: "A workflow instance has been resumed.",
|
|
2072
|
-
stability: "stable",
|
|
2073
|
-
owners: ["@workflow-team"],
|
|
2074
|
-
tags: ["workflow", "instance", "resumed"]
|
|
2075
|
-
},
|
|
2076
|
-
payload: InstanceEventPayload
|
|
2077
|
-
});
|
|
2078
|
-
var InstanceFailedEvent = defineEvent3({
|
|
2079
|
-
meta: {
|
|
2080
|
-
key: "workflow.instance.failed",
|
|
2081
|
-
version: "1.0.0",
|
|
2082
|
-
description: "A workflow instance has failed.",
|
|
2083
|
-
stability: "stable",
|
|
2084
|
-
owners: ["@workflow-team"],
|
|
2085
|
-
tags: ["workflow", "instance", "failed"]
|
|
2086
|
-
},
|
|
2087
|
-
payload: InstanceEventPayload
|
|
2088
|
-
});
|
|
2089
|
-
var InstanceTimedOutEvent = defineEvent3({
|
|
2090
|
-
meta: {
|
|
2091
|
-
key: "workflow.instance.timedOut",
|
|
2092
|
-
version: "1.0.0",
|
|
2093
|
-
description: "A workflow instance has timed out.",
|
|
2094
|
-
stability: "stable",
|
|
2095
|
-
owners: ["@workflow-team"],
|
|
2096
|
-
tags: ["workflow", "instance", "timeout"]
|
|
2097
|
-
},
|
|
2098
|
-
payload: InstanceEventPayload
|
|
2099
|
-
});
|
|
2100
|
-
// src/presentations/index.ts
|
|
2101
|
-
import {
|
|
2102
|
-
definePresentation,
|
|
2103
|
-
StabilityEnum
|
|
2104
|
-
} from "@contractspec/lib.contracts-spec";
|
|
2105
|
-
var WorkflowDesignerPresentation = definePresentation({
|
|
2106
|
-
meta: {
|
|
2107
|
-
key: "workflow.designer",
|
|
2108
|
-
version: "1.0.0",
|
|
2109
|
-
title: "Workflow Designer",
|
|
2110
|
-
description: "Visual workflow designer with drag-and-drop steps",
|
|
2111
|
-
domain: "workflow-system",
|
|
2112
|
-
owners: ["@workflow-team"],
|
|
2113
|
-
tags: ["workflow", "designer", "admin"],
|
|
1964
|
+
tags: ["workflow", "metrics", "dashboard"],
|
|
2114
1965
|
stability: StabilityEnum.Experimental,
|
|
2115
|
-
goal: "
|
|
2116
|
-
context: "
|
|
1966
|
+
goal: "Monitoring throughput and bottlenecks",
|
|
1967
|
+
context: "System performance dashboard"
|
|
2117
1968
|
},
|
|
2118
1969
|
source: {
|
|
2119
1970
|
type: "component",
|
|
2120
1971
|
framework: "react",
|
|
2121
|
-
componentKey: "
|
|
2122
|
-
props: WorkflowDefinitionModel
|
|
1972
|
+
componentKey: "WorkflowMetricsDashboard"
|
|
2123
1973
|
},
|
|
2124
|
-
targets: ["react"],
|
|
1974
|
+
targets: ["react", "markdown"],
|
|
2125
1975
|
policy: {
|
|
2126
|
-
flags: ["workflow.
|
|
1976
|
+
flags: ["workflow.metrics.enabled"]
|
|
2127
1977
|
}
|
|
2128
1978
|
});
|
|
2129
|
-
var
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
1979
|
+
var WorkflowSystemPresentations = {
|
|
1980
|
+
WorkflowDesignerPresentation,
|
|
1981
|
+
WorkflowListPresentation,
|
|
1982
|
+
WorkflowDetailPresentation,
|
|
1983
|
+
InstanceListPresentation,
|
|
1984
|
+
InstanceDetailPresentation,
|
|
1985
|
+
ProgressTrackerPresentation,
|
|
1986
|
+
ApprovalInboxPresentation,
|
|
1987
|
+
ApprovalDetailPresentation,
|
|
1988
|
+
ApprovalFormPresentation,
|
|
1989
|
+
PendingApprovalsBadgePresentation,
|
|
1990
|
+
WorkflowMetricsPresentation
|
|
1991
|
+
};
|
|
1992
|
+
// src/ui/hooks/useWorkflowList.ts
|
|
1993
|
+
import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
|
|
1994
|
+
import { useCallback, useEffect, useState } from "react";
|
|
1995
|
+
"use client";
|
|
1996
|
+
function useWorkflowList(projectIdOverride) {
|
|
1997
|
+
const { handlers, projectId: runtimeProjectId } = useTemplateRuntime();
|
|
1998
|
+
const projectId = projectIdOverride ?? runtimeProjectId;
|
|
1999
|
+
const workflow = handlers.workflow;
|
|
2000
|
+
const [definitions, setDefinitions] = useState([]);
|
|
2001
|
+
const [instances, setInstances] = useState([]);
|
|
2002
|
+
const [loading, setLoading] = useState(true);
|
|
2003
|
+
const [error, setError] = useState(null);
|
|
2004
|
+
const fetchData = useCallback(async () => {
|
|
2005
|
+
try {
|
|
2006
|
+
setLoading(true);
|
|
2007
|
+
setError(null);
|
|
2008
|
+
const [defResult, instResult] = await Promise.all([
|
|
2009
|
+
workflow.listDefinitions({ projectId, limit: 100 }),
|
|
2010
|
+
workflow.listInstances({ projectId, limit: 100 })
|
|
2011
|
+
]);
|
|
2012
|
+
setDefinitions(defResult.definitions);
|
|
2013
|
+
setInstances(instResult.instances);
|
|
2014
|
+
} catch (err) {
|
|
2015
|
+
setError(err instanceof Error ? err : new Error("Failed to load workflows"));
|
|
2016
|
+
} finally {
|
|
2017
|
+
setLoading(false);
|
|
2018
|
+
}
|
|
2019
|
+
}, [projectId, workflow]);
|
|
2020
|
+
useEffect(() => {
|
|
2021
|
+
fetchData();
|
|
2022
|
+
}, [fetchData]);
|
|
2023
|
+
const stats = {
|
|
2024
|
+
totalDefinitions: definitions.length,
|
|
2025
|
+
activeDefinitions: definitions.filter((d) => d.status === "ACTIVE").length,
|
|
2026
|
+
totalInstances: instances.length,
|
|
2027
|
+
pendingInstances: instances.filter((i) => i.status === "PENDING").length,
|
|
2028
|
+
inProgressInstances: instances.filter((i) => i.status === "IN_PROGRESS").length,
|
|
2029
|
+
completedInstances: instances.filter((i) => i.status === "COMPLETED").length,
|
|
2030
|
+
rejectedInstances: instances.filter((i) => i.status === "REJECTED").length
|
|
2031
|
+
};
|
|
2032
|
+
return {
|
|
2033
|
+
definitions,
|
|
2034
|
+
instances,
|
|
2035
|
+
loading,
|
|
2036
|
+
error,
|
|
2037
|
+
stats,
|
|
2038
|
+
refetch: fetchData
|
|
2039
|
+
};
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
// src/ui/hooks/index.ts
|
|
2043
|
+
"use client";
|
|
2044
|
+
|
|
2045
|
+
// src/shared/demo-scenario.ts
|
|
2046
|
+
var WORKFLOW_SYSTEM_DEMO_PROJECT_ID = "workflow-system-demo";
|
|
2047
|
+
var WORKFLOW_SYSTEM_DEMO_ORGANIZATION_ID = "org_demo";
|
|
2048
|
+
var WORKFLOW_SYSTEM_DEMO_DEFINITIONS = [
|
|
2049
|
+
{
|
|
2050
|
+
id: "wf_expense",
|
|
2051
|
+
name: "Expense Approval",
|
|
2052
|
+
description: "Approve non-trivial spend before finance releases budget.",
|
|
2053
|
+
type: "APPROVAL",
|
|
2054
|
+
status: "ACTIVE",
|
|
2055
|
+
createdAt: "2026-03-10T09:00:00.000Z",
|
|
2056
|
+
updatedAt: "2026-03-20T08:15:00.000Z",
|
|
2057
|
+
steps: [
|
|
2058
|
+
{
|
|
2059
|
+
id: "wfstep_expense_manager",
|
|
2060
|
+
name: "Manager Review",
|
|
2061
|
+
description: "Validate business value and team budget.",
|
|
2062
|
+
stepOrder: 1,
|
|
2063
|
+
type: "APPROVAL",
|
|
2064
|
+
requiredRoles: ["manager"],
|
|
2065
|
+
createdAt: "2026-03-10T09:00:00.000Z"
|
|
2066
|
+
},
|
|
2067
|
+
{
|
|
2068
|
+
id: "wfstep_expense_finance",
|
|
2069
|
+
name: "Finance Review",
|
|
2070
|
+
description: "Confirm ledger coding and spending threshold.",
|
|
2071
|
+
stepOrder: 2,
|
|
2072
|
+
type: "APPROVAL",
|
|
2073
|
+
requiredRoles: ["finance"],
|
|
2074
|
+
createdAt: "2026-03-10T09:10:00.000Z"
|
|
2075
|
+
}
|
|
2076
|
+
]
|
|
2141
2077
|
},
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2078
|
+
{
|
|
2079
|
+
id: "wf_vendor",
|
|
2080
|
+
name: "Vendor Onboarding",
|
|
2081
|
+
description: "Sequence security, procurement, and legal before activation.",
|
|
2082
|
+
type: "SEQUENTIAL",
|
|
2083
|
+
status: "ACTIVE",
|
|
2084
|
+
createdAt: "2026-03-08T11:00:00.000Z",
|
|
2085
|
+
updatedAt: "2026-03-19T13:10:00.000Z",
|
|
2086
|
+
steps: [
|
|
2087
|
+
{
|
|
2088
|
+
id: "wfstep_vendor_security",
|
|
2089
|
+
name: "Security Check",
|
|
2090
|
+
description: "Review data access and integration scope.",
|
|
2091
|
+
stepOrder: 1,
|
|
2092
|
+
type: "APPROVAL",
|
|
2093
|
+
requiredRoles: ["security"],
|
|
2094
|
+
createdAt: "2026-03-08T11:00:00.000Z"
|
|
2095
|
+
},
|
|
2096
|
+
{
|
|
2097
|
+
id: "wfstep_vendor_procurement",
|
|
2098
|
+
name: "Procurement Check",
|
|
2099
|
+
description: "Validate pricing, procurement policy, and owner.",
|
|
2100
|
+
stepOrder: 2,
|
|
2101
|
+
type: "APPROVAL",
|
|
2102
|
+
requiredRoles: ["procurement"],
|
|
2103
|
+
createdAt: "2026-03-08T11:05:00.000Z"
|
|
2104
|
+
},
|
|
2105
|
+
{
|
|
2106
|
+
id: "wfstep_vendor_legal",
|
|
2107
|
+
name: "Legal Sign-off",
|
|
2108
|
+
description: "Approve terms before the vendor goes live.",
|
|
2109
|
+
stepOrder: 3,
|
|
2110
|
+
type: "APPROVAL",
|
|
2111
|
+
requiredRoles: ["legal"],
|
|
2112
|
+
createdAt: "2026-03-08T11:10:00.000Z"
|
|
2113
|
+
}
|
|
2114
|
+
]
|
|
2147
2115
|
},
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2116
|
+
{
|
|
2117
|
+
id: "wf_policy_exception",
|
|
2118
|
+
name: "Policy Exception",
|
|
2119
|
+
description: "Escalate a temporary exception through team lead and compliance.",
|
|
2120
|
+
type: "APPROVAL",
|
|
2121
|
+
status: "DRAFT",
|
|
2122
|
+
createdAt: "2026-03-15T07:30:00.000Z",
|
|
2123
|
+
updatedAt: "2026-03-18T11:20:00.000Z",
|
|
2124
|
+
steps: [
|
|
2125
|
+
{
|
|
2126
|
+
id: "wfstep_policy_lead",
|
|
2127
|
+
name: "Team Lead Review",
|
|
2128
|
+
description: "Check urgency and expected blast radius.",
|
|
2129
|
+
stepOrder: 1,
|
|
2130
|
+
type: "APPROVAL",
|
|
2131
|
+
requiredRoles: ["team-lead"],
|
|
2132
|
+
createdAt: "2026-03-15T07:30:00.000Z"
|
|
2133
|
+
},
|
|
2134
|
+
{
|
|
2135
|
+
id: "wfstep_policy_compliance",
|
|
2136
|
+
name: "Compliance Review",
|
|
2137
|
+
description: "Accept or reject the exception request.",
|
|
2138
|
+
stepOrder: 2,
|
|
2139
|
+
type: "APPROVAL",
|
|
2140
|
+
requiredRoles: ["compliance"],
|
|
2141
|
+
createdAt: "2026-03-15T07:40:00.000Z"
|
|
2142
|
+
}
|
|
2143
|
+
]
|
|
2151
2144
|
}
|
|
2152
|
-
|
|
2153
|
-
var
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2145
|
+
];
|
|
2146
|
+
var WORKFLOW_SYSTEM_DEMO_INSTANCES = [
|
|
2147
|
+
{
|
|
2148
|
+
id: "wfinst_expense_open",
|
|
2149
|
+
definitionId: "wf_expense",
|
|
2150
|
+
status: "IN_PROGRESS",
|
|
2151
|
+
currentStepId: "wfstep_expense_finance",
|
|
2152
|
+
data: {
|
|
2153
|
+
amount: 4200,
|
|
2154
|
+
currency: "EUR",
|
|
2155
|
+
vendor: "Nimbus AI"
|
|
2156
|
+
},
|
|
2157
|
+
requestedBy: "sarah@contractspec.io",
|
|
2158
|
+
startedAt: "2026-03-20T08:00:00.000Z",
|
|
2159
|
+
approvals: [
|
|
2160
|
+
{
|
|
2161
|
+
id: "wfappr_expense_manager",
|
|
2162
|
+
stepId: "wfstep_expense_manager",
|
|
2163
|
+
status: "APPROVED",
|
|
2164
|
+
actorId: "manager.demo",
|
|
2165
|
+
comment: "Approved for the Q2 automation budget.",
|
|
2166
|
+
decidedAt: "2026-03-20T08:15:00.000Z",
|
|
2167
|
+
createdAt: "2026-03-20T08:05:00.000Z"
|
|
2168
|
+
},
|
|
2169
|
+
{
|
|
2170
|
+
id: "wfappr_expense_finance",
|
|
2171
|
+
stepId: "wfstep_expense_finance",
|
|
2172
|
+
status: "PENDING",
|
|
2173
|
+
createdAt: "2026-03-20T08:15:00.000Z"
|
|
2174
|
+
}
|
|
2175
|
+
]
|
|
2165
2176
|
},
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2177
|
+
{
|
|
2178
|
+
id: "wfinst_vendor_done",
|
|
2179
|
+
definitionId: "wf_vendor",
|
|
2180
|
+
status: "COMPLETED",
|
|
2181
|
+
data: {
|
|
2182
|
+
vendor: "Acme Cloud",
|
|
2183
|
+
riskTier: "medium"
|
|
2184
|
+
},
|
|
2185
|
+
requestedBy: "leo@contractspec.io",
|
|
2186
|
+
startedAt: "2026-03-19T09:30:00.000Z",
|
|
2187
|
+
completedAt: "2026-03-19T13:10:00.000Z",
|
|
2188
|
+
approvals: [
|
|
2189
|
+
{
|
|
2190
|
+
id: "wfappr_vendor_security",
|
|
2191
|
+
stepId: "wfstep_vendor_security",
|
|
2192
|
+
status: "APPROVED",
|
|
2193
|
+
actorId: "security.demo",
|
|
2194
|
+
comment: "SOC2 scope is acceptable.",
|
|
2195
|
+
decidedAt: "2026-03-19T10:10:00.000Z",
|
|
2196
|
+
createdAt: "2026-03-19T09:35:00.000Z"
|
|
2197
|
+
},
|
|
2198
|
+
{
|
|
2199
|
+
id: "wfappr_vendor_procurement",
|
|
2200
|
+
stepId: "wfstep_vendor_procurement",
|
|
2201
|
+
status: "APPROVED",
|
|
2202
|
+
actorId: "procurement.demo",
|
|
2203
|
+
comment: "Commercial terms match the preferred vendor tier.",
|
|
2204
|
+
decidedAt: "2026-03-19T11:25:00.000Z",
|
|
2205
|
+
createdAt: "2026-03-19T10:15:00.000Z"
|
|
2206
|
+
},
|
|
2207
|
+
{
|
|
2208
|
+
id: "wfappr_vendor_legal",
|
|
2209
|
+
stepId: "wfstep_vendor_legal",
|
|
2210
|
+
status: "APPROVED",
|
|
2211
|
+
actorId: "legal.demo",
|
|
2212
|
+
comment: "MSA redlines are complete.",
|
|
2213
|
+
decidedAt: "2026-03-19T13:05:00.000Z",
|
|
2214
|
+
createdAt: "2026-03-19T11:30:00.000Z"
|
|
2215
|
+
}
|
|
2216
|
+
]
|
|
2171
2217
|
},
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2218
|
+
{
|
|
2219
|
+
id: "wfinst_policy_rejected",
|
|
2220
|
+
definitionId: "wf_policy_exception",
|
|
2221
|
+
status: "REJECTED",
|
|
2222
|
+
currentStepId: "wfstep_policy_compliance",
|
|
2223
|
+
data: {
|
|
2224
|
+
policy: "Model rollout freeze",
|
|
2225
|
+
durationDays: 14
|
|
2226
|
+
},
|
|
2227
|
+
requestedBy: "maya@contractspec.io",
|
|
2228
|
+
startedAt: "2026-03-18T10:00:00.000Z",
|
|
2229
|
+
completedAt: "2026-03-18T11:20:00.000Z",
|
|
2230
|
+
approvals: [
|
|
2231
|
+
{
|
|
2232
|
+
id: "wfappr_policy_lead",
|
|
2233
|
+
stepId: "wfstep_policy_lead",
|
|
2234
|
+
status: "APPROVED",
|
|
2235
|
+
actorId: "lead.demo",
|
|
2236
|
+
comment: "Escalation justified for the release train.",
|
|
2237
|
+
decidedAt: "2026-03-18T10:30:00.000Z",
|
|
2238
|
+
createdAt: "2026-03-18T10:05:00.000Z"
|
|
2239
|
+
},
|
|
2240
|
+
{
|
|
2241
|
+
id: "wfappr_policy_compliance",
|
|
2242
|
+
stepId: "wfstep_policy_compliance",
|
|
2243
|
+
status: "REJECTED",
|
|
2244
|
+
actorId: "compliance.demo",
|
|
2245
|
+
comment: "Exception exceeds the allowed blast radius.",
|
|
2246
|
+
decidedAt: "2026-03-18T11:15:00.000Z",
|
|
2247
|
+
createdAt: "2026-03-18T10:35:00.000Z"
|
|
2248
|
+
}
|
|
2249
|
+
]
|
|
2175
2250
|
}
|
|
2176
|
-
|
|
2177
|
-
|
|
2251
|
+
];
|
|
2252
|
+
|
|
2253
|
+
// src/visualizations/catalog.ts
|
|
2254
|
+
import {
|
|
2255
|
+
defineVisualization,
|
|
2256
|
+
VisualizationRegistry
|
|
2257
|
+
} from "@contractspec/lib.contracts-spec/visualizations";
|
|
2258
|
+
var INSTANCE_LIST_REF = {
|
|
2259
|
+
key: "workflow.instance.list",
|
|
2260
|
+
version: "1.0.0"
|
|
2261
|
+
};
|
|
2262
|
+
var META = {
|
|
2263
|
+
version: "1.0.0",
|
|
2264
|
+
domain: "workflow",
|
|
2265
|
+
stability: "experimental",
|
|
2266
|
+
owners: ["@example.workflow-system"],
|
|
2267
|
+
tags: ["workflow", "visualization", "operations"]
|
|
2268
|
+
};
|
|
2269
|
+
var WorkflowInstanceStatusVisualization = defineVisualization({
|
|
2178
2270
|
meta: {
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
title: "Instance
|
|
2182
|
-
description: "
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2271
|
+
...META,
|
|
2272
|
+
key: "workflow-system.visualization.instance-status",
|
|
2273
|
+
title: "Instance Status Breakdown",
|
|
2274
|
+
description: "Distribution of workflow instance states.",
|
|
2275
|
+
goal: "Surface the current workload mix.",
|
|
2276
|
+
context: "Workflow operations overview."
|
|
2277
|
+
},
|
|
2278
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
2279
|
+
visualization: {
|
|
2280
|
+
kind: "pie",
|
|
2281
|
+
nameDimension: "status",
|
|
2282
|
+
valueMeasure: "instances",
|
|
2283
|
+
dimensions: [
|
|
2284
|
+
{ key: "status", label: "Status", dataPath: "status", type: "category" }
|
|
2285
|
+
],
|
|
2286
|
+
measures: [
|
|
2287
|
+
{
|
|
2288
|
+
key: "instances",
|
|
2289
|
+
label: "Instances",
|
|
2290
|
+
dataPath: "instances",
|
|
2291
|
+
format: "number"
|
|
2292
|
+
}
|
|
2293
|
+
],
|
|
2294
|
+
table: { caption: "Workflow instance counts by status." }
|
|
2199
2295
|
}
|
|
2200
2296
|
});
|
|
2201
|
-
var
|
|
2297
|
+
var WorkflowThroughputVisualization = defineVisualization({
|
|
2202
2298
|
meta: {
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
title: "
|
|
2206
|
-
description: "
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
key: "workflow.instance.progress",
|
|
2228
|
-
version: "1.0.0",
|
|
2229
|
-
title: "Progress Tracker",
|
|
2230
|
-
description: "Visual progress tracker showing current step in workflow",
|
|
2231
|
-
domain: "workflow-system",
|
|
2232
|
-
owners: ["@workflow-team"],
|
|
2233
|
-
tags: ["workflow", "progress", "widget"],
|
|
2234
|
-
stability: StabilityEnum.Experimental,
|
|
2235
|
-
goal: "Quick view of current progress for a workflow",
|
|
2236
|
-
context: "Embedded progress indicator in entity views"
|
|
2237
|
-
},
|
|
2238
|
-
source: {
|
|
2239
|
-
type: "component",
|
|
2240
|
-
framework: "react",
|
|
2241
|
-
componentKey: "WorkflowProgressTracker",
|
|
2242
|
-
props: WorkflowInstanceModel
|
|
2243
|
-
},
|
|
2244
|
-
targets: ["react"],
|
|
2245
|
-
policy: {
|
|
2246
|
-
flags: ["workflow.enabled"]
|
|
2247
|
-
}
|
|
2248
|
-
});
|
|
2249
|
-
var ApprovalInboxPresentation = definePresentation({
|
|
2250
|
-
meta: {
|
|
2251
|
-
key: "workflow.approval.inbox",
|
|
2252
|
-
version: "1.0.0",
|
|
2253
|
-
title: "Approval Inbox",
|
|
2254
|
-
description: "Inbox showing pending approval requests for current user",
|
|
2255
|
-
domain: "workflow-system",
|
|
2256
|
-
owners: ["@workflow-team"],
|
|
2257
|
-
tags: ["workflow", "approval", "inbox"],
|
|
2258
|
-
stability: StabilityEnum.Experimental,
|
|
2259
|
-
goal: "Managing personal workload of approval requests",
|
|
2260
|
-
context: "Personal task management"
|
|
2261
|
-
},
|
|
2262
|
-
source: {
|
|
2263
|
-
type: "component",
|
|
2264
|
-
framework: "react",
|
|
2265
|
-
componentKey: "ApprovalInbox",
|
|
2266
|
-
props: ApprovalRequestModel
|
|
2267
|
-
},
|
|
2268
|
-
targets: ["react", "markdown"],
|
|
2269
|
-
policy: {
|
|
2270
|
-
flags: ["workflow.approvals.enabled"]
|
|
2271
|
-
}
|
|
2272
|
-
});
|
|
2273
|
-
var ApprovalDetailPresentation = definePresentation({
|
|
2274
|
-
meta: {
|
|
2275
|
-
key: "workflow.approval.detail",
|
|
2276
|
-
version: "1.0.0",
|
|
2277
|
-
title: "Approval Details",
|
|
2278
|
-
description: "Detailed approval request view with context and actions",
|
|
2279
|
-
domain: "workflow-system",
|
|
2280
|
-
owners: ["@workflow-team"],
|
|
2281
|
-
tags: ["workflow", "approval", "detail"],
|
|
2282
|
-
stability: StabilityEnum.Experimental,
|
|
2283
|
-
goal: "Decision support for an approval request",
|
|
2284
|
-
context: "Specific approval action"
|
|
2285
|
-
},
|
|
2286
|
-
source: {
|
|
2287
|
-
type: "component",
|
|
2288
|
-
framework: "react",
|
|
2289
|
-
componentKey: "ApprovalRequestDetail",
|
|
2290
|
-
props: ApprovalRequestModel
|
|
2291
|
-
},
|
|
2292
|
-
targets: ["react", "markdown"],
|
|
2293
|
-
policy: {
|
|
2294
|
-
flags: ["workflow.approvals.enabled"]
|
|
2295
|
-
}
|
|
2296
|
-
});
|
|
2297
|
-
var ApprovalFormPresentation = definePresentation({
|
|
2298
|
-
meta: {
|
|
2299
|
-
key: "workflow.approval.form",
|
|
2300
|
-
version: "1.0.0",
|
|
2301
|
-
title: "Approval Form",
|
|
2302
|
-
description: "Form for submitting approval decisions",
|
|
2303
|
-
domain: "workflow-system",
|
|
2304
|
-
owners: ["@workflow-team"],
|
|
2305
|
-
tags: ["workflow", "approval", "form"],
|
|
2306
|
-
stability: StabilityEnum.Experimental,
|
|
2307
|
-
goal: "Submitting a decision on an approval request",
|
|
2308
|
-
context: "Approval decision dialog"
|
|
2309
|
-
},
|
|
2310
|
-
source: {
|
|
2311
|
-
type: "component",
|
|
2312
|
-
framework: "react",
|
|
2313
|
-
componentKey: "ApprovalDecisionForm"
|
|
2314
|
-
},
|
|
2315
|
-
targets: ["react"],
|
|
2316
|
-
policy: {
|
|
2317
|
-
flags: ["workflow.approvals.enabled"]
|
|
2299
|
+
...META,
|
|
2300
|
+
key: "workflow-system.visualization.throughput",
|
|
2301
|
+
title: "Run Throughput",
|
|
2302
|
+
description: "Daily workflow instance starts.",
|
|
2303
|
+
goal: "Show operational throughput over time.",
|
|
2304
|
+
context: "Workflow trend monitoring."
|
|
2305
|
+
},
|
|
2306
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
2307
|
+
visualization: {
|
|
2308
|
+
kind: "cartesian",
|
|
2309
|
+
variant: "line",
|
|
2310
|
+
xDimension: "day",
|
|
2311
|
+
yMeasures: ["instances"],
|
|
2312
|
+
dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
|
|
2313
|
+
measures: [
|
|
2314
|
+
{
|
|
2315
|
+
key: "instances",
|
|
2316
|
+
label: "Instances",
|
|
2317
|
+
dataPath: "instances",
|
|
2318
|
+
format: "number",
|
|
2319
|
+
color: "#0f766e"
|
|
2320
|
+
}
|
|
2321
|
+
],
|
|
2322
|
+
table: { caption: "Daily workflow instance starts." }
|
|
2318
2323
|
}
|
|
2319
2324
|
});
|
|
2320
|
-
var
|
|
2325
|
+
var WorkflowActiveMetricVisualization = defineVisualization({
|
|
2321
2326
|
meta: {
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
title: "
|
|
2325
|
-
description: "
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
},
|
|
2338
|
-
targets: ["react"],
|
|
2339
|
-
policy: {
|
|
2340
|
-
flags: ["workflow.approvals.enabled"]
|
|
2327
|
+
...META,
|
|
2328
|
+
key: "workflow-system.visualization.active-work",
|
|
2329
|
+
title: "Active Work",
|
|
2330
|
+
description: "Current in-flight or pending workflow instances.",
|
|
2331
|
+
goal: "Expose active operational workload.",
|
|
2332
|
+
context: "Workflow workload comparison."
|
|
2333
|
+
},
|
|
2334
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
2335
|
+
visualization: {
|
|
2336
|
+
kind: "metric",
|
|
2337
|
+
measure: "value",
|
|
2338
|
+
measures: [
|
|
2339
|
+
{ key: "value", label: "Instances", dataPath: "value", format: "number" }
|
|
2340
|
+
],
|
|
2341
|
+
table: { caption: "Active workflow count." }
|
|
2341
2342
|
}
|
|
2342
2343
|
});
|
|
2343
|
-
var
|
|
2344
|
+
var WorkflowCompletedMetricVisualization = defineVisualization({
|
|
2344
2345
|
meta: {
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
title: "
|
|
2348
|
-
description: "
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
},
|
|
2361
|
-
targets: ["react", "markdown"],
|
|
2362
|
-
policy: {
|
|
2363
|
-
flags: ["workflow.metrics.enabled"]
|
|
2346
|
+
...META,
|
|
2347
|
+
key: "workflow-system.visualization.completed-work",
|
|
2348
|
+
title: "Completed Work",
|
|
2349
|
+
description: "Completed workflow instances in the current sample.",
|
|
2350
|
+
goal: "Show output against active workload.",
|
|
2351
|
+
context: "Workflow workload comparison."
|
|
2352
|
+
},
|
|
2353
|
+
source: { primary: INSTANCE_LIST_REF, resultPath: "data" },
|
|
2354
|
+
visualization: {
|
|
2355
|
+
kind: "metric",
|
|
2356
|
+
measure: "value",
|
|
2357
|
+
measures: [
|
|
2358
|
+
{ key: "value", label: "Instances", dataPath: "value", format: "number" }
|
|
2359
|
+
],
|
|
2360
|
+
table: { caption: "Completed workflow count." }
|
|
2364
2361
|
}
|
|
2365
2362
|
});
|
|
2366
|
-
var
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
};
|
|
2363
|
+
var WorkflowVisualizationSpecs = [
|
|
2364
|
+
WorkflowInstanceStatusVisualization,
|
|
2365
|
+
WorkflowThroughputVisualization,
|
|
2366
|
+
WorkflowActiveMetricVisualization,
|
|
2367
|
+
WorkflowCompletedMetricVisualization
|
|
2368
|
+
];
|
|
2369
|
+
var WorkflowVisualizationRegistry = new VisualizationRegistry([
|
|
2370
|
+
...WorkflowVisualizationSpecs
|
|
2371
|
+
]);
|
|
2372
|
+
var WorkflowVisualizationRefs = WorkflowVisualizationSpecs.map((spec) => ({
|
|
2373
|
+
key: spec.meta.key,
|
|
2374
|
+
version: spec.meta.version
|
|
2375
|
+
}));
|
|
2379
2376
|
|
|
2380
|
-
// src/
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
{ key: "workflow.instance.pause", version: "1.0.0" },
|
|
2403
|
-
{ key: "workflow.instance.resume", version: "1.0.0" },
|
|
2404
|
-
{ key: "workflow.instance.cancel", version: "1.0.0" },
|
|
2405
|
-
{ key: "workflow.instance.list", version: "1.0.0" },
|
|
2406
|
-
{ key: "workflow.instance.get", version: "1.0.0" },
|
|
2407
|
-
{ key: "workflow.approval.decide", version: "1.0.0" },
|
|
2408
|
-
{ key: "workflow.approval.delegate", version: "1.0.0" },
|
|
2409
|
-
{ key: "workflow.approval.comment.add", version: "1.0.0" },
|
|
2410
|
-
{ key: "workflow.approval.list.mine", version: "1.0.0" },
|
|
2411
|
-
{ key: "workflow.approval.get", version: "1.0.0" }
|
|
2412
|
-
],
|
|
2413
|
-
events: [
|
|
2414
|
-
{ key: "workflow.definition.created", version: "1.0.0" },
|
|
2415
|
-
{ key: "workflow.definition.updated", version: "1.0.0" },
|
|
2416
|
-
{ key: "workflow.definition.published", version: "1.0.0" },
|
|
2417
|
-
{ key: "workflow.step.added", version: "1.0.0" },
|
|
2418
|
-
{ key: "workflow.instance.started", version: "1.0.0" },
|
|
2419
|
-
{ key: "workflow.step.entered", version: "1.0.0" },
|
|
2420
|
-
{ key: "workflow.step.exited", version: "1.0.0" },
|
|
2421
|
-
{ key: "workflow.instance.completed", version: "1.0.0" },
|
|
2422
|
-
{ key: "workflow.instance.cancelled", version: "1.0.0" },
|
|
2423
|
-
{ key: "workflow.instance.paused", version: "1.0.0" },
|
|
2424
|
-
{ key: "workflow.instance.resumed", version: "1.0.0" },
|
|
2425
|
-
{ key: "workflow.instance.failed", version: "1.0.0" },
|
|
2426
|
-
{ key: "workflow.instance.timedOut", version: "1.0.0" },
|
|
2427
|
-
{ key: "workflow.approval.requested", version: "1.0.0" },
|
|
2428
|
-
{ key: "workflow.approval.decided", version: "1.0.0" },
|
|
2429
|
-
{ key: "workflow.approval.delegated", version: "1.0.0" },
|
|
2430
|
-
{ key: "workflow.approval.escalated", version: "1.0.0" }
|
|
2431
|
-
],
|
|
2432
|
-
presentations: [
|
|
2433
|
-
{ key: "workflow.designer", version: "1.0.0" },
|
|
2434
|
-
{ key: "workflow.definition.viewList", version: "1.0.0" },
|
|
2435
|
-
{ key: "workflow.definition.detail", version: "1.0.0" },
|
|
2436
|
-
{ key: "workflow.instance.viewList", version: "1.0.0" },
|
|
2437
|
-
{ key: "workflow.instance.detail", version: "1.0.0" },
|
|
2438
|
-
{ key: "workflow.instance.progress", version: "1.0.0" },
|
|
2439
|
-
{ key: "workflow.approval.inbox", version: "1.0.0" },
|
|
2440
|
-
{ key: "workflow.approval.detail", version: "1.0.0" },
|
|
2441
|
-
{ key: "workflow.approval.form", version: "1.0.0" },
|
|
2442
|
-
{ key: "workflow.approval.badge", version: "1.0.0" },
|
|
2443
|
-
{ key: "workflow.metrics", version: "1.0.0" }
|
|
2444
|
-
],
|
|
2445
|
-
opToPresentation: [
|
|
2377
|
+
// src/visualizations/selectors.ts
|
|
2378
|
+
function toDayKey(value) {
|
|
2379
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
2380
|
+
return date.toISOString().slice(0, 10);
|
|
2381
|
+
}
|
|
2382
|
+
function createWorkflowVisualizationSections(instances) {
|
|
2383
|
+
const statusCounts = new Map;
|
|
2384
|
+
const throughput = new Map;
|
|
2385
|
+
let activeCount = 0;
|
|
2386
|
+
let completedCount = 0;
|
|
2387
|
+
for (const instance of instances) {
|
|
2388
|
+
statusCounts.set(instance.status, (statusCounts.get(instance.status) ?? 0) + 1);
|
|
2389
|
+
const day = toDayKey(instance.startedAt);
|
|
2390
|
+
throughput.set(day, (throughput.get(day) ?? 0) + 1);
|
|
2391
|
+
if (instance.status === "PENDING" || instance.status === "IN_PROGRESS") {
|
|
2392
|
+
activeCount += 1;
|
|
2393
|
+
}
|
|
2394
|
+
if (instance.status === "COMPLETED") {
|
|
2395
|
+
completedCount += 1;
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
const primaryItems = [
|
|
2446
2399
|
{
|
|
2447
|
-
|
|
2448
|
-
|
|
2400
|
+
key: "workflow-status",
|
|
2401
|
+
spec: WorkflowInstanceStatusVisualization,
|
|
2402
|
+
data: {
|
|
2403
|
+
data: Array.from(statusCounts.entries()).map(([status, count]) => ({
|
|
2404
|
+
status,
|
|
2405
|
+
instances: count
|
|
2406
|
+
}))
|
|
2407
|
+
},
|
|
2408
|
+
title: "Instance Status Breakdown",
|
|
2409
|
+
description: "Status mix across workflow instances.",
|
|
2410
|
+
height: 260
|
|
2449
2411
|
},
|
|
2450
2412
|
{
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2413
|
+
key: "workflow-throughput",
|
|
2414
|
+
spec: WorkflowThroughputVisualization,
|
|
2415
|
+
data: {
|
|
2416
|
+
data: Array.from(throughput.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, instances: count }))
|
|
2417
|
+
},
|
|
2418
|
+
title: "Run Throughput",
|
|
2419
|
+
description: "Daily workflow starts from current instances."
|
|
2420
|
+
}
|
|
2421
|
+
];
|
|
2422
|
+
const comparisonItems = [
|
|
2454
2423
|
{
|
|
2455
|
-
|
|
2456
|
-
|
|
2424
|
+
key: "workflow-active",
|
|
2425
|
+
spec: WorkflowActiveMetricVisualization,
|
|
2426
|
+
data: { data: [{ value: activeCount }] },
|
|
2427
|
+
title: "Active Work",
|
|
2428
|
+
description: "Pending and in-progress workflows.",
|
|
2429
|
+
height: 200
|
|
2457
2430
|
},
|
|
2458
2431
|
{
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
{
|
|
2466
|
-
key: "workflow.definition.viewList",
|
|
2467
|
-
version: "1.0.0",
|
|
2468
|
-
targets: ["react", "markdown"]
|
|
2469
|
-
},
|
|
2470
|
-
{
|
|
2471
|
-
key: "workflow.definition.detail",
|
|
2472
|
-
version: "1.0.0",
|
|
2473
|
-
targets: ["react", "markdown"]
|
|
2474
|
-
},
|
|
2475
|
-
{
|
|
2476
|
-
key: "workflow.instance.viewList",
|
|
2477
|
-
version: "1.0.0",
|
|
2478
|
-
targets: ["react", "markdown"]
|
|
2479
|
-
},
|
|
2480
|
-
{
|
|
2481
|
-
key: "workflow.instance.detail",
|
|
2482
|
-
version: "1.0.0",
|
|
2483
|
-
targets: ["react", "markdown"]
|
|
2484
|
-
},
|
|
2485
|
-
{ key: "workflow.instance.progress", version: "1.0.0", targets: ["react"] },
|
|
2486
|
-
{
|
|
2487
|
-
key: "workflow.approval.inbox",
|
|
2488
|
-
version: "1.0.0",
|
|
2489
|
-
targets: ["react", "markdown"]
|
|
2490
|
-
},
|
|
2491
|
-
{
|
|
2492
|
-
key: "workflow.approval.detail",
|
|
2493
|
-
version: "1.0.0",
|
|
2494
|
-
targets: ["react", "markdown"]
|
|
2495
|
-
},
|
|
2496
|
-
{
|
|
2497
|
-
key: "workflow.metrics",
|
|
2498
|
-
version: "1.0.0",
|
|
2499
|
-
targets: ["react", "markdown"]
|
|
2432
|
+
key: "workflow-completed",
|
|
2433
|
+
spec: WorkflowCompletedMetricVisualization,
|
|
2434
|
+
data: { data: [{ value: completedCount }] },
|
|
2435
|
+
title: "Completed Work",
|
|
2436
|
+
description: "Completed workflows in the current sample.",
|
|
2437
|
+
height: 200
|
|
2500
2438
|
}
|
|
2501
|
-
]
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
{ key: "feature-flags", version: "1.0.0" }
|
|
2508
|
-
],
|
|
2509
|
-
provides: [
|
|
2510
|
-
{ key: "workflow", version: "1.0.0" },
|
|
2511
|
-
{ key: "approval", version: "1.0.0" },
|
|
2512
|
-
{ key: "state-machine", version: "1.0.0" }
|
|
2513
|
-
]
|
|
2514
|
-
},
|
|
2515
|
-
workflows: [
|
|
2516
|
-
{ key: "workflow-system.workflow.approval-chain", version: "1.0.0" }
|
|
2517
|
-
],
|
|
2518
|
-
telemetry: [{ key: "workflow-system.telemetry", version: "1.0.0" }],
|
|
2519
|
-
jobs: [
|
|
2520
|
-
{ key: "workflow-system.job.instance-timeout", version: "1.0.0" },
|
|
2521
|
-
{ key: "workflow-system.job.escalation", version: "1.0.0" }
|
|
2522
|
-
],
|
|
2523
|
-
docs: [
|
|
2524
|
-
"docs.examples.workflow-system",
|
|
2525
|
-
"docs.examples.workflow-system.goal",
|
|
2526
|
-
"docs.examples.workflow-system.usage",
|
|
2527
|
-
"docs.examples.workflow-system.constraints"
|
|
2528
|
-
]
|
|
2529
|
-
});
|
|
2530
|
-
|
|
2439
|
+
];
|
|
2440
|
+
return {
|
|
2441
|
+
primaryItems,
|
|
2442
|
+
comparisonItems
|
|
2443
|
+
};
|
|
2444
|
+
}
|
|
2531
2445
|
// src/ui/renderers/workflow.markdown.ts
|
|
2532
|
-
var
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
{
|
|
2539
|
-
id: "s1",
|
|
2540
|
-
name: "Manager Review",
|
|
2541
|
-
order: 1,
|
|
2542
|
-
requiredRoles: ["manager"]
|
|
2543
|
-
},
|
|
2544
|
-
{
|
|
2545
|
-
id: "s2",
|
|
2546
|
-
name: "Finance Review",
|
|
2547
|
-
order: 2,
|
|
2548
|
-
requiredRoles: ["finance"]
|
|
2549
|
-
},
|
|
2550
|
-
{ id: "s3", name: "Final Approval", order: 3, requiredRoles: ["admin"] }
|
|
2551
|
-
],
|
|
2552
|
-
status: "ACTIVE"
|
|
2553
|
-
},
|
|
2554
|
-
{
|
|
2555
|
-
id: "wf-2",
|
|
2556
|
-
name: "Leave Request",
|
|
2557
|
-
type: "APPROVAL",
|
|
2558
|
-
steps: [
|
|
2559
|
-
{
|
|
2560
|
-
id: "s1",
|
|
2561
|
-
name: "Supervisor Approval",
|
|
2562
|
-
order: 1,
|
|
2563
|
-
requiredRoles: ["supervisor"]
|
|
2564
|
-
},
|
|
2565
|
-
{ id: "s2", name: "HR Review", order: 2, requiredRoles: ["hr"] }
|
|
2566
|
-
],
|
|
2567
|
-
status: "ACTIVE"
|
|
2568
|
-
},
|
|
2569
|
-
{
|
|
2570
|
-
id: "wf-3",
|
|
2571
|
-
name: "Document Review",
|
|
2572
|
-
type: "SEQUENTIAL",
|
|
2573
|
-
steps: [
|
|
2574
|
-
{ id: "s1", name: "Author Review", order: 1, requiredRoles: ["author"] },
|
|
2575
|
-
{ id: "s2", name: "Peer Review", order: 2, requiredRoles: ["reviewer"] },
|
|
2576
|
-
{ id: "s3", name: "Publish", order: 3, requiredRoles: ["publisher"] }
|
|
2577
|
-
],
|
|
2578
|
-
status: "DRAFT"
|
|
2579
|
-
}
|
|
2580
|
-
];
|
|
2581
|
-
var mockWorkflowInstances = [
|
|
2582
|
-
{
|
|
2583
|
-
id: "inst-1",
|
|
2584
|
-
definitionId: "wf-1",
|
|
2585
|
-
definitionName: "Purchase Approval",
|
|
2586
|
-
status: "IN_PROGRESS",
|
|
2587
|
-
currentStepId: "s2",
|
|
2588
|
-
startedAt: "2024-01-15T10:00:00Z",
|
|
2589
|
-
requestedBy: "John Doe"
|
|
2590
|
-
},
|
|
2591
|
-
{
|
|
2592
|
-
id: "inst-2",
|
|
2593
|
-
definitionId: "wf-1",
|
|
2594
|
-
definitionName: "Purchase Approval",
|
|
2595
|
-
status: "COMPLETED",
|
|
2596
|
-
currentStepId: null,
|
|
2597
|
-
startedAt: "2024-01-10T09:00:00Z",
|
|
2598
|
-
completedAt: "2024-01-12T14:00:00Z",
|
|
2599
|
-
requestedBy: "Jane Smith"
|
|
2600
|
-
},
|
|
2601
|
-
{
|
|
2602
|
-
id: "inst-3",
|
|
2603
|
-
definitionId: "wf-2",
|
|
2604
|
-
definitionName: "Leave Request",
|
|
2605
|
-
status: "PENDING",
|
|
2606
|
-
currentStepId: "s1",
|
|
2607
|
-
startedAt: "2024-01-16T08:00:00Z",
|
|
2608
|
-
requestedBy: "Bob Wilson"
|
|
2609
|
-
}
|
|
2610
|
-
];
|
|
2446
|
+
var workflowDefinitions = WORKFLOW_SYSTEM_DEMO_DEFINITIONS;
|
|
2447
|
+
var workflowInstances = WORKFLOW_SYSTEM_DEMO_INSTANCES;
|
|
2448
|
+
var workflowDefinitionById = new Map(workflowDefinitions.map((definition) => [definition.id, definition]));
|
|
2449
|
+
function formatDate(value) {
|
|
2450
|
+
return new Date(value).toISOString().slice(0, 10);
|
|
2451
|
+
}
|
|
2611
2452
|
var workflowDashboardMarkdownRenderer = {
|
|
2612
2453
|
target: "markdown",
|
|
2613
2454
|
render: async (desc) => {
|
|
2614
2455
|
if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowDashboard") {
|
|
2615
2456
|
throw new Error("workflowDashboardMarkdownRenderer: not WorkflowDashboard");
|
|
2616
2457
|
}
|
|
2617
|
-
const definitions =
|
|
2618
|
-
const instances =
|
|
2458
|
+
const definitions = workflowDefinitions;
|
|
2459
|
+
const instances = workflowInstances;
|
|
2460
|
+
const visualizations = createWorkflowVisualizationSections(instances);
|
|
2619
2461
|
const activeDefinitions = definitions.filter((d) => d.status === "ACTIVE");
|
|
2620
|
-
const
|
|
2621
|
-
const inProgressInstances = instances.filter((i) => i.status === "IN_PROGRESS");
|
|
2622
|
-
const completedInstances = instances.filter((i) => i.status === "COMPLETED");
|
|
2462
|
+
const awaitingActionInstances = instances.filter((i) => i.status === "PENDING" || i.status === "IN_PROGRESS");
|
|
2623
2463
|
const lines = [
|
|
2624
2464
|
"# Workflow Dashboard",
|
|
2625
2465
|
"",
|
|
2626
|
-
">
|
|
2466
|
+
"> Seeded workflow and approval overview for the sandbox demo.",
|
|
2627
2467
|
"",
|
|
2628
2468
|
"## Summary",
|
|
2629
2469
|
"",
|
|
2630
2470
|
"| Metric | Value |",
|
|
2631
2471
|
"|--------|-------|",
|
|
2632
2472
|
`| Active Workflows | ${activeDefinitions.length} |`,
|
|
2633
|
-
`|
|
|
2634
|
-
`|
|
|
2635
|
-
`|
|
|
2636
|
-
"",
|
|
2637
|
-
"## Active Workflow Definitions",
|
|
2473
|
+
`| Awaiting Action | ${awaitingActionInstances.length} |`,
|
|
2474
|
+
`| Completed | ${instances.filter((i) => i.status === "COMPLETED").length} |`,
|
|
2475
|
+
`| Rejected | ${instances.filter((i) => i.status === "REJECTED").length} |`,
|
|
2638
2476
|
""
|
|
2639
2477
|
];
|
|
2478
|
+
lines.push("## Visualization Overview");
|
|
2479
|
+
lines.push("");
|
|
2480
|
+
for (const item of [
|
|
2481
|
+
...visualizations.primaryItems,
|
|
2482
|
+
...visualizations.comparisonItems
|
|
2483
|
+
]) {
|
|
2484
|
+
lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
|
|
2485
|
+
}
|
|
2486
|
+
lines.push("");
|
|
2487
|
+
lines.push("## Active Workflow Definitions");
|
|
2488
|
+
lines.push("");
|
|
2640
2489
|
if (activeDefinitions.length === 0) {
|
|
2641
2490
|
lines.push("_No active workflow definitions._");
|
|
2642
2491
|
} else {
|
|
@@ -2655,8 +2504,9 @@ var workflowDashboardMarkdownRenderer = {
|
|
|
2655
2504
|
lines.push("| Workflow | Requested By | Status | Started |");
|
|
2656
2505
|
lines.push("|----------|--------------|--------|---------|");
|
|
2657
2506
|
for (const inst of instances.slice(0, 10)) {
|
|
2658
|
-
const startedDate =
|
|
2659
|
-
|
|
2507
|
+
const startedDate = formatDate(inst.startedAt);
|
|
2508
|
+
const definitionName = workflowDefinitionById.get(inst.definitionId)?.name ?? inst.definitionId;
|
|
2509
|
+
lines.push(`| ${definitionName} | ${inst.requestedBy} | ${inst.status} | ${startedDate} |`);
|
|
2660
2510
|
}
|
|
2661
2511
|
}
|
|
2662
2512
|
return {
|
|
@@ -2672,7 +2522,7 @@ var workflowDefinitionListMarkdownRenderer = {
|
|
|
2672
2522
|
if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowDefinitionList") {
|
|
2673
2523
|
throw new Error("workflowDefinitionListMarkdownRenderer: not WorkflowDefinitionList");
|
|
2674
2524
|
}
|
|
2675
|
-
const definitions =
|
|
2525
|
+
const definitions = workflowDefinitions;
|
|
2676
2526
|
const lines = [
|
|
2677
2527
|
"# Workflow Definitions",
|
|
2678
2528
|
"",
|
|
@@ -2687,7 +2537,7 @@ var workflowDefinitionListMarkdownRenderer = {
|
|
|
2687
2537
|
lines.push("### Steps");
|
|
2688
2538
|
lines.push("");
|
|
2689
2539
|
for (const step of def.steps) {
|
|
2690
|
-
lines.push(`${step.
|
|
2540
|
+
lines.push(`${step.stepOrder}. **${step.name}** - Roles: ${step.requiredRoles.join(", ")}`);
|
|
2691
2541
|
}
|
|
2692
2542
|
lines.push("");
|
|
2693
2543
|
}
|
|
@@ -2704,7 +2554,7 @@ var workflowInstanceDetailMarkdownRenderer = {
|
|
|
2704
2554
|
if (desc.source.type !== "component" || desc.source.componentKey !== "WorkflowInstanceDetail") {
|
|
2705
2555
|
throw new Error("workflowInstanceDetailMarkdownRenderer: not WorkflowInstanceDetail");
|
|
2706
2556
|
}
|
|
2707
|
-
const instance =
|
|
2557
|
+
const instance = workflowInstances.find((workflowInstance) => workflowInstance.status === "IN_PROGRESS") ?? workflowInstances[0];
|
|
2708
2558
|
if (!instance) {
|
|
2709
2559
|
return {
|
|
2710
2560
|
mimeType: "text/markdown",
|
|
@@ -2713,14 +2563,14 @@ var workflowInstanceDetailMarkdownRenderer = {
|
|
|
2713
2563
|
No workflow instances available.`
|
|
2714
2564
|
};
|
|
2715
2565
|
}
|
|
2716
|
-
const definition =
|
|
2566
|
+
const definition = workflowDefinitions.find((d) => d.id === instance.definitionId);
|
|
2717
2567
|
const lines = [
|
|
2718
|
-
`# Workflow: ${instance.
|
|
2568
|
+
`# Workflow: ${definition?.name ?? instance.definitionId}`,
|
|
2719
2569
|
"",
|
|
2720
2570
|
`**Instance ID:** ${instance.id}`,
|
|
2721
2571
|
`**Status:** ${instance.status}`,
|
|
2722
2572
|
`**Requested By:** ${instance.requestedBy}`,
|
|
2723
|
-
`**Started:** ${
|
|
2573
|
+
`**Started:** ${formatDate(instance.startedAt)}`,
|
|
2724
2574
|
"",
|
|
2725
2575
|
"## Steps Progress",
|
|
2726
2576
|
""
|
|
@@ -2741,7 +2591,7 @@ No workflow instances available.`
|
|
|
2741
2591
|
lines.push("## Actions");
|
|
2742
2592
|
lines.push("");
|
|
2743
2593
|
lines.push("- **Approve** - Move to next step");
|
|
2744
|
-
lines.push("- **Reject** -
|
|
2594
|
+
lines.push("- **Reject** - End the workflow with a rejection outcome");
|
|
2745
2595
|
lines.push("- **Delegate** - Assign to another approver");
|
|
2746
2596
|
return {
|
|
2747
2597
|
mimeType: "text/markdown",
|
|
@@ -2750,56 +2600,52 @@ No workflow instances available.`
|
|
|
2750
2600
|
};
|
|
2751
2601
|
}
|
|
2752
2602
|
};
|
|
2753
|
-
// src/ui/
|
|
2754
|
-
import {
|
|
2755
|
-
|
|
2603
|
+
// src/ui/WorkflowDashboard.visualizations.tsx
|
|
2604
|
+
import {
|
|
2605
|
+
ComparisonView,
|
|
2606
|
+
VisualizationCard,
|
|
2607
|
+
VisualizationGrid
|
|
2608
|
+
} from "@contractspec/lib.design-system";
|
|
2609
|
+
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
2756
2610
|
"use client";
|
|
2757
|
-
function
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
const
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
definitions,
|
|
2793
|
-
instances,
|
|
2794
|
-
loading,
|
|
2795
|
-
error,
|
|
2796
|
-
stats,
|
|
2797
|
-
refetch: fetchData
|
|
2798
|
-
};
|
|
2611
|
+
function WorkflowVisualizationOverview({
|
|
2612
|
+
instances
|
|
2613
|
+
}) {
|
|
2614
|
+
const { primaryItems, comparisonItems } = createWorkflowVisualizationSections(instances);
|
|
2615
|
+
return /* @__PURE__ */ jsxDEV("section", {
|
|
2616
|
+
className: "space-y-4",
|
|
2617
|
+
children: [
|
|
2618
|
+
/* @__PURE__ */ jsxDEV("div", {
|
|
2619
|
+
children: [
|
|
2620
|
+
/* @__PURE__ */ jsxDEV("h3", {
|
|
2621
|
+
className: "font-semibold text-lg",
|
|
2622
|
+
children: "Workflow Visualizations"
|
|
2623
|
+
}, undefined, false, undefined, this),
|
|
2624
|
+
/* @__PURE__ */ jsxDEV("p", {
|
|
2625
|
+
className: "text-muted-foreground text-sm",
|
|
2626
|
+
children: "Contract-backed charts for workflow health and throughput."
|
|
2627
|
+
}, undefined, false, undefined, this)
|
|
2628
|
+
]
|
|
2629
|
+
}, undefined, true, undefined, this),
|
|
2630
|
+
/* @__PURE__ */ jsxDEV(VisualizationGrid, {
|
|
2631
|
+
children: primaryItems.map((item) => /* @__PURE__ */ jsxDEV(VisualizationCard, {
|
|
2632
|
+
data: item.data,
|
|
2633
|
+
description: item.description,
|
|
2634
|
+
height: item.height,
|
|
2635
|
+
spec: item.spec,
|
|
2636
|
+
title: item.title
|
|
2637
|
+
}, item.key, false, undefined, this))
|
|
2638
|
+
}, undefined, false, undefined, this),
|
|
2639
|
+
/* @__PURE__ */ jsxDEV(ComparisonView, {
|
|
2640
|
+
description: "Shared comparison surface for active versus completed work.",
|
|
2641
|
+
items: comparisonItems,
|
|
2642
|
+
title: "Workload Comparison"
|
|
2643
|
+
}, undefined, false, undefined, this)
|
|
2644
|
+
]
|
|
2645
|
+
}, undefined, true, undefined, this);
|
|
2799
2646
|
}
|
|
2800
2647
|
|
|
2801
2648
|
// src/ui/WorkflowDashboard.tsx
|
|
2802
|
-
import { useState as useState2 } from "react";
|
|
2803
2649
|
import {
|
|
2804
2650
|
Button,
|
|
2805
2651
|
ErrorState,
|
|
@@ -2807,7 +2653,8 @@ import {
|
|
|
2807
2653
|
StatCard,
|
|
2808
2654
|
StatCardGroup
|
|
2809
2655
|
} from "@contractspec/lib.design-system";
|
|
2810
|
-
import {
|
|
2656
|
+
import { useState as useState2 } from "react";
|
|
2657
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
2811
2658
|
"use client";
|
|
2812
2659
|
var STATUS_COLORS = {
|
|
2813
2660
|
ACTIVE: "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400",
|
|
@@ -2827,153 +2674,150 @@ function WorkflowDashboard() {
|
|
|
2827
2674
|
{ id: "instances", label: "Instances", icon: "\uD83D\uDD04" }
|
|
2828
2675
|
];
|
|
2829
2676
|
if (loading) {
|
|
2830
|
-
return /* @__PURE__ */
|
|
2677
|
+
return /* @__PURE__ */ jsxDEV2(LoaderBlock, {
|
|
2831
2678
|
label: "Loading Workflows..."
|
|
2832
2679
|
}, undefined, false, undefined, this);
|
|
2833
2680
|
}
|
|
2834
2681
|
if (error) {
|
|
2835
|
-
return /* @__PURE__ */
|
|
2682
|
+
return /* @__PURE__ */ jsxDEV2(ErrorState, {
|
|
2836
2683
|
title: "Failed to load Workflows",
|
|
2837
2684
|
description: error.message,
|
|
2838
2685
|
onRetry: refetch,
|
|
2839
2686
|
retryLabel: "Retry"
|
|
2840
2687
|
}, undefined, false, undefined, this);
|
|
2841
2688
|
}
|
|
2842
|
-
return /* @__PURE__ */
|
|
2689
|
+
return /* @__PURE__ */ jsxDEV2("div", {
|
|
2843
2690
|
className: "space-y-6",
|
|
2844
2691
|
children: [
|
|
2845
|
-
/* @__PURE__ */
|
|
2692
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
2846
2693
|
className: "flex items-center justify-between",
|
|
2847
2694
|
children: [
|
|
2848
|
-
/* @__PURE__ */
|
|
2849
|
-
className: "text-2xl
|
|
2695
|
+
/* @__PURE__ */ jsxDEV2("h2", {
|
|
2696
|
+
className: "font-bold text-2xl",
|
|
2850
2697
|
children: "Workflow System"
|
|
2851
2698
|
}, undefined, false, undefined, this),
|
|
2852
|
-
/* @__PURE__ */
|
|
2853
|
-
onClick: () =>
|
|
2854
|
-
children:
|
|
2855
|
-
|
|
2856
|
-
className: "mr-2",
|
|
2857
|
-
children: "+"
|
|
2858
|
-
}, undefined, false, undefined, this),
|
|
2859
|
-
" New Workflow"
|
|
2860
|
-
]
|
|
2861
|
-
}, undefined, true, undefined, this)
|
|
2699
|
+
/* @__PURE__ */ jsxDEV2(Button, {
|
|
2700
|
+
onClick: () => void refetch(),
|
|
2701
|
+
children: "Refresh"
|
|
2702
|
+
}, undefined, false, undefined, this)
|
|
2862
2703
|
]
|
|
2863
2704
|
}, undefined, true, undefined, this),
|
|
2864
|
-
/* @__PURE__ */
|
|
2705
|
+
/* @__PURE__ */ jsxDEV2(StatCardGroup, {
|
|
2865
2706
|
children: [
|
|
2866
|
-
/* @__PURE__ */
|
|
2707
|
+
/* @__PURE__ */ jsxDEV2(StatCard, {
|
|
2867
2708
|
label: "Workflows",
|
|
2868
2709
|
value: stats.totalDefinitions,
|
|
2869
2710
|
hint: `${stats.activeDefinitions} active`
|
|
2870
2711
|
}, undefined, false, undefined, this),
|
|
2871
|
-
/* @__PURE__ */
|
|
2712
|
+
/* @__PURE__ */ jsxDEV2(StatCard, {
|
|
2872
2713
|
label: "Instances",
|
|
2873
2714
|
value: stats.totalInstances,
|
|
2874
2715
|
hint: "total runs"
|
|
2875
2716
|
}, undefined, false, undefined, this),
|
|
2876
|
-
/* @__PURE__ */
|
|
2877
|
-
label: "
|
|
2878
|
-
value: stats.pendingInstances,
|
|
2879
|
-
hint: "
|
|
2717
|
+
/* @__PURE__ */ jsxDEV2(StatCard, {
|
|
2718
|
+
label: "Awaiting Action",
|
|
2719
|
+
value: stats.pendingInstances + stats.inProgressInstances,
|
|
2720
|
+
hint: "open approvals"
|
|
2880
2721
|
}, undefined, false, undefined, this),
|
|
2881
|
-
/* @__PURE__ */
|
|
2722
|
+
/* @__PURE__ */ jsxDEV2(StatCard, {
|
|
2882
2723
|
label: "Completed",
|
|
2883
2724
|
value: stats.completedInstances,
|
|
2884
2725
|
hint: "finished"
|
|
2885
2726
|
}, undefined, false, undefined, this)
|
|
2886
2727
|
]
|
|
2887
2728
|
}, undefined, true, undefined, this),
|
|
2888
|
-
/* @__PURE__ */
|
|
2889
|
-
|
|
2729
|
+
/* @__PURE__ */ jsxDEV2(WorkflowVisualizationOverview, {
|
|
2730
|
+
instances
|
|
2731
|
+
}, undefined, false, undefined, this),
|
|
2732
|
+
/* @__PURE__ */ jsxDEV2("nav", {
|
|
2733
|
+
className: "flex gap-1 rounded-lg bg-muted p-1",
|
|
2890
2734
|
role: "tablist",
|
|
2891
|
-
children: tabs.map((tab) => /* @__PURE__ */
|
|
2735
|
+
children: tabs.map((tab) => /* @__PURE__ */ jsxDEV2(Button, {
|
|
2892
2736
|
type: "button",
|
|
2893
2737
|
role: "tab",
|
|
2894
2738
|
"aria-selected": activeTab === tab.id,
|
|
2895
2739
|
onClick: () => setActiveTab(tab.id),
|
|
2896
|
-
className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm
|
|
2740
|
+
className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 font-medium text-sm transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
|
|
2897
2741
|
children: [
|
|
2898
|
-
/* @__PURE__ */
|
|
2742
|
+
/* @__PURE__ */ jsxDEV2("span", {
|
|
2899
2743
|
children: tab.icon
|
|
2900
2744
|
}, undefined, false, undefined, this),
|
|
2901
2745
|
tab.label
|
|
2902
2746
|
]
|
|
2903
2747
|
}, tab.id, true, undefined, this))
|
|
2904
2748
|
}, undefined, false, undefined, this),
|
|
2905
|
-
/* @__PURE__ */
|
|
2749
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
2906
2750
|
className: "min-h-[400px]",
|
|
2907
2751
|
role: "tabpanel",
|
|
2908
2752
|
children: [
|
|
2909
|
-
activeTab === "definitions" && /* @__PURE__ */
|
|
2910
|
-
className: "
|
|
2911
|
-
children: /* @__PURE__ */
|
|
2753
|
+
activeTab === "definitions" && /* @__PURE__ */ jsxDEV2("div", {
|
|
2754
|
+
className: "rounded-lg border border-border",
|
|
2755
|
+
children: /* @__PURE__ */ jsxDEV2("table", {
|
|
2912
2756
|
className: "w-full",
|
|
2913
2757
|
children: [
|
|
2914
|
-
/* @__PURE__ */
|
|
2915
|
-
className: "border-border bg-muted/30
|
|
2916
|
-
children: /* @__PURE__ */
|
|
2758
|
+
/* @__PURE__ */ jsxDEV2("thead", {
|
|
2759
|
+
className: "border-border border-b bg-muted/30",
|
|
2760
|
+
children: /* @__PURE__ */ jsxDEV2("tr", {
|
|
2917
2761
|
children: [
|
|
2918
|
-
/* @__PURE__ */
|
|
2919
|
-
className: "px-4 py-3 text-left text-sm
|
|
2762
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2763
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
2920
2764
|
children: "Name"
|
|
2921
2765
|
}, undefined, false, undefined, this),
|
|
2922
|
-
/* @__PURE__ */
|
|
2923
|
-
className: "px-4 py-3 text-left text-sm
|
|
2766
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2767
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
2924
2768
|
children: "Type"
|
|
2925
2769
|
}, undefined, false, undefined, this),
|
|
2926
|
-
/* @__PURE__ */
|
|
2927
|
-
className: "px-4 py-3 text-left text-sm
|
|
2770
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2771
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
2928
2772
|
children: "Status"
|
|
2929
2773
|
}, undefined, false, undefined, this),
|
|
2930
|
-
/* @__PURE__ */
|
|
2931
|
-
className: "px-4 py-3 text-left text-sm
|
|
2774
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2775
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
2932
2776
|
children: "Created"
|
|
2933
2777
|
}, undefined, false, undefined, this)
|
|
2934
2778
|
]
|
|
2935
2779
|
}, undefined, true, undefined, this)
|
|
2936
2780
|
}, undefined, false, undefined, this),
|
|
2937
|
-
/* @__PURE__ */
|
|
2938
|
-
className: "divide-
|
|
2781
|
+
/* @__PURE__ */ jsxDEV2("tbody", {
|
|
2782
|
+
className: "divide-y divide-border",
|
|
2939
2783
|
children: [
|
|
2940
|
-
definitions.map((def) => /* @__PURE__ */
|
|
2784
|
+
definitions.map((def) => /* @__PURE__ */ jsxDEV2("tr", {
|
|
2941
2785
|
className: "hover:bg-muted/50",
|
|
2942
2786
|
children: [
|
|
2943
|
-
/* @__PURE__ */
|
|
2787
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
2944
2788
|
className: "px-4 py-3",
|
|
2945
2789
|
children: [
|
|
2946
|
-
/* @__PURE__ */
|
|
2790
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
2947
2791
|
className: "font-medium",
|
|
2948
2792
|
children: def.name
|
|
2949
2793
|
}, undefined, false, undefined, this),
|
|
2950
|
-
/* @__PURE__ */
|
|
2794
|
+
/* @__PURE__ */ jsxDEV2("div", {
|
|
2951
2795
|
className: "text-muted-foreground text-sm",
|
|
2952
2796
|
children: def.description
|
|
2953
2797
|
}, undefined, false, undefined, this)
|
|
2954
2798
|
]
|
|
2955
2799
|
}, undefined, true, undefined, this),
|
|
2956
|
-
/* @__PURE__ */
|
|
2800
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
2957
2801
|
className: "px-4 py-3 font-mono text-sm",
|
|
2958
2802
|
children: def.type
|
|
2959
2803
|
}, undefined, false, undefined, this),
|
|
2960
|
-
/* @__PURE__ */
|
|
2804
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
2961
2805
|
className: "px-4 py-3",
|
|
2962
|
-
children: /* @__PURE__ */
|
|
2963
|
-
className: `inline-flex rounded-full px-2 py-0.5 text-xs
|
|
2806
|
+
children: /* @__PURE__ */ jsxDEV2("span", {
|
|
2807
|
+
className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${STATUS_COLORS[def.status] ?? ""}`,
|
|
2964
2808
|
children: def.status
|
|
2965
2809
|
}, undefined, false, undefined, this)
|
|
2966
2810
|
}, undefined, false, undefined, this),
|
|
2967
|
-
/* @__PURE__ */
|
|
2968
|
-
className: "
|
|
2811
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
2812
|
+
className: "px-4 py-3 text-muted-foreground text-sm",
|
|
2969
2813
|
children: def.createdAt.toLocaleDateString()
|
|
2970
2814
|
}, undefined, false, undefined, this)
|
|
2971
2815
|
]
|
|
2972
2816
|
}, def.id, true, undefined, this)),
|
|
2973
|
-
definitions.length === 0 && /* @__PURE__ */
|
|
2974
|
-
children: /* @__PURE__ */
|
|
2817
|
+
definitions.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
|
|
2818
|
+
children: /* @__PURE__ */ jsxDEV2("td", {
|
|
2975
2819
|
colSpan: 4,
|
|
2976
|
-
className: "
|
|
2820
|
+
className: "px-4 py-8 text-center text-muted-foreground",
|
|
2977
2821
|
children: "No workflow definitions found"
|
|
2978
2822
|
}, undefined, false, undefined, this)
|
|
2979
2823
|
}, undefined, false, undefined, this)
|
|
@@ -2982,65 +2826,65 @@ function WorkflowDashboard() {
|
|
|
2982
2826
|
]
|
|
2983
2827
|
}, undefined, true, undefined, this)
|
|
2984
2828
|
}, undefined, false, undefined, this),
|
|
2985
|
-
activeTab === "instances" && /* @__PURE__ */
|
|
2986
|
-
className: "
|
|
2987
|
-
children: /* @__PURE__ */
|
|
2829
|
+
activeTab === "instances" && /* @__PURE__ */ jsxDEV2("div", {
|
|
2830
|
+
className: "rounded-lg border border-border",
|
|
2831
|
+
children: /* @__PURE__ */ jsxDEV2("table", {
|
|
2988
2832
|
className: "w-full",
|
|
2989
2833
|
children: [
|
|
2990
|
-
/* @__PURE__ */
|
|
2991
|
-
className: "border-border bg-muted/30
|
|
2992
|
-
children: /* @__PURE__ */
|
|
2834
|
+
/* @__PURE__ */ jsxDEV2("thead", {
|
|
2835
|
+
className: "border-border border-b bg-muted/30",
|
|
2836
|
+
children: /* @__PURE__ */ jsxDEV2("tr", {
|
|
2993
2837
|
children: [
|
|
2994
|
-
/* @__PURE__ */
|
|
2995
|
-
className: "px-4 py-3 text-left text-sm
|
|
2838
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2839
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
2996
2840
|
children: "Instance ID"
|
|
2997
2841
|
}, undefined, false, undefined, this),
|
|
2998
|
-
/* @__PURE__ */
|
|
2999
|
-
className: "px-4 py-3 text-left text-sm
|
|
2842
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2843
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
3000
2844
|
children: "Status"
|
|
3001
2845
|
}, undefined, false, undefined, this),
|
|
3002
|
-
/* @__PURE__ */
|
|
3003
|
-
className: "px-4 py-3 text-left text-sm
|
|
2846
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2847
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
3004
2848
|
children: "Requested By"
|
|
3005
2849
|
}, undefined, false, undefined, this),
|
|
3006
|
-
/* @__PURE__ */
|
|
3007
|
-
className: "px-4 py-3 text-left text-sm
|
|
2850
|
+
/* @__PURE__ */ jsxDEV2("th", {
|
|
2851
|
+
className: "px-4 py-3 text-left font-medium text-sm",
|
|
3008
2852
|
children: "Started"
|
|
3009
2853
|
}, undefined, false, undefined, this)
|
|
3010
2854
|
]
|
|
3011
2855
|
}, undefined, true, undefined, this)
|
|
3012
2856
|
}, undefined, false, undefined, this),
|
|
3013
|
-
/* @__PURE__ */
|
|
3014
|
-
className: "divide-
|
|
2857
|
+
/* @__PURE__ */ jsxDEV2("tbody", {
|
|
2858
|
+
className: "divide-y divide-border",
|
|
3015
2859
|
children: [
|
|
3016
|
-
instances.map((inst) => /* @__PURE__ */
|
|
2860
|
+
instances.map((inst) => /* @__PURE__ */ jsxDEV2("tr", {
|
|
3017
2861
|
className: "hover:bg-muted/50",
|
|
3018
2862
|
children: [
|
|
3019
|
-
/* @__PURE__ */
|
|
2863
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
3020
2864
|
className: "px-4 py-3 font-mono text-sm",
|
|
3021
2865
|
children: inst.id
|
|
3022
2866
|
}, undefined, false, undefined, this),
|
|
3023
|
-
/* @__PURE__ */
|
|
2867
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
3024
2868
|
className: "px-4 py-3",
|
|
3025
|
-
children: /* @__PURE__ */
|
|
3026
|
-
className: `inline-flex rounded-full px-2 py-0.5 text-xs
|
|
2869
|
+
children: /* @__PURE__ */ jsxDEV2("span", {
|
|
2870
|
+
className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${STATUS_COLORS[inst.status] ?? ""}`,
|
|
3027
2871
|
children: inst.status
|
|
3028
2872
|
}, undefined, false, undefined, this)
|
|
3029
2873
|
}, undefined, false, undefined, this),
|
|
3030
|
-
/* @__PURE__ */
|
|
2874
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
3031
2875
|
className: "px-4 py-3 text-sm",
|
|
3032
2876
|
children: inst.requestedBy
|
|
3033
2877
|
}, undefined, false, undefined, this),
|
|
3034
|
-
/* @__PURE__ */
|
|
3035
|
-
className: "
|
|
2878
|
+
/* @__PURE__ */ jsxDEV2("td", {
|
|
2879
|
+
className: "px-4 py-3 text-muted-foreground text-sm",
|
|
3036
2880
|
children: inst.startedAt.toLocaleDateString()
|
|
3037
2881
|
}, undefined, false, undefined, this)
|
|
3038
2882
|
]
|
|
3039
2883
|
}, inst.id, true, undefined, this)),
|
|
3040
|
-
instances.length === 0 && /* @__PURE__ */
|
|
3041
|
-
children: /* @__PURE__ */
|
|
2884
|
+
instances.length === 0 && /* @__PURE__ */ jsxDEV2("tr", {
|
|
2885
|
+
children: /* @__PURE__ */ jsxDEV2("td", {
|
|
3042
2886
|
colSpan: 4,
|
|
3043
|
-
className: "
|
|
2887
|
+
className: "px-4 py-8 text-center text-muted-foreground",
|
|
3044
2888
|
children: "No workflow instances found"
|
|
3045
2889
|
}, undefined, false, undefined, this)
|
|
3046
2890
|
}, undefined, false, undefined, this)
|
|
@@ -3054,20 +2898,560 @@ function WorkflowDashboard() {
|
|
|
3054
2898
|
]
|
|
3055
2899
|
}, undefined, true, undefined, this);
|
|
3056
2900
|
}
|
|
2901
|
+
// src/workflow/workflow.event.ts
|
|
2902
|
+
import { defineEvent as defineEvent3 } from "@contractspec/lib.contracts-spec";
|
|
2903
|
+
import { defineSchemaModel as defineSchemaModel8, ScalarTypeEnum as ScalarTypeEnum8 } from "@contractspec/lib.schema";
|
|
2904
|
+
var WorkflowDefinitionPayload = defineSchemaModel8({
|
|
2905
|
+
name: "WorkflowDefinitionEventPayload",
|
|
2906
|
+
description: "Payload for workflow definition events",
|
|
2907
|
+
fields: {
|
|
2908
|
+
workflowId: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2909
|
+
key: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2910
|
+
name: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2911
|
+
version: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2912
|
+
organizationId: {
|
|
2913
|
+
type: ScalarTypeEnum8.String_unsecure(),
|
|
2914
|
+
isOptional: false
|
|
2915
|
+
},
|
|
2916
|
+
createdBy: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2917
|
+
timestamp: { type: ScalarTypeEnum8.DateTime(), isOptional: false }
|
|
2918
|
+
}
|
|
2919
|
+
});
|
|
2920
|
+
var StepAddedPayload = defineSchemaModel8({
|
|
2921
|
+
name: "StepAddedEventPayload",
|
|
2922
|
+
description: "Payload when a step is added",
|
|
2923
|
+
fields: {
|
|
2924
|
+
stepId: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2925
|
+
workflowId: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2926
|
+
stepKey: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2927
|
+
stepType: { type: ScalarTypeEnum8.String_unsecure(), isOptional: false },
|
|
2928
|
+
position: { type: ScalarTypeEnum8.Int_unsecure(), isOptional: false },
|
|
2929
|
+
timestamp: { type: ScalarTypeEnum8.DateTime(), isOptional: false }
|
|
2930
|
+
}
|
|
2931
|
+
});
|
|
2932
|
+
var WorkflowCreatedEvent = defineEvent3({
|
|
2933
|
+
meta: {
|
|
2934
|
+
key: "workflow.definition.created",
|
|
2935
|
+
version: "1.0.0",
|
|
2936
|
+
description: "A new workflow definition has been created.",
|
|
2937
|
+
stability: "stable",
|
|
2938
|
+
owners: ["@workflow-team"],
|
|
2939
|
+
tags: ["workflow", "definition", "created"]
|
|
2940
|
+
},
|
|
2941
|
+
payload: WorkflowDefinitionPayload
|
|
2942
|
+
});
|
|
2943
|
+
var WorkflowUpdatedEvent = defineEvent3({
|
|
2944
|
+
meta: {
|
|
2945
|
+
key: "workflow.definition.updated",
|
|
2946
|
+
version: "1.0.0",
|
|
2947
|
+
description: "A workflow definition has been updated.",
|
|
2948
|
+
stability: "stable",
|
|
2949
|
+
owners: ["@workflow-team"],
|
|
2950
|
+
tags: ["workflow", "definition", "updated"]
|
|
2951
|
+
},
|
|
2952
|
+
payload: WorkflowDefinitionPayload
|
|
2953
|
+
});
|
|
2954
|
+
var WorkflowPublishedEvent = defineEvent3({
|
|
2955
|
+
meta: {
|
|
2956
|
+
key: "workflow.definition.published",
|
|
2957
|
+
version: "1.0.0",
|
|
2958
|
+
description: "A workflow definition has been published and is now active.",
|
|
2959
|
+
stability: "stable",
|
|
2960
|
+
owners: ["@workflow-team"],
|
|
2961
|
+
tags: ["workflow", "definition", "published"]
|
|
2962
|
+
},
|
|
2963
|
+
payload: WorkflowDefinitionPayload
|
|
2964
|
+
});
|
|
2965
|
+
var StepAddedEvent = defineEvent3({
|
|
2966
|
+
meta: {
|
|
2967
|
+
key: "workflow.step.added",
|
|
2968
|
+
version: "1.0.0",
|
|
2969
|
+
description: "A step has been added to a workflow definition.",
|
|
2970
|
+
stability: "stable",
|
|
2971
|
+
owners: ["@workflow-team"],
|
|
2972
|
+
tags: ["workflow", "step", "added"]
|
|
2973
|
+
},
|
|
2974
|
+
payload: StepAddedPayload
|
|
2975
|
+
});
|
|
3057
2976
|
|
|
3058
|
-
// src/
|
|
3059
|
-
|
|
2977
|
+
// src/workflow/workflow.operations.ts
|
|
2978
|
+
import {
|
|
2979
|
+
defineCommand as defineCommand3,
|
|
2980
|
+
defineQuery as defineQuery3
|
|
2981
|
+
} from "@contractspec/lib.contracts-spec/operations";
|
|
2982
|
+
import { defineSchemaModel as defineSchemaModel9, ScalarTypeEnum as ScalarTypeEnum9 } from "@contractspec/lib.schema";
|
|
2983
|
+
var OWNERS3 = ["@example.workflow-system"];
|
|
2984
|
+
var CreateWorkflowContract = defineCommand3({
|
|
2985
|
+
meta: {
|
|
2986
|
+
key: "workflow.definition.create",
|
|
2987
|
+
version: "1.0.0",
|
|
2988
|
+
stability: "stable",
|
|
2989
|
+
owners: [...OWNERS3],
|
|
2990
|
+
tags: ["workflow", "definition", "create"],
|
|
2991
|
+
description: "Create a new workflow definition.",
|
|
2992
|
+
goal: "Allow users to define new workflow blueprints.",
|
|
2993
|
+
context: "Workflow designer, admin panel."
|
|
2994
|
+
},
|
|
2995
|
+
io: {
|
|
2996
|
+
input: CreateWorkflowInputModel,
|
|
2997
|
+
output: WorkflowDefinitionModel
|
|
2998
|
+
},
|
|
2999
|
+
policy: { auth: "user" },
|
|
3000
|
+
sideEffects: {
|
|
3001
|
+
emits: [
|
|
3002
|
+
{
|
|
3003
|
+
key: "workflow.definition.created",
|
|
3004
|
+
version: "1.0.0",
|
|
3005
|
+
when: "Workflow is created",
|
|
3006
|
+
payload: WorkflowDefinitionModel
|
|
3007
|
+
}
|
|
3008
|
+
],
|
|
3009
|
+
audit: ["workflow.definition.created"]
|
|
3010
|
+
},
|
|
3011
|
+
acceptance: {
|
|
3012
|
+
scenarios: [
|
|
3013
|
+
{
|
|
3014
|
+
key: "create-workflow-happy-path",
|
|
3015
|
+
given: ["User is admin"],
|
|
3016
|
+
when: ["User creates new workflow definition"],
|
|
3017
|
+
then: [
|
|
3018
|
+
"Definition is created",
|
|
3019
|
+
"WorkflowDefinitionCreated event is emitted"
|
|
3020
|
+
]
|
|
3021
|
+
}
|
|
3022
|
+
],
|
|
3023
|
+
examples: [
|
|
3024
|
+
{
|
|
3025
|
+
key: "create-onboarding",
|
|
3026
|
+
input: {
|
|
3027
|
+
key: "onboarding-v1",
|
|
3028
|
+
name: "Employee Onboarding",
|
|
3029
|
+
version: "1.0.0"
|
|
3030
|
+
},
|
|
3031
|
+
output: { id: "def-123", status: "draft" }
|
|
3032
|
+
}
|
|
3033
|
+
]
|
|
3034
|
+
}
|
|
3035
|
+
});
|
|
3036
|
+
var UpdateWorkflowContract = defineCommand3({
|
|
3037
|
+
meta: {
|
|
3038
|
+
key: "workflow.definition.update",
|
|
3039
|
+
version: "1.0.0",
|
|
3040
|
+
stability: "stable",
|
|
3041
|
+
owners: [...OWNERS3],
|
|
3042
|
+
tags: ["workflow", "definition", "update"],
|
|
3043
|
+
description: "Update an existing workflow definition.",
|
|
3044
|
+
goal: "Allow users to modify workflow blueprints.",
|
|
3045
|
+
context: "Workflow designer."
|
|
3046
|
+
},
|
|
3047
|
+
io: {
|
|
3048
|
+
input: UpdateWorkflowInputModel,
|
|
3049
|
+
output: WorkflowDefinitionModel
|
|
3050
|
+
},
|
|
3051
|
+
policy: { auth: "user" },
|
|
3052
|
+
sideEffects: {
|
|
3053
|
+
emits: [
|
|
3054
|
+
{
|
|
3055
|
+
key: "workflow.definition.updated",
|
|
3056
|
+
version: "1.0.0",
|
|
3057
|
+
when: "Workflow is updated",
|
|
3058
|
+
payload: WorkflowDefinitionModel
|
|
3059
|
+
}
|
|
3060
|
+
],
|
|
3061
|
+
audit: ["workflow.definition.updated"]
|
|
3062
|
+
},
|
|
3063
|
+
acceptance: {
|
|
3064
|
+
scenarios: [
|
|
3065
|
+
{
|
|
3066
|
+
key: "update-workflow-happy-path",
|
|
3067
|
+
given: ["Workflow definition exists"],
|
|
3068
|
+
when: ["User updates definition"],
|
|
3069
|
+
then: [
|
|
3070
|
+
"Definition is updated",
|
|
3071
|
+
"WorkflowDefinitionUpdated event is emitted"
|
|
3072
|
+
]
|
|
3073
|
+
}
|
|
3074
|
+
],
|
|
3075
|
+
examples: [
|
|
3076
|
+
{
|
|
3077
|
+
key: "update-name",
|
|
3078
|
+
input: { workflowId: "def-123", name: "New Employee Onboarding" },
|
|
3079
|
+
output: { id: "def-123", name: "New Employee Onboarding" }
|
|
3080
|
+
}
|
|
3081
|
+
]
|
|
3082
|
+
}
|
|
3083
|
+
});
|
|
3084
|
+
var AddStepContract = defineCommand3({
|
|
3085
|
+
meta: {
|
|
3086
|
+
key: "workflow.step.add",
|
|
3087
|
+
version: "1.0.0",
|
|
3088
|
+
stability: "stable",
|
|
3089
|
+
owners: [...OWNERS3],
|
|
3090
|
+
tags: ["workflow", "step", "add"],
|
|
3091
|
+
description: "Add a step to a workflow definition.",
|
|
3092
|
+
goal: "Build workflow structure step by step.",
|
|
3093
|
+
context: "Workflow designer."
|
|
3094
|
+
},
|
|
3095
|
+
io: {
|
|
3096
|
+
input: AddStepInputModel,
|
|
3097
|
+
output: WorkflowStepModel
|
|
3098
|
+
},
|
|
3099
|
+
policy: { auth: "user" },
|
|
3100
|
+
sideEffects: {
|
|
3101
|
+
emits: [
|
|
3102
|
+
{
|
|
3103
|
+
key: "workflow.step.added",
|
|
3104
|
+
version: "1.0.0",
|
|
3105
|
+
when: "Step is added",
|
|
3106
|
+
payload: WorkflowStepModel
|
|
3107
|
+
}
|
|
3108
|
+
],
|
|
3109
|
+
audit: ["workflow.step.added"]
|
|
3110
|
+
},
|
|
3111
|
+
acceptance: {
|
|
3112
|
+
scenarios: [
|
|
3113
|
+
{
|
|
3114
|
+
key: "add-step-happy-path",
|
|
3115
|
+
given: ["Workflow definition exists"],
|
|
3116
|
+
when: ["User adds a step"],
|
|
3117
|
+
then: ["Step is added", "StepAdded event is emitted"]
|
|
3118
|
+
}
|
|
3119
|
+
],
|
|
3120
|
+
examples: [
|
|
3121
|
+
{
|
|
3122
|
+
key: "add-approval-step",
|
|
3123
|
+
input: {
|
|
3124
|
+
workflowId: "def-123",
|
|
3125
|
+
stepKey: "approve-contract",
|
|
3126
|
+
type: "approval"
|
|
3127
|
+
},
|
|
3128
|
+
output: { id: "step-456", key: "approve-contract" }
|
|
3129
|
+
}
|
|
3130
|
+
]
|
|
3131
|
+
}
|
|
3132
|
+
});
|
|
3133
|
+
var PublishWorkflowContract = defineCommand3({
|
|
3134
|
+
meta: {
|
|
3135
|
+
key: "workflow.definition.publish",
|
|
3136
|
+
version: "1.0.0",
|
|
3137
|
+
stability: "stable",
|
|
3138
|
+
owners: [...OWNERS3],
|
|
3139
|
+
tags: ["workflow", "definition", "publish"],
|
|
3140
|
+
description: "Publish a workflow definition to make it available for use.",
|
|
3141
|
+
goal: "Activate workflow for production use.",
|
|
3142
|
+
context: "Workflow designer, deployment."
|
|
3143
|
+
},
|
|
3144
|
+
io: {
|
|
3145
|
+
input: defineSchemaModel9({
|
|
3146
|
+
name: "PublishWorkflowInput",
|
|
3147
|
+
fields: {
|
|
3148
|
+
workflowId: {
|
|
3149
|
+
type: ScalarTypeEnum9.String_unsecure(),
|
|
3150
|
+
isOptional: false
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
}),
|
|
3154
|
+
output: WorkflowDefinitionModel
|
|
3155
|
+
},
|
|
3156
|
+
policy: { auth: "user" },
|
|
3157
|
+
sideEffects: {
|
|
3158
|
+
emits: [
|
|
3159
|
+
{
|
|
3160
|
+
key: "workflow.definition.published",
|
|
3161
|
+
version: "1.0.0",
|
|
3162
|
+
when: "Workflow is published",
|
|
3163
|
+
payload: WorkflowDefinitionModel
|
|
3164
|
+
}
|
|
3165
|
+
],
|
|
3166
|
+
audit: ["workflow.definition.published"]
|
|
3167
|
+
},
|
|
3168
|
+
acceptance: {
|
|
3169
|
+
scenarios: [
|
|
3170
|
+
{
|
|
3171
|
+
key: "publish-workflow-happy-path",
|
|
3172
|
+
given: ["Workflow definition is valid"],
|
|
3173
|
+
when: ["User publishes workflow"],
|
|
3174
|
+
then: ["Workflow becomes active", "WorkflowPublished event is emitted"]
|
|
3175
|
+
}
|
|
3176
|
+
],
|
|
3177
|
+
examples: [
|
|
3178
|
+
{
|
|
3179
|
+
key: "publish-onboarding",
|
|
3180
|
+
input: { workflowId: "def-123" },
|
|
3181
|
+
output: { id: "def-123", status: "published" }
|
|
3182
|
+
}
|
|
3183
|
+
]
|
|
3184
|
+
}
|
|
3185
|
+
});
|
|
3186
|
+
var ListWorkflowsContract = defineQuery3({
|
|
3187
|
+
meta: {
|
|
3188
|
+
key: "workflow.definition.list",
|
|
3189
|
+
version: "1.0.0",
|
|
3190
|
+
stability: "stable",
|
|
3191
|
+
owners: [...OWNERS3],
|
|
3192
|
+
tags: ["workflow", "definition", "list"],
|
|
3193
|
+
description: "List workflow definitions with filtering.",
|
|
3194
|
+
goal: "Browse and search available workflows.",
|
|
3195
|
+
context: "Workflow list, search."
|
|
3196
|
+
},
|
|
3197
|
+
io: {
|
|
3198
|
+
input: defineSchemaModel9({
|
|
3199
|
+
name: "ListWorkflowsInput",
|
|
3200
|
+
fields: {
|
|
3201
|
+
status: { type: WorkflowStatusEnum, isOptional: true },
|
|
3202
|
+
search: { type: ScalarTypeEnum9.String_unsecure(), isOptional: true },
|
|
3203
|
+
limit: {
|
|
3204
|
+
type: ScalarTypeEnum9.Int_unsecure(),
|
|
3205
|
+
isOptional: true,
|
|
3206
|
+
defaultValue: 20
|
|
3207
|
+
},
|
|
3208
|
+
offset: {
|
|
3209
|
+
type: ScalarTypeEnum9.Int_unsecure(),
|
|
3210
|
+
isOptional: true,
|
|
3211
|
+
defaultValue: 0
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
}),
|
|
3215
|
+
output: defineSchemaModel9({
|
|
3216
|
+
name: "ListWorkflowsOutput",
|
|
3217
|
+
fields: {
|
|
3218
|
+
workflows: {
|
|
3219
|
+
type: WorkflowDefinitionModel,
|
|
3220
|
+
isArray: true,
|
|
3221
|
+
isOptional: false
|
|
3222
|
+
},
|
|
3223
|
+
total: { type: ScalarTypeEnum9.Int_unsecure(), isOptional: false }
|
|
3224
|
+
}
|
|
3225
|
+
})
|
|
3226
|
+
},
|
|
3227
|
+
policy: { auth: "user" },
|
|
3228
|
+
acceptance: {
|
|
3229
|
+
scenarios: [
|
|
3230
|
+
{
|
|
3231
|
+
key: "list-workflows-happy-path",
|
|
3232
|
+
given: ["Workflow definitions exist"],
|
|
3233
|
+
when: ["User lists workflows"],
|
|
3234
|
+
then: ["List of workflows is returned"]
|
|
3235
|
+
}
|
|
3236
|
+
],
|
|
3237
|
+
examples: [
|
|
3238
|
+
{
|
|
3239
|
+
key: "list-all",
|
|
3240
|
+
input: { limit: 10 },
|
|
3241
|
+
output: { workflows: [], total: 5 }
|
|
3242
|
+
}
|
|
3243
|
+
]
|
|
3244
|
+
}
|
|
3245
|
+
});
|
|
3246
|
+
var GetWorkflowContract = defineQuery3({
|
|
3247
|
+
meta: {
|
|
3248
|
+
key: "workflow.definition.get",
|
|
3249
|
+
version: "1.0.0",
|
|
3250
|
+
stability: "stable",
|
|
3251
|
+
owners: [...OWNERS3],
|
|
3252
|
+
tags: ["workflow", "definition", "get"],
|
|
3253
|
+
description: "Get a workflow definition with all steps.",
|
|
3254
|
+
goal: "View workflow details.",
|
|
3255
|
+
context: "Workflow designer, detail view."
|
|
3256
|
+
},
|
|
3257
|
+
io: {
|
|
3258
|
+
input: defineSchemaModel9({
|
|
3259
|
+
name: "GetWorkflowInput",
|
|
3260
|
+
fields: {
|
|
3261
|
+
workflowId: {
|
|
3262
|
+
type: ScalarTypeEnum9.String_unsecure(),
|
|
3263
|
+
isOptional: false
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
}),
|
|
3267
|
+
output: WorkflowDefinitionModel
|
|
3268
|
+
},
|
|
3269
|
+
policy: { auth: "user" },
|
|
3270
|
+
acceptance: {
|
|
3271
|
+
scenarios: [
|
|
3272
|
+
{
|
|
3273
|
+
key: "get-workflow-happy-path",
|
|
3274
|
+
given: ["Workflow definition exists"],
|
|
3275
|
+
when: ["User requests workflow details"],
|
|
3276
|
+
then: ["Workflow details are returned"]
|
|
3277
|
+
}
|
|
3278
|
+
],
|
|
3279
|
+
examples: [
|
|
3280
|
+
{
|
|
3281
|
+
key: "get-details",
|
|
3282
|
+
input: { workflowId: "def-123" },
|
|
3283
|
+
output: { id: "def-123", name: "Employee Onboarding" }
|
|
3284
|
+
}
|
|
3285
|
+
]
|
|
3286
|
+
}
|
|
3287
|
+
});
|
|
3288
|
+
// src/workflow-system.feature.ts
|
|
3289
|
+
import { defineFeature } from "@contractspec/lib.contracts-spec";
|
|
3290
|
+
var WorkflowSystemFeature = defineFeature({
|
|
3291
|
+
meta: {
|
|
3292
|
+
key: "workflow-system",
|
|
3293
|
+
title: "Workflow & Approval System",
|
|
3294
|
+
description: "State machine-based workflow engine with role-based approvals, delegation, and escalation",
|
|
3295
|
+
domain: "workflow",
|
|
3296
|
+
owners: ["@workflow-team"],
|
|
3297
|
+
tags: ["workflow", "approval", "state-machine", "automation"],
|
|
3298
|
+
stability: "experimental",
|
|
3299
|
+
version: "1.0.0"
|
|
3300
|
+
},
|
|
3301
|
+
operations: [
|
|
3302
|
+
{ key: "workflow.definition.create", version: "1.0.0" },
|
|
3303
|
+
{ key: "workflow.definition.update", version: "1.0.0" },
|
|
3304
|
+
{ key: "workflow.step.add", version: "1.0.0" },
|
|
3305
|
+
{ key: "workflow.definition.publish", version: "1.0.0" },
|
|
3306
|
+
{ key: "workflow.definition.list", version: "1.0.0" },
|
|
3307
|
+
{ key: "workflow.definition.get", version: "1.0.0" },
|
|
3308
|
+
{ key: "workflow.instance.start", version: "1.0.0" },
|
|
3309
|
+
{ key: "workflow.instance.transition", version: "1.0.0" },
|
|
3310
|
+
{ key: "workflow.instance.pause", version: "1.0.0" },
|
|
3311
|
+
{ key: "workflow.instance.resume", version: "1.0.0" },
|
|
3312
|
+
{ key: "workflow.instance.cancel", version: "1.0.0" },
|
|
3313
|
+
{ key: "workflow.instance.list", version: "1.0.0" },
|
|
3314
|
+
{ key: "workflow.instance.get", version: "1.0.0" },
|
|
3315
|
+
{ key: "workflow.approval.decide", version: "1.0.0" },
|
|
3316
|
+
{ key: "workflow.approval.delegate", version: "1.0.0" },
|
|
3317
|
+
{ key: "workflow.approval.comment.add", version: "1.0.0" },
|
|
3318
|
+
{ key: "workflow.approval.list.mine", version: "1.0.0" },
|
|
3319
|
+
{ key: "workflow.approval.get", version: "1.0.0" }
|
|
3320
|
+
],
|
|
3321
|
+
events: [
|
|
3322
|
+
{ key: "workflow.definition.created", version: "1.0.0" },
|
|
3323
|
+
{ key: "workflow.definition.updated", version: "1.0.0" },
|
|
3324
|
+
{ key: "workflow.definition.published", version: "1.0.0" },
|
|
3325
|
+
{ key: "workflow.step.added", version: "1.0.0" },
|
|
3326
|
+
{ key: "workflow.instance.started", version: "1.0.0" },
|
|
3327
|
+
{ key: "workflow.step.entered", version: "1.0.0" },
|
|
3328
|
+
{ key: "workflow.step.exited", version: "1.0.0" },
|
|
3329
|
+
{ key: "workflow.instance.completed", version: "1.0.0" },
|
|
3330
|
+
{ key: "workflow.instance.cancelled", version: "1.0.0" },
|
|
3331
|
+
{ key: "workflow.instance.paused", version: "1.0.0" },
|
|
3332
|
+
{ key: "workflow.instance.resumed", version: "1.0.0" },
|
|
3333
|
+
{ key: "workflow.instance.failed", version: "1.0.0" },
|
|
3334
|
+
{ key: "workflow.instance.timedOut", version: "1.0.0" },
|
|
3335
|
+
{ key: "workflow.approval.requested", version: "1.0.0" },
|
|
3336
|
+
{ key: "workflow.approval.decided", version: "1.0.0" },
|
|
3337
|
+
{ key: "workflow.approval.delegated", version: "1.0.0" },
|
|
3338
|
+
{ key: "workflow.approval.escalated", version: "1.0.0" }
|
|
3339
|
+
],
|
|
3340
|
+
presentations: [
|
|
3341
|
+
{ key: "workflow.designer", version: "1.0.0" },
|
|
3342
|
+
{ key: "workflow.definition.viewList", version: "1.0.0" },
|
|
3343
|
+
{ key: "workflow.definition.detail", version: "1.0.0" },
|
|
3344
|
+
{ key: "workflow.instance.viewList", version: "1.0.0" },
|
|
3345
|
+
{ key: "workflow.instance.detail", version: "1.0.0" },
|
|
3346
|
+
{ key: "workflow.instance.progress", version: "1.0.0" },
|
|
3347
|
+
{ key: "workflow.approval.inbox", version: "1.0.0" },
|
|
3348
|
+
{ key: "workflow.approval.detail", version: "1.0.0" },
|
|
3349
|
+
{ key: "workflow.approval.form", version: "1.0.0" },
|
|
3350
|
+
{ key: "workflow.approval.badge", version: "1.0.0" },
|
|
3351
|
+
{ key: "workflow.metrics", version: "1.0.0" }
|
|
3352
|
+
],
|
|
3353
|
+
opToPresentation: [
|
|
3354
|
+
{
|
|
3355
|
+
op: { key: "workflow.definition.list", version: "1.0.0" },
|
|
3356
|
+
pres: { key: "workflow.definition.viewList", version: "1.0.0" }
|
|
3357
|
+
},
|
|
3358
|
+
{
|
|
3359
|
+
op: { key: "workflow.instance.list", version: "1.0.0" },
|
|
3360
|
+
pres: { key: "workflow.instance.viewList", version: "1.0.0" }
|
|
3361
|
+
},
|
|
3362
|
+
{
|
|
3363
|
+
op: { key: "workflow.approval.list.mine", version: "1.0.0" },
|
|
3364
|
+
pres: { key: "workflow.approval.inbox", version: "1.0.0" }
|
|
3365
|
+
},
|
|
3366
|
+
{
|
|
3367
|
+
op: { key: "workflow.approval.decide", version: "1.0.0" },
|
|
3368
|
+
pres: { key: "workflow.approval.form", version: "1.0.0" }
|
|
3369
|
+
}
|
|
3370
|
+
],
|
|
3371
|
+
presentationsTargets: [
|
|
3372
|
+
{ key: "workflow.designer", version: "1.0.0", targets: ["react"] },
|
|
3373
|
+
{
|
|
3374
|
+
key: "workflow.definition.viewList",
|
|
3375
|
+
version: "1.0.0",
|
|
3376
|
+
targets: ["react", "markdown"]
|
|
3377
|
+
},
|
|
3378
|
+
{
|
|
3379
|
+
key: "workflow.definition.detail",
|
|
3380
|
+
version: "1.0.0",
|
|
3381
|
+
targets: ["react", "markdown"]
|
|
3382
|
+
},
|
|
3383
|
+
{
|
|
3384
|
+
key: "workflow.instance.viewList",
|
|
3385
|
+
version: "1.0.0",
|
|
3386
|
+
targets: ["react", "markdown"]
|
|
3387
|
+
},
|
|
3388
|
+
{
|
|
3389
|
+
key: "workflow.instance.detail",
|
|
3390
|
+
version: "1.0.0",
|
|
3391
|
+
targets: ["react", "markdown"]
|
|
3392
|
+
},
|
|
3393
|
+
{ key: "workflow.instance.progress", version: "1.0.0", targets: ["react"] },
|
|
3394
|
+
{
|
|
3395
|
+
key: "workflow.approval.inbox",
|
|
3396
|
+
version: "1.0.0",
|
|
3397
|
+
targets: ["react", "markdown"]
|
|
3398
|
+
},
|
|
3399
|
+
{
|
|
3400
|
+
key: "workflow.approval.detail",
|
|
3401
|
+
version: "1.0.0",
|
|
3402
|
+
targets: ["react", "markdown"]
|
|
3403
|
+
},
|
|
3404
|
+
{
|
|
3405
|
+
key: "workflow.metrics",
|
|
3406
|
+
version: "1.0.0",
|
|
3407
|
+
targets: ["react", "markdown"]
|
|
3408
|
+
}
|
|
3409
|
+
],
|
|
3410
|
+
visualizations: WorkflowVisualizationRefs,
|
|
3411
|
+
capabilities: {
|
|
3412
|
+
requires: [
|
|
3413
|
+
{ key: "identity", version: "1.0.0" },
|
|
3414
|
+
{ key: "audit-trail", version: "1.0.0" },
|
|
3415
|
+
{ key: "notifications", version: "1.0.0" },
|
|
3416
|
+
{ key: "feature-flags", version: "1.0.0" }
|
|
3417
|
+
],
|
|
3418
|
+
provides: [
|
|
3419
|
+
{ key: "workflow", version: "1.0.0" },
|
|
3420
|
+
{ key: "approval", version: "1.0.0" },
|
|
3421
|
+
{ key: "state-machine", version: "1.0.0" }
|
|
3422
|
+
]
|
|
3423
|
+
},
|
|
3424
|
+
workflows: [
|
|
3425
|
+
{ key: "workflow-system.workflow.approval-chain", version: "1.0.0" }
|
|
3426
|
+
],
|
|
3427
|
+
telemetry: [{ key: "workflow-system.telemetry", version: "1.0.0" }],
|
|
3428
|
+
jobs: [
|
|
3429
|
+
{ key: "workflow-system.job.instance-timeout", version: "1.0.0" },
|
|
3430
|
+
{ key: "workflow-system.job.escalation", version: "1.0.0" }
|
|
3431
|
+
],
|
|
3432
|
+
docs: [
|
|
3433
|
+
"docs.examples.workflow-system",
|
|
3434
|
+
"docs.examples.workflow-system.goal",
|
|
3435
|
+
"docs.examples.workflow-system.usage",
|
|
3436
|
+
"docs.examples.workflow-system.constraints"
|
|
3437
|
+
]
|
|
3438
|
+
});
|
|
3060
3439
|
export {
|
|
3061
3440
|
workflowInstanceDetailMarkdownRenderer,
|
|
3062
3441
|
workflowDefinitionListMarkdownRenderer,
|
|
3063
3442
|
workflowDashboardMarkdownRenderer,
|
|
3064
3443
|
useWorkflowList,
|
|
3065
3444
|
mockDataStore,
|
|
3445
|
+
createWorkflowVisualizationSections,
|
|
3066
3446
|
createWorkflowHandlers,
|
|
3067
3447
|
createStateMachineEngine,
|
|
3068
3448
|
createInitialState,
|
|
3069
3449
|
buildStateMachineDefinition,
|
|
3450
|
+
WorkflowVisualizationSpecs,
|
|
3451
|
+
WorkflowVisualizationRegistry,
|
|
3452
|
+
WorkflowVisualizationRefs,
|
|
3070
3453
|
WorkflowUpdatedEvent,
|
|
3454
|
+
WorkflowThroughputVisualization,
|
|
3071
3455
|
WorkflowSystemPresentations,
|
|
3072
3456
|
WorkflowSystemFeature,
|
|
3073
3457
|
WorkflowStepModel,
|
|
@@ -3075,12 +3459,15 @@ export {
|
|
|
3075
3459
|
WorkflowPublishedEvent,
|
|
3076
3460
|
WorkflowMetricsPresentation,
|
|
3077
3461
|
WorkflowListPresentation,
|
|
3462
|
+
WorkflowInstanceStatusVisualization,
|
|
3078
3463
|
WorkflowInstanceModel,
|
|
3079
3464
|
WorkflowDetailPresentation,
|
|
3080
3465
|
WorkflowDesignerPresentation,
|
|
3081
3466
|
WorkflowDefinitionModel,
|
|
3082
3467
|
WorkflowDashboard,
|
|
3083
3468
|
WorkflowCreatedEvent,
|
|
3469
|
+
WorkflowCompletedMetricVisualization,
|
|
3470
|
+
WorkflowActiveMetricVisualization,
|
|
3084
3471
|
UpdateWorkflowInputModel,
|
|
3085
3472
|
UpdateWorkflowContract,
|
|
3086
3473
|
TriggerTypeEnum,
|