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