1/**2 * Declare application tables, permissions, and migrations without importing3 * Jazz directly.4 *5 * This module is a curated re-export of the pinned Jazz 2 schema DSL: the6 * same names and semantics, narrowed to the surface lofi documents and tests.7 * Author code imports {@link s} from here instead of `jazz-tools`, so version8 * bumps and upstream renames are absorbed by the package rather than by every9 * application schema.10 *11 * ```ts12 * import { s } from "@nzip/lofi/schema";13 *14 * export const app = s.defineApp({15 * tasks: s.table({16 * text: s.string(),17 * completed: s.boolean(),18 * createdAt: s.timestamp(),19 * }),20 * });21 * ```22 *23 * Shared-field columns ({@link sharedEncryptedText}, {@link sharedEncryptedJson})24 * declare only the sealed data shape here; the policy and key-lifecycle half —25 * group templates, key bootstrap and rotation, member reconciliation — lives in26 * `@nzip/lofi/access`, and pin remediation for changed peer keys is surfaced27 * through the main `@nzip/lofi` entry.28 *29 * @module30 */31import { schema } from "jazz-tools";32import { effect, insert, log, mutation, remove, update } from "./effects.ts";33import {34 encryptedDate,35 encryptedJson,36 encryptedNumber,37 encryptedText,38 registerEncryptedColumns,39} from "./encrypted.ts";40import {41 defineNestedApp,42 defineNestedPermissions,43 flattenNestedSchema,44 mergeNestedPermissions,45} from "./nested.ts";46import { plain, privateTable } from "./private-table.ts";47import { sharedEncryptedJson, sharedEncryptedText } from "./shared-encrypted.ts";4849/**50 * The curated schema DSL type. Every Jazz member is the pinned Jazz 251 * original, unchanged; deprecated members (`rename`) are omitted, and52 * everything else re-exports one-to-one. The nested-namespace members53 * (`defineNestedApp`, `defineNestedPermissions`, `mergeNestedPermissions`,54 * `flattenNestedSchema`) are lofi-owned: a naming layer over the pinned55 * `defineSliceableApp`, not part of the Jazz DSL.56 */57export type SchemaDsl =58 & Pick<59 typeof schema,60 // Column constructors.61 | "string"62 | "boolean"63 | "int"64 | "float"65 | "timestamp"66 | "bytes"67 | "json"68 | "enum"69 | "ref"70 | "array"71 // Column migration operations.72 | "add"73 | "drop"74 | "renameFrom"75 // Tables, schemas, and apps.76 | "table"77 | "defineSchema"78 | "defineApp"79 | "defineSliceableApp"80 // Schema migrations.81 | "defineMigration"82 | "renameTableFrom"83 // Permissions.84 | "definePermissions"85 | "permissionIntrospectionColumns"86 >87 & {88 defineNestedApp: typeof defineNestedApp;89 defineNestedPermissions: typeof defineNestedPermissions;90 mergeNestedPermissions: typeof mergeNestedPermissions;91 flattenNestedSchema: typeof flattenNestedSchema;92 encryptedText: typeof encryptedText;93 encryptedJson: typeof encryptedJson;94 encryptedNumber: typeof encryptedNumber;95 encryptedDate: typeof encryptedDate;96 privateTable: typeof privateTable;97 plain: typeof plain;98 sharedEncryptedText: typeof sharedEncryptedText;99 sharedEncryptedJson: typeof sharedEncryptedJson;100 mutation: typeof mutation;101 effect: typeof effect;102 log: typeof log;103 insert: typeof insert;104 update: typeof update;105 remove: typeof remove;106 };107108// The define entry points additionally record every encrypted column into109// the table/column registry the access layer consults; behavior and types110// are otherwise the pinned originals.111function withEncryptedColumnRegistration<112 F extends (definition: never, ...rest: never[]) => unknown,113>(define: F): F {114 return ((definition: unknown, ...rest: unknown[]) => {115 registerEncryptedColumns(definition);116 return (define as unknown as (...args: unknown[]) => unknown)(definition, ...rest);117 }) as unknown as F;118}119120/**121 * The lofi schema surface. Use in `src/schema.ts` and `src/permissions.ts` in122 * place of a raw `jazz-tools` import; Jazz member names and behavior are123 * identical to the pinned Jazz 2 DSL. The lofi-owned members: nested124 * namespaces ({@link defineNestedApp}), sealed columns ({@link encryptedText},125 * {@link encryptedJson}, {@link encryptedNumber}, {@link encryptedDate}, with126 * {@link privateTable} and {@link plain} for encrypt-by-default tables), and127 * the verb grammar — {@link mutation} declares128 * callable verbs over {@link insert}, {@link update}, and {@link remove},129 * carrying {@link effect} units and {@link log} entries. Verb calls return a130 * `WriteHandle`, observed in UI through `useWrite` and `usePendingWrites`131 * from `@nzip/lofi/preact`.132 */133export const s: SchemaDsl = {134 ...schema,135 defineSchema: withEncryptedColumnRegistration(schema.defineSchema),136 defineApp: withEncryptedColumnRegistration(schema.defineApp),137 defineSliceableApp: withEncryptedColumnRegistration(schema.defineSliceableApp),138 defineNestedApp,139 defineNestedPermissions,140 mergeNestedPermissions,141 flattenNestedSchema,142 encryptedText,143 encryptedJson,144 encryptedNumber,145 encryptedDate,146 privateTable,147 plain,148 sharedEncryptedText,149 sharedEncryptedJson,150 mutation,151 effect,152 log,153 insert,154 update,155 remove,156};157158export {159 type AnyColumnBuilder,160 plain,161 type PlainColumn,162 privateTable,163 type PrivateTableColumns,164} from "./private-table.ts";165166export {167 type SharedColumnOptions,168 sharedEncryptedJson,169 sharedEncryptedText,170 sharedFieldReady,171 type SharedFieldValue,172 unwrapSharedField,173} from "./shared-encrypted.ts";174export {175 isSharedFieldError,176 SharedFieldError,177 type SharedFieldErrorCode,178} from "./shared-crypto.ts";179export { type SharedColumnConfig } from "./shared-registry.ts";180181export {182 type EncryptedColumn,183 EncryptedColumnError,184 encryptedColumnsOf,185 encryptedDate,186 encryptedJson,187 encryptedNumber,188 type EncryptedStoredSql,189 encryptedText,190 isEncryptedColumn,191 matchDecrypted,192} from "./encrypted.ts";193export {194 defineNestedApp,195 defineNestedPermissions,196 flattenNestedSchema,197 mergeNestedPermissions,198 NESTED_SEPARATOR,199 type NestedApp,200 nestedAppDeployTarget,201 type NestedAppRoot,202 nestedAppTables,203 type NestedSchemaDefinition,204} from "./nested.ts";205export {206 effect,207 type EffectContext,208 type EffectHandlers,209 type EffectRow,210 type EffectUnit,211 type EffectUnitOptions,212 insert,213 type InsertVerb,214 log,215 mutation,216 type MutationOp,217 type MutationOpKind,218 type MutationOptions,219 type MutationVerb,220 remove,221 type RemoveVerb,222 update,223 type UpdateVerb,224} from "./effects.ts";225// Type-only, so the authoring-only module graph stays free of runtime code:226// verb calls settle through the runtime write handle, and these names let227// schema-graph modules annotate that contract without importing the runtime.228export type { WriteHandle, WriteRejection, WriteStage } from "../runtime/write-handle.ts";229230// Store provisioning (./store.ts) is deliberately NOT re-exported here: the231// Jazz schema loader bundles the author's schema module graph — this facade232// included — and executes it to derive the deployed schema, so this module233// must stay authoring-only. Import provisioning from "@nzip/lofi/schema/store".234235/**236 * Schema-authoring types re-exported from the pinned Jazz 2 DSL for use in237 * application signatures: the app and table shapes, the table handle type238 * (`TableProxy`, what a declared table is at runtime and what verb239 * operations accept), and the permission types (`PolicyContext` for240 * `definePermissions` callbacks, `CompiledPermissions` for the bundles they241 * compile to and `mergeNestedPermissions` combines). Row types for UI code242 * come from `@nzip/lofi` (`RowOf`), not from this module.243 */244export type {245 App,246 CompiledPermissions,247 DefinedTable,248 InsertOf,249 PolicyContext,250 Schema,251 SchemaDefinition,252 TableDefinition,253 TableProxy,254 WhereOf,255} from "jazz-tools";256257/**258 * Column builder types re-exported for signatures and for the alpha.53259 * workaround below: calling `.merge()` or `.transform()` on a column loses260 * the typed builder (the legacy untyped signatures shadow the typed261 * overloads upstream), so cast the result back to the intended column type.262 * The runtime object is unchanged; only the declaration needs repair:263 *264 * ```ts265 * total: s.int().default(0).merge("counter") as unknown as IntColumn<false, true>,266 * tags: s.string().transform({267 * from: (value: string) => value.split(","),268 * to: (value: string[]) => value.join(","),269 * }) as unknown as StringColumn<false, false, string[]>,270 * ```271 */272export type {273 ArrayColumn,274 BooleanColumn,275 BytesColumn,276 EnumColumn,277 FloatColumn,278 IntColumn,279 JsonColumn,280 RefColumn,281 StringColumn,282 TimestampColumn,283} from "jazz-tools";