@hotmeshio/long-tail 0.14.1 → 0.14.4
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/build/api/escalations/bulk.d.ts +18 -0
- package/build/api/escalations/bulk.js +49 -1
- package/build/api/escalations/helpers.d.ts +11 -1
- package/build/api/escalations/helpers.js +30 -3
- package/build/api/escalations/index.d.ts +1 -1
- package/build/api/escalations/index.js +2 -1
- package/build/routes/escalations/bulk.js +6 -0
- package/build/sdk/index.d.ts +4 -0
- package/build/sdk/index.js +1 -0
- package/build/services/escalation/bulk.d.ts +27 -0
- package/build/services/escalation/bulk.js +39 -0
- package/build/services/escalation/sql.d.ts +17 -0
- package/build/services/escalation/sql.js +44 -1
- package/build/shared/form-validation/field-validator.js +6 -4
- package/build/shared/form-validation/index.d.ts +2 -0
- package/build/shared/form-validation/index.js +2 -0
- package/build/shared/form-validation/validate-resolver-payload.d.ts +2 -0
- package/build/shared/form-validation/validate-resolver-payload.js +19 -0
- package/build/shared/form-validation/x-lt-options.d.ts +22 -0
- package/build/shared/form-validation/x-lt-options.js +51 -0
- package/build/shared/form-validation/x-lt-require-sum.d.ts +30 -0
- package/build/shared/form-validation/x-lt-require-sum.js +59 -0
- package/build/system/mcp-servers/admin/escalations.js +13 -1
- package/build/system/mcp-servers/admin/schemas.d.ts +10 -0
- package/build/system/mcp-servers/admin/schemas.js +6 -2
- package/build/system/seed/tool-manifests-admin.d.ts +88 -0
- package/build/system/seed/tool-manifests-admin.js +2 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/dashboard/dist/assets/{AdminDashboard-C4h1R-lz.js → AdminDashboard-CUqnrc7h.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-C4h1R-lz.js.map → AdminDashboard-CUqnrc7h.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-EWC8VQ7R.js → AgentConfigPage-lmUOwyHO.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-EWC8VQ7R.js.map → AgentConfigPage-lmUOwyHO.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-DaLfa80d.js → AgentDetailPage-C_xAw6aF.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-DaLfa80d.js.map → AgentDetailPage-C_xAw6aF.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-islj_zrh.js → AgentsPage-CHCGAkpN.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-islj_zrh.js.map → AgentsPage-CHCGAkpN.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-BvQdHMl2.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-BvQdHMl2.js.map +1 -0
- package/dashboard/dist/assets/BotPicker-Dsr8Yyj_.js +2 -0
- package/dashboard/dist/assets/{BotPicker-CnX8xfka.js.map → BotPicker-Dsr8Yyj_.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-CbUftMR2.js +2 -0
- package/dashboard/dist/assets/BulkAssignModal-CbUftMR2.js.map +1 -0
- package/dashboard/dist/assets/CapabilitiesPage-CPNUJPHs.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-DK7wGMFt.js.map → CapabilitiesPage-CPNUJPHs.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-WqEpMTyx.js → CollapsibleSection-DffGX2tR.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-WqEpMTyx.js.map → CollapsibleSection-DffGX2tR.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-Bb_VuJc8.js +2 -0
- package/dashboard/dist/assets/CountdownTimer-Bb_VuJc8.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-CfT60FiU.js → CredentialsPage-UXnD_Rau.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CfT60FiU.js.map → CredentialsPage-UXnD_Rau.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-ds7dLz6S.js → CronLabel-CctUYUlI.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-ds7dLz6S.js.map → CronLabel-CctUYUlI.js.map} +1 -1
- package/dashboard/dist/assets/{DataTable-Bir0Xs1p.js → DataTable-DFPMeqyQ.js} +2 -2
- package/dashboard/dist/assets/DataTable-DFPMeqyQ.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-DovkhN2p.js → DropZone-7UoXQ4qL.js} +2 -2
- package/dashboard/dist/assets/{DropZone-DovkhN2p.js.map → DropZone-7UoXQ4qL.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-DRQhFky_.js → ElapsedCell-C7_Y8xXn.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-DRQhFky_.js.map → ElapsedCell-C7_Y8xXn.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-nCgWdmpK.js → EntityTimelinePanel-pRu91gZK.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-nCgWdmpK.js.map → EntityTimelinePanel-pRu91gZK.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DBCnPMG9.js → EscalationListSchemaPage-B3f2mjqg.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DBCnPMG9.js.map → EscalationListSchemaPage-B3f2mjqg.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DfzRTqhV.js → EscalationSchemaPage-AJ85FRZy.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DfzRTqhV.js.map → EscalationSchemaPage-AJ85FRZy.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CWd2Ivso.js → EscalationsOverview-DMLLWzjS.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CWd2Ivso.js.map → EscalationsOverview-DMLLWzjS.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Dm9Fbab1.js → EventTable-BlNuCTN6.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Dm9Fbab1.js.map → EventTable-BlNuCTN6.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-DR4cJvTB.js → FilterBar-B-rkcWkV.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-DR4cJvTB.js.map → FilterBar-B-rkcWkV.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DQt64Ru0.js → GraphInvokePage-Bkt5tAFo.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DQt64Ru0.js.map → GraphInvokePage-Bkt5tAFo.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-D7qNiqtw.js → HomePage-CIE9bCFQ.js} +2 -2
- package/dashboard/dist/assets/{HomePage-D7qNiqtw.js.map → HomePage-CIE9bCFQ.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-BdZkpRMo.js → ListToolbar-C_-Utxqm.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-BdZkpRMo.js.map → ListToolbar-C_-Utxqm.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DHAEYY1b.js → McpOverview-c0p171OK.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DHAEYY1b.js.map → McpOverview-c0p171OK.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BfGhRO_c.js → McpQueryDetailPage-B61I9-dM.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-BfGhRO_c.js.map → McpQueryDetailPage-B61I9-dM.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-Viqi13Fa.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-3EXLX1Eq.js.map → McpQueryPage-Viqi13Fa.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DHI0F65P.js → McpRunDetailPage-CiAx_xyV.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DHI0F65P.js.map → McpRunDetailPage-CiAx_xyV.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-C6-KpYCY.js → McpRunsPage-BpfvNRbE.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-C6-KpYCY.js.map → McpRunsPage-BpfvNRbE.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-BeifzjUm.js → NamespacePill-CKp_9EaI.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-BeifzjUm.js.map → NamespacePill-CKp_9EaI.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-DGKwUE6h.js +3 -0
- package/dashboard/dist/assets/OperationsPage-DGKwUE6h.js.map +1 -0
- package/dashboard/dist/assets/{OperatorDashboard-DLp9gCTA.js → OperatorDashboard-ha-05tgB.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-DLp9gCTA.js.map → OperatorDashboard-ha-05tgB.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-BpeBHqyc.js → PageHeader-CDDpHpdv.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-BpeBHqyc.js.map → PageHeader-CDDpHpdv.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-JXeUFa_g.js → PageHeaderWithStats-DIWH6fRv.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-JXeUFa_g.js.map → PageHeaderWithStats-DIWH6fRv.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-DFv4Zwmq.js → PersonaDetailPage-DMH-D1ns.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-DFv4Zwmq.js.map → PersonaDetailPage-DMH-D1ns.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-C52o87Zv.js → PersonasPage-YLjCcQcU.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-C52o87Zv.js.map → PersonasPage-YLjCcQcU.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-CKCxXogl.js → ProcessDetailPage-W5_2FJHn.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-CKCxXogl.js.map → ProcessDetailPage-W5_2FJHn.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-D1bxIy7-.js → ProcessesListPage-5f_2S9ER.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-D1bxIy7-.js.map → ProcessesListPage-5f_2S9ER.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-_MrbOGW_.js → RoleDetailPage-CuDTO13n.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-_MrbOGW_.js.map → RoleDetailPage-CuDTO13n.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-EocCXZh0.js → RolePill-C0hExOmI.js} +2 -2
- package/dashboard/dist/assets/{RolePill-EocCXZh0.js.map → RolePill-C0hExOmI.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-ZVCkB4iF.js → RolesPage-McMYumsZ.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-ZVCkB4iF.js.map → RolesPage-McMYumsZ.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-CC87e67k.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-BAqa1Tya.js.map → RunAsSelector-CC87e67k.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-b7WkFiy-.js → ScanCodesPage-Zk6Jorv_.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-b7WkFiy-.js.map → ScanCodesPage-Zk6Jorv_.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-B79pya8o.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-B79pya8o.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-BLlHMmd_.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-CPC9CdCR.js.map → ScanStationPage-BLlHMmd_.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-H5dEqeHi.js → ScopeBadge-BBQvz4pj.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-H5dEqeHi.js.map → ScopeBadge-BBQvz4pj.js.map} +1 -1
- package/dashboard/dist/assets/StatusBadge-BDeUwPtb.js +2 -0
- package/dashboard/dist/assets/StatusBadge-BDeUwPtb.js.map +1 -0
- package/dashboard/dist/assets/{StickyPagination-CgSzarlP.js → StickyPagination-CnJgQPU1.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CgSzarlP.js.map → StickyPagination-CnJgQPU1.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-B4E3S5RB.js → StreamMessageDetail-CU5wrqO_.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-B4E3S5RB.js.map → StreamMessageDetail-CU5wrqO_.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BkcjucMZ.js → SwimlaneTimeline-D5m-_zgy.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BkcjucMZ.js.map → SwimlaneTimeline-D5m-_zgy.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-Ch5u6iPH.js → TagInput-BXxXs1JD.js} +2 -2
- package/dashboard/dist/assets/{TagInput-Ch5u6iPH.js.map → TagInput-BXxXs1JD.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-D7e8x2gX.js → TaskDetailPage-SvVSH39Q.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-D7e8x2gX.js.map → TaskDetailPage-SvVSH39Q.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-Bz146p-P.js → TaskQueuePill-BKGJBVZG.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-Bz146p-P.js.map → TaskQueuePill-BKGJBVZG.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-B4mxP9Ey.js → TasksListPage-BtpwvxkS.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-B4mxP9Ey.js.map → TasksListPage-BtpwvxkS.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-D6sbYsUO.js → TimeAgo-BPODA7Dm.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-D6sbYsUO.js.map → TimeAgo-BPODA7Dm.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DFDf3NAT.js → TimestampCell-DEQXlxbH.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DFDf3NAT.js.map → TimestampCell-DEQXlxbH.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-sj8OkBB0.js → ToolPill-BY6zLSfA.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-sj8OkBB0.js.map → ToolPill-BY6zLSfA.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-DbWw0-Le.js → ToolTestPanel-Ztc0pRSh.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-DbWw0-Le.js.map → ToolTestPanel-Ztc0pRSh.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-C6CPcvuO.js → TopicDetailPage-BmpEqg-Q.js} +4 -4
- package/dashboard/dist/assets/{TopicDetailPage-C6CPcvuO.js.map → TopicDetailPage-BmpEqg-Q.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-C8_XpeT2.js → TopicsPage-BVW5y6vE.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-C8_XpeT2.js.map → TopicsPage-BVW5y6vE.js.map} +1 -1
- package/dashboard/dist/assets/UserName-D915g7ba.js +2 -0
- package/dashboard/dist/assets/{UserName-CIoJvf_e.js.map → UserName-D915g7ba.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-CIl9ESgk.js +2 -0
- package/dashboard/dist/assets/WorkflowExecutionPage-CIl9ESgk.js.map +1 -0
- package/dashboard/dist/assets/{WorkflowPill-BcA7S3gI.js → WorkflowPill-qp5UF3-y.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-BcA7S3gI.js.map → WorkflowPill-qp5UF3-y.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-y2L_zwnf.js → WorkflowsDashboard-DtkaGgdZ.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-y2L_zwnf.js.map → WorkflowsDashboard-DtkaGgdZ.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-ChE1Mm3P.js → WorkflowsOverview-DANXhmXb.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-ChE1Mm3P.js.map → WorkflowsOverview-DANXhmXb.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-D0aY_inb.js → YamlWorkflowDetailPage-m6Ub7qtE.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-D0aY_inb.js.map → YamlWorkflowDetailPage-m6Ub7qtE.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-DJ0JitPs.js → YamlWorkflowsPage-5MOsxbLW.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-DJ0JitPs.js.map → YamlWorkflowsPage-5MOsxbLW.js.map} +1 -1
- package/dashboard/dist/assets/{agents-Bu5Ly_ER.js → agents-DacpnIqz.js} +2 -2
- package/dashboard/dist/assets/{agents-Bu5Ly_ER.js.map → agents-DacpnIqz.js.map} +1 -1
- package/dashboard/dist/assets/{bots-Cb14wZ1Y.js → bots-El47Xy5a.js} +2 -2
- package/dashboard/dist/assets/{bots-Cb14wZ1Y.js.map → bots-El47Xy5a.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DeHLk9JJ.js → capabilities-DGC__Aob.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DeHLk9JJ.js.map → capabilities-DGC__Aob.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-YBZ3SbA6.js → controlplane-Bzx-qd8m.js} +2 -2
- package/dashboard/dist/assets/{controlplane-YBZ3SbA6.js.map → controlplane-Bzx-qd8m.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-CA9DQlhA.js → escalation-columns-BmY7BriY.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-CA9DQlhA.js.map → escalation-columns-BmY7BriY.js.map} +1 -1
- package/dashboard/dist/assets/{index-D5MSJsiW.js → index-B4ZNPgcz.js} +2 -2
- package/dashboard/dist/assets/{index-D5MSJsiW.js.map → index-B4ZNPgcz.js.map} +1 -1
- package/dashboard/dist/assets/index-BPK2cB4Q.js +6 -0
- package/dashboard/dist/assets/index-BPK2cB4Q.js.map +1 -0
- package/dashboard/dist/assets/{index-B0qNe7Ux.js → index-Bwlnpbpd.js} +2 -2
- package/dashboard/dist/assets/{index-B0qNe7Ux.js.map → index-Bwlnpbpd.js.map} +1 -1
- package/dashboard/dist/assets/{index-CQriisJy.js → index-CHwg51qz.js} +2 -2
- package/dashboard/dist/assets/{index-CQriisJy.js.map → index-CHwg51qz.js.map} +1 -1
- package/dashboard/dist/assets/index-CJV2pWNH.css +1 -0
- package/dashboard/dist/assets/{index-BaDimDGQ.js → index-Ce6ghhpn.js} +2 -2
- package/dashboard/dist/assets/{index-BaDimDGQ.js.map → index-Ce6ghhpn.js.map} +1 -1
- package/dashboard/dist/assets/{index-B4Nea96C.js → index-Cfw6FARc.js} +2 -2
- package/dashboard/dist/assets/{index-B4Nea96C.js.map → index-Cfw6FARc.js.map} +1 -1
- package/dashboard/dist/assets/{index-BAKroiNw.js → index-CoIh4ipz.js} +2 -2
- package/dashboard/dist/assets/{index-BAKroiNw.js.map → index-CoIh4ipz.js.map} +1 -1
- package/dashboard/dist/assets/index-Cqc7Wu5Y.js +3 -0
- package/dashboard/dist/assets/index-Cqc7Wu5Y.js.map +1 -0
- package/dashboard/dist/assets/index-DH_xm9UQ.js +2 -0
- package/dashboard/dist/assets/{index-chMUPSOd.js.map → index-DH_xm9UQ.js.map} +1 -1
- package/dashboard/dist/assets/{index-B7fE-rND.js → index-DYz57kr_.js} +2 -2
- package/dashboard/dist/assets/{index-B7fE-rND.js.map → index-DYz57kr_.js.map} +1 -1
- package/dashboard/dist/assets/{index-YUv7aNb4.js → index-DpsVlk5z.js} +2 -2
- package/dashboard/dist/assets/{index-YUv7aNb4.js.map → index-DpsVlk5z.js.map} +1 -1
- package/dashboard/dist/assets/{index-Ntul2ZC1.js → index-SU2xrnBD.js} +29 -28
- package/dashboard/dist/assets/index-SU2xrnBD.js.map +1 -0
- package/dashboard/dist/assets/{index-BRmgxeZM.js → index-ZtpEajtq.js} +3 -3
- package/dashboard/dist/assets/{index-BRmgxeZM.js.map → index-ZtpEajtq.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-B1HqYuB2.js → knowledge-k-5jr2BN.js} +2 -2
- package/dashboard/dist/assets/{knowledge-B1HqYuB2.js.map → knowledge-k-5jr2BN.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-dhihqJpH.js → mcp-BEqxxlW9.js} +2 -2
- package/dashboard/dist/assets/{mcp-dhihqJpH.js.map → mcp-BEqxxlW9.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-B_gkB7JK.js → mcp-query-qXTlQfc_.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-B_gkB7JK.js.map → mcp-query-qXTlQfc_.js.map} +1 -1
- package/dashboard/dist/assets/{personas-Bw_OlfI6.js → personas-jJEDmBtg.js} +2 -2
- package/dashboard/dist/assets/{personas-Bw_OlfI6.js.map → personas-jJEDmBtg.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-BYwn0LXY.js → pipelines-BNPJh69x.js} +2 -2
- package/dashboard/dist/assets/{pipelines-BYwn0LXY.js.map → pipelines-BNPJh69x.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-t6bPmJ7P.js → tasks-DhD71qXJ.js} +2 -2
- package/dashboard/dist/assets/{tasks-t6bPmJ7P.js.map → tasks-DhD71qXJ.js.map} +1 -1
- package/dashboard/dist/assets/{topics-Bgo9xw80.js → topics-CrXwwuW-.js} +2 -2
- package/dashboard/dist/assets/{topics-Bgo9xw80.js.map → topics-CrXwwuW-.js.map} +1 -1
- package/dashboard/dist/assets/{useEventHooks-BJbMbg_h.js → useEventHooks-DL7R0ASv.js} +2 -2
- package/dashboard/dist/assets/{useEventHooks-BJbMbg_h.js.map → useEventHooks-DL7R0ASv.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CaXJuSFG.js → useNamespace-ETqzJakA.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CaXJuSFG.js.map → useNamespace-ETqzJakA.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-B47LQrDk.js → useYamlActivityEvents-SqY67S-F.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-B47LQrDk.js.map → useYamlActivityEvents-SqY67S-F.js.map} +1 -1
- package/dashboard/dist/assets/{users-D0jvzUqW.js → users-DF8dTbOo.js} +2 -2
- package/dashboard/dist/assets/{users-D0jvzUqW.js.map → users-DF8dTbOo.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-BPsNpK3Y.js → vendor-icons-BgsXTN4h.js} +145 -140
- package/dashboard/dist/assets/vendor-icons-BgsXTN4h.js.map +1 -0
- package/dashboard/dist/assets/{workflows-DRoZRrMH.js → workflows-Bdke7fzx.js} +2 -2
- package/dashboard/dist/assets/{workflows-DRoZRrMH.js.map → workflows-Bdke7fzx.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BdhYyIef.js → yaml-workflows-UMxHYunb.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BdhYyIef.js.map → yaml-workflows-UMxHYunb.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +29 -0
- package/docs/dashboard.md +2 -0
- package/docs/events.md +1 -1
- package/docs/hitl/form.md +1 -0
- package/docs/hitl/x-lt-footer.md +6 -0
- package/docs/hitl/x-lt-list-schema.md +4 -2
- package/docs/hitl/x-lt-validation.md +62 -1
- package/docs/hitl-guide.md +3 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-B8NjwwKQ.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-B8NjwwKQ.js.map +0 -1
- package/dashboard/dist/assets/BotPicker-CnX8xfka.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-DK7wGMFt.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-BvQw_3WJ.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-BvQw_3WJ.js.map +0 -1
- package/dashboard/dist/assets/CustomDurationPicker-D-iY1f4n.js +0 -2
- package/dashboard/dist/assets/CustomDurationPicker-D-iY1f4n.js.map +0 -1
- package/dashboard/dist/assets/DataTable-Bir0Xs1p.js.map +0 -1
- package/dashboard/dist/assets/McpQueryPage-3EXLX1Eq.js +0 -2
- package/dashboard/dist/assets/OperationsPage-BNW7uris.js +0 -3
- package/dashboard/dist/assets/OperationsPage-BNW7uris.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-BAqa1Tya.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-BCsEgS-s.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-BCsEgS-s.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-CPC9CdCR.js +0 -2
- package/dashboard/dist/assets/StatusBadge-DkgllZHv.js +0 -2
- package/dashboard/dist/assets/StatusBadge-DkgllZHv.js.map +0 -1
- package/dashboard/dist/assets/UserName-CIoJvf_e.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-Bq3kSkRr.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-Bq3kSkRr.js.map +0 -1
- package/dashboard/dist/assets/index-B5jxf81r.css +0 -1
- package/dashboard/dist/assets/index-BhurEB5s.js +0 -6
- package/dashboard/dist/assets/index-BhurEB5s.js.map +0 -1
- package/dashboard/dist/assets/index-Ntul2ZC1.js.map +0 -1
- package/dashboard/dist/assets/index-chMUPSOd.js +0 -2
- package/dashboard/dist/assets/index-uWUJXqGS.js +0 -3
- package/dashboard/dist/assets/index-uWUJXqGS.js.map +0 -1
- package/dashboard/dist/assets/vendor-icons-BPsNpK3Y.js.map +0 -1
|
@@ -49,6 +49,9 @@ export declare function bulkClaim(input: {
|
|
|
49
49
|
* @param input.query — `{ role, facets? }` selector (query form)
|
|
50
50
|
* @param input.targetUserId — user to assign to
|
|
51
51
|
* @param input.durationMinutes — assignment duration (default: 30)
|
|
52
|
+
* @param input.reassign — also take over rows under a LIVE claim (ids form
|
|
53
|
+
* only; requires admin/superadmin). Default false: live claims are skipped
|
|
54
|
+
* and counted in `skipped`.
|
|
52
55
|
* @param auth — authenticated user context
|
|
53
56
|
* @returns `{ status: 200, data: { assigned, skipped } }`
|
|
54
57
|
*/
|
|
@@ -60,6 +63,21 @@ export declare function bulkAssign(input: {
|
|
|
60
63
|
};
|
|
61
64
|
targetUserId: string;
|
|
62
65
|
durationMinutes?: number;
|
|
66
|
+
reassign?: boolean;
|
|
67
|
+
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Return claimed escalations to the available pool — the admin override of
|
|
70
|
+
* someone else's live claim (self-return stays the release verb). One
|
|
71
|
+
* guarded statement; unclaimed and terminal rows are skipped. Publishes a
|
|
72
|
+
* `released` event per returned row with the acting admin in the delta.
|
|
73
|
+
*
|
|
74
|
+
* RBAC: admin/superadmin (global escalation access) only.
|
|
75
|
+
*
|
|
76
|
+
* @param input.ids — array of escalation UUIDs
|
|
77
|
+
* @returns `{ status: 200, data: { unassigned, skipped } }`
|
|
78
|
+
*/
|
|
79
|
+
export declare function bulkUnassign(input: {
|
|
80
|
+
ids?: string[];
|
|
63
81
|
}, auth: LTApiAuth): Promise<LTApiResult>;
|
|
64
82
|
/**
|
|
65
83
|
* Route multiple escalations to a different role.
|
|
@@ -37,6 +37,7 @@ exports.releaseExpiredClaims = releaseExpiredClaims;
|
|
|
37
37
|
exports.updatePriority = updatePriority;
|
|
38
38
|
exports.bulkClaim = bulkClaim;
|
|
39
39
|
exports.bulkAssign = bulkAssign;
|
|
40
|
+
exports.bulkUnassign = bulkUnassign;
|
|
40
41
|
exports.bulkEscalate = bulkEscalate;
|
|
41
42
|
exports.bulkTriage = bulkTriage;
|
|
42
43
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
@@ -133,12 +134,15 @@ async function bulkClaim(input, auth) {
|
|
|
133
134
|
* @param input.query — `{ role, facets? }` selector (query form)
|
|
134
135
|
* @param input.targetUserId — user to assign to
|
|
135
136
|
* @param input.durationMinutes — assignment duration (default: 30)
|
|
137
|
+
* @param input.reassign — also take over rows under a LIVE claim (ids form
|
|
138
|
+
* only; requires admin/superadmin). Default false: live claims are skipped
|
|
139
|
+
* and counted in `skipped`.
|
|
136
140
|
* @param auth — authenticated user context
|
|
137
141
|
* @returns `{ status: 200, data: { assigned, skipped } }`
|
|
138
142
|
*/
|
|
139
143
|
async function bulkAssign(input, auth) {
|
|
140
144
|
try {
|
|
141
|
-
const { ids, query, targetUserId, durationMinutes } = input;
|
|
145
|
+
const { ids, query, targetUserId, durationMinutes, reassign } = input;
|
|
142
146
|
if (!targetUserId || typeof targetUserId !== 'string') {
|
|
143
147
|
return { status: 400, error: 'targetUserId is required' };
|
|
144
148
|
}
|
|
@@ -147,6 +151,14 @@ async function bulkAssign(input, auth) {
|
|
|
147
151
|
if (hasIds === hasQuery) {
|
|
148
152
|
return { status: 400, error: 'provide exactly one of ids or query' };
|
|
149
153
|
}
|
|
154
|
+
if (reassign === true && hasQuery) {
|
|
155
|
+
return { status: 400, error: 'reassign requires the ids form' };
|
|
156
|
+
}
|
|
157
|
+
// Taking over a LIVE claim is a management override — stricter than
|
|
158
|
+
// pre-assigning pool rows, which role-scoped admins may do.
|
|
159
|
+
if (reassign === true && !(await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId))) {
|
|
160
|
+
return { status: 403, error: 'Forbidden: reassign requires admin access' };
|
|
161
|
+
}
|
|
150
162
|
if (hasQuery) {
|
|
151
163
|
if (!query.role || typeof query.role !== 'string') {
|
|
152
164
|
return { status: 400, error: 'query.role is required' };
|
|
@@ -186,6 +198,14 @@ async function bulkAssign(input, auth) {
|
|
|
186
198
|
}
|
|
187
199
|
}
|
|
188
200
|
}
|
|
201
|
+
if (reassign === true) {
|
|
202
|
+
const result = await escalationService.bulkReassignEscalations(ids, targetUserId, durationMinutes ?? 30);
|
|
203
|
+
if (result.assigned > 0) {
|
|
204
|
+
const priorById = new Map(result.changes.map((c) => [c.id, c.prior_assignee]));
|
|
205
|
+
(0, helpers_1.publishBulkClaimEvents)(result.changes.map((c) => c.id), targetUserId, undefined, priorById);
|
|
206
|
+
}
|
|
207
|
+
return { status: 200, data: { assigned: result.assigned, skipped: result.skipped } };
|
|
208
|
+
}
|
|
189
209
|
const result = await escalationService.bulkAssignEscalations(ids, targetUserId, durationMinutes ?? 30);
|
|
190
210
|
if (result.assigned > 0)
|
|
191
211
|
(0, helpers_1.publishBulkClaimEvents)(ids, targetUserId);
|
|
@@ -195,6 +215,34 @@ async function bulkAssign(input, auth) {
|
|
|
195
215
|
return { status: 500, error: err.message };
|
|
196
216
|
}
|
|
197
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Return claimed escalations to the available pool — the admin override of
|
|
220
|
+
* someone else's live claim (self-return stays the release verb). One
|
|
221
|
+
* guarded statement; unclaimed and terminal rows are skipped. Publishes a
|
|
222
|
+
* `released` event per returned row with the acting admin in the delta.
|
|
223
|
+
*
|
|
224
|
+
* RBAC: admin/superadmin (global escalation access) only.
|
|
225
|
+
*
|
|
226
|
+
* @param input.ids — array of escalation UUIDs
|
|
227
|
+
* @returns `{ status: 200, data: { unassigned, skipped } }`
|
|
228
|
+
*/
|
|
229
|
+
async function bulkUnassign(input, auth) {
|
|
230
|
+
try {
|
|
231
|
+
if (!(0, helpers_1.validateIds)(input.ids ?? [])) {
|
|
232
|
+
return { status: 400, error: 'ids must be a non-empty array' };
|
|
233
|
+
}
|
|
234
|
+
if (!(await (0, helpers_1.hasGlobalEscalationAccess)(auth.userId))) {
|
|
235
|
+
return { status: 403, error: 'Forbidden: unassign requires admin access' };
|
|
236
|
+
}
|
|
237
|
+
const result = await escalationService.bulkUnassignEscalations(input.ids);
|
|
238
|
+
if (result.unassigned > 0)
|
|
239
|
+
(0, helpers_1.publishBulkReleaseEvents)(result.changes, auth.userId);
|
|
240
|
+
return { status: 200, data: { unassigned: result.unassigned, skipped: result.skipped } };
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
return { status: 500, error: err.message };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
198
246
|
/**
|
|
199
247
|
* Route multiple escalations to a different role.
|
|
200
248
|
*
|
|
@@ -150,4 +150,14 @@ export declare function publishBulkReassignEvents(beforeRows: Array<{
|
|
|
150
150
|
id: string;
|
|
151
151
|
role: string;
|
|
152
152
|
}>, targetRole: string): void;
|
|
153
|
-
export declare function publishBulkClaimEvents(ids: string[], assignedTo: string, knownRole?: string): void;
|
|
153
|
+
export declare function publishBulkClaimEvents(ids: string[], assignedTo: string, knownRole?: string, priorById?: Map<string, string | null>): void;
|
|
154
|
+
/**
|
|
155
|
+
* Per-row released events for an admin unassign — the row returns to the
|
|
156
|
+
* pool under the same verb a self-release produces, with the acting admin in
|
|
157
|
+
* the delta.
|
|
158
|
+
*/
|
|
159
|
+
export declare function publishBulkReleaseEvents(changes: Array<{
|
|
160
|
+
id: string;
|
|
161
|
+
role: string;
|
|
162
|
+
prior_assignee: string | null;
|
|
163
|
+
}>, releasedBy: string): void;
|
|
@@ -46,6 +46,7 @@ exports.resolveAssignee = resolveAssignee;
|
|
|
46
46
|
exports.ensureRoleMembership = ensureRoleMembership;
|
|
47
47
|
exports.publishBulkReassignEvents = publishBulkReassignEvents;
|
|
48
48
|
exports.publishBulkClaimEvents = publishBulkClaimEvents;
|
|
49
|
+
exports.publishBulkReleaseEvents = publishBulkReleaseEvents;
|
|
49
50
|
const escalationService = __importStar(require("../../services/escalation"));
|
|
50
51
|
const userService = __importStar(require("../../services/user"));
|
|
51
52
|
const publish_1 = require("../../lib/events/publish");
|
|
@@ -283,10 +284,11 @@ function publishBulkReassignEvents(beforeRows, targetRole) {
|
|
|
283
284
|
}
|
|
284
285
|
}
|
|
285
286
|
}
|
|
286
|
-
function publishBulkClaimEvents(ids, assignedTo, knownRole) {
|
|
287
|
+
function publishBulkClaimEvents(ids, assignedTo, knownRole, priorById) {
|
|
287
288
|
// The claimed subject carries each row's role token. Query-form callers
|
|
288
289
|
// already know the single role; id-form callers resolve roles with one
|
|
289
|
-
// indexed read. Fire-and-forget, like every event publish.
|
|
290
|
+
// indexed read. Fire-and-forget, like every event publish. `priorById`
|
|
291
|
+
// (reassign) adds the displaced assignee to each row's delta.
|
|
290
292
|
void (async () => {
|
|
291
293
|
const roleById = new Map();
|
|
292
294
|
if (knownRole) {
|
|
@@ -299,6 +301,7 @@ function publishBulkClaimEvents(ids, assignedTo, knownRole) {
|
|
|
299
301
|
roleById.set(row.id, row.role);
|
|
300
302
|
}
|
|
301
303
|
for (const id of ids) {
|
|
304
|
+
const prior = priorById?.get(id);
|
|
302
305
|
(0, publish_1.publishEscalationEvent)({
|
|
303
306
|
type: 'escalation.claimed',
|
|
304
307
|
source: 'api',
|
|
@@ -310,8 +313,32 @@ function publishBulkClaimEvents(ids, assignedTo, knownRole) {
|
|
|
310
313
|
status: 'claimed',
|
|
311
314
|
// Bulk exception to the one-shape convention (see lib/events/escalation-wire.ts):
|
|
312
315
|
// delta + `bulk: true`, no per-row fetch. Subscribers fetch by id for detail.
|
|
313
|
-
data: { assigned_to: assignedTo, bulk: true },
|
|
316
|
+
data: { assigned_to: assignedTo, bulk: true, ...(prior ? { reassigned_from: prior } : {}) },
|
|
314
317
|
});
|
|
315
318
|
}
|
|
316
319
|
})().catch(() => { });
|
|
317
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Per-row released events for an admin unassign — the row returns to the
|
|
323
|
+
* pool under the same verb a self-release produces, with the acting admin in
|
|
324
|
+
* the delta.
|
|
325
|
+
*/
|
|
326
|
+
function publishBulkReleaseEvents(changes, releasedBy) {
|
|
327
|
+
for (const change of changes) {
|
|
328
|
+
void (0, publish_1.publishEscalationEvent)({
|
|
329
|
+
type: 'escalation.released',
|
|
330
|
+
source: 'api',
|
|
331
|
+
workflowId: '',
|
|
332
|
+
workflowName: '',
|
|
333
|
+
taskQueue: '',
|
|
334
|
+
escalationId: change.id,
|
|
335
|
+
role: change.role,
|
|
336
|
+
status: 'released',
|
|
337
|
+
data: {
|
|
338
|
+
released_by: releasedBy,
|
|
339
|
+
bulk: true,
|
|
340
|
+
...(change.prior_assignee ? { unassigned_from: change.prior_assignee } : {}),
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
@@ -2,7 +2,7 @@ export { createEscalation } from './create';
|
|
|
2
2
|
export { listEscalations, listAvailableEscalations, listDistinctTypes, listFacetKeys, getEscalationStats, getStationMetrics } from './list';
|
|
3
3
|
export { getEscalation, getEscalationsByWorkflowId, escalateToRole } from './single';
|
|
4
4
|
export { claimEscalation, releaseEscalation } from './claim';
|
|
5
|
-
export { releaseExpiredClaims, updatePriority, bulkClaim, bulkAssign, bulkEscalate, bulkTriage } from './bulk';
|
|
5
|
+
export { releaseExpiredClaims, updatePriority, bulkClaim, bulkAssign, bulkUnassign, bulkEscalate, bulkTriage } from './bulk';
|
|
6
6
|
export { resolveEscalation, resolveBySignalKey, resolveByIds, resolveAllOrNone } from './resolve';
|
|
7
7
|
export { findByMetadata, claimByMetadata, resolveByMetadata } from './metadata';
|
|
8
8
|
export { cancelSingleEscalation, bulkCancel } from './cancel';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.searchByFacets = exports.bulkCancel = exports.cancelSingleEscalation = exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.resolveAllOrNone = exports.resolveByIds = exports.resolveBySignalKey = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getStationMetrics = exports.getEscalationStats = exports.listFacetKeys = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
3
|
+
exports.timelineByFacet = exports.aggregateByFacets = exports.claimByFacets = exports.claimGroups = exports.searchByFacets = exports.bulkCancel = exports.cancelSingleEscalation = exports.resolveByMetadata = exports.claimByMetadata = exports.findByMetadata = exports.resolveAllOrNone = exports.resolveByIds = exports.resolveBySignalKey = exports.resolveEscalation = exports.bulkTriage = exports.bulkEscalate = exports.bulkUnassign = exports.bulkAssign = exports.bulkClaim = exports.updatePriority = exports.releaseExpiredClaims = exports.releaseEscalation = exports.claimEscalation = exports.escalateToRole = exports.getEscalationsByWorkflowId = exports.getEscalation = exports.getStationMetrics = exports.getEscalationStats = exports.listFacetKeys = exports.listDistinctTypes = exports.listAvailableEscalations = exports.listEscalations = exports.createEscalation = void 0;
|
|
4
4
|
var create_1 = require("./create");
|
|
5
5
|
Object.defineProperty(exports, "createEscalation", { enumerable: true, get: function () { return create_1.createEscalation; } });
|
|
6
6
|
var list_1 = require("./list");
|
|
@@ -22,6 +22,7 @@ Object.defineProperty(exports, "releaseExpiredClaims", { enumerable: true, get:
|
|
|
22
22
|
Object.defineProperty(exports, "updatePriority", { enumerable: true, get: function () { return bulk_1.updatePriority; } });
|
|
23
23
|
Object.defineProperty(exports, "bulkClaim", { enumerable: true, get: function () { return bulk_1.bulkClaim; } });
|
|
24
24
|
Object.defineProperty(exports, "bulkAssign", { enumerable: true, get: function () { return bulk_1.bulkAssign; } });
|
|
25
|
+
Object.defineProperty(exports, "bulkUnassign", { enumerable: true, get: function () { return bulk_1.bulkUnassign; } });
|
|
25
26
|
Object.defineProperty(exports, "bulkEscalate", { enumerable: true, get: function () { return bulk_1.bulkEscalate; } });
|
|
26
27
|
Object.defineProperty(exports, "bulkTriage", { enumerable: true, get: function () { return bulk_1.bulkTriage; } });
|
|
27
28
|
var resolve_1 = require("./resolve");
|
|
@@ -54,9 +54,15 @@ function registerBulkRoutes(router) {
|
|
|
54
54
|
query: req.body?.query,
|
|
55
55
|
targetUserId: req.body?.targetUserId,
|
|
56
56
|
durationMinutes: req.body?.durationMinutes,
|
|
57
|
+
// Take over live claims too (ids form; admin/superadmin only).
|
|
58
|
+
reassign: req.body?.reassign === true,
|
|
57
59
|
}, req.auth);
|
|
58
60
|
res.status(result.status).json(result.data ?? { error: result.error });
|
|
59
61
|
});
|
|
62
|
+
router.post('/bulk-unassign', async (req, res) => {
|
|
63
|
+
const result = await api.bulkUnassign({ ids: req.body?.ids }, req.auth);
|
|
64
|
+
res.status(result.status).json(result.data ?? { error: result.error });
|
|
65
|
+
});
|
|
60
66
|
router.patch('/bulk-escalate', async (req, res) => {
|
|
61
67
|
const result = await api.bulkEscalate({ ids: req.body?.ids, targetRole: req.body?.targetRole }, req.auth);
|
|
62
68
|
res.status(result.status).json(result.data ?? { error: result.error });
|
package/build/sdk/index.d.ts
CHANGED
|
@@ -181,6 +181,10 @@ export declare function createClient(options?: LTClientOptions): {
|
|
|
181
181
|
};
|
|
182
182
|
targetUserId: string;
|
|
183
183
|
durationMinutes?: number;
|
|
184
|
+
reassign?: boolean;
|
|
185
|
+
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
186
|
+
bulkUnassign: (input: {
|
|
187
|
+
ids?: string[];
|
|
184
188
|
}, auth?: LTApiAuth) => Promise<LTApiResult<any>>;
|
|
185
189
|
bulkEscalate: (input: {
|
|
186
190
|
ids: string[];
|
package/build/sdk/index.js
CHANGED
|
@@ -136,6 +136,7 @@ function createClient(options = {}) {
|
|
|
136
136
|
updatePriority: bindAuth(escalationsApi.updatePriority, auth),
|
|
137
137
|
bulkClaim: bindAuth(escalationsApi.bulkClaim, auth),
|
|
138
138
|
bulkAssign: bindAuth(escalationsApi.bulkAssign, auth),
|
|
139
|
+
bulkUnassign: bindAuth(escalationsApi.bulkUnassign, auth),
|
|
139
140
|
bulkEscalate: bindAuth(escalationsApi.bulkEscalate, auth),
|
|
140
141
|
bulkTriage: bindAuth(escalationsApi.bulkTriage, auth),
|
|
141
142
|
findByMetadata: bindAuth(escalationsApi.findByMetadata, auth),
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { LTEscalationRecord } from '../../types';
|
|
2
|
+
/** One row touched by a reassign/unassign, with its pre-update assignee. */
|
|
3
|
+
export interface AssignmentChange {
|
|
4
|
+
id: string;
|
|
5
|
+
role: string;
|
|
6
|
+
prior_assignee: string | null;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* Bulk claim escalations for a user.
|
|
4
10
|
* Items already claimed by another active user are skipped.
|
|
@@ -29,6 +35,27 @@ export declare function bulkAssignEscalationsByQuery(query: {
|
|
|
29
35
|
assigned: number;
|
|
30
36
|
ids: string[];
|
|
31
37
|
}>;
|
|
38
|
+
/**
|
|
39
|
+
* Reassign pending rows to a user, INCLUDING rows under a live claim — the
|
|
40
|
+
* management override plain assign is not (claimMany skips live claims). One
|
|
41
|
+
* guarded statement; rows not returned were terminal or missing. Each
|
|
42
|
+
* returned row carries its pre-update assignee for the event.
|
|
43
|
+
*/
|
|
44
|
+
export declare function bulkReassignEscalations(ids: string[], targetUserId: string, durationMinutes?: number): Promise<{
|
|
45
|
+
assigned: number;
|
|
46
|
+
skipped: number;
|
|
47
|
+
changes: AssignmentChange[];
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Return pending claimed rows to the available pool (admin override of
|
|
51
|
+
* someone else's claim — self-return stays the release verb). One guarded
|
|
52
|
+
* statement; unclaimed and terminal rows are skipped.
|
|
53
|
+
*/
|
|
54
|
+
export declare function bulkUnassignEscalations(ids: string[]): Promise<{
|
|
55
|
+
unassigned: number;
|
|
56
|
+
skipped: number;
|
|
57
|
+
changes: AssignmentChange[];
|
|
58
|
+
}>;
|
|
32
59
|
/**
|
|
33
60
|
* Bulk reassign escalations to a different role.
|
|
34
61
|
* Clears assignment on all affected rows.
|
|
@@ -3,11 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.bulkClaimEscalations = bulkClaimEscalations;
|
|
4
4
|
exports.bulkAssignEscalations = bulkAssignEscalations;
|
|
5
5
|
exports.bulkAssignEscalationsByQuery = bulkAssignEscalationsByQuery;
|
|
6
|
+
exports.bulkReassignEscalations = bulkReassignEscalations;
|
|
7
|
+
exports.bulkUnassignEscalations = bulkUnassignEscalations;
|
|
6
8
|
exports.bulkEscalateToRole = bulkEscalateToRole;
|
|
7
9
|
exports.bulkCancelEscalations = bulkCancelEscalations;
|
|
8
10
|
exports.bulkResolveForTriage = bulkResolveForTriage;
|
|
11
|
+
const db_1 = require("../../lib/db");
|
|
9
12
|
const client_1 = require("./client");
|
|
10
13
|
const map_1 = require("./map");
|
|
14
|
+
const sql_1 = require("./sql");
|
|
11
15
|
/**
|
|
12
16
|
* Bulk claim escalations for a user.
|
|
13
17
|
* Items already claimed by another active user are skipped.
|
|
@@ -49,6 +53,41 @@ async function bulkAssignEscalationsByQuery(query, targetUserId, durationMinutes
|
|
|
49
53
|
});
|
|
50
54
|
return { assigned: claimed, ids: entries.map((e) => e.id) };
|
|
51
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Reassign pending rows to a user, INCLUDING rows under a live claim — the
|
|
58
|
+
* management override plain assign is not (claimMany skips live claims). One
|
|
59
|
+
* guarded statement; rows not returned were terminal or missing. Each
|
|
60
|
+
* returned row carries its pre-update assignee for the event.
|
|
61
|
+
*/
|
|
62
|
+
async function bulkReassignEscalations(ids, targetUserId, durationMinutes = 30) {
|
|
63
|
+
if (ids.length === 0)
|
|
64
|
+
return { assigned: 0, skipped: 0, changes: [] };
|
|
65
|
+
await (0, client_1.ensureEscalationCompatView)();
|
|
66
|
+
const { rows } = await (0, db_1.getPool)().query(sql_1.BULK_REASSIGN, [ids, targetUserId, durationMinutes]);
|
|
67
|
+
const changes = rows.map((r) => ({
|
|
68
|
+
id: r.id,
|
|
69
|
+
role: r.role,
|
|
70
|
+
prior_assignee: r.prior_assignee ?? null,
|
|
71
|
+
}));
|
|
72
|
+
return { assigned: rows.length, skipped: ids.length - rows.length, changes };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Return pending claimed rows to the available pool (admin override of
|
|
76
|
+
* someone else's claim — self-return stays the release verb). One guarded
|
|
77
|
+
* statement; unclaimed and terminal rows are skipped.
|
|
78
|
+
*/
|
|
79
|
+
async function bulkUnassignEscalations(ids) {
|
|
80
|
+
if (ids.length === 0)
|
|
81
|
+
return { unassigned: 0, skipped: 0, changes: [] };
|
|
82
|
+
await (0, client_1.ensureEscalationCompatView)();
|
|
83
|
+
const { rows } = await (0, db_1.getPool)().query(sql_1.BULK_UNASSIGN, [ids]);
|
|
84
|
+
const changes = rows.map((r) => ({
|
|
85
|
+
id: r.id,
|
|
86
|
+
role: r.role,
|
|
87
|
+
prior_assignee: r.prior_assignee ?? null,
|
|
88
|
+
}));
|
|
89
|
+
return { unassigned: rows.length, skipped: ids.length - rows.length, changes };
|
|
90
|
+
}
|
|
52
91
|
/**
|
|
53
92
|
* Bulk reassign escalations to a different role.
|
|
54
93
|
* Clears assignment on all affected rows.
|
|
@@ -8,6 +8,23 @@
|
|
|
8
8
|
* table. Clears both `assigned_until` and `claim_expires_at`.
|
|
9
9
|
*/
|
|
10
10
|
export declare const RELEASE_EXPIRED_CLAIMS = "UPDATE public.hmsh_escalations\nSET assigned_to = NULL,\n assigned_until = NULL,\n claimed_at = NULL,\n claim_expires_at = NULL,\n updated_at = NOW()\nWHERE status = 'pending'\n AND assigned_to IS NOT NULL\n AND assigned_until <= NOW()";
|
|
11
|
+
/**
|
|
12
|
+
* Reassign: hand pending rows to a user, INCLUDING rows under a live claim —
|
|
13
|
+
* the management override that plain assign (claimMany, which skips live
|
|
14
|
+
* claims) deliberately is not. One statement: the CTE reads each row's
|
|
15
|
+
* pre-update assignee (CTEs share one snapshot), so callers get
|
|
16
|
+
* prior_assignee for the event with no read-then-write window. An in-flight
|
|
17
|
+
* resolve by the prior assignee fails its claim assertion once assigned_to
|
|
18
|
+
* changes.
|
|
19
|
+
*/
|
|
20
|
+
export declare const BULK_REASSIGN = "WITH prior AS (\n SELECT id, assigned_to FROM public.hmsh_escalations WHERE id = ANY($1::uuid[])\n)\nUPDATE public.hmsh_escalations e\nSET assigned_to = $2,\n assigned_until = NOW() + ($3::int * interval '1 minute'),\n claimed_at = NOW(),\n updated_at = NOW()\nFROM prior\nWHERE e.id = prior.id\n AND e.status = 'pending'\nRETURNING e.*, prior.assigned_to AS prior_assignee";
|
|
21
|
+
/**
|
|
22
|
+
* Unassign: return pending claimed rows to the available pool (an admin
|
|
23
|
+
* override of someone else's claim — self-return stays the release verb).
|
|
24
|
+
* Clears the same field set as RELEASE_EXPIRED_CLAIMS, without the expiry
|
|
25
|
+
* predicate.
|
|
26
|
+
*/
|
|
27
|
+
export declare const BULK_UNASSIGN = "WITH prior AS (\n SELECT id, assigned_to FROM public.hmsh_escalations WHERE id = ANY($1::uuid[])\n)\nUPDATE public.hmsh_escalations e\nSET assigned_to = NULL,\n assigned_until = NULL,\n claimed_at = NULL,\n claim_expires_at = NULL,\n updated_at = NOW()\nFROM prior\nWHERE e.id = prior.id\n AND e.status = 'pending'\n AND e.assigned_to IS NOT NULL\nRETURNING e.*, prior.assigned_to AS prior_assignee";
|
|
11
28
|
/** Count matching the search WHERE (params $1–$13). */
|
|
12
29
|
export declare const COUNT_SEARCH_ESCALATIONS = "SELECT COUNT(*)::int AS total\n FROM public.lt_escalations\n WHERE ($1::text IS NULL OR status = $1)\n AND ($2::text IS NULL OR role = $2)\n AND (\n ($3::text[] IS NULL AND $10::text[] IS NULL)\n OR ($3::text[] IS NOT NULL AND role = ANY($3))\n OR ($10::text[] IS NOT NULL AND role = ANY($10) AND assigned_to = $11)\n )\n AND ($4::text IS NULL OR type = $4)\n AND ($5::text IS NULL OR subtype = $5)\n AND ($6::int IS NULL OR priority = $6)\n AND ($7::text IS NULL OR assigned_to = $7)\n AND ($8::boolean IS NULL OR available = $8)\n AND ($12::jsonb IS NULL OR metadata @> $12)\n AND ($9::text IS NULL OR origin_id = $9 OR workflow_id = $9\n OR ($13::uuid IS NOT NULL AND id = $13::uuid))";
|
|
13
30
|
/**
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// `hmsh_escalations` here rather than composed from generic SDK calls.
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.STATION_PERIOD_METRICS_SQL = exports.STATION_LIVE_COUNTS_SQL = exports.RESOLVE_BY_METADATA_ATOMIC = exports.COUNT_SEARCH_ESCALATIONS = exports.RELEASE_EXPIRED_CLAIMS = void 0;
|
|
14
|
+
exports.STATION_PERIOD_METRICS_SQL = exports.STATION_LIVE_COUNTS_SQL = exports.RESOLVE_BY_METADATA_ATOMIC = exports.COUNT_SEARCH_ESCALATIONS = exports.BULK_UNASSIGN = exports.BULK_REASSIGN = exports.RELEASE_EXPIRED_CLAIMS = void 0;
|
|
15
15
|
exports.searchEscalationsQuery = searchEscalationsQuery;
|
|
16
16
|
/**
|
|
17
17
|
* Sweep expired claims back to the available pool.
|
|
@@ -32,6 +32,49 @@ SET assigned_to = NULL,
|
|
|
32
32
|
WHERE status = 'pending'
|
|
33
33
|
AND assigned_to IS NOT NULL
|
|
34
34
|
AND assigned_until <= NOW()`;
|
|
35
|
+
/**
|
|
36
|
+
* Reassign: hand pending rows to a user, INCLUDING rows under a live claim —
|
|
37
|
+
* the management override that plain assign (claimMany, which skips live
|
|
38
|
+
* claims) deliberately is not. One statement: the CTE reads each row's
|
|
39
|
+
* pre-update assignee (CTEs share one snapshot), so callers get
|
|
40
|
+
* prior_assignee for the event with no read-then-write window. An in-flight
|
|
41
|
+
* resolve by the prior assignee fails its claim assertion once assigned_to
|
|
42
|
+
* changes.
|
|
43
|
+
*/
|
|
44
|
+
exports.BULK_REASSIGN = `\
|
|
45
|
+
WITH prior AS (
|
|
46
|
+
SELECT id, assigned_to FROM public.hmsh_escalations WHERE id = ANY($1::uuid[])
|
|
47
|
+
)
|
|
48
|
+
UPDATE public.hmsh_escalations e
|
|
49
|
+
SET assigned_to = $2,
|
|
50
|
+
assigned_until = NOW() + ($3::int * interval '1 minute'),
|
|
51
|
+
claimed_at = NOW(),
|
|
52
|
+
updated_at = NOW()
|
|
53
|
+
FROM prior
|
|
54
|
+
WHERE e.id = prior.id
|
|
55
|
+
AND e.status = 'pending'
|
|
56
|
+
RETURNING e.*, prior.assigned_to AS prior_assignee`;
|
|
57
|
+
/**
|
|
58
|
+
* Unassign: return pending claimed rows to the available pool (an admin
|
|
59
|
+
* override of someone else's claim — self-return stays the release verb).
|
|
60
|
+
* Clears the same field set as RELEASE_EXPIRED_CLAIMS, without the expiry
|
|
61
|
+
* predicate.
|
|
62
|
+
*/
|
|
63
|
+
exports.BULK_UNASSIGN = `\
|
|
64
|
+
WITH prior AS (
|
|
65
|
+
SELECT id, assigned_to FROM public.hmsh_escalations WHERE id = ANY($1::uuid[])
|
|
66
|
+
)
|
|
67
|
+
UPDATE public.hmsh_escalations e
|
|
68
|
+
SET assigned_to = NULL,
|
|
69
|
+
assigned_until = NULL,
|
|
70
|
+
claimed_at = NULL,
|
|
71
|
+
claim_expires_at = NULL,
|
|
72
|
+
updated_at = NOW()
|
|
73
|
+
FROM prior
|
|
74
|
+
WHERE e.id = prior.id
|
|
75
|
+
AND e.status = 'pending'
|
|
76
|
+
AND e.assigned_to IS NOT NULL
|
|
77
|
+
RETURNING e.*, prior.assigned_to AS prior_assignee`;
|
|
35
78
|
/**
|
|
36
79
|
* Escalation search by correlation id.
|
|
37
80
|
*
|
|
@@ -5,6 +5,7 @@ exports.validateRequireAll = validateRequireAll;
|
|
|
5
5
|
exports.validateFieldType = validateFieldType;
|
|
6
6
|
exports.validateFieldConstraints = validateFieldConstraints;
|
|
7
7
|
exports.validateField = validateField;
|
|
8
|
+
const x_lt_options_1 = require("./x-lt-options");
|
|
8
9
|
/**
|
|
9
10
|
* Resolve a checklist widget's item definitions from its `x-lt-source`
|
|
10
11
|
* "domain.path" against the escalation context. Missing domain/path or a
|
|
@@ -94,10 +95,11 @@ function validateFieldType(value, fieldSchema) {
|
|
|
94
95
|
function validateFieldConstraints(value, fieldSchema, ctx) {
|
|
95
96
|
if (!fieldSchema)
|
|
96
97
|
return undefined;
|
|
97
|
-
//
|
|
98
|
-
// callers are unconstrained, so the
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
// Option membership — the form's select widget constrains choices; API-first
|
|
99
|
+
// callers are unconstrained, so the effective option list is the contract:
|
|
100
|
+
// the static enum, or the x-lt-options list resolved from context.
|
|
101
|
+
const allowed = (0, x_lt_options_1.resolveFieldOptions)(fieldSchema, ctx);
|
|
102
|
+
if (allowed && allowed.length > 0
|
|
101
103
|
&& value !== undefined && value !== null && value !== ''
|
|
102
104
|
&& !allowed.includes(value)) {
|
|
103
105
|
return `Must be one of: ${allowed.map((v) => String(v)).join(', ')}`;
|
|
@@ -14,5 +14,7 @@ export * from './x-lt-query';
|
|
|
14
14
|
export * from './x-lt-submit-guard';
|
|
15
15
|
export * from './x-lt-show-if';
|
|
16
16
|
export * from './x-lt-require-any';
|
|
17
|
+
export * from './x-lt-require-sum';
|
|
18
|
+
export * from './x-lt-options';
|
|
17
19
|
export * from './field-validator';
|
|
18
20
|
export * from './validate-resolver-payload';
|
|
@@ -30,5 +30,7 @@ __exportStar(require("./x-lt-query"), exports);
|
|
|
30
30
|
__exportStar(require("./x-lt-submit-guard"), exports);
|
|
31
31
|
__exportStar(require("./x-lt-show-if"), exports);
|
|
32
32
|
__exportStar(require("./x-lt-require-any"), exports);
|
|
33
|
+
__exportStar(require("./x-lt-require-sum"), exports);
|
|
34
|
+
__exportStar(require("./x-lt-options"), exports);
|
|
33
35
|
__exportStar(require("./field-validator"), exports);
|
|
34
36
|
__exportStar(require("./validate-resolver-payload"), exports);
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
*
|
|
18
18
|
* Root-level x-lt-require-any groups run after the per-field pass: each group
|
|
19
19
|
* needs a value in at least one visible member (all-hidden groups are waived).
|
|
20
|
+
* x-lt-require-sum groups follow the same visibility rules but read members
|
|
21
|
+
* as numbers: the group's visible members must sum to at least its minimum.
|
|
20
22
|
*
|
|
21
23
|
* The showIf/`resolver.*` domain is always the FLAT form representation, so a
|
|
22
24
|
* condition like `resolver.approved` reads the same on both sides.
|
|
@@ -21,6 +21,8 @@ exports.validateResolverPayload = validateResolverPayload;
|
|
|
21
21
|
*
|
|
22
22
|
* Root-level x-lt-require-any groups run after the per-field pass: each group
|
|
23
23
|
* needs a value in at least one visible member (all-hidden groups are waived).
|
|
24
|
+
* x-lt-require-sum groups follow the same visibility rules but read members
|
|
25
|
+
* as numbers: the group's visible members must sum to at least its minimum.
|
|
24
26
|
*
|
|
25
27
|
* The showIf/`resolver.*` domain is always the FLAT form representation, so a
|
|
26
28
|
* condition like `resolver.approved` reads the same on both sides.
|
|
@@ -29,6 +31,7 @@ const field_validator_1 = require("./field-validator");
|
|
|
29
31
|
const x_lt_show_if_1 = require("./x-lt-show-if");
|
|
30
32
|
const x_lt_bind_1 = require("./x-lt-bind");
|
|
31
33
|
const x_lt_require_any_1 = require("./x-lt-require-any");
|
|
34
|
+
const x_lt_require_sum_1 = require("./x-lt-require-sum");
|
|
32
35
|
/**
|
|
33
36
|
* Validate FLAT form values against the form schema. This is the dashboard's
|
|
34
37
|
* entry point (the values the user edits, keyed by field name).
|
|
@@ -65,6 +68,22 @@ function validateResolverForm(schema, formValues, ctx) {
|
|
|
65
68
|
message: `Enter a value for at least one of: ${titles.join(', ')}`,
|
|
66
69
|
});
|
|
67
70
|
}
|
|
71
|
+
// Require-sum groups: the numeric values of VISIBLE members must total at
|
|
72
|
+
// least the group's minimum. A `0` is a real number here — unlike
|
|
73
|
+
// require-any, defaulted-zero quantities do not satisfy the group.
|
|
74
|
+
for (const group of (0, x_lt_require_sum_1.readRequireSumGroups)(schema)) {
|
|
75
|
+
const visible = group.fields.filter((k) => properties[k] && (0, x_lt_show_if_1.evaluateShowIf)(properties[k]['x-lt-showIf'], liveCtx));
|
|
76
|
+
if (visible.length === 0)
|
|
77
|
+
continue;
|
|
78
|
+
const total = visible.reduce((sum, k) => sum + (0, x_lt_require_sum_1.requireSumContribution)(formValues[k]), 0);
|
|
79
|
+
if (total >= group.minimum)
|
|
80
|
+
continue;
|
|
81
|
+
const titles = visible.map((k) => properties[k].title ?? k);
|
|
82
|
+
errors.push({
|
|
83
|
+
field: visible[0],
|
|
84
|
+
message: `Combined value of ${titles.join(', ')} must be at least ${group.minimum}`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
68
87
|
return errors;
|
|
69
88
|
}
|
|
70
89
|
/**
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x-lt-options — a select's option list resolved from the escalation context.
|
|
3
|
+
* The field-level token names a `"domain.path"`; the value at that path is an
|
|
4
|
+
* array of scalars (strings or numbers) that becomes the field's option list,
|
|
5
|
+
* so one static role form can offer a different legal set per escalation
|
|
6
|
+
* (e.g. `[1..N]` where N rides the envelope).
|
|
7
|
+
*
|
|
8
|
+
* x-lt-options "domain.path" — e.g. "envelope.left_quantity_options"
|
|
9
|
+
*
|
|
10
|
+
* A static `enum` takes precedence when both are present — the same
|
|
11
|
+
* static-over-dynamic rule as x-lt-minimum/x-lt-maximum. A path that resolves
|
|
12
|
+
* to nothing, or to no scalar entries, yields no options: the field renders as
|
|
13
|
+
* a plain input for its type and membership is not enforced. Non-scalar
|
|
14
|
+
* entries in a resolved array are dropped.
|
|
15
|
+
*/
|
|
16
|
+
export declare const X_LT_OPTIONS = "x-lt-options";
|
|
17
|
+
export type OptionValue = string | number;
|
|
18
|
+
/**
|
|
19
|
+
* The field's effective option list: the static `enum` when present, else the
|
|
20
|
+
* scalars at the token's `"domain.path"`. Undefined when neither yields any.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveFieldOptions(fieldSchema: Record<string, unknown> | null | undefined, ctx: Record<string, unknown> | undefined): OptionValue[] | undefined;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* x-lt-options — a select's option list resolved from the escalation context.
|
|
4
|
+
* The field-level token names a `"domain.path"`; the value at that path is an
|
|
5
|
+
* array of scalars (strings or numbers) that becomes the field's option list,
|
|
6
|
+
* so one static role form can offer a different legal set per escalation
|
|
7
|
+
* (e.g. `[1..N]` where N rides the envelope).
|
|
8
|
+
*
|
|
9
|
+
* x-lt-options "domain.path" — e.g. "envelope.left_quantity_options"
|
|
10
|
+
*
|
|
11
|
+
* A static `enum` takes precedence when both are present — the same
|
|
12
|
+
* static-over-dynamic rule as x-lt-minimum/x-lt-maximum. A path that resolves
|
|
13
|
+
* to nothing, or to no scalar entries, yields no options: the field renders as
|
|
14
|
+
* a plain input for its type and membership is not enforced. Non-scalar
|
|
15
|
+
* entries in a resolved array are dropped.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.X_LT_OPTIONS = void 0;
|
|
19
|
+
exports.resolveFieldOptions = resolveFieldOptions;
|
|
20
|
+
exports.X_LT_OPTIONS = 'x-lt-options';
|
|
21
|
+
/**
|
|
22
|
+
* The field's effective option list: the static `enum` when present, else the
|
|
23
|
+
* scalars at the token's `"domain.path"`. Undefined when neither yields any.
|
|
24
|
+
*/
|
|
25
|
+
function resolveFieldOptions(fieldSchema, ctx) {
|
|
26
|
+
if (!fieldSchema)
|
|
27
|
+
return undefined;
|
|
28
|
+
const staticEnum = fieldSchema.enum;
|
|
29
|
+
if (Array.isArray(staticEnum) && staticEnum.length > 0) {
|
|
30
|
+
return staticEnum;
|
|
31
|
+
}
|
|
32
|
+
const sourcePath = fieldSchema[exports.X_LT_OPTIONS];
|
|
33
|
+
if (typeof sourcePath !== 'string' || !ctx)
|
|
34
|
+
return undefined;
|
|
35
|
+
const dot = sourcePath.indexOf('.');
|
|
36
|
+
if (dot === -1)
|
|
37
|
+
return undefined;
|
|
38
|
+
const domainObj = ctx[sourcePath.slice(0, dot)];
|
|
39
|
+
if (!domainObj || typeof domainObj !== 'object')
|
|
40
|
+
return undefined;
|
|
41
|
+
let cur = domainObj;
|
|
42
|
+
for (const p of sourcePath.slice(dot + 1).split('.')) {
|
|
43
|
+
cur = cur[p];
|
|
44
|
+
if (cur === undefined)
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
if (!Array.isArray(cur))
|
|
48
|
+
return undefined;
|
|
49
|
+
const scalars = cur.filter((v) => typeof v === 'string' || (typeof v === 'number' && Number.isFinite(v)));
|
|
50
|
+
return scalars.length > 0 ? scalars : undefined;
|
|
51
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x-lt-require-sum — "these quantities must total at least N" as a
|
|
3
|
+
* root-schema token. Where x-lt-require-any asks that one member carry any
|
|
4
|
+
* answer (so a count defaulting to `0` vacuously satisfies it), require-sum
|
|
5
|
+
* reads the members as numbers and demands their sum reach a minimum. The
|
|
6
|
+
* canonical case: a Left quantity and a Right quantity that both default to
|
|
7
|
+
* `0`, where at least one side must be positive.
|
|
8
|
+
*
|
|
9
|
+
* x-lt-require-sum { fields: string[], minimum?: number }[]
|
|
10
|
+
* — e.g. [{ "fields": ["left_quantity", "right_quantity"] }]
|
|
11
|
+
*
|
|
12
|
+
* `minimum` defaults to 1. Numbers contribute their value and numeric strings
|
|
13
|
+
* coerce (the same reading as dynamic bounds); everything else contributes 0.
|
|
14
|
+
* Visibility rules compose the same way as require-any: a member hidden by
|
|
15
|
+
* its `x-lt-showIf` (or naming no schema property) contributes nothing and is
|
|
16
|
+
* not demanded, and a group whose members are ALL hidden is waived.
|
|
17
|
+
*/
|
|
18
|
+
export declare const X_LT_REQUIRE_SUM = "x-lt-require-sum";
|
|
19
|
+
export interface RequireSumGroup {
|
|
20
|
+
fields: string[];
|
|
21
|
+
minimum: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The schema's require-sum groups. Malformed declarations (non-array token,
|
|
25
|
+
* groups without a fields array, non-string members, non-numeric minimum)
|
|
26
|
+
* read as no groups — a bad token never bricks submission.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readRequireSumGroups(schema: Record<string, unknown> | null | undefined): RequireSumGroup[];
|
|
29
|
+
/** A member's numeric contribution: numbers as-is, numeric strings coerced, all else 0. */
|
|
30
|
+
export declare function requireSumContribution(value: unknown): number;
|