@shyk/kadak 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["z"],"sources":["../src/schema.ts","../src/error.ts","../src/query.ts","../src/connect.ts"],"sourcesContent":["// src/schema.ts — The heart of KadakORM\n// Purely declarative — no SQL generation, no database calls.\n// Same metadata drives DDL, query building, Zod validation, AND TypeScript inference.\n\nimport { z } from 'zod'\n\n// ============================================================\n// Utilities\n// ============================================================\n\n/** Converts camelCase to snake_case for PostgreSQL column naming */\n// JS convention is camelCase, PG convention is snake_case.\n// Users write camelCase, KadakORM translates to snake_case in SQL automatically.\nexport function camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`)\n}\n\n/** Flattens intersection types so IDE tooltips show clean objects, not A & B */\ntype Simplify<T> = { [K in keyof T]: T[K] } & {}\n\n// ============================================================\n// Column Configuration — runtime metadata for every column\n// ============================================================\n\n/** @internal Runtime metadata describing a column's PG type, constraints, behavior */\nexport interface ColumnConfig {\n pgType: string\n nullable: boolean\n hasDefault: boolean\n isPrimaryKey: boolean\n isUnique: boolean\n defaultValue?: unknown\n /** SQL expression for default — 'now()' or 'gen_random_uuid()' */\n defaultSql?: string\n /** DB auto-generates this value (IDENTITY columns) */\n isGenerated: boolean\n /** Zod validation hint — 'email', 'uuid' */\n zodCheck?: string\n /** Stored Zod schema — only for JSONB columns */\n zodSchema?: z.ZodType\n /** Auto-update on every UPDATE — for updatedAt patterns */\n autoUpdate: boolean\n /** Soft delete marker — findMany auto-filters, delete sets timestamp */\n softDelete: boolean\n min?: number\n max?: number\n}\n\n// ============================================================\n// Column Class — builder pattern with compile-time type tracking\n// ============================================================\n\n/**\n * A column definition carrying runtime metadata AND compile-time types.\n *\n * Three generics flow through the entire ORM:\n * - TType: JS type (string, number, boolean, Date)\n * - TNullable: whether NULL is allowed (adds `| null`)\n * - THasDefault: whether INSERT can omit this (adds `?`)\n *\n * Every modifier returns a NEW Column — immutable builder.\n */\nexport class Column<\n TType,\n TNullable extends boolean = false,\n THasDefault extends boolean = false,\n> {\n readonly _config: ColumnConfig\n\n // Brand fields — TypeScript needs these to distinguish Column<string> from Column<number>\n // at the structural type level. They're never assigned a value at runtime.\n declare readonly _type: TType\n declare readonly _nullable: TNullable\n declare readonly _hasDefault: THasDefault\n\n constructor(config: ColumnConfig) {\n // Freeze prevents accidental mutation — immutability is a core invariant\n this._config = Object.freeze({ ...config })\n }\n\n /** NOT NULL — already the default. Exists for explicit readability. */\n required(): Column<TType, false, THasDefault> {\n return new Column({ ...this._config, nullable: false })\n }\n\n /** Allow NULL — column type becomes TType | null in TypeScript */\n optional(): Column<TType, true, THasDefault> {\n return new Column({ ...this._config, nullable: true })\n }\n\n /** Add UNIQUE constraint */\n unique(): Column<TType, TNullable, THasDefault> {\n return new Column({ ...this._config, isUnique: true })\n }\n\n /** Mark as PRIMARY KEY */\n primaryKey(): Column<TType, TNullable, THasDefault> {\n return new Column({ ...this._config, isPrimaryKey: true })\n }\n\n /**\n * Set default value — makes field optional in INSERT.\n *\n * Named shortcuts are resolved per column type to avoid ambiguity:\n * - 'now' on TIMESTAMPTZ → SQL DEFAULT now()\n * - 'uuid' on UUID → SQL DEFAULT gen_random_uuid()\n * On other types, these strings are treated as literal values.\n */\n default(value: TType extends Date ? TType | 'now' : TType): Column<TType, TNullable, true> {\n // Shortcuts scoped by PG type — 'now' is only special on TIMESTAMPTZ, not TEXT\n const typeShortcuts: Record<string, Record<string, string>> = {\n TIMESTAMPTZ: { now: 'now()' },\n UUID: { uuid: 'gen_random_uuid()' },\n }\n const shortcuts = typeShortcuts[this._config.pgType] ?? {}\n const sqlExpr = typeof value === 'string' ? shortcuts[value as string] : undefined\n\n return new Column({\n ...this._config,\n hasDefault: true,\n defaultValue: sqlExpr ? undefined : value,\n defaultSql: sqlExpr ?? this._config.defaultSql,\n })\n }\n\n /** Min constraint — string length for text, numeric value for numbers */\n min(n: number): Column<TType, TNullable, THasDefault> {\n return new Column({ ...this._config, min: n })\n }\n\n /** Max constraint — string length for text, numeric value for numbers */\n max(n: number): Column<TType, TNullable, THasDefault> {\n return new Column({ ...this._config, max: n })\n }\n\n /** Auto-update on every UPDATE query — designed for updatedAt columns */\n autoUpdate(): Column<TType, TNullable, true> {\n // Implies hasDefault because the ORM injects the value automatically\n return new Column({ ...this._config, autoUpdate: true, hasDefault: true })\n }\n\n /**\n * Soft delete marker. When set on a column:\n * - findMany() auto-adds WHERE column IS NULL\n * - delete() sets this column to now() instead of DELETE\n * - findMany({ withDeleted: true }) bypasses the filter\n */\n softDelete(): Column<TType, true, true> {\n // Always nullable (null = not deleted) and has default (null)\n return new Column({ ...this._config, softDelete: true, nullable: true, hasDefault: true })\n }\n}\n\n// ============================================================\n// Column Factories — the `kadak` namespace\n// ============================================================\n\n/** Base config with required-by-default semantics */\nfunction baseConfig(pgType: string): ColumnConfig {\n return {\n pgType,\n nullable: false,\n hasDefault: false,\n isPrimaryKey: false,\n isUnique: false,\n isGenerated: false,\n autoUpdate: false,\n softDelete: false,\n }\n}\n\n/**\n * Column factory namespace. Every column definition starts here.\n *\n * ```ts\n * const users = table('users', {\n * id: kadak.id(),\n * name: kadak.text().required(),\n * email: kadak.email().unique(),\n * })\n * ```\n */\nexport const kadak = {\n /**\n * Modern auto-incrementing integer primary key.\n * Uses IDENTITY (not deprecated SERIAL).\n * DDL: INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY\n */\n id: (): Column<number, false, true> =>\n new Column({ ...baseConfig('INTEGER'), isPrimaryKey: true, isGenerated: true, hasDefault: true }),\n\n /**\n * UUID primary key with auto-generation via gen_random_uuid().\n * Built into PostgreSQL 13+ — no extensions needed.\n * Ideal for distributed systems and secure-by-default IDs.\n */\n uuidId: (): Column<string, false, true> =>\n new Column({ ...baseConfig('UUID'), isPrimaryKey: true, hasDefault: true, defaultSql: 'gen_random_uuid()' }),\n\n /**\n * Legacy SERIAL primary key — use kadak.id() for new projects.\n * Kept for compatibility with existing schemas.\n */\n serialId: (): Column<number, false, true> =>\n new Column({ ...baseConfig('SERIAL'), isPrimaryKey: true, isGenerated: true, hasDefault: true }),\n\n /** Unlimited-length text. Use .min()/.max() for Zod length validation. */\n text: (): Column<string, false, false> =>\n new Column(baseConfig('TEXT')),\n\n /** 4-byte integer. For whole numbers — counts, ages, quantities. */\n int: (): Column<number, false, false> =>\n new Column(baseConfig('INTEGER')),\n\n /**\n * Alias for kadak.int(). Maps to INTEGER.\n * ⚠️ This is NOT floating point — 9.99 becomes 9 in the database.\n * Use kadak.float() for decimals or kadak.decimal() for money.\n */\n number: (): Column<number, false, false> =>\n new Column(baseConfig('INTEGER')),\n\n /**\n * 8-byte floating point (DOUBLE PRECISION).\n * For scientific data, coordinates, measurements.\n * ⚠️ NEVER use for money — use kadak.decimal() instead.\n */\n float: (): Column<number, false, false> =>\n new Column(baseConfig('FLOAT8')),\n\n /**\n * Arbitrary precision decimal (NUMERIC).\n * Returns STRING in TypeScript — intentional to preserve precision.\n * JS floats lose precision: 0.1 + 0.2 !== 0.3\n * ✅ Use for: money, prices, financial math\n */\n decimal: (): Column<string, false, false> =>\n new Column(baseConfig('NUMERIC')),\n\n /** Boolean true/false */\n boolean: (): Column<boolean, false, false> =>\n new Column(baseConfig('BOOLEAN')),\n\n /**\n * Timestamp with timezone — always TIMESTAMPTZ.\n * Prevents the #1 PostgreSQL date/time footgun (timezone-naive timestamps).\n * Supports .default('now') for SQL DEFAULT now().\n */\n timestamp: (): Column<Date, false, false> =>\n new Column(baseConfig('TIMESTAMPTZ')),\n\n /**\n * TEXT with automatic Zod email validation.\n * PostgreSQL has no EMAIL type — this is TEXT underneath.\n * The email check is applied for free in validator().\n */\n email: (): Column<string, false, false> =>\n new Column({ ...baseConfig('TEXT'), zodCheck: 'email' }),\n\n /** UUID column (non-primary-key). For foreign keys, tokens, etc. */\n uuid: (): Column<string, false, false> =>\n new Column({ ...baseConfig('UUID'), zodCheck: 'uuid' }),\n\n /**\n * JSONB column with required Zod schema for runtime validation.\n * The schema provides BOTH the TS type (via z.infer) AND runtime validation.\n *\n * For unstructured JSON, pass z.unknown():\n * ```ts\n * metadata: kadak.json(z.unknown())\n * ```\n */\n json: <T extends z.ZodType>(schema: T): Column<z.infer<T>, false, false> =>\n new Column({ ...baseConfig('JSONB'), zodSchema: schema }),\n} as const\n\n// ============================================================\n// Table Options — table-level constraints\n// ============================================================\n\n/** Table-level constraints beyond what individual columns express */\nexport interface TableOptions {\n /**\n * Compound unique constraints — each array is a group of columns\n * that must be unique together.\n * ```ts\n * { unique: [['userId', 'teamId']] }\n * ```\n */\n unique?: string[][]\n}\n\n// ============================================================\n// Table Class\n// ============================================================\n\ntype ColumnsRecord = Record<string, Column<any, any, any>>\n\n/**\n * A table definition. Created via the `table()` function.\n * Holds column metadata and generates typed Zod validators.\n */\nexport class Table<TName extends string, TColumns extends ColumnsRecord> {\n readonly _name: TName\n readonly _columns: TColumns\n readonly _options?: TableOptions\n /** Maps camelCase TS keys → snake_case PG column names */\n readonly _columnMap: Record<string, string>\n\n constructor(name: TName, columns: TColumns, options?: TableOptions) {\n this._name = name\n this._columns = columns\n this._options = options\n\n // Pre-compute mapping once — reused by query builder and DDL generator\n this._columnMap = {}\n for (const key of Object.keys(columns)) {\n this._columnMap[key] = camelToSnake(key)\n }\n }\n\n /** Alias for insertValidator() — the most common use case (validating user input) */\n validator() {\n return this.insertValidator()\n }\n\n /** Validates data for INSERT — generated/defaulted fields are optional */\n insertValidator() {\n return z.object(this._buildShape('insert'))\n }\n\n /** Validates data for SELECT — all columns present, nullability applied */\n selectValidator() {\n return z.object(this._buildShape('select'))\n }\n\n /** Validates data for UPDATE — everything optional (partial update) */\n updateValidator() {\n return z.object(this._buildShape('update'))\n }\n\n /** @internal Builds Zod shape for a given operation mode */\n private _buildShape(mode: 'insert' | 'select' | 'update'): Record<string, z.ZodType> {\n const shape: Record<string, z.ZodType> = {}\n\n for (const [key, col] of Object.entries(this._columns)) {\n let zodType = this._baseZodType(col._config)\n\n // Apply nullable before optional — Zod order matters\n if (col._config.nullable) {\n zodType = zodType.nullable()\n }\n\n // Mode-specific optionality\n if (mode === 'insert' && (col._config.hasDefault || col._config.isGenerated)) {\n zodType = zodType.optional()\n } else if (mode === 'update') {\n // Everything is optional in an update — you only send what changed\n zodType = zodType.optional()\n }\n // mode === 'select' — nothing is optional, every column comes back from DB\n\n shape[key] = zodType\n }\n\n return shape\n }\n\n /** @internal Creates the base Zod type for a column, without nullable/optional */\n private _baseZodType(config: ColumnConfig): z.ZodType {\n // JSONB columns carry their own Zod schema — use it directly\n if (config.pgType === 'JSONB' && config.zodSchema) {\n return config.zodSchema\n }\n\n switch (config.pgType) {\n case 'TEXT': {\n let s = z.string()\n if (config.zodCheck === 'email') s = s.email()\n if (config.min !== undefined) s = s.min(config.min)\n if (config.max !== undefined) s = s.max(config.max)\n return s\n }\n case 'INTEGER': {\n let n = z.number().int()\n if (config.min !== undefined) n = n.min(config.min)\n if (config.max !== undefined) n = n.max(config.max)\n return n\n }\n case 'FLOAT8': {\n let n = z.number()\n if (config.min !== undefined) n = n.min(config.min)\n if (config.max !== undefined) n = n.max(config.max)\n return n\n }\n case 'NUMERIC':\n // Decimal returns string — validated as decimal format\n return z.string().regex(/^-?\\d+(\\.\\d+)?$/, 'Must be a valid decimal number')\n case 'BOOLEAN':\n return z.boolean()\n case 'TIMESTAMPTZ':\n // Coerce accepts both Date objects and ISO strings — handles API input gracefully\n return z.coerce.date()\n case 'UUID':\n return z.string().uuid()\n case 'SERIAL':\n return z.number().int()\n default:\n return z.unknown()\n }\n }\n}\n\n// ============================================================\n// table() Factory\n// ============================================================\n\n/**\n * Define a table. This is the primary API for declaring your database schema.\n *\n * ```ts\n * export const users = table('users', {\n * id: kadak.id(),\n * name: kadak.text().required(),\n * email: kadak.email().unique(),\n * age: kadak.int().optional(),\n * createdAt: kadak.timestamp().default('now'),\n * })\n * ```\n */\nexport function table<TName extends string, TColumns extends ColumnsRecord>(\n name: TName,\n columns: TColumns,\n options?: TableOptions,\n): Table<TName, TColumns> {\n return new Table(name, columns, options)\n}\n\n// ============================================================\n// Type Inference Utilities\n// ============================================================\n\n/** Extract the SELECT type for a column — what the database returns */\ntype ColumnSelectType<C> = C extends Column<infer T, infer N, any>\n ? N extends true ? T | null : T\n : never\n\n/** Keys of columns that are REQUIRED in INSERT (no default, not generated) */\ntype RequiredInsertKeys<C extends ColumnsRecord> = {\n [K in keyof C]: C[K] extends Column<any, any, true> ? never : K\n}[keyof C]\n\n/** Keys of columns that are OPTIONAL in INSERT (has default or is generated) */\ntype OptionalInsertKeys<C extends ColumnsRecord> = {\n [K in keyof C]: C[K] extends Column<any, any, true> ? K : never\n}[keyof C]\n\n/**\n * Infer the SELECT type — what you get back from queries.\n * Every column is present. Nullable columns have `| null`.\n *\n * ```ts\n * type User = Infer<typeof users>\n * // { id: number, name: string, email: string, age: number | null, createdAt: Date }\n * ```\n */\nexport type Infer<T extends Table<any, any>> = Simplify<{\n [K in keyof T['_columns']]: ColumnSelectType<T['_columns'][K]>\n}>\n\n/**\n * Infer the INSERT type — what you provide to create a row.\n * Generated/defaulted columns become optional. Nullable columns accept null.\n *\n * ```ts\n * type NewUser = InferInsert<typeof users>\n * // { name: string, email: string, age?: number | null, id?: number, createdAt?: Date }\n * ```\n */\nexport type InferInsert<T extends Table<any, any>> = Simplify<\n // Required fields — no default, must provide\n { [K in RequiredInsertKeys<T['_columns']>]: ColumnSelectType<T['_columns'][K]> } &\n // Optional fields — has default or generated, can omit\n { [K in OptionalInsertKeys<T['_columns']>]?: ColumnSelectType<T['_columns'][K]> }\n>\n\n/**\n * Infer the UPDATE type — what you provide for partial updates.\n * Everything is optional. Nullable columns accept null.\n *\n * ```ts\n * type UserUpdate = InferUpdate<typeof users>\n * // { id?: number, name?: string, email?: string, age?: number | null, createdAt?: Date }\n * ```\n */\nexport type InferUpdate<T extends Table<any, any>> = Simplify<\n Partial<Infer<T>>\n>\n","// src/error.ts — Human-readable error wrapping for PostgreSQL errors\n// Every raw pg error gets caught and wrapped before it reaches the user.\n\n/** All error codes KadakORM can produce */\nexport type KadakErrorCode =\n | 'NOT_NULL_VIOLATION'\n | 'UNIQUE_VIOLATION'\n | 'FOREIGN_KEY_VIOLATION'\n | 'TABLE_NOT_FOUND'\n | 'COLUMN_NOT_FOUND'\n | 'CONNECTION_ERROR'\n | 'AUTH_ERROR'\n | 'QUERY_TIMEOUT'\n | 'UNKNOWN'\n\n/** Maps PostgreSQL error codes to human-readable KadakORM codes + hints */\nconst PG_ERROR_MAP: Record<string, { code: KadakErrorCode; hint: string }> = {\n '23505': { code: 'UNIQUE_VIOLATION', hint: 'A row with this value already exists. Check your unique columns.' },\n '23502': { code: 'NOT_NULL_VIOLATION', hint: 'A required column is missing. Add .optional() if it should be nullable.' },\n '23503': { code: 'FOREIGN_KEY_VIOLATION', hint: 'The referenced row does not exist in the related table.' },\n '42P01': { code: 'TABLE_NOT_FOUND', hint: 'Did you run migrations? The table does not exist yet.' },\n '42703': { code: 'COLUMN_NOT_FOUND', hint: 'Check your schema — this column is not in the table.' },\n '08006': { code: 'CONNECTION_ERROR', hint: 'Cannot reach the database. Check your DATABASE_URL and network.' },\n '08001': { code: 'CONNECTION_ERROR', hint: 'Connection refused. Is PostgreSQL running?' },\n '28P01': { code: 'AUTH_ERROR', hint: 'Wrong username or password in your connection string.' },\n '3D000': { code: 'CONNECTION_ERROR', hint: 'This database does not exist. Check the database name in your URL.' },\n '57014': { code: 'QUERY_TIMEOUT', hint: 'Query took too long. Consider adding an index or simplifying the query.' },\n}\n\n/**\n * The one error class users ever see from KadakORM.\n * Always includes: what went wrong, which table/column, and how to fix it.\n */\nexport class KadakError extends Error {\n readonly code: KadakErrorCode\n readonly table?: string\n readonly column?: string\n readonly constraint?: string\n readonly hint: string\n /** Always preserved — the raw pg error for advanced debugging */\n readonly originalError: unknown\n\n constructor(opts: {\n code: KadakErrorCode\n message: string\n hint: string\n table?: string\n column?: string\n constraint?: string\n originalError: unknown\n }) {\n super(opts.message)\n this.name = 'KadakError'\n this.code = opts.code\n this.hint = opts.hint\n this.table = opts.table\n this.column = opts.column\n this.constraint = opts.constraint\n this.originalError = opts.originalError\n }\n}\n\n/** Wraps any postgres.js error into a KadakError with context */\nexport function wrapPgError(err: unknown, tableName?: string): KadakError {\n const pgErr = err as Record<string, any> | undefined\n const pgCode: string = pgErr?.code ?? ''\n const mapped = PG_ERROR_MAP[pgCode] ?? { code: 'UNKNOWN' as const, hint: 'An unexpected database error occurred.' }\n\n const table = pgErr?.table_name ?? tableName\n const column: string | undefined = pgErr?.column_name\n const constraint: string | undefined = pgErr?.constraint_name\n\n // Build a message that actually tells you what to do\n let message: string = pgErr?.message ?? 'Unknown database error'\n if (mapped.code === 'NOT_NULL_VIOLATION' && column) {\n message = `Column '${column}' in table '${table}' cannot be null. Did you forget to pass '${column}'?`\n } else if (mapped.code === 'UNIQUE_VIOLATION' && constraint) {\n message = `Duplicate value violates constraint '${constraint}' on table '${table}'.`\n } else if (mapped.code === 'TABLE_NOT_FOUND') {\n message = `Table '${table ?? 'unknown'}' does not exist. Have you run your migrations?`\n }\n\n return new KadakError({ code: mapped.code, message, hint: mapped.hint, table, column, constraint, originalError: err })\n}\n","// src/query.ts — Query builder for KadakORM\n// Thin layer over postgres.js tagged templates — no query string concatenation.\n// Handles camelCase↔snake_case, soft deletes, autoUpdate injection.\n\nimport type postgres from 'postgres'\nimport type { Table, Infer, InferInsert, InferUpdate, Column } from './schema'\nimport { wrapPgError } from './error'\n\n// ============================================================\n// Query Option Types\n// ============================================================\n\n/** Options for findMany/findFirst — without select (returns full row) */\nexport interface FindManyOptions<T extends Table<any, any>> {\n where?: Partial<Infer<T>>\n orderBy?: Partial<Record<keyof Infer<T>, 'asc' | 'desc'>>\n limit?: number\n offset?: number\n /** When true, includes soft-deleted rows */\n withDeleted?: boolean\n /** Reserved for relations — not yet implemented */\n include?: never\n}\n\n// ============================================================\n// TableClient — the query interface for a single table\n// ============================================================\n\n/**\n * Query client for a single table. Created by `connect()` — never instantiated directly.\n * Provides findMany, findFirst, insert, update, delete with full type safety.\n */\nexport class TableClient<T extends Table<any, any>> {\n /** @internal */ readonly _sql: postgres.Sql\n /** @internal */ readonly _table: T\n /** @internal */ readonly _reverseMap: Record<string, string>\n /** @internal */ _onError?: (err: Error) => void\n\n constructor(sql: postgres.Sql, table: T) {\n this._sql = sql\n this._table = table\n\n // Pre-compute reverse mapping: snake_case → camelCase\n // Used to transform query results back to JS convention\n this._reverseMap = {}\n for (const [camel, snake] of Object.entries(table._columnMap)) {\n this._reverseMap[snake] = camel\n }\n }\n\n // ----------------------------------------------------------\n // findMany — SELECT with filtering, ordering, pagination\n // ----------------------------------------------------------\n\n /** Find rows with optional select for precise return types */\n findMany<K extends keyof Infer<T>>(\n options: FindManyOptions<T> & { select: Record<K, true> }\n ): Promise<Pick<Infer<T>, K>[]>\n /** Find rows — returns full row type */\n findMany(options?: FindManyOptions<T>): Promise<Infer<T>[]>\n async findMany(options?: FindManyOptions<T> & { select?: Record<string, true> }): Promise<any[]> {\n try {\n const sql = this._sql\n const t = this._table\n\n // Build column list — either selected columns or all\n const cols = options?.select\n ? Object.keys(options.select).filter(k => options.select![k]).map(k => t._columnMap[k] ?? k)\n : Object.values(t._columnMap)\n\n // Assemble fragments\n const whereFragment = this._buildWhere(options?.where, options?.withDeleted)\n const orderFragment = this._buildOrderBy(options?.orderBy)\n const limitFragment = options?.limit !== undefined ? sql`LIMIT ${options.limit}` : sql``\n const offsetFragment = options?.offset !== undefined ? sql`OFFSET ${options.offset}` : sql``\n\n const rows = await sql`\n SELECT ${sql(cols)} FROM ${sql(t._name)}\n ${whereFragment} ${orderFragment} ${limitFragment} ${offsetFragment}\n `\n return rows.map(row => this._toJs(row))\n } catch (err) {\n throw wrapPgError(err, this._table._name)\n }\n }\n\n // ----------------------------------------------------------\n // findFirst — same as findMany but returns single row or null\n // ----------------------------------------------------------\n\n findFirst<K extends keyof Infer<T>>(\n options: FindManyOptions<T> & { select: Record<K, true> }\n ): Promise<Pick<Infer<T>, K> | null>\n findFirst(options?: FindManyOptions<T>): Promise<Infer<T> | null>\n async findFirst(options?: FindManyOptions<T> & { select?: Record<string, true> }): Promise<any> {\n const rows = await this.findMany({ ...options, limit: 1 } as any)\n return rows[0] ?? null\n }\n\n // ----------------------------------------------------------\n // insert — INSERT INTO with RETURNING *\n // ----------------------------------------------------------\n\n /** Insert a single row */\n async insert(data: InferInsert<T>): Promise<Infer<T>>\n /** Insert multiple rows */\n async insert(data: InferInsert<T>[]): Promise<Infer<T>[]>\n async insert(data: InferInsert<T> | InferInsert<T>[]): Promise<any> {\n try {\n const sql = this._sql\n const t = this._table\n const isBulk = Array.isArray(data)\n const items = isBulk ? data : [data]\n\n // Convert each item's keys from camelCase to snake_case\n const snakeItems = items.map(item => this._toDb(item as Record<string, unknown>))\n\n // postgres.js handles bulk insert when given an array of column names + values\n const cols = Object.keys(snakeItems[0])\n const rows = await sql`\n INSERT INTO ${sql(t._name)} ${sql(snakeItems, ...cols)} RETURNING *\n `\n\n const result = rows.map(row => this._toJs(row))\n return isBulk ? result : result[0]\n } catch (err) {\n throw wrapPgError(err, this._table._name)\n }\n }\n\n // ----------------------------------------------------------\n // update — UPDATE SET ... WHERE ... RETURNING *\n // ----------------------------------------------------------\n\n async update(options: { where: Partial<Infer<T>>; data: InferUpdate<T> }): Promise<Infer<T>[]> {\n try {\n const sql = this._sql\n const t = this._table\n\n // Convert update data to snake_case, stripping undefined values\n const snakeData: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(options.data as Record<string, unknown>)) {\n if (value !== undefined) {\n snakeData[t._columnMap[key] ?? key] = value\n }\n }\n\n // Auto-inject autoUpdate columns (e.g., updatedAt → new Date())\n for (const [key, col] of Object.entries(t._columns)) {\n if ((col as Column<any, any, any>)._config.autoUpdate) {\n snakeData[t._columnMap[key]] = new Date()\n }\n }\n\n const whereFragment = this._buildWhere(options.where, false)\n\n const rows = await sql`\n UPDATE ${sql(t._name)} SET ${sql(snakeData)} ${whereFragment} RETURNING *\n `\n return rows.map(row => this._toJs(row)) as Infer<T>[]\n } catch (err) {\n throw wrapPgError(err, this._table._name)\n }\n }\n\n // ----------------------------------------------------------\n // delete — soft delete if configured, otherwise hard delete\n // ----------------------------------------------------------\n\n async delete(options: { where: Partial<Infer<T>> }): Promise<Infer<T>[]> {\n // Find soft delete column if one exists\n const softDeleteEntry = Object.entries(this._table._columns)\n .find(([_, col]) => (col as Column<any, any, any>)._config.softDelete)\n\n if (softDeleteEntry) {\n // Soft delete — set the timestamp instead of deleting\n const [key] = softDeleteEntry\n const snakeCol = this._table._columnMap[key]\n return this.update({\n where: options.where,\n data: { [key]: new Date() } as any,\n })\n }\n\n return this.hardDelete(options)\n }\n\n /** Always performs a real DELETE — bypasses soft delete */\n async hardDelete(options: { where: Partial<Infer<T>> }): Promise<Infer<T>[]> {\n try {\n const sql = this._sql\n const whereFragment = this._buildWhere(options.where, true)\n\n const rows = await sql`\n DELETE FROM ${sql(this._table._name)} ${whereFragment} RETURNING *\n `\n return rows.map(row => this._toJs(row)) as Infer<T>[]\n } catch (err) {\n throw wrapPgError(err, this._table._name)\n }\n }\n\n // ============================================================\n // Internal helpers\n // ============================================================\n\n /** Builds a WHERE fragment from a JS object, including soft delete filter */\n private _buildWhere(\n where?: Partial<Infer<T>>,\n withDeleted?: boolean,\n ): postgres.PendingQuery<any> {\n const sql = this._sql\n const conditions: postgres.PendingQuery<any>[] = []\n\n // User-provided conditions\n if (where) {\n for (const [key, value] of Object.entries(where)) {\n const col = this._table._columnMap[key] ?? key\n if (value === undefined) continue\n if (value === null) {\n conditions.push(sql`${sql(col)} IS NULL`)\n } else {\n conditions.push(sql`${sql(col)} = ${value as postgres.SerializableParameter}`)\n }\n }\n }\n\n // Auto-add soft delete filter unless explicitly bypassed\n if (!withDeleted) {\n for (const [key, col] of Object.entries(this._table._columns)) {\n if ((col as Column<any, any, any>)._config.softDelete) {\n conditions.push(sql`${sql(this._table._columnMap[key])} IS NULL`)\n }\n }\n }\n\n if (conditions.length === 0) return sql``\n\n // Join conditions with AND using postgres.js fragment composition\n let combined = conditions[0]\n for (let i = 1; i < conditions.length; i++) {\n combined = sql`${combined} AND ${conditions[i]}`\n }\n return sql`WHERE ${combined}`\n }\n\n /** Builds an ORDER BY fragment */\n private _buildOrderBy(\n orderBy?: Partial<Record<string, 'asc' | 'desc'>>,\n ): postgres.PendingQuery<any> {\n const sql = this._sql\n if (!orderBy) return sql``\n\n const entries = Object.entries(orderBy)\n if (entries.length === 0) return sql``\n\n const parts = entries.map(([key, dir]) => {\n const col = this._table._columnMap[key] ?? key\n // postgres.js unsafe() needed for ASC/DESC since they're SQL keywords, not values\n return sql`${sql(col)} ${dir === 'desc' ? sql`DESC` : sql`ASC`}`\n })\n\n let combined = parts[0]\n for (let i = 1; i < parts.length; i++) {\n combined = sql`${combined}, ${parts[i]}`\n }\n return sql`ORDER BY ${combined}`\n }\n\n /** Converts a JS object (camelCase) to DB format (snake_case) */\n private _toDb(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined) {\n result[this._table._columnMap[key] ?? key] = value\n }\n }\n return result\n }\n\n /** Converts a DB row (snake_case) back to JS format (camelCase) */\n private _toJs(row: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {}\n for (const [snake, value] of Object.entries(row as Record<string, unknown>)) {\n result[this._reverseMap[snake] ?? snake] = value\n }\n return result\n }\n}\n","// src/connect.ts — PostgreSQL connection with sensible defaults\n// SSL auto-detection, pooling, and typed database client creation.\n\nimport postgres from 'postgres'\nimport type { Table } from './schema'\nimport { TableClient } from './query'\n\n/** Connection config for production use */\nexport interface ConnectionConfig {\n /** PostgreSQL connection URL */\n url: string\n /** Max connections in pool — default 10 */\n max?: number\n /**\n * SSL mode — default: auto-detected.\n * Localhost → false. Everything else → 'require'.\n * This means Supabase, Neon, Railway, Vercel Postgres work out of the box.\n */\n ssl?: boolean | 'require' | 'prefer' | 'allow'\n /** Query timeout in seconds */\n timeout?: number\n /** Called on connection-level errors */\n onError?: (err: Error) => void\n}\n\n/** The database client — each key is a table name mapped to its query client */\nexport type Database<TTables extends Record<string, Table<any, any>>> = {\n [K in keyof TTables]: TTables[K] extends Table<any, any> ? TableClient<TTables[K]> : never\n} & {\n /** Close all connections in the pool */\n close(): Promise<void>\n /** Raw postgres.js client — escape hatch for custom queries */\n sql: postgres.Sql\n}\n\n/**\n * Connect to PostgreSQL and create a typed database client.\n *\n * ```ts\n * const db = connect('postgresql://user:pass@localhost/mydb', { users, posts })\n * const allUsers = await db.users.findMany()\n * await db.close()\n * ```\n */\nexport function connect<TTables extends Record<string, Table<any, any>>>(\n config: string | ConnectionConfig,\n tables: TTables,\n): Database<TTables> {\n const isString = typeof config === 'string'\n const url = isString ? config : config.url\n const opts = isString ? {} as ConnectionConfig : config\n\n // Auto-detect SSL: localhost = no SSL, everything else = require\n // This single default prevents 90% of \"connection refused\" issues\n // with managed PostgreSQL services\n const isLocal = url.includes('localhost') || url.includes('127.0.0.1')\n const ssl = opts.ssl ?? (isLocal ? false : 'require')\n\n const sql = postgres(url, {\n max: opts.max ?? 10,\n idle_timeout: 20,\n connect_timeout: 30,\n ssl,\n max_lifetime: 60 * 30,\n onnotice: () => {}, // suppress PostgreSQL NOTICE messages — they confuse beginners\n })\n\n // Create a TableClient for each registered table\n const db = {} as any\n for (const [key, table] of Object.entries(tables)) {\n const client = new TableClient(sql, table as Table<any, any>)\n if (opts.onError) client._onError = opts.onError\n db[key] = client\n }\n\n db.close = () => sql.end()\n db.sql = sql\n\n return db as Database<TTables>\n}\n"],"mappings":"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"}
@@ -0,0 +1,373 @@
1
+ import { z } from "zod";
2
+ import postgres from "postgres";
3
+
4
+ //#region src/schema.d.ts
5
+ /** Converts camelCase to snake_case for PostgreSQL column naming */
6
+ declare function camelToSnake(str: string): string;
7
+ /** Flattens intersection types so IDE tooltips show clean objects, not A & B */
8
+ type Simplify<T> = { [K in keyof T]: T[K] } & {};
9
+ /** @internal Runtime metadata describing a column's PG type, constraints, behavior */
10
+ interface ColumnConfig {
11
+ pgType: string;
12
+ nullable: boolean;
13
+ hasDefault: boolean;
14
+ isPrimaryKey: boolean;
15
+ isUnique: boolean;
16
+ defaultValue?: unknown;
17
+ /** SQL expression for default — 'now()' or 'gen_random_uuid()' */
18
+ defaultSql?: string;
19
+ /** DB auto-generates this value (IDENTITY columns) */
20
+ isGenerated: boolean;
21
+ /** Zod validation hint — 'email', 'uuid' */
22
+ zodCheck?: string;
23
+ /** Stored Zod schema — only for JSONB columns */
24
+ zodSchema?: z.ZodType;
25
+ /** Auto-update on every UPDATE — for updatedAt patterns */
26
+ autoUpdate: boolean;
27
+ /** Soft delete marker — findMany auto-filters, delete sets timestamp */
28
+ softDelete: boolean;
29
+ min?: number;
30
+ max?: number;
31
+ }
32
+ /**
33
+ * A column definition carrying runtime metadata AND compile-time types.
34
+ *
35
+ * Three generics flow through the entire ORM:
36
+ * - TType: JS type (string, number, boolean, Date)
37
+ * - TNullable: whether NULL is allowed (adds `| null`)
38
+ * - THasDefault: whether INSERT can omit this (adds `?`)
39
+ *
40
+ * Every modifier returns a NEW Column — immutable builder.
41
+ */
42
+ declare class Column<TType, TNullable extends boolean = false, THasDefault extends boolean = false> {
43
+ readonly _config: ColumnConfig;
44
+ readonly _type: TType;
45
+ readonly _nullable: TNullable;
46
+ readonly _hasDefault: THasDefault;
47
+ constructor(config: ColumnConfig);
48
+ /** NOT NULL — already the default. Exists for explicit readability. */
49
+ required(): Column<TType, false, THasDefault>;
50
+ /** Allow NULL — column type becomes TType | null in TypeScript */
51
+ optional(): Column<TType, true, THasDefault>;
52
+ /** Add UNIQUE constraint */
53
+ unique(): Column<TType, TNullable, THasDefault>;
54
+ /** Mark as PRIMARY KEY */
55
+ primaryKey(): Column<TType, TNullable, THasDefault>;
56
+ /**
57
+ * Set default value — makes field optional in INSERT.
58
+ *
59
+ * Named shortcuts are resolved per column type to avoid ambiguity:
60
+ * - 'now' on TIMESTAMPTZ → SQL DEFAULT now()
61
+ * - 'uuid' on UUID → SQL DEFAULT gen_random_uuid()
62
+ * On other types, these strings are treated as literal values.
63
+ */
64
+ default(value: TType extends Date ? TType | 'now' : TType): Column<TType, TNullable, true>;
65
+ /** Min constraint — string length for text, numeric value for numbers */
66
+ min(n: number): Column<TType, TNullable, THasDefault>;
67
+ /** Max constraint — string length for text, numeric value for numbers */
68
+ max(n: number): Column<TType, TNullable, THasDefault>;
69
+ /** Auto-update on every UPDATE query — designed for updatedAt columns */
70
+ autoUpdate(): Column<TType, TNullable, true>;
71
+ /**
72
+ * Soft delete marker. When set on a column:
73
+ * - findMany() auto-adds WHERE column IS NULL
74
+ * - delete() sets this column to now() instead of DELETE
75
+ * - findMany({ withDeleted: true }) bypasses the filter
76
+ */
77
+ softDelete(): Column<TType, true, true>;
78
+ }
79
+ /**
80
+ * Column factory namespace. Every column definition starts here.
81
+ *
82
+ * ```ts
83
+ * const users = table('users', {
84
+ * id: kadak.id(),
85
+ * name: kadak.text().required(),
86
+ * email: kadak.email().unique(),
87
+ * })
88
+ * ```
89
+ */
90
+ declare const kadak: {
91
+ /**
92
+ * Modern auto-incrementing integer primary key.
93
+ * Uses IDENTITY (not deprecated SERIAL).
94
+ * DDL: INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY
95
+ */
96
+ readonly id: () => Column<number, false, true>;
97
+ /**
98
+ * UUID primary key with auto-generation via gen_random_uuid().
99
+ * Built into PostgreSQL 13+ — no extensions needed.
100
+ * Ideal for distributed systems and secure-by-default IDs.
101
+ */
102
+ readonly uuidId: () => Column<string, false, true>;
103
+ /**
104
+ * Legacy SERIAL primary key — use kadak.id() for new projects.
105
+ * Kept for compatibility with existing schemas.
106
+ */
107
+ readonly serialId: () => Column<number, false, true>; /** Unlimited-length text. Use .min()/.max() for Zod length validation. */
108
+ readonly text: () => Column<string, false, false>; /** 4-byte integer. For whole numbers — counts, ages, quantities. */
109
+ readonly int: () => Column<number, false, false>;
110
+ /**
111
+ * Alias for kadak.int(). Maps to INTEGER.
112
+ * ⚠️ This is NOT floating point — 9.99 becomes 9 in the database.
113
+ * Use kadak.float() for decimals or kadak.decimal() for money.
114
+ */
115
+ readonly number: () => Column<number, false, false>;
116
+ /**
117
+ * 8-byte floating point (DOUBLE PRECISION).
118
+ * For scientific data, coordinates, measurements.
119
+ * ⚠️ NEVER use for money — use kadak.decimal() instead.
120
+ */
121
+ readonly float: () => Column<number, false, false>;
122
+ /**
123
+ * Arbitrary precision decimal (NUMERIC).
124
+ * Returns STRING in TypeScript — intentional to preserve precision.
125
+ * JS floats lose precision: 0.1 + 0.2 !== 0.3
126
+ * ✅ Use for: money, prices, financial math
127
+ */
128
+ readonly decimal: () => Column<string, false, false>; /** Boolean true/false */
129
+ readonly boolean: () => Column<boolean, false, false>;
130
+ /**
131
+ * Timestamp with timezone — always TIMESTAMPTZ.
132
+ * Prevents the #1 PostgreSQL date/time footgun (timezone-naive timestamps).
133
+ * Supports .default('now') for SQL DEFAULT now().
134
+ */
135
+ readonly timestamp: () => Column<Date, false, false>;
136
+ /**
137
+ * TEXT with automatic Zod email validation.
138
+ * PostgreSQL has no EMAIL type — this is TEXT underneath.
139
+ * The email check is applied for free in validator().
140
+ */
141
+ readonly email: () => Column<string, false, false>; /** UUID column (non-primary-key). For foreign keys, tokens, etc. */
142
+ readonly uuid: () => Column<string, false, false>;
143
+ /**
144
+ * JSONB column with required Zod schema for runtime validation.
145
+ * The schema provides BOTH the TS type (via z.infer) AND runtime validation.
146
+ *
147
+ * For unstructured JSON, pass z.unknown():
148
+ * ```ts
149
+ * metadata: kadak.json(z.unknown())
150
+ * ```
151
+ */
152
+ readonly json: <T extends z.ZodType>(schema: T) => Column<z.infer<T>, false, false>;
153
+ };
154
+ /** Table-level constraints beyond what individual columns express */
155
+ interface TableOptions {
156
+ /**
157
+ * Compound unique constraints — each array is a group of columns
158
+ * that must be unique together.
159
+ * ```ts
160
+ * { unique: [['userId', 'teamId']] }
161
+ * ```
162
+ */
163
+ unique?: string[][];
164
+ }
165
+ type ColumnsRecord = Record<string, Column<any, any, any>>;
166
+ /**
167
+ * A table definition. Created via the `table()` function.
168
+ * Holds column metadata and generates typed Zod validators.
169
+ */
170
+ declare class Table<TName extends string, TColumns extends ColumnsRecord> {
171
+ readonly _name: TName;
172
+ readonly _columns: TColumns;
173
+ readonly _options?: TableOptions;
174
+ /** Maps camelCase TS keys → snake_case PG column names */
175
+ readonly _columnMap: Record<string, string>;
176
+ constructor(name: TName, columns: TColumns, options?: TableOptions);
177
+ /** Alias for insertValidator() — the most common use case (validating user input) */
178
+ validator(): z.ZodObject<{
179
+ [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
180
+ }, z.core.$strip>;
181
+ /** Validates data for INSERT — generated/defaulted fields are optional */
182
+ insertValidator(): z.ZodObject<{
183
+ [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
184
+ }, z.core.$strip>;
185
+ /** Validates data for SELECT — all columns present, nullability applied */
186
+ selectValidator(): z.ZodObject<{
187
+ [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
188
+ }, z.core.$strip>;
189
+ /** Validates data for UPDATE — everything optional (partial update) */
190
+ updateValidator(): z.ZodObject<{
191
+ [x: string]: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
192
+ }, z.core.$strip>;
193
+ /** @internal Builds Zod shape for a given operation mode */
194
+ private _buildShape;
195
+ /** @internal Creates the base Zod type for a column, without nullable/optional */
196
+ private _baseZodType;
197
+ }
198
+ /**
199
+ * Define a table. This is the primary API for declaring your database schema.
200
+ *
201
+ * ```ts
202
+ * export const users = table('users', {
203
+ * id: kadak.id(),
204
+ * name: kadak.text().required(),
205
+ * email: kadak.email().unique(),
206
+ * age: kadak.int().optional(),
207
+ * createdAt: kadak.timestamp().default('now'),
208
+ * })
209
+ * ```
210
+ */
211
+ declare function table<TName extends string, TColumns extends ColumnsRecord>(name: TName, columns: TColumns, options?: TableOptions): Table<TName, TColumns>;
212
+ /** Extract the SELECT type for a column — what the database returns */
213
+ type ColumnSelectType<C> = C extends Column<infer T, infer N, any> ? N extends true ? T | null : T : never;
214
+ /** Keys of columns that are REQUIRED in INSERT (no default, not generated) */
215
+ type RequiredInsertKeys<C extends ColumnsRecord> = { [K in keyof C]: C[K] extends Column<any, any, true> ? never : K }[keyof C];
216
+ /** Keys of columns that are OPTIONAL in INSERT (has default or is generated) */
217
+ type OptionalInsertKeys<C extends ColumnsRecord> = { [K in keyof C]: C[K] extends Column<any, any, true> ? K : never }[keyof C];
218
+ /**
219
+ * Infer the SELECT type — what you get back from queries.
220
+ * Every column is present. Nullable columns have `| null`.
221
+ *
222
+ * ```ts
223
+ * type User = Infer<typeof users>
224
+ * // { id: number, name: string, email: string, age: number | null, createdAt: Date }
225
+ * ```
226
+ */
227
+ type Infer<T extends Table<any, any>> = Simplify<{ [K in keyof T['_columns']]: ColumnSelectType<T['_columns'][K]> }>;
228
+ /**
229
+ * Infer the INSERT type — what you provide to create a row.
230
+ * Generated/defaulted columns become optional. Nullable columns accept null.
231
+ *
232
+ * ```ts
233
+ * type NewUser = InferInsert<typeof users>
234
+ * // { name: string, email: string, age?: number | null, id?: number, createdAt?: Date }
235
+ * ```
236
+ */
237
+ type InferInsert<T extends Table<any, any>> = Simplify<{ [K in RequiredInsertKeys<T['_columns']>]: ColumnSelectType<T['_columns'][K]> } & { [K in OptionalInsertKeys<T['_columns']>]?: ColumnSelectType<T['_columns'][K]> }>;
238
+ /**
239
+ * Infer the UPDATE type — what you provide for partial updates.
240
+ * Everything is optional. Nullable columns accept null.
241
+ *
242
+ * ```ts
243
+ * type UserUpdate = InferUpdate<typeof users>
244
+ * // { id?: number, name?: string, email?: string, age?: number | null, createdAt?: Date }
245
+ * ```
246
+ */
247
+ type InferUpdate<T extends Table<any, any>> = Simplify<Partial<Infer<T>>>;
248
+ //#endregion
249
+ //#region src/query.d.ts
250
+ /** Options for findMany/findFirst — without select (returns full row) */
251
+ interface FindManyOptions<T extends Table<any, any>> {
252
+ where?: Partial<Infer<T>>;
253
+ orderBy?: Partial<Record<keyof Infer<T>, 'asc' | 'desc'>>;
254
+ limit?: number;
255
+ offset?: number;
256
+ /** When true, includes soft-deleted rows */
257
+ withDeleted?: boolean;
258
+ /** Reserved for relations — not yet implemented */
259
+ include?: never;
260
+ }
261
+ /**
262
+ * Query client for a single table. Created by `connect()` — never instantiated directly.
263
+ * Provides findMany, findFirst, insert, update, delete with full type safety.
264
+ */
265
+ declare class TableClient<T extends Table<any, any>> {
266
+ /** @internal */
267
+ readonly _sql: postgres.Sql;
268
+ /** @internal */
269
+ readonly _table: T;
270
+ /** @internal */
271
+ readonly _reverseMap: Record<string, string>;
272
+ /** @internal */
273
+ _onError?: (err: Error) => void;
274
+ constructor(sql: postgres.Sql, table: T);
275
+ /** Find rows with optional select for precise return types */
276
+ findMany<K extends keyof Infer<T>>(options: FindManyOptions<T> & {
277
+ select: Record<K, true>;
278
+ }): Promise<Pick<Infer<T>, K>[]>;
279
+ /** Find rows — returns full row type */
280
+ findMany(options?: FindManyOptions<T>): Promise<Infer<T>[]>;
281
+ findFirst<K extends keyof Infer<T>>(options: FindManyOptions<T> & {
282
+ select: Record<K, true>;
283
+ }): Promise<Pick<Infer<T>, K> | null>;
284
+ findFirst(options?: FindManyOptions<T>): Promise<Infer<T> | null>;
285
+ /** Insert a single row */
286
+ insert(data: InferInsert<T>): Promise<Infer<T>>;
287
+ /** Insert multiple rows */
288
+ insert(data: InferInsert<T>[]): Promise<Infer<T>[]>;
289
+ update(options: {
290
+ where: Partial<Infer<T>>;
291
+ data: InferUpdate<T>;
292
+ }): Promise<Infer<T>[]>;
293
+ delete(options: {
294
+ where: Partial<Infer<T>>;
295
+ }): Promise<Infer<T>[]>;
296
+ /** Always performs a real DELETE — bypasses soft delete */
297
+ hardDelete(options: {
298
+ where: Partial<Infer<T>>;
299
+ }): Promise<Infer<T>[]>;
300
+ /** Builds a WHERE fragment from a JS object, including soft delete filter */
301
+ private _buildWhere;
302
+ /** Builds an ORDER BY fragment */
303
+ private _buildOrderBy;
304
+ /** Converts a JS object (camelCase) to DB format (snake_case) */
305
+ private _toDb;
306
+ /** Converts a DB row (snake_case) back to JS format (camelCase) */
307
+ private _toJs;
308
+ }
309
+ //#endregion
310
+ //#region src/connect.d.ts
311
+ /** Connection config for production use */
312
+ interface ConnectionConfig {
313
+ /** PostgreSQL connection URL */
314
+ url: string;
315
+ /** Max connections in pool — default 10 */
316
+ max?: number;
317
+ /**
318
+ * SSL mode — default: auto-detected.
319
+ * Localhost → false. Everything else → 'require'.
320
+ * This means Supabase, Neon, Railway, Vercel Postgres work out of the box.
321
+ */
322
+ ssl?: boolean | 'require' | 'prefer' | 'allow';
323
+ /** Query timeout in seconds */
324
+ timeout?: number;
325
+ /** Called on connection-level errors */
326
+ onError?: (err: Error) => void;
327
+ }
328
+ /** The database client — each key is a table name mapped to its query client */
329
+ type Database<TTables extends Record<string, Table<any, any>>> = { [K in keyof TTables]: TTables[K] extends Table<any, any> ? TableClient<TTables[K]> : never } & {
330
+ /** Close all connections in the pool */close(): Promise<void>; /** Raw postgres.js client — escape hatch for custom queries */
331
+ sql: postgres.Sql;
332
+ };
333
+ /**
334
+ * Connect to PostgreSQL and create a typed database client.
335
+ *
336
+ * ```ts
337
+ * const db = connect('postgresql://user:pass@localhost/mydb', { users, posts })
338
+ * const allUsers = await db.users.findMany()
339
+ * await db.close()
340
+ * ```
341
+ */
342
+ declare function connect<TTables extends Record<string, Table<any, any>>>(config: string | ConnectionConfig, tables: TTables): Database<TTables>;
343
+ //#endregion
344
+ //#region src/error.d.ts
345
+ /** All error codes KadakORM can produce */
346
+ type KadakErrorCode = 'NOT_NULL_VIOLATION' | 'UNIQUE_VIOLATION' | 'FOREIGN_KEY_VIOLATION' | 'TABLE_NOT_FOUND' | 'COLUMN_NOT_FOUND' | 'CONNECTION_ERROR' | 'AUTH_ERROR' | 'QUERY_TIMEOUT' | 'UNKNOWN';
347
+ /**
348
+ * The one error class users ever see from KadakORM.
349
+ * Always includes: what went wrong, which table/column, and how to fix it.
350
+ */
351
+ declare class KadakError extends Error {
352
+ readonly code: KadakErrorCode;
353
+ readonly table?: string;
354
+ readonly column?: string;
355
+ readonly constraint?: string;
356
+ readonly hint: string;
357
+ /** Always preserved — the raw pg error for advanced debugging */
358
+ readonly originalError: unknown;
359
+ constructor(opts: {
360
+ code: KadakErrorCode;
361
+ message: string;
362
+ hint: string;
363
+ table?: string;
364
+ column?: string;
365
+ constraint?: string;
366
+ originalError: unknown;
367
+ });
368
+ }
369
+ /** Wraps any postgres.js error into a KadakError with context */
370
+ declare function wrapPgError(err: unknown, tableName?: string): KadakError;
371
+ //#endregion
372
+ export { Column, type ColumnConfig, type ConnectionConfig, type Database, type FindManyOptions, type Infer, type InferInsert, type InferUpdate, KadakError, type KadakErrorCode, Table, TableClient, type TableOptions, camelToSnake, connect, kadak, table, wrapPgError };
373
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/schema.ts","../src/query.ts","../src/connect.ts","../src/error.ts"],"mappings":"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"}