@hotmeshio/long-tail 0.22.0 → 0.22.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/build/api/escalations/accumulate.d.ts +10 -1
- package/build/api/escalations/accumulate.js +121 -34
- package/build/api/escalations/metadata.d.ts +5 -0
- package/build/api/escalations/metadata.js +6 -2
- package/build/api/escalations/resolve-batch.js +18 -11
- package/build/api/roles.js +4 -0
- package/build/api/scan-codes/badge-policy.d.ts +10 -0
- package/build/api/scan-codes/badge-policy.js +72 -0
- package/build/api/scan-codes/choice.js +18 -11
- package/build/api/scan-codes/context.d.ts +45 -1
- package/build/api/scan-codes/context.js +51 -3
- package/build/api/scan-codes/execute.js +73 -35
- package/build/api/scan-codes/grant.d.ts +27 -0
- package/build/api/scan-codes/grant.js +67 -0
- package/build/api/scan-codes/hold.d.ts +10 -0
- package/build/api/scan-codes/hold.js +98 -0
- package/build/api/scan-codes/identity.d.ts +5 -2
- package/build/api/scan-codes/identity.js +26 -8
- package/build/api/scan-codes/subject.d.ts +15 -0
- package/build/api/scan-codes/subject.js +68 -0
- package/build/api/scan-codes/verb-accumulate.d.ts +24 -0
- package/build/api/scan-codes/verb-accumulate.js +147 -0
- package/build/api/scan-codes/verb-fill.d.ts +6 -0
- package/build/api/scan-codes/verb-fill.js +152 -0
- package/build/api/scan-codes/verbs-subject.d.ts +14 -0
- package/build/api/scan-codes/verbs-subject.js +270 -0
- package/build/api/scan-codes/verbs.d.ts +7 -22
- package/build/api/scan-codes/verbs.js +35 -114
- package/build/api/workflows/invocation.d.ts +8 -4
- package/build/api/workflows/invocation.js +26 -9
- package/build/index.d.ts +1 -0
- package/build/index.js +8 -2
- package/build/lib/cli/commands/workflows.js +9 -4
- package/build/lib/db/schemas/037_scan_gtin_and_subject_grants.sql +27 -0
- package/build/routes/escalations/accumulate.js +13 -6
- package/build/routes/escalations/acting.d.ts +5 -0
- package/build/routes/escalations/acting.js +8 -1
- package/build/routes/scan-codes.js +3 -0
- package/build/sdk/index.d.ts +3 -0
- package/build/services/escalation/crud.d.ts +2 -2
- package/build/services/escalation/crud.js +4 -2
- package/build/services/escalation/facet-sql.js +8 -0
- package/build/services/escalation/sql.d.ts +4 -2
- package/build/services/escalation/sql.js +10 -2
- package/build/services/export/index.d.ts +8 -3
- package/build/services/export/index.js +15 -21
- package/build/services/iam/acting-identity.d.ts +29 -4
- package/build/services/iam/acting-identity.js +60 -17
- package/build/services/iam/ephemeral.d.ts +21 -0
- package/build/services/iam/ephemeral.js +32 -1
- package/build/services/iam/sql.d.ts +10 -0
- package/build/services/iam/sql.js +32 -3
- package/build/services/pipelines/events.js +2 -1
- package/build/services/pipelines/execution-builder.js +2 -1
- package/build/services/pipelines/queries.js +2 -1
- package/build/services/role/badge-grant.d.ts +5 -0
- package/build/services/role/badge-grant.js +36 -0
- package/build/services/role/seed.js +5 -0
- package/build/services/role/types.d.ts +14 -0
- package/build/services/role/types.js +5 -0
- package/build/services/scan-code/index.d.ts +3 -2
- package/build/services/scan-code/index.js +7 -1
- package/build/services/scan-code/parse.d.ts +23 -20
- package/build/services/scan-code/parse.js +45 -90
- package/build/services/scan-code/read.js +1 -0
- package/build/services/scan-code/sql.d.ts +3 -3
- package/build/services/scan-code/sql.js +11 -8
- package/build/services/scan-code/validate-subject.d.ts +7 -0
- package/build/services/scan-code/validate-subject.js +158 -0
- package/build/services/scan-code/validate.d.ts +7 -0
- package/build/services/scan-code/validate.js +111 -16
- package/build/services/scan-code/write.d.ts +1 -0
- package/build/services/scan-code/write.js +9 -3
- package/build/services/workflow-state.d.ts +21 -0
- package/build/services/workflow-state.js +39 -0
- package/build/shared/form-validation/field-validator.js +4 -0
- package/build/shared/form-validation/index.d.ts +1 -0
- package/build/shared/form-validation/index.js +1 -0
- package/build/shared/form-validation/x-lt-scan.d.ts +52 -0
- package/build/shared/form-validation/x-lt-scan.js +166 -0
- package/build/shared/scan-code/gtin.d.ts +5 -0
- package/build/shared/scan-code/gtin.js +25 -0
- package/build/shared/scan-code/index.d.ts +2 -0
- package/build/shared/scan-code/index.js +10 -0
- package/build/shared/scan-code/parse.d.ts +46 -0
- package/build/shared/scan-code/parse.js +133 -0
- package/build/shared/workflow-state.d.ts +17 -0
- package/build/shared/workflow-state.js +29 -0
- package/build/system/mcp-servers/admin/escalations.js +8 -4
- package/build/system/mcp-servers/admin/scan-codes.js +10 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +792 -23
- package/build/system/mcp-servers/admin/schemas.js +61 -4
- package/build/system/mcp-servers/admin/workflows.js +20 -31
- package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
- package/build/system/seed/tool-manifests-admin.d.ts +94 -0
- package/build/system/seed/tool-manifests-admin.js +3 -3
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +2 -0
- package/build/types/escalation.js +3 -1
- package/build/types/facets.d.ts +14 -0
- package/build/types/index.d.ts +3 -3
- package/build/types/index.js +8 -1
- package/build/types/scan-code/constants.d.ts +182 -0
- package/build/types/{scan-code.js → scan-code/constants.js} +62 -12
- package/build/types/scan-code/index.d.ts +3 -0
- package/build/types/scan-code/index.js +17 -0
- package/build/types/scan-code/response.d.ts +140 -0
- package/build/types/scan-code/response.js +2 -0
- package/build/types/scan-code/rule.d.ts +199 -0
- package/build/types/scan-code/rule.js +2 -0
- package/build/types/startup.d.ts +3 -1
- package/dashboard/dist/assets/{AdminDashboard-Covdam48.js → AdminDashboard-DBW12qQt.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-Covdam48.js.map → AdminDashboard-DBW12qQt.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-CE1k6J5r.js → AgentConfigPage-CmHv8U9M.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-CE1k6J5r.js.map → AgentConfigPage-CmHv8U9M.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CWJZIZP1.js → AgentDetailPage-D1scIbz-.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CWJZIZP1.js.map → AgentDetailPage-D1scIbz-.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage---Dg5ufF.js → AgentsPage-BA_ai9HJ.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage---Dg5ufF.js.map → AgentsPage-BA_ai9HJ.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-C2_5aEFW.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-C2_5aEFW.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-D3drO3-T.js → BotPicker-BZo4Kp4a.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-D3drO3-T.js.map → BotPicker-BZo4Kp4a.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-BOAWsViq.js → BulkAssignModal-BFhyxY2T.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-BOAWsViq.js.map → BulkAssignModal-BFhyxY2T.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CvOX6vAc.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-RGgD3YZO.js.map → CapabilitiesPage-CvOX6vAc.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-DNkZn87n.js → CollapsibleSection-GCJsV9Oq.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-DNkZn87n.js.map → CollapsibleSection-GCJsV9Oq.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-BqzOwhPr.js → ConfirmDeleteModal-CAgYLcef.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-BqzOwhPr.js.map → ConfirmDeleteModal-CAgYLcef.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-Dik2z0M_.js +2 -0
- package/dashboard/dist/assets/{CountdownTimer-BaexQMK6.js.map → CountdownTimer-Dik2z0M_.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-D7abp0aS.js → CredentialsPage-twd2xCOW.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-D7abp0aS.js.map → CredentialsPage-twd2xCOW.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DZiWmTwJ.js → CronLabel-DdnIuudX.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DZiWmTwJ.js.map → CronLabel-DdnIuudX.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-f1o-GLM8.js → DropZone-B1Tdfddc.js} +2 -2
- package/dashboard/dist/assets/{DropZone-f1o-GLM8.js.map → DropZone-B1Tdfddc.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-BdGO_w4v.js → ElapsedCell-DCctVv5R.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-BdGO_w4v.js.map → ElapsedCell-DCctVv5R.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-DIDcF5Yu.js → EntityTimelinePanel-CMnskyWv.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-DIDcF5Yu.js.map → EntityTimelinePanel-CMnskyWv.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-C28rn9XC.js → EscalationListSchemaPage-VfCn6WDb.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-C28rn9XC.js.map → EscalationListSchemaPage-VfCn6WDb.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-CkBnkpDJ.js → EscalationListView-CGQZxcC-.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-CkBnkpDJ.js.map → EscalationListView-CGQZxcC-.js.map} +1 -1
- package/dashboard/dist/assets/EscalationSchemaPage-BX0tx-PM.js +9 -0
- package/dashboard/dist/assets/EscalationSchemaPage-BX0tx-PM.js.map +1 -0
- package/dashboard/dist/assets/EscalationTimeline-DKoSM56J.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-DKoSM56J.js.map +1 -0
- package/dashboard/dist/assets/{EscalationTitleSelect-CzKfavri.js → EscalationTitleSelect-DWGLBOmS.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-CzKfavri.js.map → EscalationTitleSelect-DWGLBOmS.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-Tdu3Yx2c.js → EscalationsOverview-C2XoguaA.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-Tdu3Yx2c.js.map → EscalationsOverview-C2XoguaA.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DiIxOJwO.js → EventTable-CBUWq7--.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DiIxOJwO.js.map → EventTable-CBUWq7--.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-CvMBCVIo.js → FilterBar-8IdbleZ9.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-CvMBCVIo.js.map → FilterBar-8IdbleZ9.js.map} +1 -1
- package/dashboard/dist/assets/GrantScopeField-BzWGzBfA.js +2 -0
- package/dashboard/dist/assets/GrantScopeField-BzWGzBfA.js.map +1 -0
- package/dashboard/dist/assets/{GraphInvokePage-DO-yyhi6.js → GraphInvokePage-CUvoPzsW.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DO-yyhi6.js.map → GraphInvokePage-CUvoPzsW.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-DSS3eHR2.js → HomePage-BP7v9GLJ.js} +2 -2
- package/dashboard/dist/assets/{HomePage-DSS3eHR2.js.map → HomePage-BP7v9GLJ.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-C3-Tqqub.js → ListToolbar-Cnacuwoy.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-C3-Tqqub.js.map → ListToolbar-Cnacuwoy.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DEJmsdVi.js → McpOverview-C2JoNoDA.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DEJmsdVi.js.map → McpOverview-C2JoNoDA.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryDetailPage-C_nih0w-.js +5 -0
- package/dashboard/dist/assets/McpQueryDetailPage-C_nih0w-.js.map +1 -0
- package/dashboard/dist/assets/{McpQueryPage-BBcG_UuU.js → McpQueryPage-U_wNXow2.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-BBcG_UuU.js.map → McpQueryPage-U_wNXow2.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-C6xw0kBg.js → McpRunDetailPage-DtKoJq6J.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-C6xw0kBg.js.map → McpRunDetailPage-DtKoJq6J.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-CRQqrF4Q.js → McpRunsPage-CnYtfGhf.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-CRQqrF4Q.js.map → McpRunsPage-CnYtfGhf.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-DADRJOUl.js → NamespacePill-DwM5pNA4.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-DADRJOUl.js.map → NamespacePill-DwM5pNA4.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-Dlfwzf-0.js → OperationsPage-C7hupIer.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-Dlfwzf-0.js.map → OperationsPage-C7hupIer.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-DoiDGZ9R.js → OperatorDashboard-fVuLn2D5.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-DoiDGZ9R.js.map → OperatorDashboard-fVuLn2D5.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Csq434-v.js → PageHeader-CMd3f4bz.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Csq434-v.js.map → PageHeader-CMd3f4bz.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-CSnk1p5A.js → PageHeaderWithStats-DHj8Mqox.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-CSnk1p5A.js.map → PageHeaderWithStats-DHj8Mqox.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-BzbA4Prr.js → PersonaDetailPage-C-4o8lPw.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-BzbA4Prr.js.map → PersonaDetailPage-C-4o8lPw.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-B36yn4hU.js → PersonasPage-BL1FwLmv.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-B36yn4hU.js.map → PersonasPage-BL1FwLmv.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-BkD4YfDf.js → PortalPage-tJG5sgb1.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-BkD4YfDf.js.map → PortalPage-tJG5sgb1.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BT0eiBWY.js → ProcessDetailPage-Dz_jY4Yt.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BT0eiBWY.js.map → ProcessDetailPage-Dz_jY4Yt.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-BEqeeNae.js → ProcessesListPage-Cbn9cter.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-BEqeeNae.js.map → ProcessesListPage-Cbn9cter.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-Bk8iXQ6-.js +8 -0
- package/dashboard/dist/assets/ResolverForm-Bk8iXQ6-.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-owPi6gI9.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-owPi6gI9.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-BafrASDX.js → RolePill-Di2CAHuD.js} +2 -2
- package/dashboard/dist/assets/{RolePill-BafrASDX.js.map → RolePill-Di2CAHuD.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-80quJU5-.js → RolesPage-NwmMvZFa.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-80quJU5-.js.map → RolesPage-NwmMvZFa.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-BoePhWVD.js → RunAsSelector-tgEooTyU.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-BoePhWVD.js.map → RunAsSelector-tgEooTyU.js.map} +1 -1
- package/dashboard/dist/assets/ScanCodesPage-CUv_8ic6.js +2 -0
- package/dashboard/dist/assets/ScanCodesPage-CUv_8ic6.js.map +1 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-YHqbu7oK.js +2 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-YHqbu7oK.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-B275l6r_.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-B275l6r_.js.map +1 -0
- package/dashboard/dist/assets/{ScopeBadge-b6MIBiYD.js → ScopeBadge-CSItPVOH.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-b6MIBiYD.js.map → ScopeBadge-CSItPVOH.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-9ITrei_d.js → StickyPagination-CsTI_gvJ.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-9ITrei_d.js.map → StickyPagination-CsTI_gvJ.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-BkYvEHFY.js → StreamMessageDetail-auRlvjTh.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-BkYvEHFY.js.map → StreamMessageDetail-auRlvjTh.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-B1rotFix.js → SwimlaneTimeline-BLoVHYAd.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-B1rotFix.js.map → SwimlaneTimeline-BLoVHYAd.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-ZrIIrEUP.js → TagInput-CAgdLN_b.js} +2 -2
- package/dashboard/dist/assets/{TagInput-ZrIIrEUP.js.map → TagInput-CAgdLN_b.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-zhn_U_eC.js → TaskDetailPage-BPsZ1bK_.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-zhn_U_eC.js.map → TaskDetailPage-BPsZ1bK_.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-DkQ1uc6y.js → TaskQueuePill-h0oorVMe.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-DkQ1uc6y.js.map → TaskQueuePill-h0oorVMe.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CNbNeagx.js → TasksListPage-BNGM74yT.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CNbNeagx.js.map → TasksListPage-BNGM74yT.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-0YVMBwls.js → TimeAgo-BnAHXGK7.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-0YVMBwls.js.map → TimeAgo-BnAHXGK7.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-DB7r3np8.js → TimestampCell-J4yae6mc.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-DB7r3np8.js.map → TimestampCell-J4yae6mc.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-Baxm02L6.js → ToolPill-CQCsVdzD.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-Baxm02L6.js.map → ToolPill-CQCsVdzD.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-BLfA02wv.js → ToolTestPanel-BdzzgXDu.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-BLfA02wv.js.map → ToolTestPanel-BdzzgXDu.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-eAqPKShq.js → TopicDetailPage-DJKg8lb7.js} +4 -4
- package/dashboard/dist/assets/{TopicDetailPage-eAqPKShq.js.map → TopicDetailPage-DJKg8lb7.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-BNNWD-zl.js → TopicsPage-DQV0WxG6.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-BNNWD-zl.js.map → TopicsPage-DQV0WxG6.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-Pw46tO_k.js → UserName-Ct09nGh5.js} +2 -2
- package/dashboard/dist/assets/{UserName-Pw46tO_k.js.map → UserName-Ct09nGh5.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-DvA51lT3.js → WorkflowExecutionPage-B5WJOsee.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-DvA51lT3.js.map → WorkflowExecutionPage-B5WJOsee.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-ZepbO_ny.js → WorkflowPill-Dg7BDTyM.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-ZepbO_ny.js.map → WorkflowPill-Dg7BDTyM.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DFDTwnhn.js → WorkflowsDashboard-Hc87TRgD.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DFDTwnhn.js.map → WorkflowsDashboard-Hc87TRgD.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-5i2Tcy-p.js → WorkflowsOverview-CJQbyOj-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-5i2Tcy-p.js.map → WorkflowsOverview-CJQbyOj-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-p4VEYZS0.js → YamlWorkflowDetailPage-BMeED677.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-p4VEYZS0.js.map → YamlWorkflowDetailPage-BMeED677.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-Cq-hMVxl.js → YamlWorkflowsPage-BMMg0Id6.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-Cq-hMVxl.js.map → YamlWorkflowsPage-BMMg0Id6.js.map} +1 -1
- package/dashboard/dist/assets/{agents-EyBPJMYa.js → agents-CdFkgFvg.js} +2 -2
- package/dashboard/dist/assets/{agents-EyBPJMYa.js.map → agents-CdFkgFvg.js.map} +1 -1
- package/dashboard/dist/assets/{bots-DX6jjqtF.js → bots-Mj3LHWWg.js} +2 -2
- package/dashboard/dist/assets/{bots-DX6jjqtF.js.map → bots-Mj3LHWWg.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-ZdLv9xBQ.js → capabilities-Dw1ObK2-.js} +2 -2
- package/dashboard/dist/assets/{capabilities-ZdLv9xBQ.js.map → capabilities-Dw1ObK2-.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CpvZaJuw.js → controlplane-DcNE1APv.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CpvZaJuw.js.map → controlplane-DcNE1APv.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Mvsze5eV.js → escalation-columns-D364Trpy.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Mvsze5eV.js.map → escalation-columns-D364Trpy.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cn8uJsd7.js → index-B3veJ698.js} +2 -2
- package/dashboard/dist/assets/{index-Cn8uJsd7.js.map → index-B3veJ698.js.map} +1 -1
- package/dashboard/dist/assets/index-BQeHJHYN.js +67 -0
- package/dashboard/dist/assets/index-BQeHJHYN.js.map +1 -0
- package/dashboard/dist/assets/{index-D-Xs4rAW.js → index-BRGTmoYY.js} +2 -2
- package/dashboard/dist/assets/{index-D-Xs4rAW.js.map → index-BRGTmoYY.js.map} +1 -1
- package/dashboard/dist/assets/{index-DkrBFFSO.js → index-Bd6-KmBE.js} +3 -3
- package/dashboard/dist/assets/{index-DkrBFFSO.js.map → index-Bd6-KmBE.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bhb89oHH.js → index-BiVce3n0.js} +2 -2
- package/dashboard/dist/assets/{index-Bhb89oHH.js.map → index-BiVce3n0.js.map} +1 -1
- package/dashboard/dist/assets/{index-z5Hpeidu.js → index-BmNAVd4s.js} +2 -2
- package/dashboard/dist/assets/{index-z5Hpeidu.js.map → index-BmNAVd4s.js.map} +1 -1
- package/dashboard/dist/assets/{index-BbCjGO3M.js → index-Bq5XNEzD.js} +2 -2
- package/dashboard/dist/assets/{index-BbCjGO3M.js.map → index-Bq5XNEzD.js.map} +1 -1
- package/dashboard/dist/assets/{index-DGmzBY9D.js → index-DPStdq4T.js} +2 -2
- package/dashboard/dist/assets/{index-DGmzBY9D.js.map → index-DPStdq4T.js.map} +1 -1
- package/dashboard/dist/assets/index-DcppjzP5.css +1 -0
- package/dashboard/dist/assets/{index-PfSRKerc.js → index-DkcI4V_H.js} +2 -2
- package/dashboard/dist/assets/{index-PfSRKerc.js.map → index-DkcI4V_H.js.map} +1 -1
- package/dashboard/dist/assets/{index-oFKUFGQL.js → index-Dyotfa_k.js} +2 -2
- package/dashboard/dist/assets/{index-oFKUFGQL.js.map → index-Dyotfa_k.js.map} +1 -1
- package/dashboard/dist/assets/{index-Eo-l3Lqo.js → index-MDD4JYtu.js} +2 -2
- package/dashboard/dist/assets/{index-Eo-l3Lqo.js.map → index-MDD4JYtu.js.map} +1 -1
- package/dashboard/dist/assets/index-WSm8bgE7.js +3 -0
- package/dashboard/dist/assets/index-WSm8bgE7.js.map +1 -0
- package/dashboard/dist/assets/{index-DZhtP2Ok.js → index-eDm6cz0F.js} +2 -2
- package/dashboard/dist/assets/{index-DZhtP2Ok.js.map → index-eDm6cz0F.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-CgloEkaf.js → knowledge-Bafewjxk.js} +2 -2
- package/dashboard/dist/assets/{knowledge-CgloEkaf.js.map → knowledge-Bafewjxk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-o-sGX2ST.js → mcp-query-BzTtIG90.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-o-sGX2ST.js.map → mcp-query-BzTtIG90.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bix7QYO7.js → mcp-vLIutbnc.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bix7QYO7.js.map → mcp-vLIutbnc.js.map} +1 -1
- package/dashboard/dist/assets/{personas-30azkJ_s.js → personas-WD40EDS_.js} +2 -2
- package/dashboard/dist/assets/{personas-30azkJ_s.js.map → personas-WD40EDS_.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Bfk2GFK7.js → pipelines-DFwULWs3.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Bfk2GFK7.js.map → pipelines-DFwULWs3.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CpdopewW.js → tasks-La_-WAUn.js} +2 -2
- package/dashboard/dist/assets/{tasks-CpdopewW.js.map → tasks-La_-WAUn.js.map} +1 -1
- package/dashboard/dist/assets/{topics--bvCV9Yp.js → topics-CzYMlvqm.js} +2 -2
- package/dashboard/dist/assets/{topics--bvCV9Yp.js.map → topics-CzYMlvqm.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-Da0lPmj3.js → useDebouncedValue-C0FQyANW.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-Da0lPmj3.js.map → useDebouncedValue-C0FQyANW.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DD_Esl6n.js → useNamespace-WW_XjAb3.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DD_Esl6n.js.map → useNamespace-WW_XjAb3.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-AeAhZJJk.js → useYamlActivityEvents-B3YxPeFt.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-AeAhZJJk.js.map → useYamlActivityEvents-B3YxPeFt.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-B7OcUM6b.js → vendor-icons-CeVtUKyP.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-B7OcUM6b.js.map → vendor-icons-CeVtUKyP.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BHAOOGvn.js → yaml-workflows-COHOjdhF.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BHAOOGvn.js.map → yaml-workflows-COHOjdhF.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/accumulator.md +37 -1
- package/docs/api/mcp/admin.md +3 -2
- package/docs/api/sdk/escalations.md +6 -0
- package/docs/api/sdk/exports.md +1 -1
- package/docs/api/sdk/workflows.md +23 -4
- package/docs/cli.md +1 -1
- package/docs/dashboard.md +2 -2
- package/docs/faceted-routing.md +2 -0
- package/docs/hitl/x-lt-scan.md +51 -0
- package/docs/hitl/x-lt-widget.md +5 -0
- package/docs/hitl-guide.md +2 -0
- package/docs/scan-codes.md +252 -19
- package/package.json +1 -1
- package/build/types/scan-code.d.ts +0 -308
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-CpbC8oTN.js.map +0 -1
- package/dashboard/dist/assets/CapabilitiesPage-RGgD3YZO.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-BaexQMK6.js +0 -2
- package/dashboard/dist/assets/EscalationSchemaPage-W5r0A1kj.js +0 -9
- package/dashboard/dist/assets/EscalationSchemaPage-W5r0A1kj.js.map +0 -1
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js +0 -2
- package/dashboard/dist/assets/EscalationTimeline-DKyTz6sM.js.map +0 -1
- package/dashboard/dist/assets/McpQueryDetailPage-DYJr16l7.js +0 -5
- package/dashboard/dist/assets/McpQueryDetailPage-DYJr16l7.js.map +0 -1
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js +0 -7
- package/dashboard/dist/assets/ResolverForm-BwgjIX97.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-BFuLNJXa.js.map +0 -1
- package/dashboard/dist/assets/ScanCodesPage-Cu1bKEix.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-Cu1bKEix.js.map +0 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-D9AbS6UY.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-gcZGefvT.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-gcZGefvT.js.map +0 -1
- package/dashboard/dist/assets/index-B_GT23TE.js +0 -3
- package/dashboard/dist/assets/index-B_GT23TE.js.map +0 -1
- package/dashboard/dist/assets/index-CgUcYveM.js +0 -67
- package/dashboard/dist/assets/index-CgUcYveM.js.map +0 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +0 -1
|
@@ -13,6 +13,11 @@ const types_1 = require("../../types");
|
|
|
13
13
|
const sql_1 = require("./sql");
|
|
14
14
|
const validate_1 = require("./validate");
|
|
15
15
|
const read_1 = require("./read");
|
|
16
|
+
/** Field validation, then the cross-scheme check against what is stored. */
|
|
17
|
+
async function assertSchemeInput(input) {
|
|
18
|
+
(0, validate_1.assertValidScheme)(input);
|
|
19
|
+
(0, validate_1.assertSchemesCoexist)(input, await (0, read_1.listScanSchemes)());
|
|
20
|
+
}
|
|
16
21
|
function schemeParams(input) {
|
|
17
22
|
return [
|
|
18
23
|
input.version,
|
|
@@ -26,6 +31,7 @@ function schemeParams(input) {
|
|
|
26
31
|
input.grant_ttl_seconds ?? null,
|
|
27
32
|
input.grant_max_uses ?? 0,
|
|
28
33
|
input.enabled ?? true,
|
|
34
|
+
input.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION,
|
|
29
35
|
];
|
|
30
36
|
}
|
|
31
37
|
function ruleParams(input) {
|
|
@@ -49,7 +55,7 @@ async function assertStepsForScheme(input) {
|
|
|
49
55
|
(0, validate_1.assertValidSteps)(input.steps);
|
|
50
56
|
}
|
|
51
57
|
async function upsertScanScheme(input) {
|
|
52
|
-
|
|
58
|
+
await assertSchemeInput(input);
|
|
53
59
|
const { rows } = await (0, db_1.getPool)().query(sql_1.UPSERT_SCHEME, schemeParams(input));
|
|
54
60
|
return rows[0];
|
|
55
61
|
}
|
|
@@ -80,7 +86,7 @@ async function deleteScanRule(schemeVersion, category) {
|
|
|
80
86
|
}
|
|
81
87
|
/** Insert-if-absent seeding — DB is the source of truth, never overwrite. */
|
|
82
88
|
async function seedScanScheme(input) {
|
|
83
|
-
|
|
89
|
+
await assertSchemeInput(input);
|
|
84
90
|
const { rowCount } = await (0, db_1.getPool)().query(sql_1.SEED_SCHEME, schemeParams(input));
|
|
85
91
|
return (rowCount ?? 0) > 0;
|
|
86
92
|
}
|
|
@@ -95,7 +101,7 @@ async function seedScanRule(input) {
|
|
|
95
101
|
* declaration a zero-row no-op.
|
|
96
102
|
*/
|
|
97
103
|
async function applyScanScheme(input) {
|
|
98
|
-
|
|
104
|
+
await assertSchemeInput(input);
|
|
99
105
|
const { rowCount } = await (0, db_1.getPool)().query(sql_1.APPLY_SCHEME, schemeParams(input));
|
|
100
106
|
return (rowCount ?? 0) > 0 ? 'applied' : 'unchanged';
|
|
101
107
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { WORKFLOW_STATES, isTerminated, workflowStateFromStatus, type WorkflowState } from '../shared/workflow-state';
|
|
2
|
+
export { WORKFLOW_STATES, isTerminated, workflowStateFromStatus, type WorkflowState };
|
|
3
|
+
export interface WorkflowStateReading {
|
|
4
|
+
/** HotMesh job status: above 0 running, 0 closed, below 0 terminated. */
|
|
5
|
+
status: number;
|
|
6
|
+
state: WorkflowState;
|
|
7
|
+
terminated: boolean;
|
|
8
|
+
/** The failure message, when the run closed with an error. */
|
|
9
|
+
error?: string;
|
|
10
|
+
}
|
|
11
|
+
interface StatusHandle {
|
|
12
|
+
status(): Promise<number>;
|
|
13
|
+
state(metadata?: boolean): Promise<Record<string, any> | undefined>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A workflow's state from its handle. A running run needs only the status.
|
|
17
|
+
* A closed run can still have failed, so its outcome is read for `$error`.
|
|
18
|
+
* A terminated run keeps `$error` when HotMesh still holds it; a failed read
|
|
19
|
+
* of a terminated run carries no reason and is dropped.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readWorkflowState(handle: StatusHandle): Promise<WorkflowStateReading>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.workflowStateFromStatus = exports.isTerminated = exports.WORKFLOW_STATES = void 0;
|
|
4
|
+
exports.readWorkflowState = readWorkflowState;
|
|
5
|
+
const workflow_state_1 = require("../shared/workflow-state");
|
|
6
|
+
Object.defineProperty(exports, "WORKFLOW_STATES", { enumerable: true, get: function () { return workflow_state_1.WORKFLOW_STATES; } });
|
|
7
|
+
Object.defineProperty(exports, "isTerminated", { enumerable: true, get: function () { return workflow_state_1.isTerminated; } });
|
|
8
|
+
Object.defineProperty(exports, "workflowStateFromStatus", { enumerable: true, get: function () { return workflow_state_1.workflowStateFromStatus; } });
|
|
9
|
+
function errorMessage(error) {
|
|
10
|
+
if (error && typeof error === 'object' && 'message' in error)
|
|
11
|
+
return String(error.message);
|
|
12
|
+
return typeof error === 'string' ? error : JSON.stringify(error);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A workflow's state from its handle. A running run needs only the status.
|
|
16
|
+
* A closed run can still have failed, so its outcome is read for `$error`.
|
|
17
|
+
* A terminated run keeps `$error` when HotMesh still holds it; a failed read
|
|
18
|
+
* of a terminated run carries no reason and is dropped.
|
|
19
|
+
*/
|
|
20
|
+
async function readWorkflowState(handle) {
|
|
21
|
+
const status = await handle.status();
|
|
22
|
+
if (status > 0)
|
|
23
|
+
return { status, state: workflow_state_1.WORKFLOW_STATES.RUNNING, terminated: false };
|
|
24
|
+
const terminated = (0, workflow_state_1.isTerminated)(status);
|
|
25
|
+
let failure;
|
|
26
|
+
try {
|
|
27
|
+
failure = (await handle.state())?.$error;
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (!terminated)
|
|
31
|
+
failure = err;
|
|
32
|
+
}
|
|
33
|
+
const error = failure === undefined || failure === null ? undefined : errorMessage(failure);
|
|
34
|
+
if (terminated)
|
|
35
|
+
return { status, state: workflow_state_1.WORKFLOW_STATES.FAILED, terminated, ...(error ? { error } : {}) };
|
|
36
|
+
if (error)
|
|
37
|
+
return { status, state: workflow_state_1.WORKFLOW_STATES.FAILED, terminated, error };
|
|
38
|
+
return { status, state: workflow_state_1.WORKFLOW_STATES.COMPLETED, terminated };
|
|
39
|
+
}
|
|
@@ -7,6 +7,7 @@ exports.validateRequireAll = validateRequireAll;
|
|
|
7
7
|
exports.validateFieldType = validateFieldType;
|
|
8
8
|
exports.validateFieldConstraints = validateFieldConstraints;
|
|
9
9
|
exports.validateField = validateField;
|
|
10
|
+
const x_lt_scan_1 = require("./x-lt-scan");
|
|
10
11
|
const x_lt_options_1 = require("./x-lt-options");
|
|
11
12
|
const ctx_path_1 = require("./ctx-path");
|
|
12
13
|
/**
|
|
@@ -160,6 +161,9 @@ function validateFieldConstraints(value, fieldSchema, ctx) {
|
|
|
160
161
|
return `Must be one of: ${allowed.map((o) => String(o.value)).join(', ')}`;
|
|
161
162
|
}
|
|
162
163
|
}
|
|
164
|
+
const scanError = (0, x_lt_scan_1.scanSinkError)(value, fieldSchema, ctx);
|
|
165
|
+
if (scanError)
|
|
166
|
+
return scanError;
|
|
163
167
|
if (Array.isArray(value)) {
|
|
164
168
|
return isEditableList(fieldSchema) ? validateListConstraints(value, fieldSchema, allowed, ctx) : undefined;
|
|
165
169
|
}
|
|
@@ -38,3 +38,4 @@ __exportStar(require("./validate-resolver-payload"), exports);
|
|
|
38
38
|
__exportStar(require("./invoke-context"), exports);
|
|
39
39
|
__exportStar(require("./display-only-widgets"), exports);
|
|
40
40
|
__exportStar(require("./x-lt-invoke"), exports);
|
|
41
|
+
__exportStar(require("./x-lt-scan"), exports);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export declare const X_LT_SCAN = "x-lt-scan";
|
|
2
|
+
export declare const X_LT_SCAN_SUBMIT = "x-lt-scan-submit";
|
|
3
|
+
export declare const X_LT_ORDER = "x-lt-order";
|
|
4
|
+
export interface ScanSink {
|
|
5
|
+
schemes: number[];
|
|
6
|
+
/** The scanned target (default) or the code as scanned. */
|
|
7
|
+
value: 'target' | 'code';
|
|
8
|
+
/** Context paths whose values the field accepts. */
|
|
9
|
+
expect?: string[];
|
|
10
|
+
expectError: string;
|
|
11
|
+
/** Array fields: 'count' takes a value as many times as it is expected. */
|
|
12
|
+
multiplicity: 'count' | 'once';
|
|
13
|
+
}
|
|
14
|
+
/** The parts of a parsed scan a sink reads. */
|
|
15
|
+
export interface SinkScan {
|
|
16
|
+
version: number;
|
|
17
|
+
target: string;
|
|
18
|
+
code: string;
|
|
19
|
+
}
|
|
20
|
+
type Schema = Record<string, unknown>;
|
|
21
|
+
/** The field's scan configuration, or null when it takes no scans. */
|
|
22
|
+
export declare function readScanSink(fieldSchema: Schema | undefined): ScanSink | null;
|
|
23
|
+
/** Manufacturer barcodes compare as GTINs, so a UPC-A matches its 14-digit form. */
|
|
24
|
+
export declare function sameScanValue(a: string, b: string): boolean;
|
|
25
|
+
/** The values the field accepts, flattened; null when it declares none. */
|
|
26
|
+
export declare function resolveScanExpected(sink: ScanSink, ctx: Record<string, unknown> | undefined): string[] | null;
|
|
27
|
+
/**
|
|
28
|
+
* The field's error for its current value against what it expects, or
|
|
29
|
+
* undefined. Strings must be one of the expected values; arrays may hold
|
|
30
|
+
* each expected value once (or as many times as expected, with 'count').
|
|
31
|
+
*/
|
|
32
|
+
export declare function scanSinkError(value: unknown, fieldSchema: Schema | undefined, ctx: Record<string, unknown> | undefined): string | undefined;
|
|
33
|
+
/** What a scan does to a field: the next value, or the error to show (nothing written). */
|
|
34
|
+
export declare function applyScanToField(current: unknown, scan: SinkScan, fieldSchema: Schema, ctx: Record<string, unknown> | undefined): {
|
|
35
|
+
ok: true;
|
|
36
|
+
value: unknown;
|
|
37
|
+
} | {
|
|
38
|
+
ok: false;
|
|
39
|
+
error: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* The field a scan from `version` fills: the focused field when it takes
|
|
43
|
+
* that scheme, otherwise the first (in x-lt-order) that takes it and has
|
|
44
|
+
* room, otherwise the first that takes it. Null: no field takes it, so the
|
|
45
|
+
* scan runs globally.
|
|
46
|
+
*/
|
|
47
|
+
export declare function pickScanSink(schema: Schema | null | undefined, values: Record<string, unknown>, version: number, focusedField?: string | null): string | null;
|
|
48
|
+
/** True when the form submits on its own once its scan fields are filled. */
|
|
49
|
+
export declare function wantsScanSubmit(schema: Schema | null | undefined): boolean;
|
|
50
|
+
/** True when every required scan field holds a value. */
|
|
51
|
+
export declare function scanFieldsFilled(schema: Schema | null | undefined, values: Record<string, unknown>): boolean;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.X_LT_ORDER = exports.X_LT_SCAN_SUBMIT = exports.X_LT_SCAN = void 0;
|
|
4
|
+
exports.readScanSink = readScanSink;
|
|
5
|
+
exports.sameScanValue = sameScanValue;
|
|
6
|
+
exports.resolveScanExpected = resolveScanExpected;
|
|
7
|
+
exports.scanSinkError = scanSinkError;
|
|
8
|
+
exports.applyScanToField = applyScanToField;
|
|
9
|
+
exports.pickScanSink = pickScanSink;
|
|
10
|
+
exports.wantsScanSubmit = wantsScanSubmit;
|
|
11
|
+
exports.scanFieldsFilled = scanFieldsFilled;
|
|
12
|
+
/**
|
|
13
|
+
* x-lt-scan: a form field that takes a scan.
|
|
14
|
+
*
|
|
15
|
+
* While a form is open and editable, a scan whose scheme a field accepts
|
|
16
|
+
* fills that field instead of running globally. The field may declare what
|
|
17
|
+
* it expects (paths into the escalation context); a scan outside that set
|
|
18
|
+
* is a field error and is not written, and the same check runs server-side
|
|
19
|
+
* at submit, so a typed wrong value is refused there too.
|
|
20
|
+
*
|
|
21
|
+
* "containerCode": { "type": "string", "x-lt-scan": {
|
|
22
|
+
* "schemes": [14], "expect": ["metadata.containerCode"],
|
|
23
|
+
* "expect-error": "This item goes in {{expected}}." } }
|
|
24
|
+
* "parts": { "type": "array", "items": { "type": "string" },
|
|
25
|
+
* "x-lt-scan": { "schemes": [16], "expect": ["envelope.expected_upcs"], "multiplicity": "count" } }
|
|
26
|
+
*
|
|
27
|
+
* Root `x-lt-scan-submit: true` submits once every required scan field is
|
|
28
|
+
* filled and the form validates. A string field is replaced by a scan; an
|
|
29
|
+
* array field appends, and with `multiplicity: "count"` a value expected n
|
|
30
|
+
* times takes n scans.
|
|
31
|
+
*/
|
|
32
|
+
const ctx_path_1 = require("./ctx-path");
|
|
33
|
+
exports.X_LT_SCAN = 'x-lt-scan';
|
|
34
|
+
exports.X_LT_SCAN_SUBMIT = 'x-lt-scan-submit';
|
|
35
|
+
exports.X_LT_ORDER = 'x-lt-order';
|
|
36
|
+
const DEFAULT_EXPECT_ERROR = 'Expected {{expected}}';
|
|
37
|
+
/** The field's scan configuration, or null when it takes no scans. */
|
|
38
|
+
function readScanSink(fieldSchema) {
|
|
39
|
+
const raw = fieldSchema?.[exports.X_LT_SCAN];
|
|
40
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
41
|
+
return null;
|
|
42
|
+
const cfg = raw;
|
|
43
|
+
const schemes = Array.isArray(cfg.schemes) ? cfg.schemes.filter((v) => Number.isInteger(v)) : [];
|
|
44
|
+
if (schemes.length === 0)
|
|
45
|
+
return null;
|
|
46
|
+
const expect = Array.isArray(cfg.expect) ? cfg.expect.filter((v) => typeof v === 'string') : undefined;
|
|
47
|
+
return {
|
|
48
|
+
schemes,
|
|
49
|
+
value: cfg.value === 'code' ? 'code' : 'target',
|
|
50
|
+
...(expect?.length ? { expect } : {}),
|
|
51
|
+
expectError: typeof cfg['expect-error'] === 'string' ? cfg['expect-error'] : DEFAULT_EXPECT_ERROR,
|
|
52
|
+
multiplicity: cfg.multiplicity === 'count' ? 'count' : 'once',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Manufacturer barcodes compare as GTINs, so a UPC-A matches its 14-digit form. */
|
|
56
|
+
function sameScanValue(a, b) {
|
|
57
|
+
if (a === b)
|
|
58
|
+
return true;
|
|
59
|
+
const gtin = /^[0-9]{8,14}$/;
|
|
60
|
+
return gtin.test(a) && gtin.test(b) && a.padStart(14, '0') === b.padStart(14, '0');
|
|
61
|
+
}
|
|
62
|
+
/** The values the field accepts, flattened; null when it declares none. */
|
|
63
|
+
function resolveScanExpected(sink, ctx) {
|
|
64
|
+
if (!sink.expect)
|
|
65
|
+
return null;
|
|
66
|
+
const out = [];
|
|
67
|
+
for (const path of sink.expect) {
|
|
68
|
+
const value = (0, ctx_path_1.resolveCtxPath)(path, ctx);
|
|
69
|
+
const list = Array.isArray(value) ? value : [value];
|
|
70
|
+
for (const v of list) {
|
|
71
|
+
if (typeof v === 'string' && v)
|
|
72
|
+
out.push(v);
|
|
73
|
+
else if (typeof v === 'number')
|
|
74
|
+
out.push(String(v));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function expectMessage(sink, expected) {
|
|
80
|
+
return sink.expectError.replace(/\{\{\s*expected\s*\}\}/g, [...new Set(expected)].join(', ') || 'nothing');
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The field's error for its current value against what it expects, or
|
|
84
|
+
* undefined. Strings must be one of the expected values; arrays may hold
|
|
85
|
+
* each expected value once (or as many times as expected, with 'count').
|
|
86
|
+
*/
|
|
87
|
+
function scanSinkError(value, fieldSchema, ctx) {
|
|
88
|
+
const sink = readScanSink(fieldSchema);
|
|
89
|
+
if (!sink)
|
|
90
|
+
return undefined;
|
|
91
|
+
const expected = resolveScanExpected(sink, ctx);
|
|
92
|
+
if (expected === null)
|
|
93
|
+
return undefined;
|
|
94
|
+
const values = Array.isArray(value) ? value : value === undefined || value === null || value === '' ? [] : [value];
|
|
95
|
+
// Each expected value admits one scan; 'count' keeps repeats as separate admissions.
|
|
96
|
+
const budget = sink.multiplicity === 'count' ? [...expected] : [...new Set(expected)];
|
|
97
|
+
for (const v of values) {
|
|
98
|
+
const at = budget.findIndex((e) => sameScanValue(String(v), e));
|
|
99
|
+
if (at === -1)
|
|
100
|
+
return expectMessage(sink, expected);
|
|
101
|
+
budget.splice(at, 1);
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
/** What a scan does to a field: the next value, or the error to show (nothing written). */
|
|
106
|
+
function applyScanToField(current, scan, fieldSchema, ctx) {
|
|
107
|
+
const sink = readScanSink(fieldSchema);
|
|
108
|
+
if (!sink)
|
|
109
|
+
return { ok: false, error: 'This field takes no scans' };
|
|
110
|
+
const scanned = sink.value === 'code' ? scan.code : scan.target;
|
|
111
|
+
const isArray = fieldSchema.type === 'array';
|
|
112
|
+
const next = isArray ? [...(Array.isArray(current) ? current : []), scanned] : scanned;
|
|
113
|
+
const error = scanSinkError(next, fieldSchema, ctx);
|
|
114
|
+
if (error)
|
|
115
|
+
return { ok: false, error };
|
|
116
|
+
const max = fieldSchema.maxItems;
|
|
117
|
+
if (isArray && typeof max === 'number' && next.length > max) {
|
|
118
|
+
return { ok: false, error: `At most ${max}` };
|
|
119
|
+
}
|
|
120
|
+
return { ok: true, value: next };
|
|
121
|
+
}
|
|
122
|
+
/** True when the field has room for another scan. */
|
|
123
|
+
function hasRoom(value, fieldSchema) {
|
|
124
|
+
if (fieldSchema.type === 'array') {
|
|
125
|
+
const max = fieldSchema.maxItems;
|
|
126
|
+
return typeof max !== 'number' || !Array.isArray(value) || value.length < max;
|
|
127
|
+
}
|
|
128
|
+
return value === undefined || value === null || value === '';
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The field a scan from `version` fills: the focused field when it takes
|
|
132
|
+
* that scheme, otherwise the first (in x-lt-order) that takes it and has
|
|
133
|
+
* room, otherwise the first that takes it. Null: no field takes it, so the
|
|
134
|
+
* scan runs globally.
|
|
135
|
+
*/
|
|
136
|
+
function pickScanSink(schema, values, version, focusedField) {
|
|
137
|
+
const properties = (schema?.properties ?? {});
|
|
138
|
+
const order = Array.isArray(schema?.[exports.X_LT_ORDER]) ? schema[exports.X_LT_ORDER] : [];
|
|
139
|
+
const names = [...order.filter((n) => n in properties), ...Object.keys(properties).filter((n) => !order.includes(n))];
|
|
140
|
+
const takes = names.filter((n) => readScanSink(properties[n])?.schemes.includes(version));
|
|
141
|
+
if (takes.length === 0)
|
|
142
|
+
return null;
|
|
143
|
+
if (focusedField && takes.includes(focusedField))
|
|
144
|
+
return focusedField;
|
|
145
|
+
return takes.find((n) => hasRoom(values[n], properties[n])) ?? takes[0];
|
|
146
|
+
}
|
|
147
|
+
/** True when the form submits on its own once its scan fields are filled. */
|
|
148
|
+
function wantsScanSubmit(schema) {
|
|
149
|
+
return schema?.[exports.X_LT_SCAN_SUBMIT] === true;
|
|
150
|
+
}
|
|
151
|
+
/** True when every required scan field holds a value. */
|
|
152
|
+
function scanFieldsFilled(schema, values) {
|
|
153
|
+
const properties = (schema?.properties ?? {});
|
|
154
|
+
const required = new Set(schema?.required ?? []);
|
|
155
|
+
const sinks = Object.keys(properties).filter((n) => readScanSink(properties[n]) && required.has(n));
|
|
156
|
+
if (sinks.length === 0)
|
|
157
|
+
return false;
|
|
158
|
+
return sinks.every((n) => {
|
|
159
|
+
const v = values[n];
|
|
160
|
+
if (Array.isArray(v)) {
|
|
161
|
+
const min = properties[n].minItems;
|
|
162
|
+
return v.length >= (typeof min === 'number' ? min : 1);
|
|
163
|
+
}
|
|
164
|
+
return v !== undefined && v !== null && v !== '';
|
|
165
|
+
});
|
|
166
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const GTIN_CODE_LENGTHS: readonly number[];
|
|
2
|
+
/** True when `code` is all digits, a GTIN length, and its mod-10 check digit holds. */
|
|
3
|
+
export declare function isValidGtin(code: string): boolean;
|
|
4
|
+
/** The 14-digit form of a valid GTIN: UPC-A, EAN-13 and EAN-8 left-padded with zeros. */
|
|
5
|
+
export declare function normalizeGtin(code: string): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// GTIN (UPC-A, EAN-13, EAN-8, GTIN-14) check digits and normalization.
|
|
3
|
+
// Pure; shared by the server parser and the dashboard's scan capture.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.GTIN_CODE_LENGTHS = void 0;
|
|
6
|
+
exports.isValidGtin = isValidGtin;
|
|
7
|
+
exports.normalizeGtin = normalizeGtin;
|
|
8
|
+
exports.GTIN_CODE_LENGTHS = [8, 12, 13, 14];
|
|
9
|
+
/** True when `code` is all digits, a GTIN length, and its mod-10 check digit holds. */
|
|
10
|
+
function isValidGtin(code) {
|
|
11
|
+
if (!/^[0-9]+$/.test(code) || !exports.GTIN_CODE_LENGTHS.includes(code.length))
|
|
12
|
+
return false;
|
|
13
|
+
const digits = code.split('').map(Number);
|
|
14
|
+
const check = digits.pop();
|
|
15
|
+
let sum = 0;
|
|
16
|
+
// Weights run 3,1,3,1… from the digit nearest the check digit.
|
|
17
|
+
for (let i = digits.length - 1, w = 3; i >= 0; i--, w = w === 3 ? 1 : 3) {
|
|
18
|
+
sum += digits[i] * w;
|
|
19
|
+
}
|
|
20
|
+
return (10 - (sum % 10)) % 10 === check;
|
|
21
|
+
}
|
|
22
|
+
/** The 14-digit form of a valid GTIN: UPC-A, EAN-13 and EAN-8 left-padded with zeros. */
|
|
23
|
+
function normalizeGtin(code) {
|
|
24
|
+
return code.padStart(14, '0');
|
|
25
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GTIN_CODE_LENGTHS = exports.normalizeGtin = exports.isValidGtin = exports.fixedCodeLengths = exports.parseScanCode = void 0;
|
|
4
|
+
var parse_1 = require("./parse");
|
|
5
|
+
Object.defineProperty(exports, "parseScanCode", { enumerable: true, get: function () { return parse_1.parseScanCode; } });
|
|
6
|
+
Object.defineProperty(exports, "fixedCodeLengths", { enumerable: true, get: function () { return parse_1.fixedCodeLengths; } });
|
|
7
|
+
var gtin_1 = require("./gtin");
|
|
8
|
+
Object.defineProperty(exports, "isValidGtin", { enumerable: true, get: function () { return gtin_1.isValidGtin; } });
|
|
9
|
+
Object.defineProperty(exports, "normalizeGtin", { enumerable: true, get: function () { return gtin_1.normalizeGtin; } });
|
|
10
|
+
Object.defineProperty(exports, "GTIN_CODE_LENGTHS", { enumerable: true, get: function () { return gtin_1.GTIN_CODE_LENGTHS; } });
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** The scheme fields parsing reads. The server's ScanScheme satisfies it. */
|
|
2
|
+
export interface ParseableScheme {
|
|
3
|
+
version: number;
|
|
4
|
+
name: string;
|
|
5
|
+
encoding: 'fixed' | 'delimited' | 'gtin';
|
|
6
|
+
delimiter: string;
|
|
7
|
+
target_length: number | null;
|
|
8
|
+
enabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ParsedCode {
|
|
11
|
+
version: number;
|
|
12
|
+
category: string;
|
|
13
|
+
target: string;
|
|
14
|
+
/** The code as scanned, when the target was normalized from it (GTIN). */
|
|
15
|
+
raw?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ScanParseFailure {
|
|
18
|
+
/** Why the code did not parse. */
|
|
19
|
+
reason: 'empty' | 'unknown_version' | 'scheme_disabled' | 'malformed';
|
|
20
|
+
detail: string;
|
|
21
|
+
}
|
|
22
|
+
export type ScanParseResult<S extends ParseableScheme = ParseableScheme> = {
|
|
23
|
+
ok: true;
|
|
24
|
+
parsed: ParsedCode;
|
|
25
|
+
scheme: S;
|
|
26
|
+
} | {
|
|
27
|
+
ok: false;
|
|
28
|
+
failure: ScanParseFailure;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Parse a raw scan string against the configured schemes.
|
|
32
|
+
*
|
|
33
|
+
* The leading TWO digits pick the scheme (10-99, so a code never starts with a
|
|
34
|
+
* leading zero); the scheme then defines how the remainder splits into a
|
|
35
|
+
* single-digit category (0-9) and the target:
|
|
36
|
+
* - delimited: `10:1:ABC-123` (delimiter from the scheme row)
|
|
37
|
+
* - fixed: `1017554332` (one category digit, then target_length digits)
|
|
38
|
+
*
|
|
39
|
+
* A digits-only code that no fixed scheme reads is a manufacturer barcode
|
|
40
|
+
* when a gtin scheme is configured and its check digit holds: the target is
|
|
41
|
+
* the 14-digit GTIN and the category is '0'. Config validation keeps fixed
|
|
42
|
+
* and gtin lengths apart, so the order here never decides a real code.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseScanCode<S extends ParseableScheme>(raw: string, schemes: S[]): ScanParseResult<S>;
|
|
45
|
+
/** The total code lengths a fixed scheme accepts (with and without the check-digit slack). */
|
|
46
|
+
export declare function fixedCodeLengths(scheme: Pick<ParseableScheme, 'target_length'>): number[];
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Scan-code parsing. Pure and isomorphic: the server parses every scan with
|
|
3
|
+
// it, and the dashboard parses locally to route a scan into an open form.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.parseScanCode = parseScanCode;
|
|
6
|
+
exports.fixedCodeLengths = fixedCodeLengths;
|
|
7
|
+
const gtin_1 = require("./gtin");
|
|
8
|
+
const GTIN_CATEGORY = '0';
|
|
9
|
+
/**
|
|
10
|
+
* Parse a raw scan string against the configured schemes.
|
|
11
|
+
*
|
|
12
|
+
* The leading TWO digits pick the scheme (10-99, so a code never starts with a
|
|
13
|
+
* leading zero); the scheme then defines how the remainder splits into a
|
|
14
|
+
* single-digit category (0-9) and the target:
|
|
15
|
+
* - delimited: `10:1:ABC-123` (delimiter from the scheme row)
|
|
16
|
+
* - fixed: `1017554332` (one category digit, then target_length digits)
|
|
17
|
+
*
|
|
18
|
+
* A digits-only code that no fixed scheme reads is a manufacturer barcode
|
|
19
|
+
* when a gtin scheme is configured and its check digit holds: the target is
|
|
20
|
+
* the 14-digit GTIN and the category is '0'. Config validation keeps fixed
|
|
21
|
+
* and gtin lengths apart, so the order here never decides a real code.
|
|
22
|
+
*/
|
|
23
|
+
function parseScanCode(raw, schemes) {
|
|
24
|
+
const code = raw.trim();
|
|
25
|
+
if (!code) {
|
|
26
|
+
return { ok: false, failure: { reason: 'empty', detail: 'empty scan code' } };
|
|
27
|
+
}
|
|
28
|
+
if (/^[0-9]+$/.test(code)) {
|
|
29
|
+
const fixed = schemes.find((s) => s.encoding === 'fixed' && s.version === Number(code.slice(0, 2)));
|
|
30
|
+
const fixedFits = fixed?.enabled && fitsFixed(code, fixed);
|
|
31
|
+
if (!fixedFits) {
|
|
32
|
+
const gtin = parseGtin(code, schemes);
|
|
33
|
+
if (gtin)
|
|
34
|
+
return gtin;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const versionToken = code.slice(0, 2);
|
|
38
|
+
const version = Number(versionToken);
|
|
39
|
+
if (!/^[0-9]{2}$/.test(versionToken) || version < 10 || version > 99) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
failure: { reason: 'unknown_version', detail: `code must start with a two-digit scheme 10-99, got "${versionToken}"` },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const scheme = schemes.find((s) => s.version === version);
|
|
46
|
+
if (!scheme) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
failure: { reason: 'unknown_version', detail: `no scan scheme configured for version ${version}` },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (!scheme.enabled) {
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
failure: { reason: 'scheme_disabled', detail: `scan scheme ${version} ("${scheme.name}") is disabled` },
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
if (scheme.encoding === 'gtin') {
|
|
59
|
+
return malformed(scheme, 'reads manufacturer barcodes, which carry no scheme prefix');
|
|
60
|
+
}
|
|
61
|
+
if (scheme.encoding === 'delimited') {
|
|
62
|
+
return parseDelimited(code, version, scheme);
|
|
63
|
+
}
|
|
64
|
+
return parseFixed(code, version, scheme);
|
|
65
|
+
}
|
|
66
|
+
function fitsFixed(code, scheme) {
|
|
67
|
+
const expected = 3 + (scheme.target_length ?? 0);
|
|
68
|
+
return code.length === expected || code.length === expected + 1;
|
|
69
|
+
}
|
|
70
|
+
/** A manufacturer barcode, or null when the code is not one any gtin scheme reads. */
|
|
71
|
+
function parseGtin(code, schemes) {
|
|
72
|
+
if (!(0, gtin_1.isValidGtin)(code))
|
|
73
|
+
return null;
|
|
74
|
+
const gtin = schemes.find((s) => s.encoding === 'gtin' && s.enabled)
|
|
75
|
+
?? schemes.find((s) => s.encoding === 'gtin');
|
|
76
|
+
if (!gtin)
|
|
77
|
+
return null;
|
|
78
|
+
if (!gtin.enabled) {
|
|
79
|
+
return {
|
|
80
|
+
ok: false,
|
|
81
|
+
failure: { reason: 'scheme_disabled', detail: `scan scheme ${gtin.version} ("${gtin.name}") is disabled` },
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
ok: true,
|
|
86
|
+
parsed: { version: gtin.version, category: GTIN_CATEGORY, target: (0, gtin_1.normalizeGtin)(code), raw: code },
|
|
87
|
+
scheme: gtin,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function parseDelimited(code, version, scheme) {
|
|
91
|
+
const d = scheme.delimiter;
|
|
92
|
+
// version(2 digits) <d> category(1 digit) <d> target(rest, non-empty)
|
|
93
|
+
if (code[2] !== d) {
|
|
94
|
+
return malformed(scheme, `expected "${d}" after the two-digit scheme`);
|
|
95
|
+
}
|
|
96
|
+
const category = code.slice(3, 4);
|
|
97
|
+
if (!/^[0-9]$/.test(category)) {
|
|
98
|
+
return malformed(scheme, 'category must be a single digit');
|
|
99
|
+
}
|
|
100
|
+
if (code[4] !== d) {
|
|
101
|
+
return malformed(scheme, `expected "${d}" after the category`);
|
|
102
|
+
}
|
|
103
|
+
const target = code.slice(5);
|
|
104
|
+
if (!target) {
|
|
105
|
+
return malformed(scheme, 'target is empty');
|
|
106
|
+
}
|
|
107
|
+
return { ok: true, parsed: { version, category, target }, scheme };
|
|
108
|
+
}
|
|
109
|
+
function parseFixed(code, version, scheme) {
|
|
110
|
+
const targetLength = scheme.target_length ?? 0;
|
|
111
|
+
const expected = 2 + 1 + targetLength;
|
|
112
|
+
// UPC-A wedges deliver the trailing check digit too; accept it as slack.
|
|
113
|
+
if (!/^[0-9]+$/.test(code)) {
|
|
114
|
+
return malformed(scheme, 'fixed encoding accepts digits only');
|
|
115
|
+
}
|
|
116
|
+
if (code.length !== expected && code.length !== expected + 1) {
|
|
117
|
+
return malformed(scheme, `expected ${expected} digits (or ${expected + 1} with check digit), got ${code.length}`);
|
|
118
|
+
}
|
|
119
|
+
const category = code.slice(2, 3);
|
|
120
|
+
const target = code.slice(3, 3 + targetLength);
|
|
121
|
+
return { ok: true, parsed: { version, category, target }, scheme };
|
|
122
|
+
}
|
|
123
|
+
function malformed(scheme, detail) {
|
|
124
|
+
return {
|
|
125
|
+
ok: false,
|
|
126
|
+
failure: { reason: 'malformed', detail: `scheme ${scheme.version} ("${scheme.name}"): ${detail}` },
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** The total code lengths a fixed scheme accepts (with and without the check-digit slack). */
|
|
130
|
+
function fixedCodeLengths(scheme) {
|
|
131
|
+
const expected = 3 + (scheme.target_length ?? 0);
|
|
132
|
+
return [expected, expected + 1];
|
|
133
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A workflow's lifecycle state, read from HotMesh's job status: above 0 the
|
|
3
|
+
* job is running, 0 it has closed, below 0 it was terminated (an interrupt
|
|
4
|
+
* lowers the status far below 0). A terminated run is failed. A run that
|
|
5
|
+
* closed at 0 can still have failed; `readWorkflowState` on the server tells
|
|
6
|
+
* the two apart from the job's outcome.
|
|
7
|
+
*/
|
|
8
|
+
export declare const WORKFLOW_STATES: {
|
|
9
|
+
readonly RUNNING: "running";
|
|
10
|
+
readonly COMPLETED: "completed";
|
|
11
|
+
readonly FAILED: "failed";
|
|
12
|
+
};
|
|
13
|
+
export type WorkflowState = (typeof WORKFLOW_STATES)[keyof typeof WORKFLOW_STATES];
|
|
14
|
+
/** The state a job status implies, before any outcome is read. */
|
|
15
|
+
export declare function workflowStateFromStatus(status: number): WorkflowState;
|
|
16
|
+
/** Whether a job status means the run was terminated. */
|
|
17
|
+
export declare function isTerminated(status: number): boolean;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WORKFLOW_STATES = void 0;
|
|
4
|
+
exports.workflowStateFromStatus = workflowStateFromStatus;
|
|
5
|
+
exports.isTerminated = isTerminated;
|
|
6
|
+
/**
|
|
7
|
+
* A workflow's lifecycle state, read from HotMesh's job status: above 0 the
|
|
8
|
+
* job is running, 0 it has closed, below 0 it was terminated (an interrupt
|
|
9
|
+
* lowers the status far below 0). A terminated run is failed. A run that
|
|
10
|
+
* closed at 0 can still have failed; `readWorkflowState` on the server tells
|
|
11
|
+
* the two apart from the job's outcome.
|
|
12
|
+
*/
|
|
13
|
+
exports.WORKFLOW_STATES = {
|
|
14
|
+
RUNNING: 'running',
|
|
15
|
+
COMPLETED: 'completed',
|
|
16
|
+
FAILED: 'failed',
|
|
17
|
+
};
|
|
18
|
+
/** The state a job status implies, before any outcome is read. */
|
|
19
|
+
function workflowStateFromStatus(status) {
|
|
20
|
+
if (status > 0)
|
|
21
|
+
return exports.WORKFLOW_STATES.RUNNING;
|
|
22
|
+
if (status === 0)
|
|
23
|
+
return exports.WORKFLOW_STATES.COMPLETED;
|
|
24
|
+
return exports.WORKFLOW_STATES.FAILED;
|
|
25
|
+
}
|
|
26
|
+
/** Whether a job status means the run was terminated. */
|
|
27
|
+
function isTerminated(status) {
|
|
28
|
+
return status < 0;
|
|
29
|
+
}
|