import type { ObjectOptions, Static, TAnySchema, TObject } from '@sinclair/typebox' import { Type } from '@sinclair/typebox' // HACK: @see https://github.com/elysiajs/elysia/issues/75 const EntityID = Type.String() // HACK how to configure ID format? const URL = Type.String({ format: 'URL' }) const BlockType = Type.Union([ Type.Literal('text'), Type.Literal('smartlist'), Type.Literal('tabs'), Type.Literal('survey'), ]) // ? is this best practice typebox enum syntax ? export type BlockType = Static export const TiptapContentT = Type.Object({ content: Type.Optional(Type.Any()), type: Type.Optional(Type.String()), }) export type TiptapContent = Record export const Entity = Type.Object({ isDeleted: Type.Optional(Type.Boolean()), }) export function wovinAtName(atToUse, TypeBoxDef: TAnySchema) { TypeBoxDef.wovinAtName = atToUse return TypeBoxDef } interface WovinSchemaOptions { wovinPrefix?: string } export function T(typeBoxObjectDef: DEF, wovinOptions: WovinSchemaOptions = {}) { const TypeBoxDef = Type.Object(typeBoxObjectDef, wovinOptions) // Object.assign(TypeBoxDef, wovinOptions) return TypeBoxDef as TObject } // only the props that belong in the wovin Applogs belong here // all other props needed for rendering belong on the VMs as _privates or getters export const TypeMap = { Entity, Relation: T({ // en: EntityID, block: EntityID, childOf: EntityID, isExpanded: Type.Optional(Type.Boolean()), isReply: Type.Optional(Type.Boolean()), isMirror: Type.Optional(Type.Boolean()), after: Type.Optional(EntityID), }), Block: T({ // en: EntityID, type: BlockType, content: TiptapContentT, // isTokenHidden: Type.Optional(Type.Boolean()), // TODO rename with wovinAtName or similar mirrors: Type.Optional(Type.String()), pullUrl: Type.Optional(URL), }), Provider: T({ type: Type.Optional(Type.Union([ Type.Literal('ipfs-gateway'), Type.Literal('ucan-store-proxy'), Type.Literal('web3-storage'), ])), name: wovinAtName('name', Type.Optional(Type.String())), url: wovinAtName('url', Type.Optional(Type.String())), }, { wovinPrefix: 'wovin/provider', }), AppSettings: T({ startPage: Type.Optional(Type.Union([ Type.Literal('empty-block'), Type.Literal('timeline'), Type.Literal('home-block'), ])), homeBlock: Type.Optional(EntityID), autocollapseDepth: Type.Optional(Type.Number()), autocollapseDepthFocussed: Type.Optional(Type.Number()), autocollapseDepthTimeline: Type.Optional(Type.Number()), autocollapseDepthTimelineSmartlist: Type.Optional(Type.Number()), }, { wovinPrefix: 'note3/settings', }), Publication: T({ // en: EntityID, name: Type.String(), // TODO ... }), Subscription: T({ // en: EntityID, name: Type.String(), // TODO ... }), } as const // export const AutoVMs = wovinMakeAutoVMs(TypeMap) // const wovinMakeAutoVMs = Object.fromEntries( // Object.entries(TypeMap) // .map(([eachEntityName, eachDef]) => [`${eachEntityName}VM`, makeAutoVM(eachEntityName, eachDef)]), // ) const _archive = { // 'Provider2': AttributePrefix( // 'wovin/provider', // recursive prefix // Type.Object({ // type: Type.String(), // url: AttributeRename('url', Type.String(/* { rename: 'url' } as StringOptions*/) ), // // url: AttributeRename('foo/url', Type.String()), // AttributeRename will remove parent prefixs ? how to make obvious // }/* , { // // Theoretically possible, but far uglier and meant for other shenanigans // additionalProperties: { // '[Kind]': 'prefix', // params: [], // prefix: 'wovin/provider', // static: false, // }, // } */), // ), }