/** * rSwag Automerge document schemas. * * Stores shared design metadata for collaborative artifact management. * Actual image files remain server-side; this doc syncs titles, product * types, status, and artifact references across space members. * * DocId format: {space}:swag:designs */ import type { DocSchema } from '../../shared/local-first/document'; // ── Document types ── export interface SwagDesignProduct { type: string; provider: 'printful' | 'prodigi' | 'cosmolocal'; sku: string; variants: string[]; retailPrice: number; } export interface SwagDesign { id: string; title: string; productType: 'sticker' | 'poster' | 'tee' | 'hoodie'; /** Server artifact ID (if generated) */ artifactId: string | null; /** How this design was created */ source: 'upload' | 'ai-generated' | 'artifact'; /** Design lifecycle status */ status: 'draft' | 'active' | 'paused' | 'removed'; /** URL to the design image (server-side path) */ imageUrl: string | null; /** POD product configurations for this design */ products: SwagDesignProduct[]; /** Design slug (URL-friendly identifier) */ slug: string | null; /** Description / concept text */ description: string | null; /** Tags for categorization */ tags: string[]; createdBy: string | null; createdAt: number; updatedAt: number; } export interface SwagDoc { meta: { module: string; collection: string; version: number; spaceSlug: string; createdAt: number; }; designs: Record; /** Currently active design ID for the space */ activeDesignId: string | null; } // ── Schema registration ── export const swagSchema: DocSchema = { module: 'swag', collection: 'designs', version: 2, init: (): SwagDoc => ({ meta: { module: 'swag', collection: 'designs', version: 2, spaceSlug: '', createdAt: Date.now(), }, designs: {}, activeDesignId: null, }), migrate: (doc: any, _fromVersion: number) => { if (!doc.designs) doc.designs = {}; if (!('activeDesignId' in doc)) doc.activeDesignId = null; // v2 migration: add new fields to existing designs for (const design of Object.values(doc.designs) as any[]) { if (!('source' in design)) design.source = 'artifact'; if (!('status' in design)) design.status = design.artifactId ? 'active' : 'draft'; if (!('imageUrl' in design)) design.imageUrl = null; if (!('products' in design)) design.products = []; if (!('slug' in design)) design.slug = null; if (!('description' in design)) design.description = null; if (!('tags' in design)) design.tags = []; } doc.meta.version = 2; return doc; }, }; // ── Helpers ── export function swagDocId(space: string) { return `${space}:swag:designs` as const; }