import z from "zod"; /** * Pool section. `min` and `max` are non-negative integers; `min` is bounded * above by `max` via a refine in the parent schema. */ export const PoolConfigSchema = z.object({ min: z.number().int().min(0).default(1), max: z.number().int().min(1).default(10), idleMs: z.number().int().min(0).default(30_000), acquireTimeoutMs: z.number().int().min(0).default(5_000), }); /** Retry section. */ export const RetryConfigSchema = z.object({ maxAttempts: z.number().int().min(1).default(3), baseBackoffMs: z.number().int().min(1).default(50), maxBackoffMs: z.number().int().min(1).default(2_000), jitter: z.boolean().default(true), }); /** Tenancy section. */ export const TenancyConfigSchema = z.object({ strategy: z .enum(["shared", "namespace-per-tenant", "database-per-tenant"]) .default("shared"), }); /** Migrations section. */ export const MigrationConfigSchema = z.object({ autoRun: z.boolean().default(true), directory: z.string().default("./surql"), ledgerTable: z.string().default("_migrations"), lockTable: z.string().default("_migration_lock"), leaseMs: z.number().int().min(1_000).default(60_000), }); /** * Public options bundle accepted by `createDatabasePlugin`. Every nested * section is optional and falls through to defaults; only `url` is * effectively required (the default is `ws://localhost:8000/rpc` which * matches the surrealdb dev surface). */ export const DatabasePluginOptionsSchema = z .object({ url: z.string().url().default("ws://localhost:8000/rpc"), namespace: z.string().default("app"), database: z.string().default("main"), username: z.string().default("root"), password: z.string().default("root"), autoConnect: z.boolean().default(true), pool: PoolConfigSchema.default({ min: 1, max: 10, idleMs: 30_000, acquireTimeoutMs: 5_000, }), retry: RetryConfigSchema.default({ maxAttempts: 3, baseBackoffMs: 50, maxBackoffMs: 2_000, jitter: true, }), tenancy: TenancyConfigSchema.default({ strategy: "shared" }), migrations: MigrationConfigSchema.default({ autoRun: true, directory: "./surql", ledgerTable: "_migrations", lockTable: "_migration_lock", leaseMs: 60_000, }), }) .superRefine((value, ctx) => { if (value.pool.min > value.pool.max) { ctx.addIssue({ code: "custom", message: "pool.min must be <= pool.max", path: ["pool", "min"], }); } if (value.retry.baseBackoffMs > value.retry.maxBackoffMs) { ctx.addIssue({ code: "custom", message: "retry.baseBackoffMs must be <= retry.maxBackoffMs", path: ["retry", "baseBackoffMs"], }); } }); /** Fully-resolved configuration after Zod parse. */ export type DatabasePluginConfigParsed = z.infer< typeof DatabasePluginOptionsSchema >;