@hotmeshio/long-tail 0.30.5 → 0.31.1
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/labels/errors.d.ts +3 -0
- package/build/api/labels/errors.js +15 -0
- package/build/api/labels/index.d.ts +2 -0
- package/build/api/labels/index.js +17 -0
- package/build/api/labels/issue.d.ts +54 -0
- package/build/api/labels/issue.js +144 -0
- package/build/api/labels/templates.d.ts +29 -0
- package/build/api/labels/templates.js +98 -0
- package/build/api/users.d.ts +8 -4
- package/build/api/users.js +51 -13
- package/build/index.d.ts +1 -0
- package/build/index.js +4 -2
- package/build/lib/db/schemas/044_label_sheets.sql +65 -0
- package/build/lib/db/schemas/045_label_job_delivery.sql +14 -0
- package/build/lib/labels/transports.d.ts +23 -0
- package/build/lib/labels/transports.js +39 -0
- package/build/modules/auth.d.ts +2 -0
- package/build/modules/auth.js +3 -1
- package/build/modules/capabilities.d.ts +5 -1
- package/build/modules/capabilities.js +38 -8
- package/build/modules/config.d.ts +10 -0
- package/build/modules/config.js +10 -0
- package/build/routes/index.js +2 -0
- package/build/routes/labels.d.ts +2 -0
- package/build/routes/labels.js +135 -0
- package/build/routes/users.js +1 -1
- package/build/scripts/bambu-boat.d.ts +4 -2
- package/build/scripts/bambu-boat.js +4 -2
- package/build/scripts/bambu-print.d.ts +2 -1
- package/build/scripts/bambu-print.js +7 -3
- package/build/scripts/machine-line.js +2 -1
- package/build/services/labels/content.d.ts +13 -0
- package/build/services/labels/content.js +81 -0
- package/build/services/labels/errors.d.ts +5 -0
- package/build/services/labels/errors.js +12 -0
- package/build/services/labels/index.d.ts +11 -0
- package/build/services/labels/index.js +52 -0
- package/build/services/labels/issue.d.ts +38 -0
- package/build/services/labels/issue.js +181 -0
- package/build/services/labels/jobs.d.ts +37 -0
- package/build/services/labels/jobs.js +75 -0
- package/build/services/labels/media.d.ts +11 -0
- package/build/services/labels/media.js +44 -0
- package/build/services/labels/reissue.d.ts +13 -0
- package/build/services/labels/reissue.js +65 -0
- package/build/services/labels/render-pdf.d.ts +11 -0
- package/build/services/labels/render-pdf.js +138 -0
- package/build/services/labels/targets.d.ts +18 -0
- package/build/services/labels/targets.js +216 -0
- package/build/services/labels/templates/index.d.ts +3 -0
- package/build/services/labels/templates/index.js +18 -0
- package/build/services/labels/templates/read.d.ts +4 -0
- package/build/services/labels/templates/read.js +36 -0
- package/build/services/labels/templates/sql.d.ts +8 -0
- package/build/services/labels/templates/sql.js +50 -0
- package/build/services/labels/templates/validate.d.ts +19 -0
- package/build/services/labels/templates/validate.js +93 -0
- package/build/services/labels/templates/write.d.ts +16 -0
- package/build/services/labels/templates/write.js +75 -0
- package/build/services/labels/token.d.ts +9 -0
- package/build/services/labels/token.js +28 -0
- package/build/services/labels/verify.d.ts +4 -0
- package/build/services/labels/verify.js +38 -0
- package/build/services/scan-code/validate.d.ts +3 -0
- package/build/services/scan-code/validate.js +10 -0
- package/build/services/user/crud.d.ts +13 -1
- package/build/services/user/crud.js +42 -11
- package/build/services/user/index.d.ts +3 -2
- package/build/services/user/index.js +7 -1
- package/build/services/user/redact.d.ts +17 -0
- package/build/services/user/redact.js +32 -0
- package/build/services/user/sql.d.ts +8 -15
- package/build/services/user/sql.js +27 -3
- package/build/services/user/types.d.ts +21 -1
- package/build/shared/labels/compose.d.ts +12 -0
- package/build/shared/labels/compose.js +43 -0
- package/build/shared/labels/index.d.ts +9 -0
- package/build/shared/labels/index.js +54 -0
- package/build/shared/labels/label-content.d.ts +17 -0
- package/build/shared/labels/label-content.js +137 -0
- package/build/shared/labels/layout.d.ts +23 -0
- package/build/shared/labels/layout.js +81 -0
- package/build/shared/labels/media.d.ts +22 -0
- package/build/shared/labels/media.js +116 -0
- package/build/shared/labels/render-svg.d.ts +10 -0
- package/build/shared/labels/render-svg.js +58 -0
- package/build/shared/labels/render-zpl.d.ts +9 -0
- package/build/shared/labels/render-zpl.js +63 -0
- package/build/shared/labels/symbol.d.ts +18 -0
- package/build/shared/labels/symbol.js +74 -0
- package/build/shared/labels/tokens.d.ts +18 -0
- package/build/shared/labels/tokens.js +43 -0
- package/build/shared/labels/types.d.ts +105 -0
- package/build/shared/labels/types.js +11 -0
- package/build/start/adapters.js +16 -0
- package/build/start/workers.js +18 -2
- package/build/system/mcp-servers/admin/index.js +2 -0
- package/build/system/mcp-servers/admin/labels-schemas.d.ts +192 -0
- package/build/system/mcp-servers/admin/labels-schemas.js +46 -0
- package/build/system/mcp-servers/admin/labels.d.ts +9 -0
- package/build/system/mcp-servers/admin/labels.js +101 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +30 -30
- package/build/system/mcp-servers/admin/users.js +1 -1
- package/build/system/seed/tool-manifests-admin.js +5 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/capability.d.ts +2 -1
- package/build/types/index.d.ts +2 -1
- package/build/types/labels/index.d.ts +4 -0
- package/build/types/labels/index.js +2 -0
- package/build/types/labels/job.d.ts +51 -0
- package/build/types/labels/job.js +2 -0
- package/build/types/labels/source.d.ts +44 -0
- package/build/types/labels/source.js +2 -0
- package/build/types/labels/template.d.ts +46 -0
- package/build/types/labels/template.js +2 -0
- package/build/types/labels/transport.d.ts +24 -0
- package/build/types/labels/transport.js +2 -0
- package/build/types/scan-code/rule.d.ts +5 -0
- package/build/types/startup.d.ts +37 -0
- package/build/types/user.d.ts +2 -0
- package/dashboard/dist/assets/{AdminDashboard-D12QiMM5.js → AdminDashboard-BafKaq50.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-D12QiMM5.js.map → AdminDashboard-BafKaq50.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BKQd9b8m.js → AgentConfigPage-CFHf31DT.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-BKQd9b8m.js.map → AgentConfigPage-CFHf31DT.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-ie-DxsIj.js → AgentDetailPage-CEvz5rJr.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-ie-DxsIj.js.map → AgentDetailPage-CEvz5rJr.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-Nqm2DxCP.js → AgentsPage-DjQaio0O.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-Nqm2DxCP.js.map → AgentsPage-DjQaio0O.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-BizdmeJp.js → BotPicker-C7MNWOF7.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-BizdmeJp.js.map → BotPicker-C7MNWOF7.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-h5fX-_cV.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-BWfzPrRk.js.map → BulkAssignModal-h5fX-_cV.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-DT8q7Zlh.js → CapabilitiesPage-BIzDl-ZT.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-DT8q7Zlh.js.map → CapabilitiesPage-BIzDl-ZT.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-al5mqR4O.js → CollapsibleSection-B5TivtEg.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-al5mqR4O.js.map → CollapsibleSection-B5TivtEg.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-BrlVktv2.js → ConfirmDeleteModal-CB4nKePb.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-BrlVktv2.js.map → ConfirmDeleteModal-CB4nKePb.js.map} +1 -1
- package/dashboard/dist/assets/{ConnectedAppsPage-CLAsJ2yQ.js → ConnectedAppsPage-B3S5gVWw.js} +2 -2
- package/dashboard/dist/assets/{ConnectedAppsPage-CLAsJ2yQ.js.map → ConnectedAppsPage-B3S5gVWw.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-D2D68exl.js → CountdownTimer-BHVIq3kA.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-D2D68exl.js.map → CountdownTimer-BHVIq3kA.js.map} +1 -1
- package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js +2 -0
- package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-DWrZbEI0.js → CredentialsPage-BtCGBJrT.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-DWrZbEI0.js.map → CredentialsPage-BtCGBJrT.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DuXR8iWq.js → CronLabel-BG1rZK-5.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DuXR8iWq.js.map → CronLabel-BG1rZK-5.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-DefYTYQy.js → DropZone-D8ZVdEb5.js} +2 -2
- package/dashboard/dist/assets/{DropZone-DefYTYQy.js.map → DropZone-D8ZVdEb5.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-ronqG5-E.js → ElapsedCell-l4m8Yvfv.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-ronqG5-E.js.map → ElapsedCell-l4m8Yvfv.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-CKsktd84.js → EntityTimelinePanel-BOHlIaxF.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-CKsktd84.js.map → EntityTimelinePanel-BOHlIaxF.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-C954ngy3.js → EscalationListSchemaPage-BotlwlX3.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-C954ngy3.js.map → EscalationListSchemaPage-BotlwlX3.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-Dij9K0ON.js → EscalationSchemaPage-CfZSVOSD.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-Dij9K0ON.js.map → EscalationSchemaPage-CfZSVOSD.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-DT2Owdl0.js → EscalationTimeline-CCKpuRBU.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-DT2Owdl0.js.map → EscalationTimeline-CCKpuRBU.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-BdbfMA98.js → EscalationTitleSelect-cpTzPHiW.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-BdbfMA98.js.map → EscalationTitleSelect-cpTzPHiW.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-niahs84P.js → EscalationsOverview-DS-nK0qV.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-niahs84P.js.map → EscalationsOverview-DS-nK0qV.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-DuLMBrSx.js → EventTable-UfebhJf0.js} +2 -2
- package/dashboard/dist/assets/{EventTable-DuLMBrSx.js.map → EventTable-UfebhJf0.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-jtY6KNpL.js → FilterBar-newA5l-X.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-jtY6KNpL.js.map → FilterBar-newA5l-X.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-DSRAI0Zt.js → GraphInvokePage-6SCDyQcK.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-DSRAI0Zt.js.map → GraphInvokePage-6SCDyQcK.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-BEc-XdKj.js +2 -0
- package/dashboard/dist/assets/{HomePage-BUlSnCg8.js.map → HomePage-BEc-XdKj.js.map} +1 -1
- package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js +2 -0
- package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js.map +1 -0
- package/dashboard/dist/assets/{LinePage-BJKhVM9Y.js → LinePage-NYxJQ-ex.js} +3 -3
- package/dashboard/dist/assets/{LinePage-BJKhVM9Y.js.map → LinePage-NYxJQ-ex.js.map} +1 -1
- package/dashboard/dist/assets/{LinesPage-CrpJua3_.js → LinesPage-RbWTaQRh.js} +3 -3
- package/dashboard/dist/assets/{LinesPage-CrpJua3_.js.map → LinesPage-RbWTaQRh.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-BN0UPt0L.js → ListToolbar-B-E9-toh.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-BN0UPt0L.js.map → ListToolbar-B-E9-toh.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BgbJXYPh.js → McpOverview-Shcf9QhZ.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BgbJXYPh.js.map → McpOverview-Shcf9QhZ.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-BNjm2nrc.js → McpQueryDetailPage-D8kmjy2v.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-BNjm2nrc.js.map → McpQueryDetailPage-D8kmjy2v.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-DplR8wP9.js → McpQueryPage-ck-o5m8A.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-DplR8wP9.js.map → McpQueryPage-ck-o5m8A.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-BJKkM9-3.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-BHVEcKV5.js.map → McpRunDetailPage-BJKkM9-3.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-CtlLagcs.js → McpRunsPage-DqhHfD5G.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-CtlLagcs.js.map → McpRunsPage-DqhHfD5G.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js → NamespacePill--uIaGtrN.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js.map → NamespacePill--uIaGtrN.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-DH67bcW9.js → OperationsPage-D6B9Vv__.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-DH67bcW9.js.map → OperationsPage-D6B9Vv__.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-CIH1cxjQ.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-CMkgMewd.js.map → OperatorDashboard-CIH1cxjQ.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js → PageHeader-DClJ33fV.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js.map → PageHeader-DClJ33fV.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js → PageHeaderWithStats-C-TrbKQL.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js.map → PageHeaderWithStats-C-TrbKQL.js.map} +1 -1
- package/dashboard/dist/assets/PersonaDetailPage-DjvfyIph.js +2 -0
- package/dashboard/dist/assets/{PersonaDetailPage-Cs1FFdNq.js.map → PersonaDetailPage-DjvfyIph.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-CHTRdneF.js → PersonasPage-D7ryA8Vc.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-CHTRdneF.js.map → PersonasPage-D7ryA8Vc.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-ChB5pBTZ.js → PortalPage-D3ybr0mo.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-ChB5pBTZ.js.map → PortalPage-D3ybr0mo.js.map} +1 -1
- package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js +2 -0
- package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-CzyqSfal.js → ProcessDetailPage-0xS9EdHe.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-CzyqSfal.js.map → ProcessDetailPage-0xS9EdHe.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-rOwNkaU9.js → ProcessesListPage-93SMj1Fd.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-rOwNkaU9.js.map → ProcessesListPage-93SMj1Fd.js.map} +1 -1
- package/dashboard/dist/assets/{ResolverForm-DibnlZ-A.js → ResolverForm-DfogHDzl.js} +5 -5
- package/dashboard/dist/assets/{ResolverForm-DibnlZ-A.js.map → ResolverForm-DfogHDzl.js.map} +1 -1
- package/dashboard/dist/assets/{RoleDetailPage-Bv9R7iQC.js → RoleDetailPage-DlUOJWSB.js} +3 -3
- package/dashboard/dist/assets/{RoleDetailPage-Bv9R7iQC.js.map → RoleDetailPage-DlUOJWSB.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-D3hkAdKf.js → RolePill-BjD1Qw5y.js} +2 -2
- package/dashboard/dist/assets/{RolePill-D3hkAdKf.js.map → RolePill-BjD1Qw5y.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-DqhHSvaw.js +2 -0
- package/dashboard/dist/assets/{RolesPage-CUP7EH5U.js.map → RolesPage-DqhHSvaw.js.map} +1 -1
- package/dashboard/dist/assets/{RosterWidget-DZtmQcjU.js → RosterWidget-BrIq61HR.js} +2 -2
- package/dashboard/dist/assets/{RosterWidget-DZtmQcjU.js.map → RosterWidget-BrIq61HR.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-D6zQrCNr.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-B9-1vgZr.js.map → RunAsSelector-D6zQrCNr.js.map} +1 -1
- package/dashboard/dist/assets/ScanCodesPage-B2S9DR2f.js +2 -0
- package/dashboard/dist/assets/{ScanCodesPage-KN_e2rJl.js.map → ScanCodesPage-B2S9DR2f.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js +5 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-B-UTgXsG.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-B0qbUOwc.js.map → ScanStationPage-B-UTgXsG.js.map} +1 -1
- package/dashboard/dist/assets/{SchemeMatchFields-CL7TKnw3.js → SchemeMatchFields-BK24aa7K.js} +2 -2
- package/dashboard/dist/assets/{SchemeMatchFields-CL7TKnw3.js.map → SchemeMatchFields-BK24aa7K.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js → ScopeBadge-ofLQ6HW-.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js.map → ScopeBadge-ofLQ6HW-.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-CUwxfBQH.js → StickyPagination-CgVv7vc_.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-CUwxfBQH.js.map → StickyPagination-CgVv7vc_.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-DOjcO7d2.js → StreamMessageDetail-B9sxDVw4.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-DOjcO7d2.js.map → StreamMessageDetail-B9sxDVw4.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-SPMpoLHP.js → SwimlaneTimeline-DQc0CYSL.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-SPMpoLHP.js.map → SwimlaneTimeline-DQc0CYSL.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-DaIdhv3h.js → TagInput-47qVYzke.js} +2 -2
- package/dashboard/dist/assets/{TagInput-DaIdhv3h.js.map → TagInput-47qVYzke.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DvfzR2IQ.js → TaskDetailPage-D6VOsA1f.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DvfzR2IQ.js.map → TaskDetailPage-D6VOsA1f.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js → TaskQueuePill-C5KmdXAl.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js.map → TaskQueuePill-C5KmdXAl.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-Jp6wmL7t.js → TasksListPage-DG8hvO8G.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-Jp6wmL7t.js.map → TasksListPage-DG8hvO8G.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BCQA0Gb_.js → TimeAgo-CL02EhFi.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BCQA0Gb_.js.map → TimeAgo-CL02EhFi.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-xhdMHDQt.js → TimestampCell-BE7oKVJg.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-xhdMHDQt.js.map → TimestampCell-BE7oKVJg.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js → ToolPill-Cp9Drk1s.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js.map → ToolPill-Cp9Drk1s.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-D8M3ITrJ.js → ToolTestPanel-CRecLh6S.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-D8M3ITrJ.js.map → ToolTestPanel-CRecLh6S.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DdBJQp31.js → TopicDetailPage-QzkinTfN.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-DdBJQp31.js.map → TopicDetailPage-QzkinTfN.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-vpvsynD9.js → TopicsPage-D8dW6J65.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-vpvsynD9.js.map → TopicsPage-D8dW6J65.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BK6Lzsdw.js → UserName-Dw3R_zrl.js} +2 -2
- package/dashboard/dist/assets/{UserName-BK6Lzsdw.js.map → UserName-Dw3R_zrl.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-BTocv8or.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-DkM1TS4I.js.map → WorkflowExecutionPage-BTocv8or.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js → WorkflowPill-BiLYq__w.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js.map → WorkflowPill-BiLYq__w.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-CIPEt3et.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-g_N4y3QS.js.map → WorkflowsDashboard-CIPEt3et.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-Drjo-Lu-.js → WorkflowsOverview-Bj4MJIE-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-Drjo-Lu-.js.map → WorkflowsOverview-Bj4MJIE-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CLltNHjZ.js → YamlWorkflowDetailPage-DMEk5k9-.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CLltNHjZ.js.map → YamlWorkflowDetailPage-DMEk5k9-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CxQCB-Zi.js → YamlWorkflowsPage-F2yyyoiB.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CxQCB-Zi.js.map → YamlWorkflowsPage-F2yyyoiB.js.map} +1 -1
- package/dashboard/dist/assets/{agents-Dk25jjhj.js → agents-mSgxEPpI.js} +2 -2
- package/dashboard/dist/assets/{agents-Dk25jjhj.js.map → agents-mSgxEPpI.js.map} +1 -1
- package/dashboard/dist/assets/{bots-bRkCqhlq.js → bots-p4Hp0CV6.js} +2 -2
- package/dashboard/dist/assets/{bots-bRkCqhlq.js.map → bots-p4Hp0CV6.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-DARawLry.js → capabilities-D_-I_SXR.js} +2 -2
- package/dashboard/dist/assets/{capabilities-DARawLry.js.map → capabilities-D_-I_SXR.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-DKccxxs6.js → controlplane-DjdoQnRU.js} +2 -2
- package/dashboard/dist/assets/{controlplane-DKccxxs6.js.map → controlplane-DjdoQnRU.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-BaYuzMYf.js → escalation-columns-R_IEVQjQ.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-BaYuzMYf.js.map → escalation-columns-R_IEVQjQ.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-items-CwbNFnsH.js → escalation-items-BGZlJMpk.js} +2 -2
- package/dashboard/dist/assets/{escalation-items-CwbNFnsH.js.map → escalation-items-BGZlJMpk.js.map} +1 -1
- package/dashboard/dist/assets/{index-Cf6qCgTf.js → index-BEMdD58x.js} +2 -2
- package/dashboard/dist/assets/{index-Cf6qCgTf.js.map → index-BEMdD58x.js.map} +1 -1
- package/dashboard/dist/assets/index-BUmz0NMg.css +1 -0
- package/dashboard/dist/assets/{index-hKOlahpE.js → index-BuCEhhnl.js} +2 -2
- package/dashboard/dist/assets/{index-hKOlahpE.js.map → index-BuCEhhnl.js.map} +1 -1
- package/dashboard/dist/assets/{index-D1uliPqS.js → index-BxbQmeqh.js} +2 -2
- package/dashboard/dist/assets/{index-D1uliPqS.js.map → index-BxbQmeqh.js.map} +1 -1
- package/dashboard/dist/assets/index-C5osluV3.js +2 -0
- package/dashboard/dist/assets/{index-CtrSYqmL.js.map → index-C5osluV3.js.map} +1 -1
- package/dashboard/dist/assets/{index-CU2UW2y6.js → index-C_dAJUzh.js} +25 -25
- package/dashboard/dist/assets/index-C_dAJUzh.js.map +1 -0
- package/dashboard/dist/assets/{index-Bx9HVzuT.js → index-D-FYj9jT.js} +2 -2
- package/dashboard/dist/assets/{index-Bx9HVzuT.js.map → index-D-FYj9jT.js.map} +1 -1
- package/dashboard/dist/assets/{index-BZgtzkkG.js → index-D6K_IgCz.js} +2 -2
- package/dashboard/dist/assets/{index-BZgtzkkG.js.map → index-D6K_IgCz.js.map} +1 -1
- package/dashboard/dist/assets/index-D7L_VoBD.js +2 -0
- package/dashboard/dist/assets/index-D7L_VoBD.js.map +1 -0
- package/dashboard/dist/assets/{index-DgpL_Lgc.js → index-D9RAN9sA.js} +2 -2
- package/dashboard/dist/assets/{index-DgpL_Lgc.js.map → index-D9RAN9sA.js.map} +1 -1
- package/dashboard/dist/assets/{index-dShcvdg3.js → index-DUYAGxwc.js} +2 -2
- package/dashboard/dist/assets/{index-dShcvdg3.js.map → index-DUYAGxwc.js.map} +1 -1
- package/dashboard/dist/assets/{index-E_hJ7vtX.js → index-Dk2KKo0z.js} +2 -2
- package/dashboard/dist/assets/{index-E_hJ7vtX.js.map → index-Dk2KKo0z.js.map} +1 -1
- package/dashboard/dist/assets/{index-DU2QCbgH.js → index-DlJkZ12b.js} +2 -2
- package/dashboard/dist/assets/{index-DU2QCbgH.js.map → index-DlJkZ12b.js.map} +1 -1
- package/dashboard/dist/assets/{index-kzifJWbM.js → index-FiNThtNU.js} +3 -3
- package/dashboard/dist/assets/{index-kzifJWbM.js.map → index-FiNThtNU.js.map} +1 -1
- package/dashboard/dist/assets/{knowledge-DOe5ks-E.js → knowledge-DSsPTqkK.js} +2 -2
- package/dashboard/dist/assets/{knowledge-DOe5ks-E.js.map → knowledge-DSsPTqkK.js.map} +1 -1
- package/dashboard/dist/assets/{machines-Zq_00v7k.js → machines-DSgGtqqr.js} +2 -2
- package/dashboard/dist/assets/{machines-Zq_00v7k.js.map → machines-DSgGtqqr.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-BL8kD0oh.js → mcp-Cg-_uLw8.js} +2 -2
- package/dashboard/dist/assets/{mcp-BL8kD0oh.js.map → mcp-Cg-_uLw8.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-BpokmJWi.js → mcp-query-DQombEK_.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-BpokmJWi.js.map → mcp-query-DQombEK_.js.map} +1 -1
- package/dashboard/dist/assets/{personas-BubCnQZ8.js → personas-DYrcoVBu.js} +2 -2
- package/dashboard/dist/assets/{personas-BubCnQZ8.js.map → personas-DYrcoVBu.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines--DUoMx7K.js → pipelines-wdb4xsey.js} +2 -2
- package/dashboard/dist/assets/{pipelines--DUoMx7K.js.map → pipelines-wdb4xsey.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CJXN4OB4.js → tasks-Bil7gvm9.js} +2 -2
- package/dashboard/dist/assets/{tasks-CJXN4OB4.js.map → tasks-Bil7gvm9.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CAG08Ruo.js → topics-wBqaVhRR.js} +2 -2
- package/dashboard/dist/assets/{topics-CAG08Ruo.js.map → topics-wBqaVhRR.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-DQ2D8cm2.js → useDebouncedValue-CwrY8TpV.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-DQ2D8cm2.js.map → useDebouncedValue-CwrY8TpV.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-DjEVAlJQ.js → useNamespace-Sod_xApz.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-DjEVAlJQ.js.map → useNamespace-Sod_xApz.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-etcpfIwo.js → useYamlActivityEvents-CKLInV3C.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-etcpfIwo.js.map → useYamlActivityEvents-CKLInV3C.js.map} +1 -1
- package/dashboard/dist/assets/{validate-YJK_6a7m.js → validate-CYhW1xMJ.js} +2 -2
- package/dashboard/dist/assets/{validate-YJK_6a7m.js.map → validate-CYhW1xMJ.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js → vendor-icons-ed7mYQw4.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js.map → vendor-icons-ed7mYQw4.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-D97Bz6li.js → yaml-workflows-C20qHo3L.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-D97Bz6li.js.map → yaml-workflows-C20qHo3L.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/labels.md +115 -0
- package/docs/api/http/users.md +2 -0
- package/docs/api/mcp/admin.md +76 -1
- package/docs/code-owned-configuration.md +1 -1
- package/docs/iam.md +12 -0
- package/docs/label-sheets.md +267 -0
- package/docs/machines.md +2 -2
- package/docs/scan-codes.md +11 -5
- package/package.json +4 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-BRKyG5qZ.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-BRKyG5qZ.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-BWfzPrRk.js +0 -2
- package/dashboard/dist/assets/HomePage-BUlSnCg8.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-BHVEcKV5.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-CMkgMewd.js +0 -2
- package/dashboard/dist/assets/PersonaDetailPage-Cs1FFdNq.js +0 -2
- package/dashboard/dist/assets/RolesPage-CUP7EH5U.js +0 -2
- package/dashboard/dist/assets/RunAsSelector-B9-1vgZr.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-KN_e2rJl.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-CqItQ67Y.js +0 -5
- package/dashboard/dist/assets/ScanSchemeDetailPage-CqItQ67Y.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-B0qbUOwc.js +0 -2
- package/dashboard/dist/assets/WorkflowExecutionPage-DkM1TS4I.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-g_N4y3QS.js +0 -2
- package/dashboard/dist/assets/index-BmzscsXK.css +0 -1
- package/dashboard/dist/assets/index-CU2UW2y6.js.map +0 -1
- package/dashboard/dist/assets/index-CtrSYqmL.js +0 -2
- package/dashboard/dist/assets/index-DU-1gMks.js +0 -2
- package/dashboard/dist/assets/index-DU-1gMks.js.map +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// LabelSheet → PDF at exact page size. Text uses Helvetica unless the host
|
|
3
|
+
// registers a font (start({ labels: { font } })) for scripts beyond Latin-1.
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.registerLabelFonts = registerLabelFonts;
|
|
39
|
+
exports.scalePath = scalePath;
|
|
40
|
+
exports.renderSheetPdf = renderSheetPdf;
|
|
41
|
+
const pdf_lib_1 = require("pdf-lib");
|
|
42
|
+
const layout_1 = require("../../shared/labels/layout");
|
|
43
|
+
const PT_PER_MM = 72 / 25.4;
|
|
44
|
+
const BLACK = (0, pdf_lib_1.rgb)(0, 0, 0);
|
|
45
|
+
const WHITE = (0, pdf_lib_1.rgb)(1, 1, 1);
|
|
46
|
+
const pt = (mm) => mm * PT_PER_MM;
|
|
47
|
+
let hostFonts = null;
|
|
48
|
+
/** Fonts for label text in PDFs (TrueType or OpenType bytes). */
|
|
49
|
+
function registerLabelFonts(fonts) {
|
|
50
|
+
hostFonts = fonts;
|
|
51
|
+
}
|
|
52
|
+
/** Characters Helvetica (WinAnsi) cannot draw become "?"; a host font draws them all. */
|
|
53
|
+
function drawable(text, font) {
|
|
54
|
+
try {
|
|
55
|
+
font.encodeText(text);
|
|
56
|
+
return text;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return Array.from(text, (ch) => {
|
|
60
|
+
try {
|
|
61
|
+
font.encodeText(ch);
|
|
62
|
+
return ch;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return '?';
|
|
66
|
+
}
|
|
67
|
+
}).join('');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function drawElement(page, el, ox, oy, height, fonts) {
|
|
71
|
+
const y = (mm) => height - pt(oy + mm);
|
|
72
|
+
if (el.kind === 'rect') {
|
|
73
|
+
page.drawRectangle({
|
|
74
|
+
x: pt(ox + el.x), y: y(el.y + el.h), width: pt(el.w), height: pt(el.h),
|
|
75
|
+
...(el.fill ? { color: BLACK } : { borderColor: BLACK, borderWidth: pt(el.stroke ?? 0.3) }),
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (el.kind === 'text') {
|
|
80
|
+
const font = el.weight === 'bold' ? fonts.bold : fonts.regular;
|
|
81
|
+
const text = drawable(el.text, font);
|
|
82
|
+
let size = pt(el.size);
|
|
83
|
+
const max = pt(el.w);
|
|
84
|
+
const measured = font.widthOfTextAtSize(text, size);
|
|
85
|
+
if (measured > max)
|
|
86
|
+
size *= max / measured;
|
|
87
|
+
const width = font.widthOfTextAtSize(text, size);
|
|
88
|
+
const x = el.align === 'center' ? pt(ox + el.x) + (max - width) / 2 : pt(ox + el.x);
|
|
89
|
+
page.drawText(text, { x, y: y(el.y + el.size * 0.8), size, font, color: el.inverse ? WHITE : BLACK });
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (el.masked) {
|
|
93
|
+
page.drawRectangle({ x: pt(ox + el.x), y: y(el.y + el.h), width: pt(el.w), height: pt(el.h), color: (0, pdf_lib_1.rgb)(0.87, 0.87, 0.87) });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const scaleY = el.symbology === 'code128' ? pt(el.h) : pt(el.moduleMm);
|
|
97
|
+
page.drawSvgPath(scalePath(el.path, pt(el.moduleMm), scaleY), { x: pt(ox + el.x), y: height - pt(oy + el.y), color: BLACK });
|
|
98
|
+
}
|
|
99
|
+
/** Scale an SVG path of M/h/v/z commands by (sx, sy); pdf-lib's own scale is uniform. */
|
|
100
|
+
function scalePath(path, sx, sy) {
|
|
101
|
+
return path.replace(/([Mhv])(-?[\d.]+)(?: (-?[\d.]+))?/g, (_m, cmd, a, b) => {
|
|
102
|
+
if (cmd === 'M')
|
|
103
|
+
return `M${Number(a) * sx} ${Number(b) * sy}`;
|
|
104
|
+
return `${cmd}${Number(a) * (cmd === 'h' ? sx : sy)}`;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/** Render a sheet as a PDF document. */
|
|
108
|
+
async function renderSheetPdf(sheet) {
|
|
109
|
+
const doc = await pdf_lib_1.PDFDocument.create();
|
|
110
|
+
let fonts;
|
|
111
|
+
if (hostFonts) {
|
|
112
|
+
const fontkit = (await Promise.resolve().then(() => __importStar(require('@pdf-lib/fontkit')))).default;
|
|
113
|
+
doc.registerFontkit(fontkit);
|
|
114
|
+
const regular = await doc.embedFont(hostFonts.regular, { subset: true });
|
|
115
|
+
fonts = { regular, bold: hostFonts.bold ? await doc.embedFont(hostFonts.bold, { subset: true }) : regular };
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
fonts = { regular: await doc.embedFont(pdf_lib_1.StandardFonts.Helvetica), bold: await doc.embedFont(pdf_lib_1.StandardFonts.HelveticaBold) };
|
|
119
|
+
}
|
|
120
|
+
const { media } = sheet;
|
|
121
|
+
const width = pt(media.pageWidthMm);
|
|
122
|
+
const height = pt(media.pageHeightMm);
|
|
123
|
+
for (const sheetPage of sheet.pages) {
|
|
124
|
+
const page = doc.addPage([width, height]);
|
|
125
|
+
if (sheet.cutMarks) {
|
|
126
|
+
for (const [x1, y1, x2, y2] of (0, layout_1.cutMarkSegments)(media)) {
|
|
127
|
+
page.drawLine({ start: { x: pt(x1), y: height - pt(y1) }, end: { x: pt(x2), y: height - pt(y2) }, thickness: pt(0.15), color: BLACK });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
for (const placed of sheetPage.labels) {
|
|
131
|
+
for (const el of placed.elements)
|
|
132
|
+
drawElement(page, el, placed.x, placed.y, height, fonts);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
doc.setProducer('Long Tail label sheets');
|
|
136
|
+
doc.setCreationDate(new Date(0));
|
|
137
|
+
return doc.save();
|
|
138
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ScanScheme } from '../../types';
|
|
2
|
+
import type { LTApiAuth } from '../../types/sdk';
|
|
3
|
+
import type { LabelSource, LabelTarget } from '../../types/labels';
|
|
4
|
+
export declare const MAX_RANGE_PAD = 12;
|
|
5
|
+
/** Targets from pasted lines or CSV. A first row naming `target` is a header; its columns become item tokens. */
|
|
6
|
+
export declare function parseListSource(text: string): LabelTarget[];
|
|
7
|
+
/** Targets from a numeric run: prefix + zero-padded number + suffix. */
|
|
8
|
+
export declare function expandRangeSource(source: Extract<LabelSource, {
|
|
9
|
+
kind: 'range';
|
|
10
|
+
}>, max: number): LabelTarget[];
|
|
11
|
+
/**
|
|
12
|
+
* The targets a source names. Identity schemes read users only: a pasted or
|
|
13
|
+
* ranged credential would mint a badge for no one. Rows are read as the
|
|
14
|
+
* caller, so a job never prints what the caller cannot see.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveLabelTargets(source: LabelSource, scheme: ScanScheme, auth: LTApiAuth): Promise<LabelTarget[]>;
|
|
17
|
+
/** Marks which action targets name a row today, in one statement. */
|
|
18
|
+
export declare function markResolvedTargets(targets: LabelTarget[], scheme: ScanScheme): Promise<void>;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Resolves a print job's source into targets, reading as the caller.
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.MAX_RANGE_PAD = void 0;
|
|
38
|
+
exports.parseListSource = parseListSource;
|
|
39
|
+
exports.expandRangeSource = expandRangeSource;
|
|
40
|
+
exports.resolveLabelTargets = resolveLabelTargets;
|
|
41
|
+
exports.markResolvedTargets = markResolvedTargets;
|
|
42
|
+
const db_1 = require("../../lib/db");
|
|
43
|
+
const config_1 = require("../../modules/config");
|
|
44
|
+
const types_1 = require("../../types");
|
|
45
|
+
const errors_1 = require("./errors");
|
|
46
|
+
exports.MAX_RANGE_PAD = 12;
|
|
47
|
+
function cap(scheme) {
|
|
48
|
+
return scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY
|
|
49
|
+
? config_1.config.LT_LABELS_MAX_CREDENTIALS_PER_JOB
|
|
50
|
+
: config_1.config.LT_LABELS_MAX_PER_JOB;
|
|
51
|
+
}
|
|
52
|
+
function assertCount(n, scheme) {
|
|
53
|
+
if (n === 0)
|
|
54
|
+
throw new errors_1.LabelRequestError(400, 'the source names no targets');
|
|
55
|
+
if (n > cap(scheme))
|
|
56
|
+
throw new errors_1.LabelRequestError(400, `the source names ${n} targets; one job prints at most ${cap(scheme)}`);
|
|
57
|
+
}
|
|
58
|
+
/** Targets from pasted lines or CSV. A first row naming `target` is a header; its columns become item tokens. */
|
|
59
|
+
function parseListSource(text) {
|
|
60
|
+
const rows = text.split(/\r?\n/).map((l) => l.trim()).filter(Boolean)
|
|
61
|
+
.map((l) => l.split(/[,\t]/).map((c) => c.trim()));
|
|
62
|
+
if (rows.length === 0)
|
|
63
|
+
return [];
|
|
64
|
+
const header = rows[0][0].toLowerCase() === 'target' ? rows.shift().map((h) => h.replace(/[^a-zA-Z0-9_]/g, '_')) : null;
|
|
65
|
+
return rows.map((cells) => {
|
|
66
|
+
const item = {};
|
|
67
|
+
cells.slice(1).forEach((value, i) => { item[header?.[i + 1] || `col${i + 2}`] = value; });
|
|
68
|
+
return { target: cells[0], item };
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/** Targets from a numeric run: prefix + zero-padded number + suffix. */
|
|
72
|
+
function expandRangeSource(source, max) {
|
|
73
|
+
const { from, to, pad = 0, prefix = '', suffix = '' } = source;
|
|
74
|
+
if (!Number.isInteger(from) || !Number.isInteger(to) || from < 0 || to < from) {
|
|
75
|
+
throw new errors_1.LabelRequestError(400, 'a range needs whole numbers with from ≤ to');
|
|
76
|
+
}
|
|
77
|
+
if (!Number.isInteger(pad) || pad < 0 || pad > exports.MAX_RANGE_PAD) {
|
|
78
|
+
throw new errors_1.LabelRequestError(400, `pad must be between 0 and ${exports.MAX_RANGE_PAD}`);
|
|
79
|
+
}
|
|
80
|
+
if (to - from + 1 > max)
|
|
81
|
+
throw new errors_1.LabelRequestError(400, `the range names ${to - from + 1} targets; one job prints at most ${max}`);
|
|
82
|
+
return Array.from({ length: to - from + 1 }, (_, i) => ({
|
|
83
|
+
target: `${prefix}${String(from + i).padStart(pad, '0')}${suffix}`,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
/** Rows read at once for a selection; each read applies the caller's own access check. */
|
|
87
|
+
const ESCALATION_READ_CHUNK = 25;
|
|
88
|
+
async function escalationTargets(ids, scheme, auth) {
|
|
89
|
+
const { getEscalation } = await Promise.resolve().then(() => __importStar(require('../../api/escalations/single')));
|
|
90
|
+
const unique = [...new Set(ids)];
|
|
91
|
+
const byTarget = new Map();
|
|
92
|
+
for (let i = 0; i < unique.length; i += ESCALATION_READ_CHUNK) {
|
|
93
|
+
const chunk = unique.slice(i, i + ESCALATION_READ_CHUNK);
|
|
94
|
+
const results = await Promise.all(chunk.map((id) => getEscalation({ id }, auth)));
|
|
95
|
+
results.forEach((result, j) => {
|
|
96
|
+
if (result.status !== 200) {
|
|
97
|
+
throw new errors_1.LabelRequestError(result.status === 404 ? 404 : 403, `escalation ${chunk[j]}: ${result.error}`);
|
|
98
|
+
}
|
|
99
|
+
addRow(byTarget, result.data, scheme);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
return [...byTarget.values()];
|
|
103
|
+
}
|
|
104
|
+
async function facetTargets(source, scheme, auth) {
|
|
105
|
+
const { searchByFacets } = await Promise.resolve().then(() => __importStar(require('../../api/escalations/facets')));
|
|
106
|
+
const result = await searchByFacets({ ...source.query, limit: cap(scheme) + 1 }, auth);
|
|
107
|
+
if (result.status !== 200)
|
|
108
|
+
throw new errors_1.LabelRequestError(result.status === 400 ? 400 : 403, result.error ?? 'facet search refused');
|
|
109
|
+
const byTarget = new Map();
|
|
110
|
+
for (const row of result.data.escalations)
|
|
111
|
+
addRow(byTarget, row, scheme);
|
|
112
|
+
return [...byTarget.values()];
|
|
113
|
+
}
|
|
114
|
+
/** Keep the newest row per target; a member facet contributes each of its values. */
|
|
115
|
+
function addRow(byTarget, row, scheme) {
|
|
116
|
+
const value = row.metadata?.[scheme.target_facet];
|
|
117
|
+
const values = Array.isArray(value) && scheme.target_match === types_1.SCAN_TARGET_MATCH.MEMBER ? value : [value];
|
|
118
|
+
for (const v of values) {
|
|
119
|
+
if (v === undefined || v === null || v === '')
|
|
120
|
+
continue;
|
|
121
|
+
const target = String(v);
|
|
122
|
+
const seen = byTarget.get(target);
|
|
123
|
+
if (!seen || String(row.created_at) > String(seen.item?.__created_at ?? '')) {
|
|
124
|
+
byTarget.set(target, { target, item: { ...row.metadata, __created_at: row.created_at }, resolved: true });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const USERS_WITH_KEY = `
|
|
129
|
+
SELECT u.id FROM lt_users u
|
|
130
|
+
WHERE u.metadata ? $1
|
|
131
|
+
AND ($2::uuid[] IS NOT NULL OR u.status = 'active')
|
|
132
|
+
AND ($2::uuid[] IS NULL OR u.id = ANY($2::uuid[]))
|
|
133
|
+
AND ($3::text IS NULL OR EXISTS (SELECT 1 FROM lt_user_roles r WHERE r.user_id = u.id AND r.role = $3))
|
|
134
|
+
ORDER BY u.display_name NULLS LAST, u.external_id
|
|
135
|
+
LIMIT $4`;
|
|
136
|
+
async function userTargets(source, scheme) {
|
|
137
|
+
const { getUser, getIdentityPropertyKeys } = await Promise.resolve().then(() => __importStar(require('../user')));
|
|
138
|
+
const { onlyUuids } = await Promise.resolve().then(() => __importStar(require('../../lib/uuid')));
|
|
139
|
+
const ids = source.userIds ? onlyUuids(source.userIds) : null;
|
|
140
|
+
if (source.userIds && ids.length !== new Set(source.userIds).size) {
|
|
141
|
+
throw new errors_1.LabelRequestError(400, 'userIds must be user ids');
|
|
142
|
+
}
|
|
143
|
+
const { rows } = await (0, db_1.getPool)().query(USERS_WITH_KEY, [scheme.target_facet, ids, source.role ?? null, cap(scheme) + 1]);
|
|
144
|
+
const identityKeys = await getIdentityPropertyKeys();
|
|
145
|
+
const users = await Promise.all(rows.map((r) => getUser(r.id)));
|
|
146
|
+
return users.filter((u) => u !== null).map((u) => {
|
|
147
|
+
const metadata = { ...(u.metadata ?? {}) };
|
|
148
|
+
for (const key of identityKeys)
|
|
149
|
+
delete metadata[key];
|
|
150
|
+
return {
|
|
151
|
+
target: String(u.metadata[scheme.target_facet]),
|
|
152
|
+
userId: u.id,
|
|
153
|
+
resolved: u.status === 'active',
|
|
154
|
+
user: {
|
|
155
|
+
...metadata,
|
|
156
|
+
name: u.display_name ?? u.external_id,
|
|
157
|
+
display_name: u.display_name,
|
|
158
|
+
email: u.email,
|
|
159
|
+
roles: u.roles.map((r) => r.role),
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The targets a source names. Identity schemes read users only: a pasted or
|
|
166
|
+
* ranged credential would mint a badge for no one. Rows are read as the
|
|
167
|
+
* caller, so a job never prints what the caller cannot see.
|
|
168
|
+
*/
|
|
169
|
+
async function resolveLabelTargets(source, scheme, auth) {
|
|
170
|
+
const identity = scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY;
|
|
171
|
+
if (identity && source.kind !== 'users') {
|
|
172
|
+
throw new errors_1.LabelRequestError(400, 'identity labels print for users; use a users source');
|
|
173
|
+
}
|
|
174
|
+
if (!identity && source.kind === 'users') {
|
|
175
|
+
throw new errors_1.LabelRequestError(400, 'a users source prints identity labels only');
|
|
176
|
+
}
|
|
177
|
+
let targets;
|
|
178
|
+
switch (source.kind) {
|
|
179
|
+
case 'escalations':
|
|
180
|
+
if (!Array.isArray(source.ids))
|
|
181
|
+
throw new errors_1.LabelRequestError(400, 'ids must be a list');
|
|
182
|
+
assertCount(new Set(source.ids).size, scheme);
|
|
183
|
+
targets = await escalationTargets(source.ids, scheme, auth);
|
|
184
|
+
break;
|
|
185
|
+
case 'facets':
|
|
186
|
+
targets = await facetTargets(source, scheme, auth);
|
|
187
|
+
break;
|
|
188
|
+
case 'users':
|
|
189
|
+
targets = await userTargets(source, scheme);
|
|
190
|
+
break;
|
|
191
|
+
case 'list':
|
|
192
|
+
targets = parseListSource(String(source.text ?? ''));
|
|
193
|
+
break;
|
|
194
|
+
case 'range':
|
|
195
|
+
targets = expandRangeSource(source, cap(scheme));
|
|
196
|
+
break;
|
|
197
|
+
default:
|
|
198
|
+
throw new errors_1.LabelRequestError(400, `unknown source kind "${source.kind}"`);
|
|
199
|
+
}
|
|
200
|
+
for (const t of targets)
|
|
201
|
+
delete t.item?.__created_at;
|
|
202
|
+
assertCount(targets.length, scheme);
|
|
203
|
+
return targets;
|
|
204
|
+
}
|
|
205
|
+
/** Marks which action targets name a row today, in one statement. */
|
|
206
|
+
async function markResolvedTargets(targets, scheme) {
|
|
207
|
+
const unchecked = targets.filter((t) => t.resolved === undefined);
|
|
208
|
+
if (unchecked.length === 0)
|
|
209
|
+
return;
|
|
210
|
+
const member = scheme.target_match === types_1.SCAN_TARGET_MATCH.MEMBER;
|
|
211
|
+
const { rows } = await (0, db_1.getPool)().query(`SELECT t FROM unnest($2::text[]) AS t
|
|
212
|
+
WHERE EXISTS (SELECT 1 FROM lt_escalations e WHERE e.metadata @> ${member ? 'jsonb_build_object($1::text, jsonb_build_array(t))' : 'jsonb_build_object($1::text, t)'})`, [scheme.target_facet, unchecked.map((t) => t.target)]);
|
|
213
|
+
const found = new Set(rows.map((r) => r.t));
|
|
214
|
+
for (const t of unchecked)
|
|
215
|
+
t.resolved = found.has(t.target);
|
|
216
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { listLabelTemplates, getLabelTemplate, mapTemplate } from './read';
|
|
2
|
+
export { upsertLabelTemplate, deleteLabelTemplate, seedLabelTemplate, applyLabelTemplate, LabelTemplateConflictError, } from './write';
|
|
3
|
+
export { assertValidTemplate, LabelTemplateValidationError, MAX_TEMPLATE_CODES, MAX_TEMPLATE_LINES, type TemplateContext, } from './validate';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_TEMPLATE_LINES = exports.MAX_TEMPLATE_CODES = exports.LabelTemplateValidationError = exports.assertValidTemplate = exports.LabelTemplateConflictError = exports.applyLabelTemplate = exports.seedLabelTemplate = exports.deleteLabelTemplate = exports.upsertLabelTemplate = exports.mapTemplate = exports.getLabelTemplate = exports.listLabelTemplates = void 0;
|
|
4
|
+
var read_1 = require("./read");
|
|
5
|
+
Object.defineProperty(exports, "listLabelTemplates", { enumerable: true, get: function () { return read_1.listLabelTemplates; } });
|
|
6
|
+
Object.defineProperty(exports, "getLabelTemplate", { enumerable: true, get: function () { return read_1.getLabelTemplate; } });
|
|
7
|
+
Object.defineProperty(exports, "mapTemplate", { enumerable: true, get: function () { return read_1.mapTemplate; } });
|
|
8
|
+
var write_1 = require("./write");
|
|
9
|
+
Object.defineProperty(exports, "upsertLabelTemplate", { enumerable: true, get: function () { return write_1.upsertLabelTemplate; } });
|
|
10
|
+
Object.defineProperty(exports, "deleteLabelTemplate", { enumerable: true, get: function () { return write_1.deleteLabelTemplate; } });
|
|
11
|
+
Object.defineProperty(exports, "seedLabelTemplate", { enumerable: true, get: function () { return write_1.seedLabelTemplate; } });
|
|
12
|
+
Object.defineProperty(exports, "applyLabelTemplate", { enumerable: true, get: function () { return write_1.applyLabelTemplate; } });
|
|
13
|
+
Object.defineProperty(exports, "LabelTemplateConflictError", { enumerable: true, get: function () { return write_1.LabelTemplateConflictError; } });
|
|
14
|
+
var validate_1 = require("./validate");
|
|
15
|
+
Object.defineProperty(exports, "assertValidTemplate", { enumerable: true, get: function () { return validate_1.assertValidTemplate; } });
|
|
16
|
+
Object.defineProperty(exports, "LabelTemplateValidationError", { enumerable: true, get: function () { return validate_1.LabelTemplateValidationError; } });
|
|
17
|
+
Object.defineProperty(exports, "MAX_TEMPLATE_CODES", { enumerable: true, get: function () { return validate_1.MAX_TEMPLATE_CODES; } });
|
|
18
|
+
Object.defineProperty(exports, "MAX_TEMPLATE_LINES", { enumerable: true, get: function () { return validate_1.MAX_TEMPLATE_LINES; } });
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { LabelTemplate } from '../../../types/labels';
|
|
2
|
+
export declare function mapTemplate(row: any): LabelTemplate;
|
|
3
|
+
export declare function listLabelTemplates(schemeVersion?: number): Promise<LabelTemplate[]>;
|
|
4
|
+
export declare function getLabelTemplate(name: string): Promise<LabelTemplate | null>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapTemplate = mapTemplate;
|
|
4
|
+
exports.listLabelTemplates = listLabelTemplates;
|
|
5
|
+
exports.getLabelTemplate = getLabelTemplate;
|
|
6
|
+
const db_1 = require("../../../lib/db");
|
|
7
|
+
const sql_1 = require("./sql");
|
|
8
|
+
function mapTemplate(row) {
|
|
9
|
+
return {
|
|
10
|
+
name: row.name,
|
|
11
|
+
scheme_version: row.scheme_version,
|
|
12
|
+
title: row.title,
|
|
13
|
+
description: row.description ?? null,
|
|
14
|
+
codes: row.codes ?? [],
|
|
15
|
+
text: row.text ?? {},
|
|
16
|
+
symbology: row.symbology,
|
|
17
|
+
human_readable: row.human_readable,
|
|
18
|
+
media: row.media ?? null,
|
|
19
|
+
sensitive: row.sensitive,
|
|
20
|
+
enabled: row.enabled,
|
|
21
|
+
revision: row.revision,
|
|
22
|
+
source: row.source,
|
|
23
|
+
created_at: row.created_at,
|
|
24
|
+
updated_at: row.updated_at,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
async function listLabelTemplates(schemeVersion) {
|
|
28
|
+
const { rows } = schemeVersion === undefined
|
|
29
|
+
? await (0, db_1.getPool)().query(sql_1.LIST_TEMPLATES)
|
|
30
|
+
: await (0, db_1.getPool)().query(sql_1.LIST_TEMPLATES_BY_SCHEME, [schemeVersion]);
|
|
31
|
+
return rows.map(mapTemplate);
|
|
32
|
+
}
|
|
33
|
+
async function getLabelTemplate(name) {
|
|
34
|
+
const { rows } = await (0, db_1.getPool)().query(sql_1.GET_TEMPLATE, [name]);
|
|
35
|
+
return rows[0] ? mapTemplate(rows[0]) : null;
|
|
36
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const LIST_TEMPLATES = "SELECT * FROM lt_config_label_templates ORDER BY scheme_version, name";
|
|
2
|
+
export declare const LIST_TEMPLATES_BY_SCHEME = "SELECT * FROM lt_config_label_templates WHERE scheme_version = $1 ORDER BY name";
|
|
3
|
+
export declare const GET_TEMPLATE = "SELECT * FROM lt_config_label_templates WHERE name = $1";
|
|
4
|
+
export declare const DELETE_TEMPLATE = "DELETE FROM lt_config_label_templates WHERE name = $1";
|
|
5
|
+
/** API write. $13 is the expected revision; null writes unconditionally. */
|
|
6
|
+
export declare const UPSERT_TEMPLATE = "INSERT INTO lt_config_label_templates (name, scheme_version, title, description, codes, text, symbology,\n human_readable, media, sensitive, enabled, source)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (name) DO UPDATE SET scheme_version = EXCLUDED.scheme_version,\n title = EXCLUDED.title,\n description = EXCLUDED.description,\n codes = EXCLUDED.codes,\n text = EXCLUDED.text,\n symbology = EXCLUDED.symbology,\n human_readable = EXCLUDED.human_readable,\n media = EXCLUDED.media,\n sensitive = EXCLUDED.sensitive,\n enabled = EXCLUDED.enabled,\n source = EXCLUDED.source,\n revision = lt_config_label_templates.revision + 1\nWHERE $13::int IS NULL OR lt_config_label_templates.revision = $13::int\nRETURNING *";
|
|
7
|
+
export declare const SEED_TEMPLATE = "INSERT INTO lt_config_label_templates (name, scheme_version, title, description, codes, text, symbology,\n human_readable, media, sensitive, enabled, source)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (name) DO NOTHING";
|
|
8
|
+
export declare const APPLY_TEMPLATE = "INSERT INTO lt_config_label_templates (name, scheme_version, title, description, codes, text, symbology,\n human_readable, media, sensitive, enabled, source)\nVALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)\nON CONFLICT (name) DO UPDATE SET scheme_version = EXCLUDED.scheme_version,\n title = EXCLUDED.title,\n description = EXCLUDED.description,\n codes = EXCLUDED.codes,\n text = EXCLUDED.text,\n symbology = EXCLUDED.symbology,\n human_readable = EXCLUDED.human_readable,\n media = EXCLUDED.media,\n sensitive = EXCLUDED.sensitive,\n enabled = EXCLUDED.enabled,\n source = EXCLUDED.source,\n revision = lt_config_label_templates.revision + 1\nWHERE (lt_config_label_templates.scheme_version, lt_config_label_templates.title,\n lt_config_label_templates.description, lt_config_label_templates.codes,\n lt_config_label_templates.text, lt_config_label_templates.symbology,\n lt_config_label_templates.human_readable, lt_config_label_templates.media,\n lt_config_label_templates.sensitive, lt_config_label_templates.enabled,\n lt_config_label_templates.source)\n IS DISTINCT FROM\n (EXCLUDED.scheme_version, EXCLUDED.title, EXCLUDED.description, EXCLUDED.codes,\n EXCLUDED.text, EXCLUDED.symbology, EXCLUDED.human_readable, EXCLUDED.media,\n EXCLUDED.sensitive, EXCLUDED.enabled, EXCLUDED.source)\nRETURNING (xmax = 0) AS inserted";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// lt_config_label_templates. Writes bump `revision`; the apply pass is a
|
|
3
|
+
// zero-row no-op when the declaration is unchanged.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.APPLY_TEMPLATE = exports.SEED_TEMPLATE = exports.UPSERT_TEMPLATE = exports.DELETE_TEMPLATE = exports.GET_TEMPLATE = exports.LIST_TEMPLATES_BY_SCHEME = exports.LIST_TEMPLATES = void 0;
|
|
6
|
+
const COLUMNS = `name, scheme_version, title, description, codes, text, symbology,
|
|
7
|
+
human_readable, media, sensitive, enabled, source`;
|
|
8
|
+
const VALUES = '$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12';
|
|
9
|
+
const SET = `scheme_version = EXCLUDED.scheme_version,
|
|
10
|
+
title = EXCLUDED.title,
|
|
11
|
+
description = EXCLUDED.description,
|
|
12
|
+
codes = EXCLUDED.codes,
|
|
13
|
+
text = EXCLUDED.text,
|
|
14
|
+
symbology = EXCLUDED.symbology,
|
|
15
|
+
human_readable = EXCLUDED.human_readable,
|
|
16
|
+
media = EXCLUDED.media,
|
|
17
|
+
sensitive = EXCLUDED.sensitive,
|
|
18
|
+
enabled = EXCLUDED.enabled,
|
|
19
|
+
source = EXCLUDED.source,
|
|
20
|
+
revision = lt_config_label_templates.revision + 1`;
|
|
21
|
+
exports.LIST_TEMPLATES = 'SELECT * FROM lt_config_label_templates ORDER BY scheme_version, name';
|
|
22
|
+
exports.LIST_TEMPLATES_BY_SCHEME = 'SELECT * FROM lt_config_label_templates WHERE scheme_version = $1 ORDER BY name';
|
|
23
|
+
exports.GET_TEMPLATE = 'SELECT * FROM lt_config_label_templates WHERE name = $1';
|
|
24
|
+
exports.DELETE_TEMPLATE = 'DELETE FROM lt_config_label_templates WHERE name = $1';
|
|
25
|
+
/** API write. $13 is the expected revision; null writes unconditionally. */
|
|
26
|
+
exports.UPSERT_TEMPLATE = `\
|
|
27
|
+
INSERT INTO lt_config_label_templates (${COLUMNS})
|
|
28
|
+
VALUES (${VALUES})
|
|
29
|
+
ON CONFLICT (name) DO UPDATE SET ${SET}
|
|
30
|
+
WHERE $13::int IS NULL OR lt_config_label_templates.revision = $13::int
|
|
31
|
+
RETURNING *`;
|
|
32
|
+
exports.SEED_TEMPLATE = `\
|
|
33
|
+
INSERT INTO lt_config_label_templates (${COLUMNS})
|
|
34
|
+
VALUES (${VALUES})
|
|
35
|
+
ON CONFLICT (name) DO NOTHING`;
|
|
36
|
+
exports.APPLY_TEMPLATE = `\
|
|
37
|
+
INSERT INTO lt_config_label_templates (${COLUMNS})
|
|
38
|
+
VALUES (${VALUES})
|
|
39
|
+
ON CONFLICT (name) DO UPDATE SET ${SET}
|
|
40
|
+
WHERE (lt_config_label_templates.scheme_version, lt_config_label_templates.title,
|
|
41
|
+
lt_config_label_templates.description, lt_config_label_templates.codes,
|
|
42
|
+
lt_config_label_templates.text, lt_config_label_templates.symbology,
|
|
43
|
+
lt_config_label_templates.human_readable, lt_config_label_templates.media,
|
|
44
|
+
lt_config_label_templates.sensitive, lt_config_label_templates.enabled,
|
|
45
|
+
lt_config_label_templates.source)
|
|
46
|
+
IS DISTINCT FROM
|
|
47
|
+
(EXCLUDED.scheme_version, EXCLUDED.title, EXCLUDED.description, EXCLUDED.codes,
|
|
48
|
+
EXCLUDED.text, EXCLUDED.symbology, EXCLUDED.human_readable, EXCLUDED.media,
|
|
49
|
+
EXCLUDED.sensitive, EXCLUDED.enabled, EXCLUDED.source)
|
|
50
|
+
RETURNING (xmax = 0) AS inserted`;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ScanRule, type ScanScheme } from '../../../types';
|
|
2
|
+
import type { LabelTemplateInput } from '../../../types/labels';
|
|
3
|
+
/** A template declaration that cannot be stored. */
|
|
4
|
+
export declare class LabelTemplateValidationError extends Error {
|
|
5
|
+
status: number;
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
export declare const MAX_TEMPLATE_CODES = 4;
|
|
9
|
+
export declare const MAX_TEMPLATE_LINES = 2;
|
|
10
|
+
export interface TemplateContext {
|
|
11
|
+
scheme: ScanScheme | null;
|
|
12
|
+
rules: ScanRule[];
|
|
13
|
+
/** Every identity key in use, so a token can never print a credential as text. */
|
|
14
|
+
identityKeys: string[];
|
|
15
|
+
/** Media preset ids the deployment knows. */
|
|
16
|
+
mediaIds: string[];
|
|
17
|
+
}
|
|
18
|
+
/** Throws LabelTemplateValidationError unless the template fits its scheme. */
|
|
19
|
+
export declare function assertValidTemplate(input: LabelTemplateInput, ctx: TemplateContext): void;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Template validation against its scheme, its rules and the identity keys.
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.MAX_TEMPLATE_LINES = exports.MAX_TEMPLATE_CODES = exports.LabelTemplateValidationError = void 0;
|
|
5
|
+
exports.assertValidTemplate = assertValidTemplate;
|
|
6
|
+
const types_1 = require("../../../shared/labels/types");
|
|
7
|
+
const compose_1 = require("../../../shared/labels/compose");
|
|
8
|
+
const tokens_1 = require("../../../shared/labels/tokens");
|
|
9
|
+
const types_2 = require("../../../types");
|
|
10
|
+
/** A template declaration that cannot be stored. */
|
|
11
|
+
class LabelTemplateValidationError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.status = 400;
|
|
15
|
+
this.name = 'LabelTemplateValidationError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.LabelTemplateValidationError = LabelTemplateValidationError;
|
|
19
|
+
exports.MAX_TEMPLATE_CODES = 4;
|
|
20
|
+
exports.MAX_TEMPLATE_LINES = 2;
|
|
21
|
+
const MAX_TEXT_LENGTH = 160;
|
|
22
|
+
const NAME = /^[a-z0-9][a-z0-9-]{0,62}$/;
|
|
23
|
+
function fail(message) {
|
|
24
|
+
throw new LabelTemplateValidationError(message);
|
|
25
|
+
}
|
|
26
|
+
function assertText(label, text) {
|
|
27
|
+
if (typeof text !== 'string')
|
|
28
|
+
fail(`${label} must be text`);
|
|
29
|
+
if (text.length > MAX_TEXT_LENGTH)
|
|
30
|
+
fail(`${label} is longer than ${MAX_TEXT_LENGTH} characters`);
|
|
31
|
+
}
|
|
32
|
+
/** Throws LabelTemplateValidationError unless the template fits its scheme. */
|
|
33
|
+
function assertValidTemplate(input, ctx) {
|
|
34
|
+
if (typeof input.name !== 'string' || !NAME.test(input.name)) {
|
|
35
|
+
fail('name must be lowercase letters, digits and dashes, starting with a letter or digit');
|
|
36
|
+
}
|
|
37
|
+
const { scheme } = ctx;
|
|
38
|
+
if (!scheme)
|
|
39
|
+
fail(`scan scheme ${input.scheme_version} does not exist`);
|
|
40
|
+
if (!(0, compose_1.isMintableScheme)(scheme)) {
|
|
41
|
+
fail(`scheme ${scheme.version} reads ${scheme.encoding} codes; templates print fixed and delimited codes only`);
|
|
42
|
+
}
|
|
43
|
+
if (!input.title || typeof input.title !== 'string')
|
|
44
|
+
fail('title is required');
|
|
45
|
+
assertText('title', input.title);
|
|
46
|
+
if (input.description != null)
|
|
47
|
+
assertText('description', input.description);
|
|
48
|
+
if (!Array.isArray(input.codes) || input.codes.length < 1 || input.codes.length > exports.MAX_TEMPLATE_CODES) {
|
|
49
|
+
fail(`a template prints 1 to ${exports.MAX_TEMPLATE_CODES} codes`);
|
|
50
|
+
}
|
|
51
|
+
const categories = new Set();
|
|
52
|
+
for (const code of input.codes) {
|
|
53
|
+
if (!ctx.rules.some((r) => r.category === code.category)) {
|
|
54
|
+
fail(`scheme ${scheme.version} has no rule for category "${code.category}"`);
|
|
55
|
+
}
|
|
56
|
+
if (categories.has(code.category))
|
|
57
|
+
fail(`category "${code.category}" is printed twice`);
|
|
58
|
+
categories.add(code.category);
|
|
59
|
+
if (!types_1.LABEL_TONES.includes(code.tone))
|
|
60
|
+
fail(`tone must be one of ${types_1.LABEL_TONES.join(', ')}`);
|
|
61
|
+
if (code.caption != null)
|
|
62
|
+
assertText('caption', code.caption);
|
|
63
|
+
}
|
|
64
|
+
const lines = input.text?.lines ?? [];
|
|
65
|
+
if (!Array.isArray(lines) || lines.length > exports.MAX_TEMPLATE_LINES)
|
|
66
|
+
fail(`a template prints up to ${exports.MAX_TEMPLATE_LINES} lines`);
|
|
67
|
+
const texts = [input.text?.title ?? '', ...lines, ...input.codes.map((c) => c.caption ?? '')];
|
|
68
|
+
texts.forEach((t, i) => assertText(i === 0 ? 'text title' : 'text line', t));
|
|
69
|
+
const identity = scheme.kind === types_2.SCAN_SCHEME_KINDS.IDENTITY;
|
|
70
|
+
for (const text of texts) {
|
|
71
|
+
const unknown = (0, tokens_1.unknownLabelTokens)(text);
|
|
72
|
+
if (unknown.length)
|
|
73
|
+
fail(`unknown token {${unknown[0]}}; use {target}, {item.<facet>}, {user.<key>} or {scheme.name}`);
|
|
74
|
+
const tokens = (0, tokens_1.listLabelTokens)(text);
|
|
75
|
+
if (identity && tokens.some((t) => t.startsWith('item.')))
|
|
76
|
+
fail('an identity template reads {user.<key>} tokens, not {item.<facet>}');
|
|
77
|
+
if (!identity && tokens.some((t) => t.startsWith('user.')))
|
|
78
|
+
fail('{user.<key>} tokens print on identity templates only');
|
|
79
|
+
const credential = (0, tokens_1.userTokenKeys)(text).find((k) => ctx.identityKeys.includes(k) || k === scheme.target_facet);
|
|
80
|
+
if (credential)
|
|
81
|
+
fail(`{user.${credential}} is an identity credential and never prints as text`);
|
|
82
|
+
if (identity && tokens.includes('target'))
|
|
83
|
+
fail('{target} on an identity template is the credential; it never prints as text');
|
|
84
|
+
}
|
|
85
|
+
const symbology = input.symbology ?? 'code128';
|
|
86
|
+
if (!types_1.LABEL_SYMBOLOGIES.includes(symbology)) {
|
|
87
|
+
fail(`symbology must be one of ${types_1.LABEL_SYMBOLOGIES.join(', ')}`);
|
|
88
|
+
}
|
|
89
|
+
if (input.media != null && !ctx.mediaIds.includes(input.media))
|
|
90
|
+
fail(`unknown media "${input.media}"`);
|
|
91
|
+
if (identity && input.sensitive === false)
|
|
92
|
+
fail('a template on an identity scheme is always sensitive');
|
|
93
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LabelTemplate, LabelTemplateInput } from '../../../types/labels';
|
|
2
|
+
/** An API write raced another: the stored revision is not the one the caller read. */
|
|
3
|
+
export declare class LabelTemplateConflictError extends Error {
|
|
4
|
+
status: number;
|
|
5
|
+
constructor(name: string, revision: number);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Create or replace a template from the API. With `expectedRevision`, the
|
|
9
|
+
* write lands only on that revision; otherwise LabelTemplateConflictError.
|
|
10
|
+
*/
|
|
11
|
+
export declare function upsertLabelTemplate(input: LabelTemplateInput, expectedRevision?: number): Promise<LabelTemplate>;
|
|
12
|
+
export declare function deleteLabelTemplate(name: string): Promise<boolean>;
|
|
13
|
+
/** Insert a template only when absent (database-owned configuration). */
|
|
14
|
+
export declare function seedLabelTemplate(input: LabelTemplateInput): Promise<boolean>;
|
|
15
|
+
/** Apply a template declared in code; unchanged declarations write nothing. */
|
|
16
|
+
export declare function applyLabelTemplate(input: LabelTemplateInput): Promise<'applied' | 'unchanged'>;
|