{"version":3,"file":"tailordb-ddl-Fgm2cNvT.mjs","names":[],"sources":["../src/utils/field-column-type.ts","../src/utils/tailordb-ddl.ts"],"sourcesContent":["/** The Kysely column type a TailorDB field maps to, before array/null modifiers. */\nexport type FieldColumnType = \"string\" | \"number\" | \"boolean\" | \"Timestamp\";\n\n/**\n * Map a scalar TailorDB field type to the column type generated code uses for it.\n *\n * `date` resolves to `Timestamp` because the function runtime hands back a\n * `Date` for a date column, same as for datetime.\n *\n * `enum` and `nested` carry their own shape, so each generator resolves them\n * before reaching here; passing either is a caller bug rather than a `string`\n * column.\n * @param fieldType - TailorDB scalar field type name\n * @returns The column type for the field, defaulting to `string`\n * @throws If given `enum` or `nested`\n */\nexport function mapFieldTypeToColumnType(fieldType: string): FieldColumnType {\n  switch (fieldType) {\n    case \"uuid\":\n    case \"string\":\n    case \"decimal\":\n      return \"string\";\n    case \"integer\":\n    case \"float\":\n      return \"number\";\n    case \"date\":\n    case \"datetime\":\n      return \"Timestamp\";\n    case \"bool\":\n    case \"boolean\":\n      return \"boolean\";\n    case \"enum\":\n    case \"nested\":\n      throw new Error(\n        `Field type \"${fieldType}\" has no scalar column type; resolve it before mapping.`,\n      );\n    default:\n      return \"string\";\n  }\n}\n\n/** The select and write types a `ColumnType`-shaped alias expands to. */\nexport type ColumnTypeAliasExpansion = {\n  /** Type the alias reads back as. */\n  readonly select: string;\n  /** Type the alias accepts on insert and update. */\n  readonly write: string;\n};\n\n/**\n * Column types whose alias expands to a `ColumnType`, mapped to that expansion.\n *\n * Kysely only unwraps a `ColumnType` at the top level of a table property, so an\n * array of one of these stays wrapped in `ArrayColumnType<...>` rather than taking\n * a `[]` suffix, which would nest the `ColumnType` out of Kysely's reach. Where a\n * generator has to spell out the slots itself, it reads the expansion from here\n * rather than inlining the alias, which would nest just the same.\n *\n * Both type generators track alias usage per alias to decide which declarations to\n * emit, so adding an entry here also means teaching them to report the new alias.\n */\nexport const COLUMN_TYPE_ALIASES: ReadonlyMap<string, ColumnTypeAliasExpansion> = new Map<\n  FieldColumnType,\n  ColumnTypeAliasExpansion\n>([[\"Timestamp\", { select: \"Date\", write: \"Date | string\" }]]);\n","/**\n * PostgreSQL DDL derived from TailorDB table definitions, for creating the\n * tables a PGlite-backed test needs. The columns match the flat shape the\n * Kysely type generators emit, not TailorDB's storage layout.\n */\n\n/** The field shape the DDL generator reads; parsed and snapshot field configs are both assignable. */\nexport interface DDLFieldConfig {\n  type: string;\n  required?: boolean;\n  array?: boolean;\n  unique?: boolean;\n  serial?: { start: number; maxValue?: number; format?: string };\n  scale?: number;\n  default?: unknown;\n  optionalOnCreate?: boolean;\n  hooks?: { create?: unknown; update?: unknown };\n  fields?: Record<string, DDLFieldConfig>;\n}\n\n/** A table to emit DDL for. */\nexport interface DDLTableConfig {\n  name: string;\n  fields: Record<string, DDLFieldConfig>;\n  indexes?: Record<string, { fields: string[]; unique?: boolean }>;\n}\n\nconst MAX_IDENTIFIER_BYTES = 63;\n// The platform rounds decimals to their scale (6 unless configured); numeric\n// needs a precision to carry a scale, and the maximum leaves it unconstrained.\nconst DECIMAL_PRECISION = 1000;\nconst DEFAULT_DECIMAL_SCALE = 6;\nconst utf8 = new TextEncoder();\n\n/**\n * Map a TailorDB field type to the PostgreSQL column type PGlite tests use for it.\n * @param fieldType - TailorDB field type name\n * @returns The PostgreSQL type name\n * @throws If the type is not a TailorDB field type\n */\nexport function mapFieldTypeToPostgresType(fieldType: string): string {\n  switch (fieldType) {\n    case \"uuid\":\n      return \"uuid\";\n    case \"string\":\n    case \"enum\":\n      return \"text\";\n    case \"boolean\":\n    case \"bool\":\n      return \"boolean\";\n    case \"integer\":\n      return \"integer\";\n    case \"float\":\n      return \"double precision\";\n    case \"decimal\":\n      return \"numeric\";\n    case \"date\":\n      return \"date\";\n    case \"datetime\":\n      return \"timestamptz\";\n    case \"time\":\n      return \"time\";\n    case \"nested\":\n      return \"jsonb\";\n    default:\n      throw new Error(`Field type \"${fieldType}\" has no PostgreSQL column type.`);\n  }\n}\n\nfunction identifier(name: string): string {\n  return `\"${name.replaceAll('\"', '\"\"')}\"`;\n}\n\nfunction fnv1aHex(value: string): string {\n  let hash = 0x811c9dc5;\n  for (const byte of utf8.encode(value)) {\n    hash = Math.imul(hash ^ byte, 0x01000193) >>> 0;\n  }\n  return hash.toString(16).padStart(8, \"0\");\n}\n\nfunction derivedIdentifier(tableName: string, memberName: string, kind: \"seq\" | \"idx\"): string {\n  const suffix = `_${fnv1aHex(JSON.stringify([tableName, memberName, kind]))}_${kind}`;\n  let head = `${tableName}_${memberName}`;\n  while (utf8.encode(head + suffix).length > MAX_IDENTIFIER_BYTES) head = head.slice(0, -1);\n  return identifier(head + suffix);\n}\n\nfunction stringLiteral(value: string): string {\n  return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction columnType(field: DDLFieldConfig): string {\n  const base =\n    field.type === \"decimal\"\n      ? `numeric(${DECIMAL_PRECISION}, ${field.scale ?? DEFAULT_DECIMAL_SCALE})`\n      : mapFieldTypeToPostgresType(field.type);\n  return field.array && field.type !== \"nested\" ? `${base}[]` : base;\n}\n\nfunction scalarLiteral(value: unknown, field: DDLFieldConfig, label: string): string {\n  const pgType = mapFieldTypeToPostgresType(field.type);\n  if (value instanceof Date) {\n    if (Number.isNaN(value.getTime())) {\n      throw new Error(`Default of field ${label} is an invalid Date.`);\n    }\n    return `${stringLiteral(value.toISOString())}::${pgType}`;\n  }\n  switch (typeof value) {\n    case \"string\":\n      return pgType === \"text\" ? stringLiteral(value) : `${stringLiteral(value)}::${pgType}`;\n    case \"number\":\n      if (!Number.isFinite(value)) {\n        throw new Error(`Default of field ${label} is not a finite number.`);\n      }\n      return String(value);\n    case \"boolean\":\n      return value ? \"TRUE\" : \"FALSE\";\n    default:\n      throw new Error(`Default of field ${label} cannot be rendered as a SQL literal.`);\n  }\n}\n\nconst CURRENT_TIME_EXPRESSIONS = new Map([\n  [\"datetime\", \"now()\"],\n  [\"date\", \"CURRENT_DATE\"],\n  [\"time\", \"LOCALTIME\"],\n]);\n\nfunction defaultExpression(field: DDLFieldConfig, label: string): string {\n  const value = field.default;\n  const currentTime = CURRENT_TIME_EXPRESSIONS.get(field.type);\n  if (value === \"now\" && currentTime !== undefined) {\n    return currentTime;\n  }\n  if (field.array) {\n    if (!Array.isArray(value)) {\n      throw new Error(`Default of array field ${label} must be an array.`);\n    }\n    const pgType = columnType(field);\n    if (value.length === 0) return `'{}'::${pgType}`;\n    return `ARRAY[${value.map((v) => scalarLiteral(v, field, label)).join(\", \")}]::${pgType}`;\n  }\n  return scalarLiteral(value, field, label);\n}\n\ninterface SerialFormat {\n  prefix: string;\n  width: number;\n  zeroPad: boolean;\n  conversion: \"d\" | \"x\" | \"X\";\n  suffix: string;\n}\n\n// printf-style with exactly one conversion specifier; octal has no Postgres\n// formatting function to stand in for it.\nfunction parseSerialFormat(format: string, label: string): SerialFormat {\n  const match =\n    /^(?<prefix>[^%]*)%(?<zero>0?)(?<width>\\d*)(?<conversion>[a-zA-Z])(?<suffix>[^%]*)$/.exec(\n      format,\n    );\n  const groups = match?.groups;\n  const conversion = groups?.conversion;\n  if (!groups || (conversion !== \"d\" && conversion !== \"x\" && conversion !== \"X\")) {\n    throw new Error(\n      `Serial format \"${format}\" of field ${label} is not supported; use a single %d, %x, or %X specifier with an optional width (e.g. \"INV-%05d\").`,\n    );\n  }\n  return {\n    prefix: groups.prefix ?? \"\",\n    zeroPad: groups.zero === \"0\",\n    width: groups.width ? Number(groups.width) : 0,\n    conversion,\n    suffix: groups.suffix ?? \"\",\n  };\n}\n\nfunction sequenceName(tableName: string, fieldName: string): string {\n  return derivedIdentifier(tableName, fieldName, \"seq\");\n}\n\n// A sequence's minimum defaults to 1, which rejects a start of 0.\nfunction sequenceRange(serial: NonNullable<DDLFieldConfig[\"serial\"]>): string {\n  const range = [`START WITH ${serial.start}`, `MINVALUE ${serial.start}`];\n  if (serial.maxValue !== undefined) range.push(`MAXVALUE ${serial.maxValue}`);\n  return range.join(\" \");\n}\n\nconst SERIAL_CONVERSIONS: Record<SerialFormat[\"conversion\"], (nextval: string) => string> = {\n  d: (nextval) => nextval,\n  x: (nextval) => `to_hex(${nextval})`,\n  X: (nextval) => `upper(to_hex(${nextval}))`,\n};\n\nfunction serialStringDefault(sequence: string, format: string | undefined, label: string): string {\n  const nextval = `nextval(${stringLiteral(sequence)})`;\n  if (format === undefined) return `(${nextval}::text)`;\n  const { prefix, width, zeroPad, conversion, suffix } = parseSerialFormat(format, label);\n  const number = SERIAL_CONVERSIONS[conversion](nextval);\n  let value = conversion === \"d\" ? `${number}::text` : number;\n  if (width > 0) {\n    value = `format('%${width}s', ${number})`;\n    if (zeroPad) value = `translate(${value}, ' ', '0')`;\n  }\n  const parts = [\n    ...(prefix ? [stringLiteral(prefix)] : []),\n    value,\n    ...(suffix ? [stringLiteral(suffix)] : []),\n  ];\n  return `(${parts.join(\" || \")})`;\n}\n\nfunction columnDefinition(tableName: string, fieldName: string, field: DDLFieldConfig): string {\n  const column = identifier(fieldName);\n  const label = `${identifier(tableName)}.${column}`;\n  const parts = [column, columnType(field)];\n\n  if (field.serial) {\n    if (field.type === \"integer\") {\n      parts.push(`GENERATED BY DEFAULT AS IDENTITY (${sequenceRange(field.serial)})`);\n      if (field.unique) parts.push(\"UNIQUE\");\n      return parts.join(\" \");\n    }\n    if (field.required) parts.push(\"NOT NULL\");\n    if (field.unique) parts.push(\"UNIQUE\");\n    parts.push(\n      `DEFAULT ${serialStringDefault(sequenceName(tableName, fieldName), field.serial.format, label)}`,\n    );\n    return parts.join(\" \");\n  }\n\n  const hasDefault = field.default !== undefined;\n  const filledOnCreate = field.hooks?.create !== undefined || field.optionalOnCreate === true;\n  if (field.required && (hasDefault || !filledOnCreate)) parts.push(\"NOT NULL\");\n  if (field.unique) parts.push(\"UNIQUE\");\n  if (hasDefault) parts.push(`DEFAULT ${defaultExpression(field, label)}`);\n  return parts.join(\" \");\n}\n\n/**\n * DDL statements that create one table: any sequences its string serial\n * fields draw from, the table, the sequences' ownership of their columns,\n * then its unique indexes. Every statement is `IF NOT EXISTS` or otherwise\n * idempotent, so re-applying the script on a database that already has the\n * table is a no-op. Owning a sequence makes `DROP TABLE` drop it and\n * `TRUNCATE ... RESTART IDENTITY` reset it to the configured start. Index\n * names end in `_idx` so they cannot take the `<table>_<column>_key` name\n * Postgres gives a UNIQUE column, which `IF NOT EXISTS` would otherwise\n * silently skip.\n * @param table - Table name, fields, and indexes\n * @returns Statements in execution order, without trailing semicolons\n * @throws If a field type, default, or serial format cannot be expressed\n */\nexport function generateTableDDL(table: DDLTableConfig): string[] {\n  const tableIdentifier = identifier(table.name);\n  const sequences: string[] = [];\n  const ownerships: string[] = [];\n  const columns = [`  \"id\" uuid PRIMARY KEY DEFAULT gen_random_uuid()`];\n\n  for (const [fieldName, field] of Object.entries(table.fields)) {\n    if (fieldName === \"id\") continue;\n    if (field.serial && field.type !== \"integer\") {\n      const sequence = sequenceName(table.name, fieldName);\n      sequences.push(`CREATE SEQUENCE IF NOT EXISTS ${sequence} ${sequenceRange(field.serial)}`);\n      ownerships.push(\n        `ALTER SEQUENCE ${sequence} OWNED BY ${tableIdentifier}.${identifier(fieldName)}`,\n      );\n    }\n    columns.push(`  ${columnDefinition(table.name, fieldName, field)}`);\n  }\n\n  const indexes = Object.entries(table.indexes ?? {})\n    .filter(([, index]) => index.unique)\n    .map(\n      ([name, index]) =>\n        `CREATE UNIQUE INDEX IF NOT EXISTS ${derivedIdentifier(table.name, name, \"idx\")} ON ${tableIdentifier} (${index.fields.map(identifier).join(\", \")})`,\n    );\n\n  return [\n    ...sequences,\n    `CREATE TABLE IF NOT EXISTS ${tableIdentifier} (\\n${columns.join(\",\\n\")}\\n)`,\n    ...ownerships,\n    ...indexes,\n  ];\n}\n\n/**\n * A single SQL script creating every given table, for `pglite.exec()`.\n * @param tables - Tables in the order to create them\n * @returns The script, empty when there are no tables\n */\nexport function generateSchemaDDL(tables: readonly DDLTableConfig[]): string {\n  return tables\n    .map((table) =>\n      generateTableDDL(table)\n        .map((statement) => `${statement};`)\n        .join(\"\\n\"),\n    )\n    .join(\"\\n\\n\");\n}\n\n/** One namespace's tables, as the schema module groups them. */\nexport interface PgliteSchemaNamespace {\n  namespace: string;\n  tables: readonly DDLTableConfig[];\n}\n\n/** Options for {@link generatePgliteSchemaModule}. */\nexport interface PgliteSchemaModuleOptions {\n  /** Named in the generated header as the producer users must not edit around. */\n  generatedBy: string;\n}\n\n// A template literal keeps line feeds but folds a carriage return into one.\nfunction templateLiteral(value: string): string {\n  const escaped = value\n    .replaceAll(\"\\\\\", \"\\\\\\\\\")\n    .replaceAll(\"`\", \"\\\\`\")\n    .replaceAll(\"${\", \"\\\\${\")\n    .replaceAll(\"\\r\", \"\\\\r\");\n  return `\\`${escaped}\\``;\n}\n\n/**\n * Render the module that exports each namespace's `CREATE TABLE` script for\n * `pglite.exec()`.\n * @param namespaces - Namespaces with the tables to create\n * @param options - Header wording\n * @returns TypeScript source of the schema module\n */\nexport function generatePgliteSchemaModule(\n  namespaces: readonly PgliteSchemaNamespace[],\n  options: PgliteSchemaModuleOptions,\n): string {\n  const entries = namespaces.map(\n    ({ namespace, tables }) =>\n      `  ${JSON.stringify(namespace)}: ${templateLiteral(generateSchemaDDL(tables))},`,\n  );\n  return [\n    \"/**\",\n    \" * Auto-generated PGlite schema for TailorDB tables.\",\n    \" * Create a namespace's tables in a test with `pglite.exec(pgliteSchema[namespace])`.\",\n    \" *\",\n    ` * DO NOT EDIT - This file is auto-generated by ${options.generatedBy}.`,\n    \" */\",\n    \"\",\n    \"export const pgliteSchema = {\",\n    ...entries,\n    \"} as const;\",\n    \"\",\n  ].join(\"\\n\");\n}\n"],"mappings":"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"}