Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 37x 37x 37x 37x 37x 2x 26x 26x 26x 2x 2x 35x 28x 28x 35x 35x 18x 18x 35x 9x 9x 9x 9x 9x 9x | import type { TicketProcessValue, TicketStyle } from '@eink/print-dialog'
/**
* Runtime guard for a persisted TicketStyle — the print-settings overlay the
* user tunes in the print dialog (base preset name + sparse process
* overrides). `@eink/print-dialog` exports the TYPE but no runtime validator,
* and the overlay round-trips through a DB text column, so writes are gated
* here. Returns null on anything that isn't a structurally valid TicketStyle;
* semantic validity against a capability doc (unknown preset, out-of-range
* value) is the service's call at submit time, not ours.
*/
function isScalar(v: unknown): v is number | boolean | string {
return (
(typeof v === 'number' && Number.isFinite(v)) || typeof v === 'boolean' || typeof v === 'string'
)
}
function isProcessValue(v: unknown): v is TicketProcessValue {
return isScalar(v) || (Array.isArray(v) && v.length > 0 && v.every(isScalar))
}
export function parseTicketStyle(input: unknown): TicketStyle | null {
if (typeof input !== 'object' || input === null || Array.isArray(input)) return null
const { basePreset, process } = input as { basePreset?: unknown; process?: unknown }
if (typeof basePreset !== 'string' || basePreset.length === 0) return null
if (typeof process !== 'object' || process === null || Array.isArray(process)) return null
const entries = Object.entries(process as Record<string, unknown>)
if (!entries.every(([, v]) => isProcessValue(v))) return null
return {
basePreset,
process: Object.fromEntries(entries) as Readonly<Record<string, TicketProcessValue>>,
}
}
|