import { CREATE as MSSQL_CREATE, } from '../../providers/mssql/queries/labeltemplate.js'; import { CREATE as SQLITE_CREATE, } from '../../providers/sqlite3/queries/labeltemplate.js'; import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js'; import makeRunner from '../runner.js'; const VALID_TYPES = new Set(['zpl']); const VALID_DPIS = new Set([203, 300]); function shape(row) { return { id: row.id, company_id: row.company_id ?? row.companyId, name: row.name, width: row.width, height: row.height, dpi: row.dpi, type: row.type, content: typeof row.content === 'string' ? JSON.parse(row.content) : row.content, thumb: row.thumb ?? null, }; } export default function create(provider) { const access = resolveSelectedCompanyAccess(provider); const isSqlite = provider?.dialect === 'sqlite3'; const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE; /** * Creates a new label template for the user's selected company. * * @param {number} googleAuthId - The id of the Google auth user. * @param {object} input - Label template input. * @param {string} input.name - Template name. * @param {number} input.width - Canvas width in pixels. * @param {number} input.height - Canvas height in pixels. * @param {number} input.dpi - Printer DPI (203 or 300). * @param {string} input.type - Template type ("zpl"). * @param {object} input.content - Template content (JSON). * @param {Buffer|null} [input.thumb] - 50×50 1-bit PNG thumbnail buffer. * @param {object} [tx] - Optional transaction to run within. * @returns {Promise<{id: number, company_id: number, name: string, width: number, height: number, dpi: number, type: string, content: object, thumb: Buffer|null}>} * @throws {Error} If required fields are missing or invalid. * * @example * const template = await store.labeltemplate.create(googleAuthId, { * name: 'Product Label', * width: 448, * height: 200, * dpi: 203, * type: 'zpl', * content: { objects: [] }, * }); */ return async (googleAuthId, input = {}, tx) => { const name = typeof input.name === 'string' ? input.name.trim() : ''; if (!name) { throw new Error('Name required'); } const width = Number(input.width); if (!Number.isInteger(width) || width <= 0) { throw new Error('Invalid width'); } const height = Number(input.height); if (!Number.isInteger(height) || height <= 0) { throw new Error('Invalid height'); } const dpi = Number(input.dpi); if (!VALID_DPIS.has(dpi)) { throw new Error('Invalid dpi: must be 203 or 300'); } const type = typeof input.type === 'string' ? input.type.trim() : ''; if (!type || !VALID_TYPES.has(type)) { throw new Error('Invalid type: must be "zpl"'); } if (input.content == null) { throw new Error('Content required'); } const content = typeof input.content === 'string' ? input.content : JSON.stringify(input.content); const thumb = input.thumb instanceof Buffer ? input.thumb : null; const runner = makeRunner(provider, tx); const { companyId } = await access(googleAuthId, runner); const result = await runner.query(createSql, { companyId, name, width, height, dpi, type, content, thumb, }); const row = result.rows[0] ?? { id: result.insertId, company_id: companyId, name, width, height, dpi, type, content, thumb, }; return shape(row); }; }