{"version":3,"file":"postgres-js.mjs","names":[],"sources":["../src/adapters/postgres-js.ts"],"sourcesContent":["import postgres, { Row, RowList, TransactionSql } from 'postgres';\nimport {\n  AdapterConfigBase,\n  MaybeArray,\n  QueryArraysResult,\n  QueryResult,\n  QueryResultRow,\n  returnArg,\n  DbOptions,\n  DefaultColumnTypes,\n  DefaultSchemaConfig,\n  DbResult,\n  ColumnSchemaConfig,\n  AdapterClass,\n  DriverAdapter,\n  QuerySchema,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\n\nexport interface CreatePostgresJsDbOptions<\n  SchemaConfig extends ColumnSchemaConfig,\n  ColumnTypes,\n>\n  extends PostgresJsAdapterOptions, DbOptions<SchemaConfig, ColumnTypes> {}\n\nexport const createDb = <\n  SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig,\n  ColumnTypes = DefaultColumnTypes<SchemaConfig>,\n>(\n  options: CreatePostgresJsDbOptions<SchemaConfig, ColumnTypes>,\n): DbResult<ColumnTypes> => {\n  return createDbWithAdapter({\n    ...options,\n    adapter: new AdapterClass({\n      driverAdapter: PostgresJsAdapter,\n      config: options,\n    }),\n  });\n};\n\nexport interface PostgresJsAdapterOptions\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  extends postgres.Options<any>, Omit<AdapterConfigBase, 'searchPath' | 'ssl'> {\n  databaseURL?: string;\n  schema?: QuerySchema;\n}\n\ntype RawResult = RowList<(Row & Iterable<Row>)[]>;\n\nclass PostgresJsResult<T extends QueryResultRow> implements QueryResult<T> {\n  rowCount: number;\n  rows: T[];\n  fields: QueryResult<T>['fields'];\n\n  constructor(result: RawResult) {\n    this.rowCount = result.count;\n    this.rows = result as never;\n    this.fields = result.statement.columns;\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst wrapResult = (result: MaybeArray<RawResult>): QueryArraysResult<any> => {\n  if (result.constructor === Array) {\n    return (result as RawResult[]).map(\n      (res) => new PostgresJsResult(res),\n    ) as never;\n  } else {\n    return new PostgresJsResult(result as RawResult);\n  }\n};\n\nconst types: Record<string, Partial<postgres.PostgresType>> = {\n  bytea: {\n    to: 17,\n    from: 17 as never,\n    serialize: (x) => '\\\\x' + Buffer.from(x).toString('hex'),\n    // omit parse, let bytea return a string, so it remains consistent with when it's selected via JSON\n  },\n  dateAndTimestampAsStrings: {\n    to: 25,\n    from: [1082, 1114, 1184],\n    parse: returnArg,\n  },\n  interval: {\n    from: [1186],\n    serialize: returnArg,\n    parse(str: string) {\n      const [years, , months, , days, , time] = str.split(' ');\n      const [hours, minutes, seconds] = time.split(':');\n\n      return {\n        years: years ? Number(years) : 0,\n        months: months ? Number(months) : 0,\n        days: days ? Number(days) : 0,\n        hours: hours ? Number(hours) : 0,\n        minutes: minutes ? Number(minutes) : 0,\n        seconds: seconds ? Number(seconds) : 0,\n      };\n    },\n  },\n  // overrides the built-in json type to not serialize it, because it incorrectly serializes\n  json: {\n    to: 114,\n    from: [114, 3802],\n    serialize: returnArg,\n    parse: (x) => {\n      return JSON.parse(x);\n    },\n  },\n};\n\nexport const PostgresJsAdapter: DriverAdapter = {\n  manualPool: false,\n\n  errorClass: postgres.PostgresError,\n  errorFields: {\n    message: 'message',\n    severity: 'severity',\n    code: 'code',\n    detail: 'detail',\n    schema: 'schema_name',\n    table: 'table_name',\n    constraint: 'constraint_name',\n    hint: 'hint',\n    position: 'position',\n    where: 'where',\n    file: 'file',\n    line: 'line',\n    routine: 'routine',\n  },\n\n  configure(params: PostgresJsAdapterOptions): postgres.Sql {\n    const config: PostgresJsAdapterOptions = { ...params, types };\n\n    if (config.setConfig?.search_path) {\n      config.connection = {\n        ...config.connection,\n        search_path: config.setConfig.search_path,\n      };\n    }\n\n    let sql;\n    if (config.databaseURL) {\n      sql = postgres(config.databaseURL, config);\n    } else {\n      sql = postgres(config);\n    }\n\n    return sql;\n  },\n\n  queryClient<T extends QueryResultRow = QueryResultRow>(\n    client: TransactionSql,\n    text: string,\n    values?: unknown[],\n    // only has effect in a transaction\n    startingSavepoint?: string,\n    releasingSavepoint?: string,\n    // SQL session state (role and setConfig) from async storage\n    arraysMode?: boolean,\n  ): Promise<QueryResult<T>> {\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let query = client.unsafe(text, values as never) as any;\n\n    if (arraysMode) query = query.values();\n\n    if (!startingSavepoint && !releasingSavepoint) {\n      return query.then(wrapResult);\n    }\n\n    return Promise.all([\n      startingSavepoint && client.unsafe(`SAVEPOINT \"${startingSavepoint}\"`),\n      query,\n      releasingSavepoint &&\n        client.unsafe(`RELEASE SAVEPOINT \"${releasingSavepoint}\"`),\n    ]).then(\n      (results: RawResult[]) => {\n        return wrapResult(results[1]);\n      },\n      (err) => {\n        if (!releasingSavepoint) {\n          throw err;\n        }\n\n        return client\n          .unsafe(`ROLLBACK TO SAVEPOINT \"${releasingSavepoint}\"`)\n          .then(() => {\n            throw err;\n          });\n      },\n    );\n  },\n\n  borrow(client: postgres.Sql): Promise<postgres.ReservedSql> {\n    return client.reserve();\n  },\n\n  release(client: postgres.ReservedSql): void {\n    client.release();\n  },\n\n  begin<DriverClient, Result>(\n    client: postgres.Sql,\n    cb: (adapter: DriverClient) => Promise<Result>,\n    options?: string,\n  ): Promise<Result> {\n    let ok: boolean | undefined;\n    let result: unknown;\n\n    const fn = (sql: TransactionSql): Promise<Result> =>\n      cb(sql as DriverClient).then((res) => {\n        ok = true;\n        return (result = res);\n      });\n\n    return (options ? client.begin(options, fn) : client.begin(fn)).catch(\n      (err) => {\n        if (ok) return result;\n\n        throw err;\n      },\n    ) as never;\n  },\n\n  close(client: postgres.Sql): Promise<void> {\n    return client.end();\n  },\n};\n"],"mappings":"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"}