@hotmeshio/long-tail 0.22.1 → 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.js +38 -19
- 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 +16 -10
- 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 +1 -21
- package/build/api/scan-codes/verbs.js +26 -115
- package/build/index.d.ts +1 -0
- package/build/index.js +8 -2
- package/build/lib/db/schemas/037_scan_gtin_and_subject_grants.sql +27 -0
- 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/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/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 +94 -18
- package/build/services/scan-code/write.d.ts +1 -0
- package/build/services/scan-code/write.js +9 -3
- 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/system/mcp-servers/admin/scan-codes.js +10 -4
- package/build/system/mcp-servers/admin/schemas.d.ts +754 -23
- package/build/system/mcp-servers/admin/schemas.js +57 -4
- package/build/system/mcp-servers/human-queue-schemas.d.ts +6 -6
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +2 -0
- package/build/types/escalation.js +3 -1
- package/build/types/index.d.ts +2 -2
- 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} +72 -11
- 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-BbWve-Ax.js → AdminDashboard-DBW12qQt.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-BbWve-Ax.js.map → AdminDashboard-DBW12qQt.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js → AgentConfigPage-CmHv8U9M.js} +2 -2
- package/dashboard/dist/assets/{AgentConfigPage-M-9eTKhP.js.map → AgentConfigPage-CmHv8U9M.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js → AgentDetailPage-D1scIbz-.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-CsakSlx5.js.map → AgentDetailPage-D1scIbz-.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js → AgentsPage-BA_ai9HJ.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-Cj_cRTT1.js.map → AgentsPage-BA_ai9HJ.js.map} +1 -1
- package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js → AvailableEscalationsPage-C2_5aEFW.js} +2 -2
- package/dashboard/dist/assets/{AvailableEscalationsPage-BXJmMBM1.js.map → AvailableEscalationsPage-C2_5aEFW.js.map} +1 -1
- package/dashboard/dist/assets/{BotPicker-CGB16rYU.js → BotPicker-BZo4Kp4a.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGB16rYU.js.map → BotPicker-BZo4Kp4a.js.map} +1 -1
- package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js → BulkAssignModal-BFhyxY2T.js} +2 -2
- package/dashboard/dist/assets/{BulkAssignModal-MjxcU7N1.js.map → BulkAssignModal-BFhyxY2T.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-CvOX6vAc.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-BxadotXn.js.map → CapabilitiesPage-CvOX6vAc.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js → CollapsibleSection-GCJsV9Oq.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BBNpP-6h.js.map → CollapsibleSection-GCJsV9Oq.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js → ConfirmDeleteModal-CAgYLcef.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-D_kAbT_D.js.map → ConfirmDeleteModal-CAgYLcef.js.map} +1 -1
- package/dashboard/dist/assets/CountdownTimer-Dik2z0M_.js +2 -0
- package/dashboard/dist/assets/{CountdownTimer-CI_JOAvk.js.map → CountdownTimer-Dik2z0M_.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js → CredentialsPage-twd2xCOW.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-C9OA1Q2J.js.map → CredentialsPage-twd2xCOW.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js → CronLabel-DdnIuudX.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-sxLLBf2I.js.map → CronLabel-DdnIuudX.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js → ElapsedCell-DCctVv5R.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-jH9m8Dgl.js.map → ElapsedCell-DCctVv5R.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js → EntityTimelinePanel-CMnskyWv.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-Dl3Nr2kk.js.map → EntityTimelinePanel-CMnskyWv.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js → EscalationListSchemaPage-VfCn6WDb.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-DAK6It5J.js.map → EscalationListSchemaPage-VfCn6WDb.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js → EscalationListView-CGQZxcC-.js} +2 -2
- package/dashboard/dist/assets/{EscalationListView-CAHbdxKR.js.map → EscalationListView-CGQZxcC-.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js → EscalationSchemaPage-BX0tx-PM.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-DotfAMCL.js.map → EscalationSchemaPage-BX0tx-PM.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js → EscalationTimeline-DKoSM56J.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-DqmFydnU.js.map → EscalationTimeline-DKoSM56J.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js → EscalationTitleSelect-DWGLBOmS.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-BpRquguO.js.map → EscalationTitleSelect-DWGLBOmS.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js → EscalationsOverview-C2XoguaA.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DtGOqnP4.js.map → EscalationsOverview-C2XoguaA.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DSHqKyX2.js → EventTable-CBUWq7--.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DSHqKyX2.js.map → EventTable-CBUWq7--.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.js → FilterBar-8IdbleZ9.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-Dxd0wNSW.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-ChqqGkro.js → GraphInvokePage-CUvoPzsW.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-ChqqGkro.js.map → GraphInvokePage-CUvoPzsW.js.map} +1 -1
- package/dashboard/dist/assets/{HomePage-ByKesG8w.js → HomePage-BP7v9GLJ.js} +2 -2
- package/dashboard/dist/assets/{HomePage-ByKesG8w.js.map → HomePage-BP7v9GLJ.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js → ListToolbar-Cnacuwoy.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-Ddz_S2av.js.map → ListToolbar-Cnacuwoy.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-CVe13tEv.js → McpOverview-C2JoNoDA.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-CVe13tEv.js.map → McpOverview-C2JoNoDA.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js → McpQueryDetailPage-C_nih0w-.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-BQYF2Mjq.js.map → McpQueryDetailPage-C_nih0w-.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js → McpQueryPage-U_wNXow2.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DZi5lm7s.js.map → McpQueryPage-U_wNXow2.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js → McpRunDetailPage-DtKoJq6J.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-DreARTE1.js.map → McpRunDetailPage-DtKoJq6J.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js → McpRunsPage-CnYtfGhf.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-DmO0YVhT.js.map → McpRunsPage-CnYtfGhf.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js → OperationsPage-C7hupIer.js} +2 -2
- package/dashboard/dist/assets/{OperationsPage-DpjCO85T.js.map → OperationsPage-C7hupIer.js.map} +1 -1
- package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js → OperatorDashboard-fVuLn2D5.js} +2 -2
- package/dashboard/dist/assets/{OperatorDashboard-Vv_MEBkv.js.map → OperatorDashboard-fVuLn2D5.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js → PersonaDetailPage-C-4o8lPw.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-CW-2uBHY.js.map → PersonaDetailPage-C-4o8lPw.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js → PersonasPage-BL1FwLmv.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-CO6yYQdm.js.map → PersonasPage-BL1FwLmv.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js → PortalPage-tJG5sgb1.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-DcNqhBlg.js.map → PortalPage-tJG5sgb1.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js → ProcessDetailPage-Dz_jY4Yt.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-BuipGZcC.js.map → ProcessDetailPage-Dz_jY4Yt.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.js → ProcessesListPage-Cbn9cter.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-D9DYntvl.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/{RolesPage-0QJOBSzF.js → RolesPage-NwmMvZFa.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-0QJOBSzF.js.map → RolesPage-NwmMvZFa.js.map} +1 -1
- package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.js → RunAsSelector-tgEooTyU.js} +2 -2
- package/dashboard/dist/assets/{RunAsSelector-Dh4lyyRo.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/{StickyPagination-BSUyf5ja.js → StickyPagination-CsTI_gvJ.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-BSUyf5ja.js.map → StickyPagination-CsTI_gvJ.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js → StreamMessageDetail-auRlvjTh.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail--tp7l2Sd.js.map → StreamMessageDetail-auRlvjTh.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js → SwimlaneTimeline-BLoVHYAd.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-CxBZ2THh.js.map → SwimlaneTimeline-BLoVHYAd.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js → TaskDetailPage-BPsZ1bK_.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-BJ1QrmPH.js.map → TaskDetailPage-BPsZ1bK_.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js → TasksListPage-BNGM74yT.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-5BydGWmt.js.map → TasksListPage-BNGM74yT.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js → TimeAgo-BnAHXGK7.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CCnz84Y4.js.map → TimeAgo-BnAHXGK7.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js → TimestampCell-J4yae6mc.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-D0ru7Lya.js.map → TimestampCell-J4yae6mc.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js → ToolTestPanel-BdzzgXDu.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-3Kpofmen.js.map → ToolTestPanel-BdzzgXDu.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js → TopicDetailPage-DJKg8lb7.js} +2 -2
- package/dashboard/dist/assets/{TopicDetailPage-BaBXD_AK.js.map → TopicDetailPage-DJKg8lb7.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js → TopicsPage-DQV0WxG6.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Cnm1AAjh.js.map → TopicsPage-DQV0WxG6.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-CXsdPiMZ.js → UserName-Ct09nGh5.js} +2 -2
- package/dashboard/dist/assets/{UserName-CXsdPiMZ.js.map → UserName-Ct09nGh5.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js → WorkflowExecutionPage-B5WJOsee.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-zx3AUJFd.js.map → WorkflowExecutionPage-B5WJOsee.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js → WorkflowsDashboard-Hc87TRgD.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsDashboard-DfAGK1l7.js.map → WorkflowsDashboard-Hc87TRgD.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js → WorkflowsOverview-CJQbyOj-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-QIYvoa13.js.map → WorkflowsOverview-CJQbyOj-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js → YamlWorkflowDetailPage-BMeED677.js} +8 -8
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-DGgO3hyB.js.map → YamlWorkflowDetailPage-BMeED677.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js → YamlWorkflowsPage-BMMg0Id6.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CEsHm0B9.js.map → YamlWorkflowsPage-BMMg0Id6.js.map} +1 -1
- package/dashboard/dist/assets/{agents-v_HH3Rji.js → agents-CdFkgFvg.js} +2 -2
- package/dashboard/dist/assets/{agents-v_HH3Rji.js.map → agents-CdFkgFvg.js.map} +1 -1
- package/dashboard/dist/assets/{bots-bwvWYrXz.js → bots-Mj3LHWWg.js} +2 -2
- package/dashboard/dist/assets/{bots-bwvWYrXz.js.map → bots-Mj3LHWWg.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js → capabilities-Dw1ObK2-.js} +2 -2
- package/dashboard/dist/assets/{capabilities-D4vaw_nQ.js.map → capabilities-Dw1ObK2-.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js → controlplane-DcNE1APv.js} +2 -2
- package/dashboard/dist/assets/{controlplane-CiiZ6LJF.js.map → controlplane-DcNE1APv.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js → escalation-columns-D364Trpy.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Dv-MB3eC.js.map → escalation-columns-D364Trpy.js.map} +1 -1
- package/dashboard/dist/assets/{index-IJmtbuLh.js → index-B3veJ698.js} +2 -2
- package/dashboard/dist/assets/{index-IJmtbuLh.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-D2VKBMng.js → index-BRGTmoYY.js} +2 -2
- package/dashboard/dist/assets/{index-D2VKBMng.js.map → index-BRGTmoYY.js.map} +1 -1
- package/dashboard/dist/assets/{index-C4Lce2ET.js → index-Bd6-KmBE.js} +3 -3
- package/dashboard/dist/assets/{index-C4Lce2ET.js.map → index-Bd6-KmBE.js.map} +1 -1
- package/dashboard/dist/assets/{index-CcuvGdvf.js → index-BiVce3n0.js} +2 -2
- package/dashboard/dist/assets/{index-CcuvGdvf.js.map → index-BiVce3n0.js.map} +1 -1
- package/dashboard/dist/assets/{index-D6pBLZFu.js → index-BmNAVd4s.js} +2 -2
- package/dashboard/dist/assets/{index-D6pBLZFu.js.map → index-BmNAVd4s.js.map} +1 -1
- package/dashboard/dist/assets/{index-CjenRVX_.js → index-Bq5XNEzD.js} +2 -2
- package/dashboard/dist/assets/{index-CjenRVX_.js.map → index-Bq5XNEzD.js.map} +1 -1
- package/dashboard/dist/assets/{index-CzjUgFt_.js → index-DPStdq4T.js} +2 -2
- package/dashboard/dist/assets/{index-CzjUgFt_.js.map → index-DPStdq4T.js.map} +1 -1
- package/dashboard/dist/assets/index-DcppjzP5.css +1 -0
- package/dashboard/dist/assets/{index-C3WutFpT.js → index-DkcI4V_H.js} +2 -2
- package/dashboard/dist/assets/{index-C3WutFpT.js.map → index-DkcI4V_H.js.map} +1 -1
- package/dashboard/dist/assets/{index-2tzsxFat.js → index-Dyotfa_k.js} +2 -2
- package/dashboard/dist/assets/{index-2tzsxFat.js.map → index-Dyotfa_k.js.map} +1 -1
- package/dashboard/dist/assets/{index-C_ISDOWJ.js → index-MDD4JYtu.js} +2 -2
- package/dashboard/dist/assets/{index-C_ISDOWJ.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-BLB77tc8.js → index-eDm6cz0F.js} +2 -2
- package/dashboard/dist/assets/{index-BLB77tc8.js.map → index-eDm6cz0F.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-D1YP2NzS.js → knowledge-Bafewjxk.js} +2 -2
- package/dashboard/dist/assets/{knowledge-D1YP2NzS.js.map → knowledge-Bafewjxk.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js → mcp-query-BzTtIG90.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-D5jUdZwN.js.map → mcp-query-BzTtIG90.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-Bb5psC61.js → mcp-vLIutbnc.js} +2 -2
- package/dashboard/dist/assets/{mcp-Bb5psC61.js.map → mcp-vLIutbnc.js.map} +1 -1
- package/dashboard/dist/assets/{personas-CDndbkp4.js → personas-WD40EDS_.js} +2 -2
- package/dashboard/dist/assets/{personas-CDndbkp4.js.map → personas-WD40EDS_.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js → pipelines-DFwULWs3.js} +2 -2
- package/dashboard/dist/assets/{pipelines-Dq3kNhKu.js.map → pipelines-DFwULWs3.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-BlpDsWCy.js → tasks-La_-WAUn.js} +2 -2
- package/dashboard/dist/assets/{tasks-BlpDsWCy.js.map → tasks-La_-WAUn.js.map} +1 -1
- package/dashboard/dist/assets/{topics-C0YaR9fu.js → topics-CzYMlvqm.js} +2 -2
- package/dashboard/dist/assets/{topics-C0YaR9fu.js.map → topics-CzYMlvqm.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js → useDebouncedValue-C0FQyANW.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-B-KC5ba3.js.map → useDebouncedValue-C0FQyANW.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js → useNamespace-WW_XjAb3.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-Dkr5g2Ac.js.map → useNamespace-WW_XjAb3.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js → useYamlActivityEvents-B3YxPeFt.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BANBOshA.js.map → useYamlActivityEvents-B3YxPeFt.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js → yaml-workflows-COHOjdhF.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-BLYoJfmB.js.map → yaml-workflows-COHOjdhF.js.map} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/docs/dashboard.md +1 -1
- package/docs/hitl/x-lt-scan.md +51 -0
- package/docs/hitl-guide.md +2 -0
- package/docs/scan-codes.md +221 -21
- package/package.json +1 -1
- package/build/types/scan-code.d.ts +0 -317
- package/dashboard/dist/assets/CapabilitiesPage-BxadotXn.js +0 -2
- package/dashboard/dist/assets/CountdownTimer-CI_JOAvk.js +0 -2
- package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js +0 -8
- package/dashboard/dist/assets/ResolverForm-BVG8X0sS.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-KCXDqoJz.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-KCXDqoJz.js.map +0 -1
- package/dashboard/dist/assets/ScanCodesPage-CUhCz-Yr.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-CUhCz-Yr.js.map +0 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-qzXKNqJK.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-qzXKNqJK.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-D8e8cG3t.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-D8e8cG3t.js.map +0 -1
- package/dashboard/dist/assets/index-CT-FN6CW.js +0 -3
- package/dashboard/dist/assets/index-CT-FN6CW.js.map +0 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +0 -1
- package/dashboard/dist/assets/index-N71QQ3J5.js +0 -67
- package/dashboard/dist/assets/index-N71QQ3J5.js.map +0 -1
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.assertValidScheme = assertValidScheme;
|
|
4
|
+
exports.assertSchemesCoexist = assertSchemesCoexist;
|
|
4
5
|
exports.assertValidIdentityRule = assertValidIdentityRule;
|
|
5
6
|
exports.assertValidSteps = assertValidSteps;
|
|
6
7
|
const types_1 = require("../../types");
|
|
8
|
+
const scan_code_1 = require("../../shared/scan-code");
|
|
7
9
|
const facet_sql_1 = require("../escalation/facet-sql");
|
|
10
|
+
const validate_subject_1 = require("./validate-subject");
|
|
8
11
|
const VALID_VERBS = new Set(Object.values(types_1.SCAN_VERBS));
|
|
9
12
|
/** Double-scan selection tokens — short, label-printable, never scheme-shaped. */
|
|
10
13
|
const CHOICE_CODE = /^[A-Za-z0-9_-]{1,32}$/;
|
|
@@ -22,6 +25,12 @@ function assertValidScheme(scheme) {
|
|
|
22
25
|
if (!scheme.target_facet)
|
|
23
26
|
throw new Error('scheme target_facet is required');
|
|
24
27
|
const encoding = scheme.encoding ?? types_1.SCAN_ENCODINGS.FIXED;
|
|
28
|
+
if (!Object.values(types_1.SCAN_ENCODINGS).includes(encoding)) {
|
|
29
|
+
throw new Error(`unknown scheme encoding "${encoding}"`);
|
|
30
|
+
}
|
|
31
|
+
if (encoding === types_1.SCAN_ENCODINGS.GTIN && (scheme.kind ?? types_1.SCAN_SCHEME_KINDS.ACTION) !== types_1.SCAN_SCHEME_KINDS.ACTION) {
|
|
32
|
+
throw new Error('gtin encoding applies only to action schemes');
|
|
33
|
+
}
|
|
25
34
|
if (encoding === types_1.SCAN_ENCODINGS.FIXED) {
|
|
26
35
|
if (!Number.isInteger(scheme.target_length) || scheme.target_length < 1) {
|
|
27
36
|
throw new Error('fixed encoding requires a positive integer target_length');
|
|
@@ -48,11 +57,50 @@ function assertValidScheme(scheme) {
|
|
|
48
57
|
if (!Number.isInteger(scheme.grant_max_uses ?? 0) || (scheme.grant_max_uses ?? 0) < 0) {
|
|
49
58
|
throw new Error('grant_max_uses must be a non-negative integer');
|
|
50
59
|
}
|
|
60
|
+
const scope = scheme.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION;
|
|
61
|
+
if (!Object.values(types_1.SCAN_GRANT_SCOPES).includes(scope)) {
|
|
62
|
+
throw new Error(`unknown grant_scope "${scope}"`);
|
|
63
|
+
}
|
|
51
64
|
}
|
|
52
|
-
else if (scheme.grant_ttl_seconds != null || (scheme.grant_max_uses ?? 0) !== 0
|
|
65
|
+
else if (scheme.grant_ttl_seconds != null || (scheme.grant_max_uses ?? 0) !== 0
|
|
66
|
+
|| (scheme.grant_scope ?? types_1.SCAN_GRANT_SCOPES.ACTION) !== types_1.SCAN_GRANT_SCOPES.ACTION) {
|
|
53
67
|
throw new Error('grant policy applies only to identity schemes');
|
|
54
68
|
}
|
|
55
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* A scheme must read codes no other scheme reads. Delimited and fixed
|
|
72
|
+
* schemes are told apart by their version prefix; a gtin scheme has none,
|
|
73
|
+
* so there is at most one, and no enabled fixed scheme may accept a GTIN
|
|
74
|
+
* length while it is enabled. Throws naming both schemes.
|
|
75
|
+
*/
|
|
76
|
+
function assertSchemesCoexist(candidate, existing) {
|
|
77
|
+
const others = existing.filter((s) => s.version !== candidate.version);
|
|
78
|
+
const encoding = candidate.encoding ?? types_1.SCAN_ENCODINGS.FIXED;
|
|
79
|
+
const enabled = candidate.enabled ?? true;
|
|
80
|
+
if (encoding === types_1.SCAN_ENCODINGS.GTIN) {
|
|
81
|
+
const gtin = others.find((s) => s.encoding === types_1.SCAN_ENCODINGS.GTIN);
|
|
82
|
+
if (gtin) {
|
|
83
|
+
throw new Error(`scheme ${gtin.version} ("${gtin.name}") already reads manufacturer barcodes; only one gtin scheme is allowed`);
|
|
84
|
+
}
|
|
85
|
+
if (!enabled)
|
|
86
|
+
return;
|
|
87
|
+
const clash = others.find((s) => s.enabled && s.encoding === types_1.SCAN_ENCODINGS.FIXED
|
|
88
|
+
&& (0, scan_code_1.fixedCodeLengths)(s).some((n) => types_1.GTIN_LENGTHS.includes(n)));
|
|
89
|
+
if (clash) {
|
|
90
|
+
throw new Error(`fixed scheme ${clash.version} ("${clash.name}") accepts ${(0, scan_code_1.fixedCodeLengths)(clash).join(' or ')}-digit codes, which a gtin scheme also reads; change its target_length or leave the gtin scheme disabled`);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (encoding === types_1.SCAN_ENCODINGS.FIXED && enabled) {
|
|
95
|
+
const lengths = (0, scan_code_1.fixedCodeLengths)({ target_length: candidate.target_length ?? null });
|
|
96
|
+
if (!lengths.some((n) => types_1.GTIN_LENGTHS.includes(n)))
|
|
97
|
+
return;
|
|
98
|
+
const gtin = others.find((s) => s.enabled && s.encoding === types_1.SCAN_ENCODINGS.GTIN);
|
|
99
|
+
if (gtin) {
|
|
100
|
+
throw new Error(`a fixed scheme accepting ${lengths.join(' or ')}-digit codes collides with gtin scheme ${gtin.version} ("${gtin.name}"); change target_length or disable the gtin scheme`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
56
104
|
/** Identity rules never walk steps — their fallback is the unknown-badge screen. */
|
|
57
105
|
function assertValidIdentityRule(steps) {
|
|
58
106
|
if (Array.isArray(steps) && steps.length > 0) {
|
|
@@ -73,7 +121,8 @@ function assertValidChoices(choices, at) {
|
|
|
73
121
|
throw new Error(`${cat}: label is required`);
|
|
74
122
|
if (!VALID_VERBS.has(choice.verb))
|
|
75
123
|
throw new Error(`${cat}: unknown verb "${choice.verb}"`);
|
|
76
|
-
if (choice.verb === types_1.SCAN_VERBS.PRESENT || choice.verb === types_1.SCAN_VERBS.SHOW_LIST
|
|
124
|
+
if (choice.verb === types_1.SCAN_VERBS.PRESENT || choice.verb === types_1.SCAN_VERBS.SHOW_LIST
|
|
125
|
+
|| choice.verb === types_1.SCAN_VERBS.FILL) {
|
|
77
126
|
throw new Error(`${cat}: ${choice.verb} cannot be a choice verb`);
|
|
78
127
|
}
|
|
79
128
|
if (choice.confirm && !choice.confirm.prompt) {
|
|
@@ -172,14 +221,23 @@ function assertValidSteps(steps) {
|
|
|
172
221
|
&& (!container.facets || typeof container.facets !== 'object' || Array.isArray(container.facets))) {
|
|
173
222
|
throw new Error(`${at}: params.accumulate.container.facets must be an object`);
|
|
174
223
|
}
|
|
175
|
-
if (!options?.containerFacet) {
|
|
176
|
-
throw new Error(`${at}: params.accumulate.container requires params.accumulate.containerFacet`);
|
|
224
|
+
if (!options?.containerFacet && options?.from !== 'subject') {
|
|
225
|
+
throw new Error(`${at}: params.accumulate.container requires params.accumulate.containerFacet or from: 'subject'`);
|
|
177
226
|
}
|
|
178
227
|
}
|
|
179
|
-
if (!options?.containerFacet && !step.params?.itemKey) {
|
|
228
|
+
if (!options?.containerFacet && !options?.into && !step.params?.itemKey) {
|
|
180
229
|
throw new Error(`${at}: accumulate requires params.itemKey or params.accumulate.containerFacet`);
|
|
181
230
|
}
|
|
182
231
|
}
|
|
232
|
+
(0, validate_subject_1.assertValidSubjectStep)(step, at);
|
|
233
|
+
if (step.done !== undefined) {
|
|
234
|
+
if (!step.done || typeof step.done !== 'object' || typeof step.done.markdown !== 'string' || !step.done.markdown) {
|
|
235
|
+
throw new Error(`${at}: done.markdown is required`);
|
|
236
|
+
}
|
|
237
|
+
if (!types_1.SCAN_MUTATING_VERBS.includes(step.verb)) {
|
|
238
|
+
throw new Error(`${at}: done applies only to steps that write`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
183
241
|
assertValidTemplateTokens(step, at);
|
|
184
242
|
if (step.query && step.query.roles && !Array.isArray(step.query.roles)) {
|
|
185
243
|
throw new Error(`${at}: query.roles must be an array`);
|
|
@@ -198,21 +256,39 @@ function assertValidSteps(steps) {
|
|
|
198
256
|
}
|
|
199
257
|
});
|
|
200
258
|
}
|
|
201
|
-
const BAG_TOKEN = /\{(claim|item)\.([^}]*)\}/g;
|
|
259
|
+
const BAG_TOKEN = /\{(claim|item|subject|container|fill)\.([^}]*)\}/g;
|
|
202
260
|
/**
|
|
203
|
-
*
|
|
204
|
-
* the
|
|
261
|
+
* Bag tokens name facet keys and may only read what the step has:
|
|
262
|
+
* `{item.…}` the row an item-mode accumulate or a hold located,
|
|
263
|
+
* `{subject.…}` the held subject (steps with a subject gate), and
|
|
264
|
+
* `{container.…}` / `{fill.…}` only inside refusal and done copy, where a
|
|
265
|
+
* subject accumulate or a fill has read them.
|
|
205
266
|
*/
|
|
206
267
|
function assertValidTemplateTokens(step, at) {
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
268
|
+
const itemRow = (step.verb === types_1.SCAN_VERBS.ACCUMULATE && !!step.params?.accumulate?.containerFacet)
|
|
269
|
+
|| step.verb === types_1.SCAN_VERBS.HOLD;
|
|
270
|
+
const check = (value, inRefusal) => {
|
|
271
|
+
for (const match of JSON.stringify(value ?? {}).matchAll(BAG_TOKEN)) {
|
|
272
|
+
const [token, bag, facet] = match;
|
|
273
|
+
if (!facet_sql_1.FACET_KEY.test(facet)) {
|
|
274
|
+
throw new Error(`${at}: template token ${token} must name a facet key`);
|
|
275
|
+
}
|
|
276
|
+
if (bag === 'item' && !itemRow) {
|
|
277
|
+
throw new Error(`${at}: ${token} reads the located item row, which only an item-mode accumulate or a hold step has`);
|
|
278
|
+
}
|
|
279
|
+
if (bag === 'subject' && !step.subject) {
|
|
280
|
+
throw new Error(`${at}: ${token} reads the held subject, which only a step with a subject gate has`);
|
|
281
|
+
}
|
|
282
|
+
if (bag === 'container' && !(inRefusal && step.params?.accumulate?.from === 'subject')) {
|
|
283
|
+
throw new Error(`${at}: ${token} is readable only in the refusal or done copy of a from-subject accumulate step`);
|
|
284
|
+
}
|
|
285
|
+
if (bag === 'fill' && !(inRefusal && step.verb === types_1.SCAN_VERBS.FILL)) {
|
|
286
|
+
throw new Error(`${at}: ${token} is readable only in the refusal or done copy of a fill step`);
|
|
287
|
+
}
|
|
216
288
|
}
|
|
217
|
-
}
|
|
289
|
+
};
|
|
290
|
+
check(step.params, false);
|
|
291
|
+
check(step.match, false);
|
|
292
|
+
check(step.refuse, true);
|
|
293
|
+
check(step.done, true);
|
|
218
294
|
}
|
|
@@ -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
|
}
|
|
@@ -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[];
|