{"version":3,"sources":["../src/backend/row-mappers.ts","../src/store/claims/removal-sql.ts"],"names":["DatabaseOperationError","canonicalizeDatabaseTimestamp","rowPropsToJsonText","sql","edgeCardinalityAxesForKind"],"mappings":"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","file":"chunk-76OB5RSH.cjs","sourcesContent":["/**\n * Shared database row-mapping utilities.\n */\n\nimport { DatabaseOperationError } from \"../errors\";\nimport { canonicalizeDatabaseTimestamp } from \"../utils/date\";\nimport {\n  type EdgeRow,\n  type NodeRow,\n  rowPropsToJsonText,\n  type SchemaVersionRow,\n  type UniqueRow,\n} from \"./types\";\n\nfunction asString(value: unknown, field: string): string {\n  if (typeof value !== \"string\") {\n    throw new DatabaseOperationError(\n      `Expected ${field} to be string, got ${typeof value}`,\n      { operation: \"select\", entity: \"row\" },\n    );\n  }\n  return value;\n}\n\nfunction asOptionalString(value: unknown, field: string): string | undefined {\n  if (value === null || value === undefined) return undefined;\n  return asString(value, field);\n}\n\nfunction asNumber(value: unknown, field: string): number {\n  if (typeof value !== \"number\") {\n    throw new DatabaseOperationError(\n      `Expected ${field} to be number, got ${typeof value}`,\n      { operation: \"select\", entity: \"row\" },\n    );\n  }\n  return value;\n}\n\nexport function nowIso(): string {\n  return new Date().toISOString();\n}\n\n/**\n * Formats PostgreSQL timestamps used by internal status-table adapters.\n * Row metadata uses the stricter {@link normalizeRowTimestamp} contract.\n */\nexport function formatPostgresTimestamp(value: unknown): string | undefined {\n  if (value === null || value === undefined) return undefined;\n  if (value instanceof Date) return value.toISOString();\n  if (typeof value === \"string\") {\n    if (value.includes(\"T\")) return value;\n    const date = new Date(value);\n    if (!Number.isNaN(date.getTime())) return date.toISOString();\n    return value;\n  }\n  return undefined;\n}\n\n/**\n * Canonicalizes database-driver timestamp values at the row-mapping boundary.\n * Every store and compiled-query metadata projection uses this owner so driver\n * rendering differences cannot become public values.\n */\nexport function normalizeRowTimestamp(\n  value: unknown,\n  field: string,\n): string | undefined {\n  if (value === null || value === undefined) return undefined;\n  const canonical = canonicalizeDatabaseTimestamp(value);\n  if (canonical === undefined) {\n    throw new DatabaseOperationError(\n      `Expected ${field} to be a database timestamp, got ${typeof value}`,\n      { operation: \"select\", entity: \"row\" },\n    );\n  }\n  return canonical;\n}\n\nexport function normalizeRequiredRowTimestamp(\n  value: unknown,\n  field: string,\n): string {\n  const timestamp = normalizeRowTimestamp(value, field);\n  if (timestamp === undefined) {\n    throw new DatabaseOperationError(`Expected non-null ${field} timestamp`, {\n      operation: \"select\",\n      entity: \"row\",\n    });\n  }\n  return timestamp;\n}\n\n/**\n * Coerce a fulltext relevance score to `number` at the backend\n * boundary. Postgres returns `numeric` as a string to preserve\n * precision; a custom `FulltextStrategy` on either dialect could\n * likewise yield a string. Shared so both backends enforce the same\n * `FulltextSearchResult.score: number` contract and reject garbage\n * loudly instead of propagating `NaN`.\n */\nexport function coerceNumericScore(value: number | string): number {\n  if (typeof value === \"number\") return value;\n  const parsed = Number.parseFloat(value);\n  if (Number.isNaN(parsed)) {\n    throw new TypeError(\n      `Backend returned non-numeric fulltext score: ${JSON.stringify(value)}`,\n    );\n  }\n  return parsed;\n}\n\n/**\n * Normalizes a JSON column that may be returned as a parsed object (JSONB)\n * or string. PostgreSQL drivers hand jsonb back already parsed — keep the\n * object instead of re-stringifying it, so the read path pays zero JSON\n * work per row (consumers normalize via rowPropsToObject /\n * rowPropsToJsonText at the point of use). SQLite text passes through.\n */\nfunction normalizeJsonColumn(value: unknown): string | Record<string, unknown> {\n  if (typeof value === \"string\") return value;\n  if (value !== null && typeof value === \"object\") {\n    return value as Record<string, unknown>;\n  }\n  return JSON.stringify(value ?? {});\n}\n\n/**\n * Dialect-specific configuration for row mappers.\n *\n * Row mapper factories accept this config to produce dialect-appropriate\n * mappers. Timestamp normalization is dialect-independent and owned by\n * {@link normalizeRowTimestamp}; only JSON columns need dialect configuration.\n */\ntype DialectRowMapperConfig = Readonly<{\n  normalizeJson: (value: unknown) => string | Record<string, unknown>;\n}>;\n\n/**\n * SQLite row mapper config. JSON is stored as TEXT.\n */\nexport const SQLITE_ROW_MAPPER_CONFIG: DialectRowMapperConfig = {\n  normalizeJson: (value) => {\n    if (typeof value !== \"string\") {\n      throw new DatabaseOperationError(\n        `Expected JSON column to be string, got ${typeof value}`,\n        { operation: \"select\", entity: \"row\" },\n      );\n    }\n    return value;\n  },\n};\n\n/**\n * PostgreSQL row mapper config. JSONB is returned as parsed objects.\n */\nexport const POSTGRES_ROW_MAPPER_CONFIG: DialectRowMapperConfig = {\n  normalizeJson: normalizeJsonColumn,\n};\n\n// Trust boundary: Drizzle raw SQL returns Record<string, unknown> rows.\n// The field access patterns below are intentional unsafe casts at the\n// database driver boundary where we know the column shapes.\n\nexport function createNodeRowMapper(\n  config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => NodeRow {\n  return (row) => ({\n    graph_id: asString(row[\"graph_id\"], \"graph_id\"),\n    kind: asString(row[\"kind\"], \"kind\"),\n    id: asString(row[\"id\"], \"id\"),\n    props: config.normalizeJson(row[\"props\"]),\n    version: asNumber(row[\"version\"], \"version\"),\n    valid_from: normalizeRowTimestamp(row[\"valid_from\"], \"valid_from\"),\n    valid_to: normalizeRowTimestamp(row[\"valid_to\"], \"valid_to\"),\n    created_at: normalizeRequiredRowTimestamp(row[\"created_at\"], \"created_at\"),\n    updated_at: normalizeRequiredRowTimestamp(row[\"updated_at\"], \"updated_at\"),\n    deleted_at: normalizeRowTimestamp(row[\"deleted_at\"], \"deleted_at\"),\n  });\n}\n\nexport function createEdgeRowMapper(\n  config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => EdgeRow {\n  return (row) => {\n    const matchIdentityName = asOptionalString(\n      row[\"match_identity_name\"],\n      \"match_identity_name\",\n    );\n    const matchIdentityKey = asOptionalString(\n      row[\"match_identity_key\"],\n      \"match_identity_key\",\n    );\n    return {\n      graph_id: asString(row[\"graph_id\"], \"graph_id\"),\n      id: asString(row[\"id\"], \"id\"),\n      kind: asString(row[\"kind\"], \"kind\"),\n      from_kind: asString(row[\"from_kind\"], \"from_kind\"),\n      from_id: asString(row[\"from_id\"], \"from_id\"),\n      to_kind: asString(row[\"to_kind\"], \"to_kind\"),\n      to_id: asString(row[\"to_id\"], \"to_id\"),\n      props: config.normalizeJson(row[\"props\"]),\n      ...(matchIdentityName === undefined ?\n        {}\n      : { match_identity_name: matchIdentityName }),\n      ...(matchIdentityKey === undefined ?\n        {}\n      : { match_identity_key: matchIdentityKey }),\n      valid_from: normalizeRowTimestamp(row[\"valid_from\"], \"valid_from\"),\n      valid_to: normalizeRowTimestamp(row[\"valid_to\"], \"valid_to\"),\n      created_at: normalizeRequiredRowTimestamp(\n        row[\"created_at\"],\n        \"created_at\",\n      ),\n      updated_at: normalizeRequiredRowTimestamp(\n        row[\"updated_at\"],\n        \"updated_at\",\n      ),\n      deleted_at: normalizeRowTimestamp(row[\"deleted_at\"], \"deleted_at\"),\n    };\n  };\n}\n\nfunction mapUniqueRow(row: Record<string, unknown>): UniqueRow {\n  return {\n    graph_id: asString(row[\"graph_id\"], \"graph_id\"),\n    node_kind: asString(row[\"node_kind\"], \"node_kind\"),\n    constraint_name: asString(row[\"constraint_name\"], \"constraint_name\"),\n    key: asString(row[\"key\"], \"key\"),\n    node_id: asString(row[\"node_id\"], \"node_id\"),\n    concrete_kind: asString(row[\"concrete_kind\"], \"concrete_kind\"),\n    deleted_at: normalizeRowTimestamp(row[\"deleted_at\"], \"deleted_at\"),\n  };\n}\n\nexport function createUniqueRowMapper(\n  _config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => UniqueRow {\n  return mapUniqueRow;\n}\n\nexport function createSchemaVersionRowMapper(\n  config: DialectRowMapperConfig,\n): (row: Record<string, unknown>) => SchemaVersionRow {\n  return (row) => {\n    const isActiveValue = row[\"is_active\"];\n    const isActive =\n      isActiveValue === true || isActiveValue === 1 || isActiveValue === \"1\";\n\n    return {\n      graph_id: asString(row[\"graph_id\"], \"graph_id\"),\n      version: asNumber(row[\"version\"], \"version\"),\n      schema_hash: asString(row[\"schema_hash\"], \"schema_hash\"),\n      schema_doc: rowPropsToJsonText(config.normalizeJson(row[\"schema_doc\"])),\n      created_at: normalizeRequiredRowTimestamp(\n        row[\"created_at\"],\n        \"created_at\",\n      ),\n      is_active: isActive,\n    };\n  };\n}\n","/**\n * Statement builders for the claim relations' bulk-removal paths.\n *\n * These are statements over the claim relations — the uniqueness claims a\n * kind's nodes own, and the edge-cardinality claims an edge kind's edges\n * hold — so their owner is `src/store/claims/`, exactly like every other\n * claim decision. `edgeCardinalityAxesForKind` already lives here (see\n * `./edge-claims`), so this module reads it directly instead of reaching\n * back out to an adapter that reaches back in.\n *\n * `src/backend/drizzle/operations/uniques.ts` and\n * `src/backend/drizzle/operations/edge-claims.ts` re-export these three\n * builders from their previous addresses, so `CommonOperationStrategy` and\n * `operation-backend-core.ts` see no change: one owner, two addresses, no\n * duplicate.\n */\nimport type { HardDeleteUniquesByConcreteKindParams } from \"../../backend/types\";\nimport { sql as fragmentSql, type SqlFragment } from \"../../query/sql-fragment\";\nimport { edgeCardinalityAxesForKind } from \"./edge-claims\";\n\n/**\n * THE definition of \"the uniqueness claims nodes of this kind own\": every row\n * whose `concrete_kind` is the kind, at whatever axis the row sits on.\n *\n * Kind reaping is a different predicate from a lifecycle release — \"every claim\n * this kind's nodes own\" rather than \"this node's claim for one constraint and\n * key\" — and it is a hard delete rather than a tombstone, so it is its own\n * builder. It is nonetheless the ONLY spelling of that predicate: both the\n * `hardDeleteUniquesByConcreteKind` backend member and `materializeRemovals`'\n * removed-kind cleanup compile this fragment. Keying on `node_kind` instead\n * would leak a claim whose axis is a sibling kind, delete a surviving sibling's\n * claim when the removed kind IS the axis, and never match a claim whose axis\n * is not a kind at all.\n *\n * Takes the relation NAME rather than the Drizzle table so the store-side\n * caller, which knows only its configured table names, can build the same\n * statement; the fragment renders on either dialect.\n */\nexport function buildHardDeleteUniquesByConcreteKind(\n  uniquesTableName: string,\n  params: HardDeleteUniquesByConcreteKindParams,\n): SqlFragment {\n  return fragmentSql`DELETE FROM ${fragmentSql.identifier(uniquesTableName)} WHERE ${fragmentSql.identifier(\"graph_id\")} = ${params.graphId} AND ${fragmentSql.identifier(\"concrete_kind\")} = ${params.concreteKind}`;\n}\n\n/**\n * THE definition of \"the cardinality claims an edge kind owns\": every row at\n * one of the kind's declared-cardinality axes.\n *\n * Keyed on the axis rather than on the holder's id because a removed kind's\n * edges are deleted in the same pass, which would leave a claim naming a row\n * that no longer exists — takeable, but never reaped. Takes the relation NAME\n * rather than the Drizzle table so `materializeRemovals`, which knows only its\n * configured table names, compiles the same statement.\n */\nexport function buildHardDeleteEdgeClaimsByEdgeKind(\n  edgeClaimsTableName: string,\n  params: Readonly<{ graphId: string; edgeKind: string }>,\n): SqlFragment {\n  const axes = edgeCardinalityAxesForKind(params.edgeKind).map(\n    (axis) => fragmentSql`${axis}`,\n  );\n  return fragmentSql`DELETE FROM ${fragmentSql.identifier(edgeClaimsTableName)} WHERE ${fragmentSql.identifier(\"graph_id\")} = ${params.graphId} AND ${fragmentSql.identifier(\"axis\")} IN (${fragmentSql.join(axes, fragmentSql`, `)})`;\n}\n\n/**\n * Housekeeping for node-kind removal: deletes every claim held by an edge whose\n * source or target has the removed kind.\n *\n * The holder ids are selected before those edges are deleted. Filtering claim\n * axes cannot express this ownership: an edge kind may connect several node\n * kinds, while its claim axis names only its cardinality and edge kind.\n */\nexport function buildHardDeleteEdgeClaimsByNodeKind(\n  edgeClaimsTableName: string,\n  edgesTableName: string,\n  params: Readonly<{ graphId: string; nodeKind: string }>,\n): SqlFragment {\n  return fragmentSql`DELETE FROM ${fragmentSql.identifier(edgeClaimsTableName)} WHERE ${fragmentSql.identifier(\"graph_id\")} = ${params.graphId} AND ${fragmentSql.identifier(\"edge_id\")} IN (SELECT ${fragmentSql.identifier(\"id\")} FROM ${fragmentSql.identifier(edgesTableName)} WHERE ${fragmentSql.identifier(\"graph_id\")} = ${params.graphId} AND (${fragmentSql.identifier(\"from_kind\")} = ${params.nodeKind} OR ${fragmentSql.identifier(\"to_kind\")} = ${params.nodeKind}))`;\n}\n"]}