/** * ═══════════════════════════════════════════════════════════════ * Schema Adapter Examples * ═══════════════════════════════════════════════════════════════ * * This file demonstrates how to use each schema adapter with the * generic ViewModel factory. Uncomment the adapter you want to use. * * Each section is self-contained and shows: * 1. Schema definition * 2. Adapter creation * 3. ViewModel factory usage * 4. Basic VM usage * * Note: Not all schema libraries are installed as dependencies. * ✓ TypeBox — peer dependency of @wovin/core (available) * ✓ Zod — dependency of @wovin/core (available) * ✗ ArkType — NOT installed (example shown for pattern reference) * ✗ Typia — NOT installed (example shown for pattern reference) */ import { createViewModelFactory, ObjectBuilder, type ISchemaAdapter, type VMAttributeDef } from '../index.ts' import type { Thread } from '../../thread/basic.ts' import type { ApplogValue, EntityID } from '../../applog/datom-types.ts' // ═══════════════════════════════════════════════════════════════ // Shared helpers for examples // ═══════════════════════════════════════════════════════════════ /** Dummy thread for examples */ function createMockThread(): Thread { return { name: 'mock', applogs: [], filters: [], subscribe: () => () => {} } as unknown as Thread } interface Note extends Record { title: string body: string tags?: string } // ═══════════════════════════════════════════════════════════════ // 1. TypeBox Adapter Example // ═══════════════════════════════════════════════════════════════ // import { Type } from '@sinclair/typebox' // import { Static } from '@sinclair/typebox' // import { createTypeBoxAdapter } from '../adapters/typebox.ts' export function typeBoxExample() { /* const NoteSchema = Type.Object({ title: Type.String(), body: Type.String(), tags: Type.Optional(Type.String()), }) type Note = Static const NoteVM = createViewModelFactory({ adapter: createTypeBoxAdapter(NoteSchema, 'note', { atOverrides: { title: 'note/title', body: 'note/body', tags: 'note/tags', }, }), vmName: 'Note', }) const thread = createMockThread() const note = NoteVM.get('abc123' as EntityID, thread) console.log(note.title) // reactive read note.title = 'Hello' // writes to thread via applog */ } // ═══════════════════════════════════════════════════════════════ // 2. Zod Adapter Example // ═══════════════════════════════════════════════════════════════ // import { z } from 'zod' // import { createZodAdapter } from '../adapters/zod.ts' export function zodExample() { /* const NoteSchema = z.object({ title: z.string(), body: z.string(), tags: z.string().optional(), }) type Note = z.infer const NoteVM = createViewModelFactory({ adapter: createZodAdapter(NoteSchema, 'note', { atOverrides: { title: 'note/title', body: 'note/body', tags: 'note/tags', }, }), vmName: 'Note', }) const thread = createMockThread() const note = NoteVM.get('abc123' as EntityID, thread) console.log(note.title) note.title = 'Hello' */ } // ═══════════════════════════════════════════════════════════════ // 3. ArkType Adapter Pattern // ═══════════════════════════════════════════════════════════════ // ArkType is NOT a dependency. This shows the pattern if you install it. // import { createArkTypeAdapter } from '../adapters/arktype.ts' export function arkTypePattern() { /* // First, define attributes manually (ArkType doesn't expose runtime props) const attrs: VMAttributeDef[] = [ { name: 'title', atPath: 'note/title', optional: false }, { name: 'body', atPath: 'note/body', optional: false }, { name: 'tags', atPath: 'note/tags', optional: true }, ] // Then create the adapter with a validator // import { type } from 'arktype' // const NoteSchema = type({ title: 'string', body: 'string', 'tags?': 'string' }) const NoteVM = createViewModelFactory({ adapter: createArkTypeAdapter( // NoteSchema, // your arktype validator {} as any, // placeholder 'note', { attributes: attrs }, ), vmName: 'Note', }) */ } // ═══════════════════════════════════════════════════════════════ // 4. Typia Adapter Pattern // ═══════════════════════════════════════════════════════════════ // Typia is NOT a dependency. This shows the pattern if you install it. // import { createTypiaAdapter } from '../adapters/typia.ts' export function typiaPattern() { /* // Define attributes manually (Typia strips types at compile time) const attrs: VMAttributeDef[] = [ { name: 'title', atPath: 'note/title', optional: false }, { name: 'body', atPath: 'note/body', optional: false }, { name: 'tags', atPath: 'note/tags', optional: true }, ] // Then create the adapter with a typia validator // import typia from 'typia' // interface Note { title: string; body: string; tags?: string } // const validate = typia.createValidate() const NoteVM = createViewModelFactory({ adapter: createTypiaAdapter( // validate, // your typia validator {} as any, // placeholder 'note', { attributes: attrs }, ), vmName: 'Note', }) */ } // ═══════════════════════════════════════════════════════════════ // 5. Minimal adapter (no schema library) // ═══════════════════════════════════════════════════════════════ export function minimalNoSchemaExample() { // You don't need a schema library at all — use createAdapterFromAttributes const adapter: ISchemaAdapter = { getAttributeDefs: (): VMAttributeDef[] => [ { name: 'title', atPath: 'note/title', optional: false }, { name: 'body', atPath: 'note/body', optional: false }, { name: 'tags', atPath: 'note/tags', optional: true }, ], getDefaults: () => ({ title: '', body: '' }), getEntityPrefix: () => 'note', } const NoteVM = createViewModelFactory({ adapter, vmName: 'Note', }) console.log('Minimal NoteVM created:', NoteVM.vmName) }