@hotmeshio/long-tail 0.30.5 → 0.31.0
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/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/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,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Preview and issue label sheets. Issuing writes the ledger row before any
|
|
3
|
+
// code is composed, so a print the ledger does not hold never happens.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.assertMayPrint = assertMayPrint;
|
|
6
|
+
exports.previewLabels = previewLabels;
|
|
7
|
+
exports.issueLabels = issueLabels;
|
|
8
|
+
const transports_1 = require("../../lib/labels/transports");
|
|
9
|
+
const capabilities_1 = require("../../modules/capabilities");
|
|
10
|
+
const layout_1 = require("../../shared/labels/layout");
|
|
11
|
+
const media_1 = require("../../shared/labels/media");
|
|
12
|
+
const render_zpl_1 = require("../../shared/labels/render-zpl");
|
|
13
|
+
const types_1 = require("../../types");
|
|
14
|
+
const scan_code_1 = require("../scan-code");
|
|
15
|
+
const content_1 = require("./content");
|
|
16
|
+
const errors_1 = require("./errors");
|
|
17
|
+
const jobs_1 = require("./jobs");
|
|
18
|
+
const config_1 = require("../../modules/config");
|
|
19
|
+
const media_2 = require("./media");
|
|
20
|
+
const render_pdf_1 = require("./render-pdf");
|
|
21
|
+
const targets_1 = require("./targets");
|
|
22
|
+
const templates_1 = require("./templates");
|
|
23
|
+
const verify_1 = require("./verify");
|
|
24
|
+
async function load(name) {
|
|
25
|
+
const template = await (0, templates_1.getLabelTemplate)(name);
|
|
26
|
+
if (!template)
|
|
27
|
+
throw new errors_1.LabelRequestError(404, `label template "${name}" does not exist`);
|
|
28
|
+
if (!template.enabled)
|
|
29
|
+
throw new errors_1.LabelRequestError(400, `label template "${name}" is disabled`);
|
|
30
|
+
const scheme = await (0, scan_code_1.getScanScheme)(template.scheme_version);
|
|
31
|
+
if (!scheme)
|
|
32
|
+
throw new errors_1.LabelRequestError(404, `scan scheme ${template.scheme_version} does not exist`);
|
|
33
|
+
const rules = await (0, scan_code_1.listScanRules)(scheme.version);
|
|
34
|
+
return { template, scheme, rules, identity: scheme.kind === types_1.SCAN_SCHEME_KINDS.IDENTITY };
|
|
35
|
+
}
|
|
36
|
+
/** Identity labels need credentialIssuer; item labels need admin or role management. */
|
|
37
|
+
async function assertMayPrint(identity, auth) {
|
|
38
|
+
const allowed = identity
|
|
39
|
+
? await (0, capabilities_1.mayIssueCredentials)(auth)
|
|
40
|
+
: (await (0, capabilities_1.mayAdminister)(auth)) || (await (0, capabilities_1.mayManageRoles)(auth));
|
|
41
|
+
if (!allowed) {
|
|
42
|
+
throw new errors_1.LabelRequestError(403, identity
|
|
43
|
+
? 'printing badges requires credential-issuer access'
|
|
44
|
+
: 'printing labels requires admin or role-management access');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function layoutSheet(loaded, contents, layout = {}) {
|
|
48
|
+
try {
|
|
49
|
+
return (0, layout_1.buildLabelSheet)({
|
|
50
|
+
media: (0, media_2.mediaForJob)(layout.media, loaded.template.media),
|
|
51
|
+
labels: contents,
|
|
52
|
+
symbology: loaded.template.symbology,
|
|
53
|
+
humanReadable: loaded.template.human_readable,
|
|
54
|
+
startPosition: layout.startPosition,
|
|
55
|
+
copies: layout.copies,
|
|
56
|
+
onePerPage: layout.onePerPage,
|
|
57
|
+
cutMarks: layout.cutMarks,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
if (err instanceof layout_1.LabelLayoutError || err instanceof media_1.LabelMediaError)
|
|
62
|
+
throw new errors_1.LabelRequestError(400, err.message);
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function compose(loaded, targets, layout, masked) {
|
|
67
|
+
if (!loaded.identity)
|
|
68
|
+
await (0, targets_1.markResolvedTargets)(targets, loaded.scheme);
|
|
69
|
+
const built = (0, content_1.buildLabelContents)(loaded.template, loaded.scheme, loaded.rules, targets, masked);
|
|
70
|
+
const sheet = layoutSheet(loaded, built.contents, layout);
|
|
71
|
+
const verified = (0, verify_1.verifyLabels)(loaded.template, loaded.scheme, await (0, scan_code_1.listScanSchemes)(), loaded.rules, targets, built.contents);
|
|
72
|
+
const warnings = [...built.warnings, ...verified, ...sheet.warnings];
|
|
73
|
+
return { sheet: { ...sheet, warnings }, warnings };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Lay out a job without printing it. Sensitive templates are masked: the
|
|
77
|
+
* preview shows where each code goes, never the code. Nothing is recorded.
|
|
78
|
+
*/
|
|
79
|
+
async function previewLabels(req, auth) {
|
|
80
|
+
const loaded = await load(req.template);
|
|
81
|
+
await assertMayPrint(loaded.identity, auth);
|
|
82
|
+
const targets = await (0, targets_1.resolveLabelTargets)(req.source, loaded.scheme, auth);
|
|
83
|
+
const { sheet, warnings } = await compose(loaded, targets, req.layout, loaded.template.sensitive);
|
|
84
|
+
return { template: loaded.template, sheet, warnings, labelCount: targets.length };
|
|
85
|
+
}
|
|
86
|
+
function transportFor(output, format) {
|
|
87
|
+
const name = output.slice('transport:'.length);
|
|
88
|
+
const transport = transports_1.labelTransportRegistry.get(name);
|
|
89
|
+
return { name, transport, format: format ?? (transport.formats.includes('zpl') ? 'zpl' : 'pdf') };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Issue a job: check access and confirmation, record it, then compose and
|
|
93
|
+
* deliver the codes as a sheet, a PDF, ZPL, or through a transport.
|
|
94
|
+
*/
|
|
95
|
+
async function issueLabels(req, auth) {
|
|
96
|
+
const loaded = await load(req.template);
|
|
97
|
+
await assertMayPrint(loaded.identity, auth);
|
|
98
|
+
if (loaded.template.sensitive && req.confirm !== true) {
|
|
99
|
+
throw new errors_1.LabelRequestError(428, 'this template prints credentials or sensitive labels; confirm to print');
|
|
100
|
+
}
|
|
101
|
+
const transport = req.output.startsWith('transport:') ? transportFor(req.output, null) : null;
|
|
102
|
+
if (!transport && !['sheet', 'pdf', 'zpl'].includes(req.output)) {
|
|
103
|
+
throw new errors_1.LabelRequestError(400, `unknown output "${req.output}"`);
|
|
104
|
+
}
|
|
105
|
+
const resolved = await (0, targets_1.resolveLabelTargets)(req.source, loaded.scheme, auth);
|
|
106
|
+
const only = req.only ? new Set(req.only) : null;
|
|
107
|
+
const targets = only ? resolved.filter((t) => only.has(loaded.identity ? t.userId : t.target)) : resolved;
|
|
108
|
+
if (targets.length === 0)
|
|
109
|
+
throw new errors_1.LabelRequestError(400, 'none of the selected labels are in the source any more');
|
|
110
|
+
const media = (0, media_2.mediaForJob)(req.layout?.media, loaded.template.media);
|
|
111
|
+
const wantsZpl = req.output === 'zpl' || transport?.format === 'zpl';
|
|
112
|
+
if (wantsZpl && media.family !== 'thermal') {
|
|
113
|
+
throw new errors_1.LabelRequestError(400, `ZPL prints on thermal media; "${media.id}" is sheet stock`);
|
|
114
|
+
}
|
|
115
|
+
const { job, replay } = await (0, jobs_1.recordLabelJob)({
|
|
116
|
+
action: 'print',
|
|
117
|
+
requested_by: auth.userId,
|
|
118
|
+
idempotency_key: req.idempotencyKey ?? null,
|
|
119
|
+
template_name: loaded.template.name,
|
|
120
|
+
template_revision: loaded.template.revision,
|
|
121
|
+
template_snapshot: loaded.template,
|
|
122
|
+
scheme_version: loaded.scheme.version,
|
|
123
|
+
scheme_kind: loaded.scheme.kind,
|
|
124
|
+
sensitive: loaded.template.sensitive,
|
|
125
|
+
source: req.source,
|
|
126
|
+
subject_user_ids: loaded.identity ? targets.map((t) => t.userId) : null,
|
|
127
|
+
targets: loaded.identity ? null : targets.map((t) => t.target),
|
|
128
|
+
label_count: targets.length * (req.layout?.copies ?? 1),
|
|
129
|
+
media,
|
|
130
|
+
output: req.output,
|
|
131
|
+
});
|
|
132
|
+
if (replay && (job.template_name !== loaded.template.name || job.output !== req.output)) {
|
|
133
|
+
throw new errors_1.LabelRequestError(409, 'this idempotency key was used for a different label request');
|
|
134
|
+
}
|
|
135
|
+
if (replay && transport && job.delivered_at)
|
|
136
|
+
return { job, replay, warnings: [], delivered: true };
|
|
137
|
+
// A replay prints the labels the first request recorded, nothing it did not.
|
|
138
|
+
const recorded = new Set((loaded.identity ? job.subject_user_ids : job.targets) ?? []);
|
|
139
|
+
const printing = replay ? targets.filter((t) => recorded.has(loaded.identity ? t.userId : t.target)) : targets;
|
|
140
|
+
const { sheet, warnings } = await compose(loaded, printing, req.layout, false);
|
|
141
|
+
const result = { job, replay, warnings };
|
|
142
|
+
try {
|
|
143
|
+
if (req.output === 'sheet')
|
|
144
|
+
result.sheet = sheet;
|
|
145
|
+
if (req.output === 'pdf')
|
|
146
|
+
result.pdf = await (0, render_pdf_1.renderSheetPdf)(sheet);
|
|
147
|
+
if (req.output === 'zpl')
|
|
148
|
+
result.zpl = (0, render_zpl_1.renderSheetZpl)(sheet);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
if (err instanceof render_zpl_1.ZplRenderError)
|
|
152
|
+
throw new errors_1.LabelRequestError(400, err.message);
|
|
153
|
+
throw err;
|
|
154
|
+
}
|
|
155
|
+
if (transport)
|
|
156
|
+
await deliver(job, transport, sheet, req.destination, result);
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Send a recorded job through its transport under the delivery lease: the
|
|
161
|
+
* claim is one statement, so concurrent retries of one job send once, and a
|
|
162
|
+
* job whose sender crashed is sent by the first retry after the lease lapses.
|
|
163
|
+
*/
|
|
164
|
+
async function deliver(job, transport, sheet, destination, result) {
|
|
165
|
+
if (!(await (0, jobs_1.claimLabelDelivery)(job.id, config_1.config.LT_LABELS_DELIVERY_LEASE_SECONDS))) {
|
|
166
|
+
result.delivered = false;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const payload = transport.format === 'zpl' ? (0, render_zpl_1.renderSheetZpl)(sheet) : await (0, render_pdf_1.renderSheetPdf)(sheet);
|
|
171
|
+
result.receipt = await transport.transport.send({
|
|
172
|
+
jobId: job.id, format: transport.format, payload, labelCount: job.label_count, destination,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
await (0, jobs_1.releaseLabelDelivery)(job.id);
|
|
177
|
+
throw new errors_1.LabelRequestError(502, `transport "${transport.name}" failed: ${err?.message ?? 'unknown error'}`);
|
|
178
|
+
}
|
|
179
|
+
await (0, jobs_1.markLabelDelivered)(job.id);
|
|
180
|
+
result.delivered = true;
|
|
181
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { LabelJob } from '../../types/labels';
|
|
2
|
+
export interface NewLabelJob {
|
|
3
|
+
action: LabelJob['action'];
|
|
4
|
+
requested_by: string;
|
|
5
|
+
idempotency_key?: string | null;
|
|
6
|
+
template_name: string;
|
|
7
|
+
template_revision: number;
|
|
8
|
+
template_snapshot: unknown;
|
|
9
|
+
scheme_version: number;
|
|
10
|
+
scheme_kind: string;
|
|
11
|
+
sensitive: boolean;
|
|
12
|
+
source: unknown;
|
|
13
|
+
subject_user_ids: string[] | null;
|
|
14
|
+
targets: string[] | null;
|
|
15
|
+
label_count: number;
|
|
16
|
+
media: unknown;
|
|
17
|
+
output: string;
|
|
18
|
+
}
|
|
19
|
+
/** Record a job. With an idempotency key already used, returns that job and `replay: true`. */
|
|
20
|
+
export declare function recordLabelJob(job: NewLabelJob): Promise<{
|
|
21
|
+
job: LabelJob;
|
|
22
|
+
replay: boolean;
|
|
23
|
+
}>;
|
|
24
|
+
/** True when this caller now holds the job's delivery lease. */
|
|
25
|
+
export declare function claimLabelDelivery(id: string, leaseSeconds: number): Promise<boolean>;
|
|
26
|
+
export declare function markLabelDelivered(id: string): Promise<void>;
|
|
27
|
+
/** Give the lease back after a failed send, so a retry need not wait for it to lapse. */
|
|
28
|
+
export declare function releaseLabelDelivery(id: string): Promise<void>;
|
|
29
|
+
export declare function getLabelJob(id: string): Promise<LabelJob | null>;
|
|
30
|
+
export declare function listLabelJobs(opts: {
|
|
31
|
+
readerId: string;
|
|
32
|
+
seesCredentials: boolean;
|
|
33
|
+
template?: string;
|
|
34
|
+
subjectUserId?: string;
|
|
35
|
+
limit?: number;
|
|
36
|
+
offset?: number;
|
|
37
|
+
}): Promise<LabelJob[]>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// lt_label_jobs: insert-only. A print row is written before any code leaves
|
|
3
|
+
// the server; a repeated idempotency key returns the first row.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.recordLabelJob = recordLabelJob;
|
|
6
|
+
exports.claimLabelDelivery = claimLabelDelivery;
|
|
7
|
+
exports.markLabelDelivered = markLabelDelivered;
|
|
8
|
+
exports.releaseLabelDelivery = releaseLabelDelivery;
|
|
9
|
+
exports.getLabelJob = getLabelJob;
|
|
10
|
+
exports.listLabelJobs = listLabelJobs;
|
|
11
|
+
const db_1 = require("../../lib/db");
|
|
12
|
+
const INSERT_JOB = `
|
|
13
|
+
INSERT INTO lt_label_jobs (
|
|
14
|
+
action, requested_by, idempotency_key, template_name, template_revision, template_snapshot,
|
|
15
|
+
scheme_version, scheme_kind, sensitive, source, subject_user_ids, targets, label_count, media, output
|
|
16
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
17
|
+
ON CONFLICT (idempotency_key) DO NOTHING
|
|
18
|
+
RETURNING *`;
|
|
19
|
+
const GET_JOB_BY_KEY = 'SELECT * FROM lt_label_jobs WHERE idempotency_key = $1';
|
|
20
|
+
/** Take the delivery lease: only an undelivered job whose lease is free or lapsed. One statement, so one claimer wins. */
|
|
21
|
+
const CLAIM_DELIVERY = `
|
|
22
|
+
UPDATE lt_label_jobs SET delivery_claimed_at = NOW()
|
|
23
|
+
WHERE id = $1 AND delivered_at IS NULL
|
|
24
|
+
AND (delivery_claimed_at IS NULL OR delivery_claimed_at < NOW() - make_interval(secs => $2))
|
|
25
|
+
RETURNING id`;
|
|
26
|
+
const MARK_DELIVERED = 'UPDATE lt_label_jobs SET delivered_at = NOW() WHERE id = $1 AND delivered_at IS NULL';
|
|
27
|
+
const RELEASE_DELIVERY = 'UPDATE lt_label_jobs SET delivery_claimed_at = NULL WHERE id = $1 AND delivered_at IS NULL';
|
|
28
|
+
const GET_JOB = 'SELECT * FROM lt_label_jobs WHERE id = $1';
|
|
29
|
+
/** History as a reader may see it: everything for an issuer; item jobs and their own otherwise. */
|
|
30
|
+
const LIST_JOBS = `
|
|
31
|
+
SELECT * FROM lt_label_jobs
|
|
32
|
+
WHERE ($1::boolean OR NOT sensitive OR requested_by = $2::uuid)
|
|
33
|
+
AND ($3::text IS NULL OR template_name = $3)
|
|
34
|
+
AND ($4::uuid IS NULL OR $4::uuid = ANY(subject_user_ids))
|
|
35
|
+
ORDER BY created_at DESC
|
|
36
|
+
LIMIT $5 OFFSET $6`;
|
|
37
|
+
function mapJob(row) {
|
|
38
|
+
return { ...row };
|
|
39
|
+
}
|
|
40
|
+
/** Record a job. With an idempotency key already used, returns that job and `replay: true`. */
|
|
41
|
+
async function recordLabelJob(job) {
|
|
42
|
+
const { rows } = await (0, db_1.getPool)().query(INSERT_JOB, [
|
|
43
|
+
job.action, job.requested_by, job.idempotency_key ?? null, job.template_name, job.template_revision,
|
|
44
|
+
JSON.stringify(job.template_snapshot), job.scheme_version, job.scheme_kind, job.sensitive,
|
|
45
|
+
JSON.stringify(job.source), job.subject_user_ids, job.targets, job.label_count,
|
|
46
|
+
JSON.stringify(job.media), job.output,
|
|
47
|
+
]);
|
|
48
|
+
if (rows[0])
|
|
49
|
+
return { job: mapJob(rows[0]), replay: false };
|
|
50
|
+
const existing = await (0, db_1.getPool)().query(GET_JOB_BY_KEY, [job.idempotency_key]);
|
|
51
|
+
return { job: mapJob(existing.rows[0]), replay: true };
|
|
52
|
+
}
|
|
53
|
+
/** True when this caller now holds the job's delivery lease. */
|
|
54
|
+
async function claimLabelDelivery(id, leaseSeconds) {
|
|
55
|
+
const { rows } = await (0, db_1.getPool)().query(CLAIM_DELIVERY, [id, leaseSeconds]);
|
|
56
|
+
return rows.length > 0;
|
|
57
|
+
}
|
|
58
|
+
async function markLabelDelivered(id) {
|
|
59
|
+
await (0, db_1.getPool)().query(MARK_DELIVERED, [id]);
|
|
60
|
+
}
|
|
61
|
+
/** Give the lease back after a failed send, so a retry need not wait for it to lapse. */
|
|
62
|
+
async function releaseLabelDelivery(id) {
|
|
63
|
+
await (0, db_1.getPool)().query(RELEASE_DELIVERY, [id]);
|
|
64
|
+
}
|
|
65
|
+
async function getLabelJob(id) {
|
|
66
|
+
const { rows } = await (0, db_1.getPool)().query(GET_JOB, [id]);
|
|
67
|
+
return rows[0] ? mapJob(rows[0]) : null;
|
|
68
|
+
}
|
|
69
|
+
async function listLabelJobs(opts) {
|
|
70
|
+
const { rows } = await (0, db_1.getPool)().query(LIST_JOBS, [
|
|
71
|
+
opts.seesCredentials, opts.readerId, opts.template ?? null, opts.subjectUserId ?? null,
|
|
72
|
+
Math.min(opts.limit ?? 50, 200), opts.offset ?? 0,
|
|
73
|
+
]);
|
|
74
|
+
return rows.map(mapJob);
|
|
75
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LabelMedia } from '../../shared/labels/types';
|
|
2
|
+
/** Replace the host's media presets; each must fit its page and not shadow a shipped id. */
|
|
3
|
+
export declare function registerLabelMedia(media: LabelMedia[]): void;
|
|
4
|
+
/** Set the deployment's default media; it must be a known preset. */
|
|
5
|
+
export declare function setDefaultLabelMedia(id: string): void;
|
|
6
|
+
export declare function labelMediaPresets(): LabelMedia[];
|
|
7
|
+
export declare function defaultLabelMediaId(): string;
|
|
8
|
+
/** The media a job prints on: the job's choice, the template's, then the deployment default. */
|
|
9
|
+
export declare function mediaForJob(requested: string | LabelMedia | undefined, templateMedia: string | null): LabelMedia;
|
|
10
|
+
/** Restore the shipped presets and the configured default. For tests. */
|
|
11
|
+
export declare function resetLabelMedia(): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The media a deployment prints on: the shipped presets plus any the host
|
|
3
|
+
// declares in start({ labels: { media } }).
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.registerLabelMedia = registerLabelMedia;
|
|
6
|
+
exports.setDefaultLabelMedia = setDefaultLabelMedia;
|
|
7
|
+
exports.labelMediaPresets = labelMediaPresets;
|
|
8
|
+
exports.defaultLabelMediaId = defaultLabelMediaId;
|
|
9
|
+
exports.mediaForJob = mediaForJob;
|
|
10
|
+
exports.resetLabelMedia = resetLabelMedia;
|
|
11
|
+
const config_1 = require("../../modules/config");
|
|
12
|
+
const media_1 = require("../../shared/labels/media");
|
|
13
|
+
let hostMedia = [];
|
|
14
|
+
let defaultMediaId = config_1.config.LT_LABELS_DEFAULT_MEDIA;
|
|
15
|
+
/** Replace the host's media presets; each must fit its page and not shadow a shipped id. */
|
|
16
|
+
function registerLabelMedia(media) {
|
|
17
|
+
for (const m of media) {
|
|
18
|
+
(0, media_1.assertValidMedia)(m);
|
|
19
|
+
if (media_1.LABEL_MEDIA.some((shipped) => shipped.id === m.id)) {
|
|
20
|
+
throw new Error(`label media "${m.id}" is a shipped preset; give the host preset its own id`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
hostMedia = [...media];
|
|
24
|
+
}
|
|
25
|
+
/** Set the deployment's default media; it must be a known preset. */
|
|
26
|
+
function setDefaultLabelMedia(id) {
|
|
27
|
+
(0, media_1.resolveMedia)(id, labelMediaPresets());
|
|
28
|
+
defaultMediaId = id;
|
|
29
|
+
}
|
|
30
|
+
function labelMediaPresets() {
|
|
31
|
+
return [...media_1.LABEL_MEDIA, ...hostMedia];
|
|
32
|
+
}
|
|
33
|
+
function defaultLabelMediaId() {
|
|
34
|
+
return defaultMediaId;
|
|
35
|
+
}
|
|
36
|
+
/** The media a job prints on: the job's choice, the template's, then the deployment default. */
|
|
37
|
+
function mediaForJob(requested, templateMedia) {
|
|
38
|
+
return (0, media_1.resolveMedia)(requested ?? templateMedia ?? defaultMediaId, labelMediaPresets());
|
|
39
|
+
}
|
|
40
|
+
/** Restore the shipped presets and the configured default. For tests. */
|
|
41
|
+
function resetLabelMedia() {
|
|
42
|
+
hostMedia = [];
|
|
43
|
+
defaultMediaId = config_1.config.LT_LABELS_DEFAULT_MEDIA;
|
|
44
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { LTApiAuth } from '../../types/sdk';
|
|
2
|
+
import type { LabelLayoutRequest } from '../../types/labels';
|
|
3
|
+
import { type LabelIssueResult } from './issue';
|
|
4
|
+
export interface ReissueRequest {
|
|
5
|
+
userId: string;
|
|
6
|
+
template: string;
|
|
7
|
+
layout?: LabelLayoutRequest;
|
|
8
|
+
output: 'sheet' | 'pdf' | 'zpl' | `transport:${string}`;
|
|
9
|
+
confirm?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function reissueBadge(req: ReissueRequest, auth: LTApiAuth): Promise<LabelIssueResult & {
|
|
12
|
+
reissueJobId: string;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Reissue a badge: rotate the user's credential and print the new badge in
|
|
3
|
+
// one act. The rotation and its ledger row land in one statement, so the old
|
|
4
|
+
// code stops resolving the moment the new one exists.
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.reissueBadge = reissueBadge;
|
|
7
|
+
const types_1 = require("../../types");
|
|
8
|
+
const scan_code_1 = require("../scan-code");
|
|
9
|
+
const user_1 = require("../user");
|
|
10
|
+
const errors_1 = require("./errors");
|
|
11
|
+
const issue_1 = require("./issue");
|
|
12
|
+
const media_1 = require("./media");
|
|
13
|
+
const templates_1 = require("./templates");
|
|
14
|
+
const token_1 = require("./token");
|
|
15
|
+
/** The rotation and its ledger row in one statement; a refused patch becomes a label request error. */
|
|
16
|
+
async function rotate(userId, set, record) {
|
|
17
|
+
try {
|
|
18
|
+
return await (0, user_1.patchUserPropertiesRecorded)(userId, { set }, record);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
if (err?.status === 400 || err?.status === 409)
|
|
22
|
+
throw new errors_1.LabelRequestError(err.status, err.message);
|
|
23
|
+
throw err;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async function reissueBadge(req, auth) {
|
|
27
|
+
const template = await (0, templates_1.getLabelTemplate)(req.template);
|
|
28
|
+
if (!template)
|
|
29
|
+
throw new errors_1.LabelRequestError(404, `label template "${req.template}" does not exist`);
|
|
30
|
+
const scheme = await (0, scan_code_1.getScanScheme)(template.scheme_version);
|
|
31
|
+
if (!scheme || scheme.kind !== types_1.SCAN_SCHEME_KINDS.IDENTITY) {
|
|
32
|
+
throw new errors_1.LabelRequestError(400, 'reissue needs a template on an identity scheme');
|
|
33
|
+
}
|
|
34
|
+
await (0, issue_1.assertMayPrint)(true, auth);
|
|
35
|
+
if (req.confirm !== true)
|
|
36
|
+
throw new errors_1.LabelRequestError(428, 'reissuing a badge replaces the old one; confirm to reissue');
|
|
37
|
+
const user = await (0, user_1.getUser)(req.userId);
|
|
38
|
+
if (!user)
|
|
39
|
+
throw new errors_1.LabelRequestError(404, 'user not found');
|
|
40
|
+
const media = (0, media_1.mediaForJob)(req.layout?.media, template.media);
|
|
41
|
+
const rotated = await rotate(user.id, { [scheme.target_facet]: (0, token_1.mintIdentityToken)(scheme) }, {
|
|
42
|
+
action: 'reissue',
|
|
43
|
+
requested_by: auth.userId,
|
|
44
|
+
require_active: true,
|
|
45
|
+
source: { keys: [scheme.target_facet] },
|
|
46
|
+
label_count: 1,
|
|
47
|
+
template_name: template.name,
|
|
48
|
+
template_revision: template.revision,
|
|
49
|
+
template_snapshot: template,
|
|
50
|
+
scheme_version: scheme.version,
|
|
51
|
+
scheme_kind: scheme.kind,
|
|
52
|
+
media,
|
|
53
|
+
output: req.output,
|
|
54
|
+
});
|
|
55
|
+
if (!rotated)
|
|
56
|
+
throw new errors_1.LabelRequestError(404, 'user not found');
|
|
57
|
+
const printed = await (0, issue_1.issueLabels)({
|
|
58
|
+
template: template.name,
|
|
59
|
+
source: { kind: 'users', userIds: [user.id] },
|
|
60
|
+
layout: req.layout,
|
|
61
|
+
output: req.output,
|
|
62
|
+
confirm: true,
|
|
63
|
+
}, auth);
|
|
64
|
+
return { ...printed, reissueJobId: rotated.jobId };
|
|
65
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { LabelSheet } from '../../shared/labels/types';
|
|
2
|
+
export interface LabelFonts {
|
|
3
|
+
regular: Uint8Array;
|
|
4
|
+
bold?: Uint8Array;
|
|
5
|
+
}
|
|
6
|
+
/** Fonts for label text in PDFs (TrueType or OpenType bytes). */
|
|
7
|
+
export declare function registerLabelFonts(fonts: LabelFonts | null): void;
|
|
8
|
+
/** Scale an SVG path of M/h/v/z commands by (sx, sy); pdf-lib's own scale is uniform. */
|
|
9
|
+
export declare function scalePath(path: string, sx: number, sy: number): string;
|
|
10
|
+
/** Render a sheet as a PDF document. */
|
|
11
|
+
export declare function renderSheetPdf(sheet: LabelSheet): Promise<Uint8Array>;
|
|
@@ -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>;
|