pqb 0.68.0 → 0.69.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.
@@ -1645,6 +1645,8 @@ declare class BooleanColumn$1<Schema extends ColumnSchemaConfig$1> extends Colum
1645
1645
  querySchema: ReturnType<Schema['boolean']>;
1646
1646
  private static _instance;
1647
1647
  static get instance(): BooleanColumn$1<DefaultSchemaConfig$1>;
1648
+ private static _instanceSkipValueToArray;
1649
+ static get instanceSkipValueToArray(): BooleanColumn$1<DefaultSchemaConfig$1>;
1648
1650
  constructor(schema: Schema);
1649
1651
  toCode(ctx: ColumnToCodeCtx$1, key: string): Code$1;
1650
1652
  }
@@ -2150,21 +2152,23 @@ declare class UnsafeSqlExpression extends Expression$1 {
2150
2152
  constructor(sql: string | number | boolean);
2151
2153
  makeSQL(): string;
2152
2154
  }
2153
- type getValueKey = typeof getValueKey;
2154
- declare const getValueKey: unique symbol;
2155
2155
  interface PickQueryDataParsers {
2156
2156
  defaultParsers?: ColumnsParsers;
2157
2157
  parsers?: ColumnsParsers;
2158
2158
  batchParsers?: BatchParsers;
2159
2159
  }
2160
2160
  type ColumnParser = FnUnknownToUnknown;
2161
+ interface BatchParserPathEntry {
2162
+ key: string;
2163
+ returnType: QueryReturnType$1;
2164
+ }
2161
2165
  interface BatchParser {
2162
- path: string[];
2163
- fn: (path: string[], queryResult: {
2166
+ path: BatchParserPathEntry[];
2167
+ fn: (path: BatchParserPathEntry[], queryResult: {
2164
2168
  rows: unknown[];
2165
2169
  }) => MaybePromise$1<void>;
2166
2170
  }
2167
- type ColumnsParsers = { [K in string | getValueKey]?: ColumnParser };
2171
+ type ColumnsParsers = { [K in string]?: ColumnParser };
2168
2172
  type BatchParsers = BatchParser[];
2169
2173
  interface QueryThen<T> {
2170
2174
  <TResult1 = T, TResult2 = never>(onfulfilled?: (value: T) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>): Promise<TResult1 | TResult2>;
@@ -5039,6 +5043,8 @@ interface Base$1<Value> {
5039
5043
  __hasSelect: true;
5040
5044
  equals: Operator<Value | IsQuery$1 | Expression$1, BooleanQueryColumn>;
5041
5045
  not: Operator<Value | IsQuery$1 | Expression$1, BooleanQueryColumn>;
5046
+ isDistinctFrom: Operator<Value | IsQuery$1 | Expression$1, BooleanQueryColumn>;
5047
+ isNotDistinctFrom: Operator<Value | IsQuery$1 | Expression$1, BooleanQueryColumn>;
5042
5048
  in: Operator<Value[] | IsQuery$1 | Expression$1, BooleanQueryColumn>;
5043
5049
  notIn: Operator<Value[] | IsQuery$1 | Expression$1, BooleanQueryColumn>;
5044
5050
  }
@@ -5262,6 +5268,7 @@ interface ExpressionData$1 extends HasBeforeAndBeforeSet {
5262
5268
  expr?: Expression$1;
5263
5269
  before?: QueryBeforeHook$1[];
5264
5270
  dynamicBefore?: boolean;
5271
+ getColumn?: Column$1;
5265
5272
  }
5266
5273
  declare abstract class Expression$1<T extends Column$1.Pick.QueryColumn = Column$1.Pick.QueryColumn> {
5267
5274
  abstract result: {
@@ -7250,35 +7257,37 @@ declare namespace Column$1 {
7250
7257
  unique: Name;
7251
7258
  };
7252
7259
  };
7253
- export type Nullable<T extends Column$1.Pick.ForNullable, InputSchema, OutputSchema, QuerySchema> = { [K in keyof T]: K extends '__type' ? T['__type'] | null : K extends '__inputType' ? T['__inputType'] | null : K extends 'inputSchema' ? InputSchema : K extends '__outputType' ? T['__outputType'] | (unknown extends T['__nullType'] ? null : T['__nullType']) : K extends 'outputSchema' ? OutputSchema : K extends '__queryType' ? T['__queryType'] | null : K extends 'querySchema' ? QuerySchema : K extends 'data' ? T['data'] & DataNullable : K extends 'operators' ? { [K in keyof T['operators']]: K extends 'equals' | 'not' ? Operator<T | null> : T['operators'][K] } : T[K] };
7260
+ export type Nullable<T extends Column.Pick.ForNullable, InputSchema, OutputSchema, QuerySchema> = { [K in keyof T]: K extends '__type' ? T['__type'] | null : K extends '__inputType' ? T['__inputType'] | null : K extends 'inputSchema' ? InputSchema : K extends '__outputType' ? T['__outputType'] | (unknown extends T['__nullType'] ? null : T['__nullType']) : K extends 'outputSchema' ? OutputSchema : K extends '__queryType' ? T['__queryType'] | null : K extends 'querySchema' ? QuerySchema : K extends 'data' ? T['data'] & DataNullable : K extends 'operators' ? { [K in keyof T['operators']]: K extends 'equals' | 'not' | 'isDistinctFrom' | 'isNotDistinctFrom' ? Operator<T['__queryType'] | null, T> : T['operators'][K] } : T[K] };
7254
7261
  export type QueryColumnToNullable<C> = { [K in keyof C]: K extends '__outputType' | '__queryType' ? C[K] | null : C[K] };
7255
7262
  export type QueryColumnToOptional<C> = { [K in keyof C]: K extends '__outputType' ? C[K] | undefined : C[K] };
7256
7263
  interface DataNullable {
7257
7264
  isNullable: true;
7258
7265
  optional: true;
7259
7266
  }
7260
- export interface OperatorsNullable<T> {
7261
- equals: Operator<T | null>;
7262
- not: Operator<T | null>;
7267
+ export interface OperatorsNullable<Column extends Column.Pick.QueryColumn> {
7268
+ equals: Operator<Column['__queryType'] | null, Column>;
7269
+ not: Operator<Column['__queryType'] | null, Column>;
7270
+ isDistinctFrom: Operator<Column['__queryType'] | null, Column>;
7271
+ isNotDistinctFrom: Operator<Column['__queryType'] | null, Column>;
7263
7272
  }
7264
7273
  export type Encode<T, InputSchema, Input> = { [K in keyof T]: K extends '__inputType' ? Input : K extends 'inputSchema' ? InputSchema : T[K] };
7265
7274
  export type Parse<T extends Pick.ForParse, OutputSchema, Output> = { [K in keyof T]: K extends '__outputType' ? null extends T['__type'] ? (Output extends null ? never : Output) | (unknown extends T['__nullType'] ? null : T['__nullType']) : Output : K extends 'outputSchema' ? null extends T['__type'] ? OutputSchema | T['nullSchema'] : OutputSchema : T[K] };
7266
- export type ParseNull<T extends Column$1.Pick.ForParseNull, NullSchema, NullType> = { [K in keyof T]: K extends '__outputType' ? null extends T['__type'] ? Exclude<T['__outputType'], null> | NullType : T['__outputType'] : K extends '__nullType' ? NullType : K extends 'outputSchema' ? null extends T['__type'] ? T['outputSchema'] | NullSchema : T['outputSchema'] : K extends 'nullSchema' ? NullSchema : T[K] };
7267
- type DefaultData<T extends Column$1.Data, Value> = { [K in keyof T]: K extends 'default' ? Value extends null ? never : Value : K extends 'optional' ? true : T[K] };
7268
- export type Default<T extends Column$1.Pick.Data, Value> = { [K in keyof T]: K extends 'data' ? DefaultData<T['data'], Value> : T[K] };
7269
- type DefaultSelectData<T extends Column$1.Data, Value> = { [K in keyof T]: K extends 'explicitSelect' ? Value extends true ? false : true : T[K] };
7270
- export type DefaultSelect<T extends Column$1.Pick.Data, Value extends boolean> = { [K in keyof T]: K extends 'data' ? DefaultSelectData<T['data'], Value> : T[K] };
7275
+ export type ParseNull<T extends Column.Pick.ForParseNull, NullSchema, NullType> = { [K in keyof T]: K extends '__outputType' ? null extends T['__type'] ? Exclude<T['__outputType'], null> | NullType : T['__outputType'] : K extends '__nullType' ? NullType : K extends 'outputSchema' ? null extends T['__type'] ? T['outputSchema'] | NullSchema : T['outputSchema'] : K extends 'nullSchema' ? NullSchema : T[K] };
7276
+ type DefaultData<T extends Column.Data, Value> = { [K in keyof T]: K extends 'default' ? Value extends null ? never : Value : K extends 'optional' ? true : T[K] };
7277
+ export type Default<T extends Column.Pick.Data, Value> = { [K in keyof T]: K extends 'data' ? DefaultData<T['data'], Value> : T[K] };
7278
+ type DefaultSelectData<T extends Column.Data, Value> = { [K in keyof T]: K extends 'explicitSelect' ? Value extends true ? false : true : T[K] };
7279
+ export type DefaultSelect<T extends Column.Pick.Data, Value extends boolean> = { [K in keyof T]: K extends 'data' ? DefaultSelectData<T['data'], Value> : T[K] };
7271
7280
  export interface IsAppReadOnly {
7272
7281
  data: {
7273
7282
  appReadOnly: true;
7274
7283
  };
7275
7284
  }
7276
- export type Generated<T extends Column$1.Pick.Data> = { [K in keyof T]: K extends 'data' ? { [K in keyof T['data']]: K extends 'default' ? true : T['data'][K] } : K extends '__inputType' ? never : T[K] };
7285
+ export type Generated<T extends Column.Pick.Data> = { [K in keyof T]: K extends 'data' ? { [K in keyof T['data']]: K extends 'default' ? true : T['data'][K] } : K extends '__inputType' ? never : T[K] };
7277
7286
  export {};
7278
7287
  }
7279
7288
  export namespace Pick {
7280
7289
  interface Data {
7281
- data: Column$1.Data;
7290
+ data: Column.Data;
7282
7291
  }
7283
7292
  interface Type {
7284
7293
  __type: unknown;
@@ -7323,7 +7332,7 @@ declare namespace Column$1 {
7323
7332
  dataType: T;
7324
7333
  }
7325
7334
  interface QueryInit extends QueryColumn, InputType {
7326
- data: Column$1.QueryData;
7335
+ data: Column.QueryData;
7327
7336
  }
7328
7337
  interface OutputSchema {
7329
7338
  outputSchema: any;
@@ -7346,17 +7355,17 @@ declare namespace Column$1 {
7346
7355
  }
7347
7356
  export namespace Shape {
7348
7357
  interface Data {
7349
- [K: string]: Column$1.Pick.Data;
7358
+ [K: string]: Column.Pick.Data;
7350
7359
  }
7351
7360
  interface QueryInit {
7352
- [K: string]: Column$1.Pick.QueryInit;
7361
+ [K: string]: Column.Pick.QueryInit;
7353
7362
  }
7354
7363
  interface ForValidation {
7355
- [K: string]: Column$1.Pick.ForValidation;
7364
+ [K: string]: Column.Pick.ForValidation;
7356
7365
  }
7357
7366
  }
7358
7367
  export interface QueryColumns {
7359
- [K: string]: Column$1.Pick.QueryColumn;
7368
+ [K: string]: Column.Pick.QueryColumn;
7360
7369
  }
7361
7370
  export interface QueryColumnsInit {
7362
7371
  [K: string]: Pick.QueryInit;
@@ -7370,7 +7379,7 @@ declare namespace Column$1 {
7370
7379
  interface TableParam {
7371
7380
  new (): TableParamInstance;
7372
7381
  }
7373
- type ColumnNameOfTable<Table extends Column$1.ForeignKey.TableParam> = Table extends (new () => {
7382
+ type ColumnNameOfTable<Table extends Column.ForeignKey.TableParam> = Table extends (new () => {
7374
7383
  columns: {
7375
7384
  shape: infer R;
7376
7385
  };
@@ -7417,10 +7426,10 @@ declare namespace Column$1 {
7417
7426
  defaultDefault: unknown;
7418
7427
  runtimeDefault?(): unknown;
7419
7428
  explicitSelect?: boolean;
7420
- as?: Column$1.Pick.Data;
7429
+ as?: Column.Pick.Data;
7421
7430
  unique?: string;
7422
- modifyQuery?(q: Query, column: Column$1.Pick.Data): void;
7423
- checks?: Column$1.Data.Check[];
7431
+ modifyQuery?(q: Query, column: Column.Pick.Data): void;
7432
+ checks?: Column.Data.Check[];
7424
7433
  isOfCustomType?: boolean;
7425
7434
  errors?: RecordString$1;
7426
7435
  defaultTimestamp?: 'createdAt' | 'updatedAt';
@@ -7452,6 +7461,8 @@ declare namespace Column$1 {
7452
7461
  identity?: TableData$1.Identity;
7453
7462
  generated?: Data.Generated;
7454
7463
  readonly?: boolean;
7464
+ valueToArray?: boolean;
7465
+ skipValueToArray?: boolean;
7455
7466
  }
7456
7467
  export namespace Data {
7457
7468
  interface Check {
@@ -8345,7 +8356,7 @@ type SelectAllColumn = string | SelectAllColumnExpression;
8345
8356
  interface QueryData$1 extends QueryDataAliases, PickQueryDataParsers, HasHookSelect, MutativeQueriesSelectRelationsQueryData {
8346
8357
  type: QueryType;
8347
8358
  adapter: Adapter$1;
8348
- shape: ColumnsShape$1;
8359
+ selectShape: ColumnsShape$1;
8349
8360
  handleResult: HandleResult;
8350
8361
  catch?: boolean;
8351
8362
  returnType: QueryReturnType$1;
@@ -37,19 +37,13 @@ const createDb = ({ log, ...options }) => {
37
37
  });
38
38
  };
39
39
  const { types } = pg.default;
40
- const defaultTypeParsers = {};
41
- for (const key in types.builtins) {
42
- const id = types.builtins[key];
43
- defaultTypeParsers[id] = types.getTypeParser(id);
44
- }
45
- [
46
- types.builtins.DATE,
47
- types.builtins.TIMESTAMP,
48
- types.builtins.TIMESTAMPTZ,
49
- types.builtins.CIRCLE
50
- ].forEach((id) => {
51
- delete defaultTypeParsers[id];
52
- });
40
+ const defaultTypeParsers = {
41
+ [types.builtins.DATE]: pqb_internal.returnArg,
42
+ [types.builtins.TIMESTAMP]: pqb_internal.returnArg,
43
+ [types.builtins.TIMESTAMPTZ]: pqb_internal.returnArg,
44
+ [types.builtins.CIRCLE]: pqb_internal.returnArg,
45
+ 600: pqb_internal.returnArg
46
+ };
53
47
  const queryClient = (client, text, values, arraysMode) => {
54
48
  const params = {
55
49
  text,
@@ -192,8 +186,8 @@ const NodePostgresAdapter = {
192
186
  return pool.end();
193
187
  }
194
188
  };
195
- const defaultTypesConfig = { getTypeParser(id) {
196
- return defaultTypeParsers[id] || pqb_internal.returnArg;
189
+ const defaultTypesConfig = { getTypeParser(id, format) {
190
+ return defaultTypeParsers[id] || types.getTypeParser(id, format);
197
191
  } };
198
192
  const normalizeArraysResult = (result) => {
199
193
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"node-postgres.js","names":["AdapterClass","noop","DatabaseError","returnArg"],"sources":["../src/adapters/node-postgres.ts"],"sourcesContent":["import pg, { DatabaseError, Pool, PoolClient, PoolConfig } from 'pg';\nimport {\n AdapterConfigBase,\n ColumnSchemaConfig,\n noop,\n QueryResult,\n QueryResultRow,\n RecordUnknown,\n returnArg,\n DefaultColumnTypes,\n DefaultSchemaConfig,\n DbOptions,\n DbResult,\n QuerySchema,\n AdapterClass,\n DriverAdapter,\n defaultSchemaConfig,\n quoteIdentifier,\n AdapterSchemaConfigOptions,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\nimport { HackySavepointState } from './adapter';\n\nconst schemaConfig: AdapterSchemaConfigOptions = {\n jsonEncodedByDriver: false,\n};\n\nexport const nodePostgresSchemaConfig = Object.assign(\n () => defaultSchemaConfig(schemaConfig),\n schemaConfig,\n);\n\nexport const createDb = <\n SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig,\n ColumnTypes = DefaultColumnTypes<SchemaConfig>,\n>({\n log,\n ...options\n}: DbOptions<SchemaConfig, ColumnTypes> &\n Omit<NodePostgresAdapterOptions, 'log'>): DbResult<ColumnTypes> => {\n return createDbWithAdapter({\n schemaConfig: nodePostgresSchemaConfig as unknown as () => SchemaConfig,\n ...options,\n log,\n adapter: new AdapterClass({\n driverAdapter: NodePostgresAdapter,\n config: options,\n }),\n });\n};\n\nconst { types } = pg;\n\nexport interface TypeParsers {\n [K: number]: (input: string) => unknown;\n}\n\nconst defaultTypeParsers: TypeParsers = {};\n\nfor (const key in types.builtins) {\n const id = types.builtins[key as keyof typeof types.builtins];\n defaultTypeParsers[id] = types.getTypeParser(id);\n}\n\n[\n types.builtins.DATE,\n types.builtins.TIMESTAMP,\n types.builtins.TIMESTAMPTZ,\n types.builtins.CIRCLE,\n].forEach((id) => {\n delete defaultTypeParsers[id];\n});\n\nexport interface AdapterConfig\n extends\n Omit<AdapterConfigBase, 'searchPath' | 'ssl'>,\n Omit<PoolConfig, 'types' | 'connectionString'> {\n databaseURL?: string;\n}\n\nexport interface NodePostgresAdapterOptions extends Omit<AdapterConfig, 'log'> {\n schema?: QuerySchema;\n}\n\nconst queryClient = <T = QueryResultRow>(\n client: PoolClient,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n): Promise<QueryResult<T>> => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any = {\n text,\n values,\n rowMode: arraysMode ? 'array' : undefined,\n types: defaultTypesConfig,\n };\n\n // When using save points (it's in transaction), need to perform a single query at a time.\n // stating 1 then 2 then releasing 1 would fail.\n // Start 1, release 1, start 2, release 2, and so on.\n const { __lock } = client as unknown as { __lock?: Promise<unknown> };\n if (__lock) {\n let resolve: () => void | undefined;\n (client as unknown as RecordUnknown).__lock = new Promise<void>((res) => {\n resolve = () => {\n res();\n };\n });\n\n return __lock.then(() => {\n const promise = client.query(params) as Promise<QueryResult>;\n promise.then(resolve, resolve);\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n });\n }\n\n const promise = client.query(params) as Promise<QueryResult>;\n\n (client as unknown as { __lock?: Promise<unknown> }).__lock =\n promise.catch(noop);\n\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n};\n\nexport const NodePostgresAdapter: DriverAdapter = {\n manualPool: true,\n schemaConfig,\n errorClass: DatabaseError,\n errorFields: {\n message: 'message',\n length: 'length',\n name: 'name',\n severity: 'severity',\n code: 'code',\n detail: 'detail',\n hint: 'hint',\n position: 'position',\n internalPosition: 'internalPosition',\n internalQuery: 'internalQuery',\n where: 'where',\n schema: 'schema',\n table: 'table',\n column: 'column',\n dataType: 'dataType',\n constraint: 'constraint',\n file: 'file',\n line: 'line',\n routine: 'routine',\n },\n\n configure(config: NodePostgresAdapterOptions): pg.Pool {\n if (config.databaseURL) {\n (config as PoolConfig).connectionString = config.databaseURL;\n }\n\n if (config.setConfig?.search_path) {\n config = {\n ...config,\n options: `${config.options ? `${config.options} ` : ''}-c search_path=\"${config.setConfig.search_path}\"`,\n };\n }\n\n return new pg.Pool(config);\n },\n\n queryClient,\n\n borrow(pool: Pool): Promise<PoolClient> {\n return pool.connect();\n },\n\n release(client: PoolClient): void {\n client.release();\n },\n\n async begin<DriverClient, Result>(\n pool: Pool,\n cb: (adapter: DriverClient) => Promise<Result>,\n options?: string,\n ): Promise<Result> {\n const client = await pool.connect();\n\n try {\n await queryClient(client, options ? 'BEGIN ' + options : 'BEGIN');\n\n let result;\n try {\n result = await cb(client as DriverClient);\n } catch (err) {\n await queryClient(client, 'ROLLBACK');\n throw err;\n }\n await queryClient(client, 'COMMIT');\n return result as Result;\n } finally {\n client.release();\n }\n },\n\n async savepoint<T>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n name: string,\n cb: () => Promise<T>,\n ): Promise<T> {\n const safeName = quoteIdentifier(name);\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n const res = await cb();\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return res;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n },\n\n async hackySavepoint<T extends QueryResultRow>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n state: HackySavepointState,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n ): Promise<QueryResult<T>> {\n const safeName = state.name.replaceAll('\"', '\"\"');\n\n let resolve: () => void;\n let reject: (err: unknown) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n let resultResolve: (res: QueryResult<T>) => void;\n let resultReject: (err: unknown) => void;\n const resultPromise = new Promise<QueryResult<T>>((res, rej) => {\n resultResolve = res;\n resultReject = rej;\n });\n\n const savepointPromise = (async () => {\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n\n try {\n const res = await queryClient<T>(client, text, values, arraysMode);\n resultResolve!(res as QueryResult<T>);\n } catch (err) {\n resultReject!(err);\n throw err;\n }\n\n const result = await promise;\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return result;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n })();\n\n state.activeSavepoint = {\n async release() {\n resolve();\n await savepointPromise;\n },\n async rollback(err) {\n reject(err);\n await savepointPromise.catch(noop);\n },\n };\n\n return resultPromise;\n },\n\n close(pool: Pool): Promise<void> {\n return pool.end();\n },\n};\n\nconst defaultTypesConfig = {\n getTypeParser(id: number) {\n return defaultTypeParsers[id] || returnArg;\n },\n};\n\nconst normalizeArraysResult = <\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n R extends any[] = any[],\n>(\n result: QueryResult,\n): QueryResult<R> => {\n return result as unknown as QueryResult<R>;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"node-postgres.js","names":["AdapterClass","returnArg","noop","DatabaseError"],"sources":["../src/adapters/node-postgres.ts"],"sourcesContent":["import pg, { DatabaseError, Pool, PoolClient, PoolConfig } from 'pg';\nimport {\n AdapterConfigBase,\n ColumnSchemaConfig,\n noop,\n QueryResult,\n QueryResultRow,\n RecordUnknown,\n returnArg,\n DefaultColumnTypes,\n DefaultSchemaConfig,\n DbOptions,\n DbResult,\n QuerySchema,\n AdapterClass,\n DriverAdapter,\n defaultSchemaConfig,\n quoteIdentifier,\n AdapterSchemaConfigOptions,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\nimport { HackySavepointState } from './adapter';\n\nconst schemaConfig: AdapterSchemaConfigOptions = {\n jsonEncodedByDriver: false,\n};\n\nexport const nodePostgresSchemaConfig = Object.assign(\n () => defaultSchemaConfig(schemaConfig),\n schemaConfig,\n);\n\nexport const createDb = <\n SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig,\n ColumnTypes = DefaultColumnTypes<SchemaConfig>,\n>({\n log,\n ...options\n}: DbOptions<SchemaConfig, ColumnTypes> &\n Omit<NodePostgresAdapterOptions, 'log'>): DbResult<ColumnTypes> => {\n return createDbWithAdapter({\n schemaConfig: nodePostgresSchemaConfig as unknown as () => SchemaConfig,\n ...options,\n log,\n adapter: new AdapterClass({\n driverAdapter: NodePostgresAdapter,\n config: options,\n }),\n });\n};\n\nconst { types } = pg;\n\nexport interface TypeParsers {\n [K: number]: (input: string) => unknown;\n}\n\nconst defaultTypeParsers: TypeParsers = {\n [types.builtins.DATE]: returnArg,\n [types.builtins.TIMESTAMP]: returnArg,\n [types.builtins.TIMESTAMPTZ]: returnArg,\n [types.builtins.CIRCLE]: returnArg,\n 600: returnArg, // point\n};\n\nexport interface AdapterConfig\n extends\n Omit<AdapterConfigBase, 'searchPath' | 'ssl'>,\n Omit<PoolConfig, 'types' | 'connectionString'> {\n databaseURL?: string;\n}\n\nexport interface NodePostgresAdapterOptions extends Omit<AdapterConfig, 'log'> {\n schema?: QuerySchema;\n}\n\nconst queryClient = <T = QueryResultRow>(\n client: PoolClient,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n): Promise<QueryResult<T>> => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any = {\n text,\n values,\n rowMode: arraysMode ? 'array' : undefined,\n types: defaultTypesConfig,\n };\n\n // When using save points (it's in transaction), need to perform a single query at a time.\n // stating 1 then 2 then releasing 1 would fail.\n // Start 1, release 1, start 2, release 2, and so on.\n const { __lock } = client as unknown as { __lock?: Promise<unknown> };\n if (__lock) {\n let resolve: () => void | undefined;\n (client as unknown as RecordUnknown).__lock = new Promise<void>((res) => {\n resolve = () => {\n res();\n };\n });\n\n return __lock.then(() => {\n const promise = client.query(params) as Promise<QueryResult>;\n promise.then(resolve, resolve);\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n });\n }\n\n const promise = client.query(params) as Promise<QueryResult>;\n\n (client as unknown as { __lock?: Promise<unknown> }).__lock =\n promise.catch(noop);\n\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n};\n\nexport const NodePostgresAdapter: DriverAdapter = {\n manualPool: true,\n schemaConfig,\n errorClass: DatabaseError,\n errorFields: {\n message: 'message',\n length: 'length',\n name: 'name',\n severity: 'severity',\n code: 'code',\n detail: 'detail',\n hint: 'hint',\n position: 'position',\n internalPosition: 'internalPosition',\n internalQuery: 'internalQuery',\n where: 'where',\n schema: 'schema',\n table: 'table',\n column: 'column',\n dataType: 'dataType',\n constraint: 'constraint',\n file: 'file',\n line: 'line',\n routine: 'routine',\n },\n\n configure(config: NodePostgresAdapterOptions): pg.Pool {\n if (config.databaseURL) {\n (config as PoolConfig).connectionString = config.databaseURL;\n }\n\n if (config.setConfig?.search_path) {\n config = {\n ...config,\n options: `${config.options ? `${config.options} ` : ''}-c search_path=\"${config.setConfig.search_path}\"`,\n };\n }\n\n return new pg.Pool(config);\n },\n\n queryClient,\n\n borrow(pool: Pool): Promise<PoolClient> {\n return pool.connect();\n },\n\n release(client: PoolClient): void {\n client.release();\n },\n\n async begin<DriverClient, Result>(\n pool: Pool,\n cb: (adapter: DriverClient) => Promise<Result>,\n options?: string,\n ): Promise<Result> {\n const client = await pool.connect();\n\n try {\n await queryClient(client, options ? 'BEGIN ' + options : 'BEGIN');\n\n let result;\n try {\n result = await cb(client as DriverClient);\n } catch (err) {\n await queryClient(client, 'ROLLBACK');\n throw err;\n }\n await queryClient(client, 'COMMIT');\n return result as Result;\n } finally {\n client.release();\n }\n },\n\n async savepoint<T>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n name: string,\n cb: () => Promise<T>,\n ): Promise<T> {\n const safeName = quoteIdentifier(name);\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n const res = await cb();\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return res;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n },\n\n async hackySavepoint<T extends QueryResultRow>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n state: HackySavepointState,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n ): Promise<QueryResult<T>> {\n const safeName = state.name.replaceAll('\"', '\"\"');\n\n let resolve: () => void;\n let reject: (err: unknown) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n let resultResolve: (res: QueryResult<T>) => void;\n let resultReject: (err: unknown) => void;\n const resultPromise = new Promise<QueryResult<T>>((res, rej) => {\n resultResolve = res;\n resultReject = rej;\n });\n\n const savepointPromise = (async () => {\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n\n try {\n const res = await queryClient<T>(client, text, values, arraysMode);\n resultResolve!(res as QueryResult<T>);\n } catch (err) {\n resultReject!(err);\n throw err;\n }\n\n const result = await promise;\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return result;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n })();\n\n state.activeSavepoint = {\n async release() {\n resolve();\n await savepointPromise;\n },\n async rollback(err) {\n reject(err);\n await savepointPromise.catch(noop);\n },\n };\n\n return resultPromise;\n },\n\n close(pool: Pool): Promise<void> {\n return pool.end();\n },\n};\n\nconst defaultTypesConfig = {\n getTypeParser(id: number, format?: 'text' | 'binary') {\n return defaultTypeParsers[id] || types.getTypeParser(id, format as 'text');\n },\n};\n\nconst normalizeArraysResult = <\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n R extends any[] = any[],\n>(\n result: QueryResult,\n): QueryResult<R> => {\n return result as unknown as QueryResult<R>;\n};\n"],"mappings":"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"}
@@ -15,19 +15,13 @@ const createDb = ({ log, ...options }) => {
15
15
  });
16
16
  };
17
17
  const { types } = pg;
18
- const defaultTypeParsers = {};
19
- for (const key in types.builtins) {
20
- const id = types.builtins[key];
21
- defaultTypeParsers[id] = types.getTypeParser(id);
22
- }
23
- [
24
- types.builtins.DATE,
25
- types.builtins.TIMESTAMP,
26
- types.builtins.TIMESTAMPTZ,
27
- types.builtins.CIRCLE
28
- ].forEach((id) => {
29
- delete defaultTypeParsers[id];
30
- });
18
+ const defaultTypeParsers = {
19
+ [types.builtins.DATE]: returnArg,
20
+ [types.builtins.TIMESTAMP]: returnArg,
21
+ [types.builtins.TIMESTAMPTZ]: returnArg,
22
+ [types.builtins.CIRCLE]: returnArg,
23
+ 600: returnArg
24
+ };
31
25
  const queryClient = (client, text, values, arraysMode) => {
32
26
  const params = {
33
27
  text,
@@ -170,8 +164,8 @@ const NodePostgresAdapter = {
170
164
  return pool.end();
171
165
  }
172
166
  };
173
- const defaultTypesConfig = { getTypeParser(id) {
174
- return defaultTypeParsers[id] || returnArg;
167
+ const defaultTypesConfig = { getTypeParser(id, format) {
168
+ return defaultTypeParsers[id] || types.getTypeParser(id, format);
175
169
  } };
176
170
  const normalizeArraysResult = (result) => {
177
171
  return result;
@@ -1 +1 @@
1
- {"version":3,"file":"node-postgres.mjs","names":[],"sources":["../src/adapters/node-postgres.ts"],"sourcesContent":["import pg, { DatabaseError, Pool, PoolClient, PoolConfig } from 'pg';\nimport {\n AdapterConfigBase,\n ColumnSchemaConfig,\n noop,\n QueryResult,\n QueryResultRow,\n RecordUnknown,\n returnArg,\n DefaultColumnTypes,\n DefaultSchemaConfig,\n DbOptions,\n DbResult,\n QuerySchema,\n AdapterClass,\n DriverAdapter,\n defaultSchemaConfig,\n quoteIdentifier,\n AdapterSchemaConfigOptions,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\nimport { HackySavepointState } from './adapter';\n\nconst schemaConfig: AdapterSchemaConfigOptions = {\n jsonEncodedByDriver: false,\n};\n\nexport const nodePostgresSchemaConfig = Object.assign(\n () => defaultSchemaConfig(schemaConfig),\n schemaConfig,\n);\n\nexport const createDb = <\n SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig,\n ColumnTypes = DefaultColumnTypes<SchemaConfig>,\n>({\n log,\n ...options\n}: DbOptions<SchemaConfig, ColumnTypes> &\n Omit<NodePostgresAdapterOptions, 'log'>): DbResult<ColumnTypes> => {\n return createDbWithAdapter({\n schemaConfig: nodePostgresSchemaConfig as unknown as () => SchemaConfig,\n ...options,\n log,\n adapter: new AdapterClass({\n driverAdapter: NodePostgresAdapter,\n config: options,\n }),\n });\n};\n\nconst { types } = pg;\n\nexport interface TypeParsers {\n [K: number]: (input: string) => unknown;\n}\n\nconst defaultTypeParsers: TypeParsers = {};\n\nfor (const key in types.builtins) {\n const id = types.builtins[key as keyof typeof types.builtins];\n defaultTypeParsers[id] = types.getTypeParser(id);\n}\n\n[\n types.builtins.DATE,\n types.builtins.TIMESTAMP,\n types.builtins.TIMESTAMPTZ,\n types.builtins.CIRCLE,\n].forEach((id) => {\n delete defaultTypeParsers[id];\n});\n\nexport interface AdapterConfig\n extends\n Omit<AdapterConfigBase, 'searchPath' | 'ssl'>,\n Omit<PoolConfig, 'types' | 'connectionString'> {\n databaseURL?: string;\n}\n\nexport interface NodePostgresAdapterOptions extends Omit<AdapterConfig, 'log'> {\n schema?: QuerySchema;\n}\n\nconst queryClient = <T = QueryResultRow>(\n client: PoolClient,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n): Promise<QueryResult<T>> => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any = {\n text,\n values,\n rowMode: arraysMode ? 'array' : undefined,\n types: defaultTypesConfig,\n };\n\n // When using save points (it's in transaction), need to perform a single query at a time.\n // stating 1 then 2 then releasing 1 would fail.\n // Start 1, release 1, start 2, release 2, and so on.\n const { __lock } = client as unknown as { __lock?: Promise<unknown> };\n if (__lock) {\n let resolve: () => void | undefined;\n (client as unknown as RecordUnknown).__lock = new Promise<void>((res) => {\n resolve = () => {\n res();\n };\n });\n\n return __lock.then(() => {\n const promise = client.query(params) as Promise<QueryResult>;\n promise.then(resolve, resolve);\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n });\n }\n\n const promise = client.query(params) as Promise<QueryResult>;\n\n (client as unknown as { __lock?: Promise<unknown> }).__lock =\n promise.catch(noop);\n\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n};\n\nexport const NodePostgresAdapter: DriverAdapter = {\n manualPool: true,\n schemaConfig,\n errorClass: DatabaseError,\n errorFields: {\n message: 'message',\n length: 'length',\n name: 'name',\n severity: 'severity',\n code: 'code',\n detail: 'detail',\n hint: 'hint',\n position: 'position',\n internalPosition: 'internalPosition',\n internalQuery: 'internalQuery',\n where: 'where',\n schema: 'schema',\n table: 'table',\n column: 'column',\n dataType: 'dataType',\n constraint: 'constraint',\n file: 'file',\n line: 'line',\n routine: 'routine',\n },\n\n configure(config: NodePostgresAdapterOptions): pg.Pool {\n if (config.databaseURL) {\n (config as PoolConfig).connectionString = config.databaseURL;\n }\n\n if (config.setConfig?.search_path) {\n config = {\n ...config,\n options: `${config.options ? `${config.options} ` : ''}-c search_path=\"${config.setConfig.search_path}\"`,\n };\n }\n\n return new pg.Pool(config);\n },\n\n queryClient,\n\n borrow(pool: Pool): Promise<PoolClient> {\n return pool.connect();\n },\n\n release(client: PoolClient): void {\n client.release();\n },\n\n async begin<DriverClient, Result>(\n pool: Pool,\n cb: (adapter: DriverClient) => Promise<Result>,\n options?: string,\n ): Promise<Result> {\n const client = await pool.connect();\n\n try {\n await queryClient(client, options ? 'BEGIN ' + options : 'BEGIN');\n\n let result;\n try {\n result = await cb(client as DriverClient);\n } catch (err) {\n await queryClient(client, 'ROLLBACK');\n throw err;\n }\n await queryClient(client, 'COMMIT');\n return result as Result;\n } finally {\n client.release();\n }\n },\n\n async savepoint<T>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n name: string,\n cb: () => Promise<T>,\n ): Promise<T> {\n const safeName = quoteIdentifier(name);\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n const res = await cb();\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return res;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n },\n\n async hackySavepoint<T extends QueryResultRow>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n state: HackySavepointState,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n ): Promise<QueryResult<T>> {\n const safeName = state.name.replaceAll('\"', '\"\"');\n\n let resolve: () => void;\n let reject: (err: unknown) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n let resultResolve: (res: QueryResult<T>) => void;\n let resultReject: (err: unknown) => void;\n const resultPromise = new Promise<QueryResult<T>>((res, rej) => {\n resultResolve = res;\n resultReject = rej;\n });\n\n const savepointPromise = (async () => {\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n\n try {\n const res = await queryClient<T>(client, text, values, arraysMode);\n resultResolve!(res as QueryResult<T>);\n } catch (err) {\n resultReject!(err);\n throw err;\n }\n\n const result = await promise;\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return result;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n })();\n\n state.activeSavepoint = {\n async release() {\n resolve();\n await savepointPromise;\n },\n async rollback(err) {\n reject(err);\n await savepointPromise.catch(noop);\n },\n };\n\n return resultPromise;\n },\n\n close(pool: Pool): Promise<void> {\n return pool.end();\n },\n};\n\nconst defaultTypesConfig = {\n getTypeParser(id: number) {\n return defaultTypeParsers[id] || returnArg;\n },\n};\n\nconst normalizeArraysResult = <\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n R extends any[] = any[],\n>(\n result: QueryResult,\n): QueryResult<R> => {\n return result as unknown as QueryResult<R>;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"node-postgres.mjs","names":[],"sources":["../src/adapters/node-postgres.ts"],"sourcesContent":["import pg, { DatabaseError, Pool, PoolClient, PoolConfig } from 'pg';\nimport {\n AdapterConfigBase,\n ColumnSchemaConfig,\n noop,\n QueryResult,\n QueryResultRow,\n RecordUnknown,\n returnArg,\n DefaultColumnTypes,\n DefaultSchemaConfig,\n DbOptions,\n DbResult,\n QuerySchema,\n AdapterClass,\n DriverAdapter,\n defaultSchemaConfig,\n quoteIdentifier,\n AdapterSchemaConfigOptions,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\nimport { HackySavepointState } from './adapter';\n\nconst schemaConfig: AdapterSchemaConfigOptions = {\n jsonEncodedByDriver: false,\n};\n\nexport const nodePostgresSchemaConfig = Object.assign(\n () => defaultSchemaConfig(schemaConfig),\n schemaConfig,\n);\n\nexport const createDb = <\n SchemaConfig extends ColumnSchemaConfig = DefaultSchemaConfig,\n ColumnTypes = DefaultColumnTypes<SchemaConfig>,\n>({\n log,\n ...options\n}: DbOptions<SchemaConfig, ColumnTypes> &\n Omit<NodePostgresAdapterOptions, 'log'>): DbResult<ColumnTypes> => {\n return createDbWithAdapter({\n schemaConfig: nodePostgresSchemaConfig as unknown as () => SchemaConfig,\n ...options,\n log,\n adapter: new AdapterClass({\n driverAdapter: NodePostgresAdapter,\n config: options,\n }),\n });\n};\n\nconst { types } = pg;\n\nexport interface TypeParsers {\n [K: number]: (input: string) => unknown;\n}\n\nconst defaultTypeParsers: TypeParsers = {\n [types.builtins.DATE]: returnArg,\n [types.builtins.TIMESTAMP]: returnArg,\n [types.builtins.TIMESTAMPTZ]: returnArg,\n [types.builtins.CIRCLE]: returnArg,\n 600: returnArg, // point\n};\n\nexport interface AdapterConfig\n extends\n Omit<AdapterConfigBase, 'searchPath' | 'ssl'>,\n Omit<PoolConfig, 'types' | 'connectionString'> {\n databaseURL?: string;\n}\n\nexport interface NodePostgresAdapterOptions extends Omit<AdapterConfig, 'log'> {\n schema?: QuerySchema;\n}\n\nconst queryClient = <T = QueryResultRow>(\n client: PoolClient,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n): Promise<QueryResult<T>> => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const params: any = {\n text,\n values,\n rowMode: arraysMode ? 'array' : undefined,\n types: defaultTypesConfig,\n };\n\n // When using save points (it's in transaction), need to perform a single query at a time.\n // stating 1 then 2 then releasing 1 would fail.\n // Start 1, release 1, start 2, release 2, and so on.\n const { __lock } = client as unknown as { __lock?: Promise<unknown> };\n if (__lock) {\n let resolve: () => void | undefined;\n (client as unknown as RecordUnknown).__lock = new Promise<void>((res) => {\n resolve = () => {\n res();\n };\n });\n\n return __lock.then(() => {\n const promise = client.query(params) as Promise<QueryResult>;\n promise.then(resolve, resolve);\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n });\n }\n\n const promise = client.query(params) as Promise<QueryResult>;\n\n (client as unknown as { __lock?: Promise<unknown> }).__lock =\n promise.catch(noop);\n\n return promise.then((result) =>\n arraysMode ? normalizeArraysResult(result) : result,\n ) as Promise<QueryResult<T>>;\n};\n\nexport const NodePostgresAdapter: DriverAdapter = {\n manualPool: true,\n schemaConfig,\n errorClass: DatabaseError,\n errorFields: {\n message: 'message',\n length: 'length',\n name: 'name',\n severity: 'severity',\n code: 'code',\n detail: 'detail',\n hint: 'hint',\n position: 'position',\n internalPosition: 'internalPosition',\n internalQuery: 'internalQuery',\n where: 'where',\n schema: 'schema',\n table: 'table',\n column: 'column',\n dataType: 'dataType',\n constraint: 'constraint',\n file: 'file',\n line: 'line',\n routine: 'routine',\n },\n\n configure(config: NodePostgresAdapterOptions): pg.Pool {\n if (config.databaseURL) {\n (config as PoolConfig).connectionString = config.databaseURL;\n }\n\n if (config.setConfig?.search_path) {\n config = {\n ...config,\n options: `${config.options ? `${config.options} ` : ''}-c search_path=\"${config.setConfig.search_path}\"`,\n };\n }\n\n return new pg.Pool(config);\n },\n\n queryClient,\n\n borrow(pool: Pool): Promise<PoolClient> {\n return pool.connect();\n },\n\n release(client: PoolClient): void {\n client.release();\n },\n\n async begin<DriverClient, Result>(\n pool: Pool,\n cb: (adapter: DriverClient) => Promise<Result>,\n options?: string,\n ): Promise<Result> {\n const client = await pool.connect();\n\n try {\n await queryClient(client, options ? 'BEGIN ' + options : 'BEGIN');\n\n let result;\n try {\n result = await cb(client as DriverClient);\n } catch (err) {\n await queryClient(client, 'ROLLBACK');\n throw err;\n }\n await queryClient(client, 'COMMIT');\n return result as Result;\n } finally {\n client.release();\n }\n },\n\n async savepoint<T>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n name: string,\n cb: () => Promise<T>,\n ): Promise<T> {\n const safeName = quoteIdentifier(name);\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n const res = await cb();\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return res;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n },\n\n async hackySavepoint<T extends QueryResultRow>(\n client: PoolClient,\n // node-postgres doesn't need to switch the client in a savepoint\n _setClient: (client: PoolClient) => void,\n state: HackySavepointState,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n ): Promise<QueryResult<T>> {\n const safeName = state.name.replaceAll('\"', '\"\"');\n\n let resolve: () => void;\n let reject: (err: unknown) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n let resultResolve: (res: QueryResult<T>) => void;\n let resultReject: (err: unknown) => void;\n const resultPromise = new Promise<QueryResult<T>>((res, rej) => {\n resultResolve = res;\n resultReject = rej;\n });\n\n const savepointPromise = (async () => {\n try {\n await queryClient(client, `SAVEPOINT ${safeName}`);\n\n try {\n const res = await queryClient<T>(client, text, values, arraysMode);\n resultResolve!(res as QueryResult<T>);\n } catch (err) {\n resultReject!(err);\n throw err;\n }\n\n const result = await promise;\n await queryClient(client, `RELEASE SAVEPOINT ${safeName}`);\n return result;\n } catch (err) {\n await queryClient(client, `ROLLBACK TO SAVEPOINT ${safeName}`);\n throw err;\n }\n })();\n\n state.activeSavepoint = {\n async release() {\n resolve();\n await savepointPromise;\n },\n async rollback(err) {\n reject(err);\n await savepointPromise.catch(noop);\n },\n };\n\n return resultPromise;\n },\n\n close(pool: Pool): Promise<void> {\n return pool.end();\n },\n};\n\nconst defaultTypesConfig = {\n getTypeParser(id: number, format?: 'text' | 'binary') {\n return defaultTypeParsers[id] || types.getTypeParser(id, format as 'text');\n },\n};\n\nconst normalizeArraysResult = <\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n R extends any[] = any[],\n>(\n result: QueryResult,\n): QueryResult<R> => {\n return result as unknown as QueryResult<R>;\n};\n"],"mappings":"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"}
@@ -39,6 +39,69 @@ const parseInterval = (str) => {
39
39
  milliseconds: Math.round(timeMultiplier * (secondsFloat - wholeSeconds) * 1e6) / 1e3
40
40
  };
41
41
  };
42
+ const patchPostgresJsArrayParsers = (sql) => {
43
+ const options = sql.options;
44
+ const { parsers } = options;
45
+ const serializers = options.serializers;
46
+ options.serializers = new Proxy(serializers, { set(target, property, value, receiver) {
47
+ const result = Reflect.set(target, property, value, receiver);
48
+ if (typeof property === "symbol") return result;
49
+ const typarray = Number(property);
50
+ if (!Number.isInteger(typarray) || !parsers[typarray]?.array) return result;
51
+ const oid = findTypeOidByArrayOid(options.shared.typeArrayMap, typarray);
52
+ if (!oid) return result;
53
+ const itemParser = parsers[oid];
54
+ const arrayParser = (input) => parsePostgresArray(input, itemParser, typarray);
55
+ arrayParser.array = true;
56
+ parsers[typarray] = arrayParser;
57
+ return result;
58
+ } });
59
+ };
60
+ const findTypeOidByArrayOid = (typeArrayMap, typarray) => {
61
+ for (const oid in typeArrayMap) if (typeArrayMap[oid] === typarray) return Number(oid);
62
+ };
63
+ const parsePostgresArray = (input, parser, typarray) => {
64
+ return parsePostgresArrayLoop({
65
+ i: 0,
66
+ char: null,
67
+ str: "",
68
+ quoted: false,
69
+ last: 0
70
+ }, input, parser, typarray);
71
+ };
72
+ const parsePostgresArrayLoop = (state, input, parser, typarray) => {
73
+ const result = [];
74
+ const delimiter = typarray === 1020 ? ";" : ",";
75
+ for (; state.i < input.length; state.i++) {
76
+ state.char = input[state.i];
77
+ if (state.quoted) if (state.char === "\\") state.str += input[++state.i];
78
+ else if (state.char === "\"") {
79
+ result.push(parser ? parser(state.str) : state.str);
80
+ state.str = "";
81
+ state.quoted = input[state.i + 1] === "\"";
82
+ state.last = state.i + 2;
83
+ } else state.str += state.char;
84
+ else if (state.char === "\"") state.quoted = true;
85
+ else if (state.char === "{") {
86
+ state.last = ++state.i;
87
+ result.push(parsePostgresArrayLoop(state, input, parser, typarray));
88
+ } else if (state.char === "}") {
89
+ state.quoted = false;
90
+ if (state.last < state.i) result.push(parseArrayValue(input.slice(state.last, state.i), parser));
91
+ state.last = state.i + 1;
92
+ break;
93
+ } else if (state.char === delimiter && state.p !== "}" && state.p !== "\"") {
94
+ result.push(parseArrayValue(input.slice(state.last, state.i), parser));
95
+ state.last = state.i + 1;
96
+ }
97
+ state.p = state.char;
98
+ }
99
+ if (state.last < state.i) result.push(parseArrayValue(input.slice(state.last, state.i + 1), parser));
100
+ return result;
101
+ };
102
+ const parseArrayValue = (input, parser) => {
103
+ return input === "NULL" ? null : parser ? parser(input) : input;
104
+ };
42
105
  const createDb = (options) => {
43
106
  return (0, pqb.createDbWithAdapter)({
44
107
  ...options,
@@ -121,6 +184,7 @@ const PostgresJsAdapter = {
121
184
  let sql;
122
185
  if (config.databaseURL) sql = (0, postgres.default)(config.databaseURL, config);
123
186
  else sql = (0, postgres.default)(config);
187
+ patchPostgresJsArrayParsers(sql);
124
188
  return sql;
125
189
  },
126
190
  async queryClient(client, text, values, arraysMode) {
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-js.js","names":["AdapterClass","returnArg","noop"],"sources":["../src/adapters/driver-adapter-shared.ts","../src/adapters/postgres-js.ts"],"sourcesContent":["export interface PostgresInterval {\n years: number;\n months: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n milliseconds: number;\n}\n\nconst intervalRegExp =\n /^\\s*(?:([+-]?\\d+)\\s+years?)?\\s*(?:([+-]?\\d+)\\s+mons?)?\\s*(?:([+-]?\\d+)\\s+days?)?\\s*(?:([+-])?(\\d+):(\\d\\d):(\\d\\d(?:\\.\\d{1,6})?))?\\s*$/;\n\nexport const parseInterval = (str: string): PostgresInterval => {\n const [, years, months, days, timeSign, hours, minutes, seconds] =\n intervalRegExp.exec(str) || [];\n const timeMultiplier = timeSign === '-' ? -1 : 1;\n const secondsFloat = Number(seconds) || 0;\n const wholeSeconds = Math.floor(secondsFloat);\n\n return {\n years: years ? Number(years) : 0,\n months: months ? Number(months) : 0,\n days: days ? Number(days) : 0,\n hours: hours ? timeMultiplier * Number(hours) : 0,\n minutes: minutes ? timeMultiplier * Number(minutes) : 0,\n seconds: timeMultiplier * wholeSeconds,\n milliseconds:\n Math.round(timeMultiplier * (secondsFloat - wholeSeconds) * 1000000) /\n 1000,\n };\n};\n","import postgres, { Row, RowList, TransactionSql } from 'postgres';\nimport {\n AdapterConfigBase,\n QueryResult,\n QueryResultRow,\n returnArg,\n DbOptions,\n DefaultColumnTypes,\n DefaultSchemaConfig,\n DbResult,\n ColumnSchemaConfig,\n AdapterClass,\n DriverAdapter,\n QuerySchema,\n noop,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\nimport { HackySavepointState } from './adapter';\nimport { parseInterval } from './driver-adapter-shared';\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\nclass PostgresJsArraysResult<\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n R extends any[],\n> implements QueryResult<R> {\n rowCount: number;\n rows: R[];\n fields: QueryResult['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\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 parse: (x: string) => Buffer.from(x.slice(2), 'hex'),\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: parseInterval,\n },\n json: {\n to: 114,\n from: [114, 3802],\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 = {\n ...params,\n types,\n };\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 async queryClient<T = QueryResultRow>(\n client: TransactionSql,\n text: string,\n values?: unknown[],\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 const result = await query;\n if (result.constructor === Array) {\n return (result as RawResult[]).map((res) =>\n makePostgresJsResult(res, arraysMode),\n ) as never;\n } else {\n return makePostgresJsResult(\n result as RawResult,\n arraysMode,\n ) as QueryResult<T>;\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 async savepoint<T>(\n client: postgres.TransactionSql,\n setClient: (client: postgres.TransactionSql) => void,\n name: string,\n cb: () => Promise<T>,\n ): Promise<T> {\n let result: T | undefined;\n await client\n .savepoint(name, async (savepointClient) => {\n setClient(savepointClient);\n result = await cb();\n })\n .finally(() => {\n setClient(client);\n });\n return result as T;\n },\n\n async hackySavepoint<T extends QueryResultRow>(\n client: postgres.TransactionSql,\n setClient: (client: postgres.TransactionSql) => void,\n state: HackySavepointState,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n ): Promise<QueryResult<T>> {\n let resolve: () => void;\n let reject: (err: unknown) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n let resultResolve: (res: QueryResult<T>) => void;\n let resultReject: (err: unknown) => void;\n const resultPromise = new Promise<QueryResult<T>>((res, rej) => {\n resultResolve = res;\n resultReject = rej;\n });\n\n const savepointPromise = client\n .savepoint<void>(state.name, async (savepointClient) => {\n try {\n setClient(savepointClient);\n\n const res = await this.queryClient<T>(\n savepointClient,\n text,\n values,\n arraysMode,\n );\n resultResolve(res as QueryResult<T>);\n } catch (err) {\n resultReject(err);\n throw err;\n }\n\n return promise;\n })\n .finally(() => {\n setClient(client);\n });\n\n state.activeSavepoint = {\n async release() {\n resolve();\n await savepointPromise;\n },\n async rollback(err) {\n reject(err);\n await savepointPromise.catch(noop);\n },\n };\n\n return resultPromise;\n },\n\n close(client: postgres.Sql): Promise<void> {\n return client.end();\n },\n};\n\nconst makePostgresJsResult = (\n result: RawResult,\n arraysMode?: boolean,\n): QueryResult => {\n return arraysMode\n ? new PostgresJsArraysResult(result)\n : new PostgresJsResult(result);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"postgres-js.js","names":["AdapterClass","returnArg","noop"],"sources":["../src/adapters/driver-adapter-shared.ts","../src/adapters/postgres-js-array-parser-patch.ts","../src/adapters/postgres-js.ts"],"sourcesContent":["export interface PostgresInterval {\n years: number;\n months: number;\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n milliseconds: number;\n}\n\nconst intervalRegExp =\n /^\\s*(?:([+-]?\\d+)\\s+years?)?\\s*(?:([+-]?\\d+)\\s+mons?)?\\s*(?:([+-]?\\d+)\\s+days?)?\\s*(?:([+-])?(\\d+):(\\d\\d):(\\d\\d(?:\\.\\d{1,6})?))?\\s*$/;\n\nexport const parseInterval = (str: string): PostgresInterval => {\n const [, years, months, days, timeSign, hours, minutes, seconds] =\n intervalRegExp.exec(str) || [];\n const timeMultiplier = timeSign === '-' ? -1 : 1;\n const secondsFloat = Number(seconds) || 0;\n const wholeSeconds = Math.floor(secondsFloat);\n\n return {\n years: years ? Number(years) : 0,\n months: months ? Number(months) : 0,\n days: days ? Number(days) : 0,\n hours: hours ? timeMultiplier * Number(hours) : 0,\n minutes: minutes ? timeMultiplier * Number(minutes) : 0,\n seconds: timeMultiplier * wholeSeconds,\n milliseconds:\n Math.round(timeMultiplier * (secondsFloat - wholeSeconds) * 1000000) /\n 1000,\n };\n};\n","import postgres from 'postgres';\n\ninterface PostgresJsParser {\n (input: string): unknown;\n array?: boolean;\n}\n\ninterface PostgresJsOptionsWithArrays extends postgres.ParsedOptions {\n shared: {\n typeArrayMap: Record<number, number>;\n };\n parsers: Record<number, PostgresJsParser>;\n}\n\nexport const patchPostgresJsArrayParsers = (sql: postgres.Sql): void => {\n const options = sql.options as PostgresJsOptionsWithArrays;\n const { parsers } = options;\n const serializers = options.serializers;\n\n options.serializers = new Proxy(serializers, {\n set(target, property, value, receiver) {\n const result = Reflect.set(target, property, value, receiver);\n if (typeof property === 'symbol') return result;\n\n const typarray = Number(property);\n if (!Number.isInteger(typarray) || !parsers[typarray]?.array) {\n return result;\n }\n\n const oid = findTypeOidByArrayOid(options.shared.typeArrayMap, typarray);\n if (!oid) return result;\n\n const itemParser = parsers[oid];\n const arrayParser: PostgresJsParser = (input) =>\n parsePostgresArray(input, itemParser, typarray);\n arrayParser.array = true;\n parsers[typarray] = arrayParser;\n\n return result;\n },\n });\n};\n\nconst findTypeOidByArrayOid = (\n typeArrayMap: Record<number, number>,\n typarray: number,\n): number | undefined => {\n for (const oid in typeArrayMap) {\n if (typeArrayMap[oid] === typarray) return Number(oid);\n }\n\n return undefined;\n};\n\ninterface ArrayParserState {\n i: number;\n char: string | null;\n str: string;\n quoted: boolean;\n last: number;\n p?: string | null;\n}\n\nconst parsePostgresArray = (\n input: string,\n parser: PostgresJsParser | undefined,\n typarray: number,\n): unknown[] => {\n return parsePostgresArrayLoop(\n {\n i: 0,\n char: null,\n str: '',\n quoted: false,\n last: 0,\n },\n input,\n parser,\n typarray,\n );\n};\n\nconst parsePostgresArrayLoop = (\n state: ArrayParserState,\n input: string,\n parser: PostgresJsParser | undefined,\n typarray: number,\n): unknown[] => {\n const result: unknown[] = [];\n // Only _box (1020) has the ';' delimiter for arrays, all other types use ','.\n const delimiter = typarray === 1020 ? ';' : ',';\n\n for (; state.i < input.length; state.i++) {\n state.char = input[state.i];\n if (state.quoted) {\n if (state.char === '\\\\') {\n state.str += input[++state.i];\n } else if (state.char === '\"') {\n result.push(parser ? parser(state.str) : state.str);\n state.str = '';\n state.quoted = input[state.i + 1] === '\"';\n state.last = state.i + 2;\n } else {\n state.str += state.char;\n }\n } else if (state.char === '\"') {\n state.quoted = true;\n } else if (state.char === '{') {\n state.last = ++state.i;\n result.push(parsePostgresArrayLoop(state, input, parser, typarray));\n } else if (state.char === '}') {\n state.quoted = false;\n if (state.last < state.i) {\n result.push(parseArrayValue(input.slice(state.last, state.i), parser));\n }\n state.last = state.i + 1;\n break;\n } else if (state.char === delimiter && state.p !== '}' && state.p !== '\"') {\n result.push(parseArrayValue(input.slice(state.last, state.i), parser));\n state.last = state.i + 1;\n }\n\n state.p = state.char;\n }\n\n if (state.last < state.i) {\n result.push(parseArrayValue(input.slice(state.last, state.i + 1), parser));\n }\n\n return result;\n};\n\nconst parseArrayValue = (\n input: string,\n parser: PostgresJsParser | undefined,\n): unknown => {\n return input === 'NULL' ? null : parser ? parser(input) : input;\n};\n","import postgres, { Row, RowList, TransactionSql } from 'postgres';\nimport {\n AdapterConfigBase,\n QueryResult,\n QueryResultRow,\n returnArg,\n DbOptions,\n DefaultColumnTypes,\n DefaultSchemaConfig,\n DbResult,\n ColumnSchemaConfig,\n AdapterClass,\n DriverAdapter,\n QuerySchema,\n noop,\n} from 'pqb/internal';\nimport { createDbWithAdapter } from 'pqb';\nimport { HackySavepointState } from './adapter';\nimport { parseInterval } from './driver-adapter-shared';\nimport { patchPostgresJsArrayParsers } from './postgres-js-array-parser-patch';\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\nclass PostgresJsArraysResult<\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n R extends any[],\n> implements QueryResult<R> {\n rowCount: number;\n rows: R[];\n fields: QueryResult['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\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 parse: (x: string) => Buffer.from(x.slice(2), 'hex'),\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: parseInterval,\n },\n json: {\n to: 114,\n from: [114, 3802],\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 = {\n ...params,\n types,\n };\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 patchPostgresJsArrayParsers(sql);\n\n return sql;\n },\n\n async queryClient<T = QueryResultRow>(\n client: TransactionSql,\n text: string,\n values?: unknown[],\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 const result = await query;\n if (result.constructor === Array) {\n return (result as RawResult[]).map((res) =>\n makePostgresJsResult(res, arraysMode),\n ) as never;\n } else {\n return makePostgresJsResult(\n result as RawResult,\n arraysMode,\n ) as QueryResult<T>;\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 async savepoint<T>(\n client: postgres.TransactionSql,\n setClient: (client: postgres.TransactionSql) => void,\n name: string,\n cb: () => Promise<T>,\n ): Promise<T> {\n let result: T | undefined;\n await client\n .savepoint(name, async (savepointClient) => {\n setClient(savepointClient);\n result = await cb();\n })\n .finally(() => {\n setClient(client);\n });\n return result as T;\n },\n\n async hackySavepoint<T extends QueryResultRow>(\n client: postgres.TransactionSql,\n setClient: (client: postgres.TransactionSql) => void,\n state: HackySavepointState,\n text: string,\n values?: unknown[],\n arraysMode?: boolean,\n ): Promise<QueryResult<T>> {\n let resolve: () => void;\n let reject: (err: unknown) => void;\n const promise = new Promise<void>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n let resultResolve: (res: QueryResult<T>) => void;\n let resultReject: (err: unknown) => void;\n const resultPromise = new Promise<QueryResult<T>>((res, rej) => {\n resultResolve = res;\n resultReject = rej;\n });\n\n const savepointPromise = client\n .savepoint<void>(state.name, async (savepointClient) => {\n try {\n setClient(savepointClient);\n\n const res = await this.queryClient<T>(\n savepointClient,\n text,\n values,\n arraysMode,\n );\n resultResolve(res as QueryResult<T>);\n } catch (err) {\n resultReject(err);\n throw err;\n }\n\n return promise;\n })\n .finally(() => {\n setClient(client);\n });\n\n state.activeSavepoint = {\n async release() {\n resolve();\n await savepointPromise;\n },\n async rollback(err) {\n reject(err);\n await savepointPromise.catch(noop);\n },\n };\n\n return resultPromise;\n },\n\n close(client: postgres.Sql): Promise<void> {\n return client.end();\n },\n};\n\nconst makePostgresJsResult = (\n result: RawResult,\n arraysMode?: boolean,\n): QueryResult => {\n return arraysMode\n ? new PostgresJsArraysResult(result)\n : new PostgresJsResult(result);\n};\n"],"mappings":"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"}
@@ -17,6 +17,69 @@ const parseInterval = (str) => {
17
17
  milliseconds: Math.round(timeMultiplier * (secondsFloat - wholeSeconds) * 1e6) / 1e3
18
18
  };
19
19
  };
20
+ const patchPostgresJsArrayParsers = (sql) => {
21
+ const options = sql.options;
22
+ const { parsers } = options;
23
+ const serializers = options.serializers;
24
+ options.serializers = new Proxy(serializers, { set(target, property, value, receiver) {
25
+ const result = Reflect.set(target, property, value, receiver);
26
+ if (typeof property === "symbol") return result;
27
+ const typarray = Number(property);
28
+ if (!Number.isInteger(typarray) || !parsers[typarray]?.array) return result;
29
+ const oid = findTypeOidByArrayOid(options.shared.typeArrayMap, typarray);
30
+ if (!oid) return result;
31
+ const itemParser = parsers[oid];
32
+ const arrayParser = (input) => parsePostgresArray(input, itemParser, typarray);
33
+ arrayParser.array = true;
34
+ parsers[typarray] = arrayParser;
35
+ return result;
36
+ } });
37
+ };
38
+ const findTypeOidByArrayOid = (typeArrayMap, typarray) => {
39
+ for (const oid in typeArrayMap) if (typeArrayMap[oid] === typarray) return Number(oid);
40
+ };
41
+ const parsePostgresArray = (input, parser, typarray) => {
42
+ return parsePostgresArrayLoop({
43
+ i: 0,
44
+ char: null,
45
+ str: "",
46
+ quoted: false,
47
+ last: 0
48
+ }, input, parser, typarray);
49
+ };
50
+ const parsePostgresArrayLoop = (state, input, parser, typarray) => {
51
+ const result = [];
52
+ const delimiter = typarray === 1020 ? ";" : ",";
53
+ for (; state.i < input.length; state.i++) {
54
+ state.char = input[state.i];
55
+ if (state.quoted) if (state.char === "\\") state.str += input[++state.i];
56
+ else if (state.char === "\"") {
57
+ result.push(parser ? parser(state.str) : state.str);
58
+ state.str = "";
59
+ state.quoted = input[state.i + 1] === "\"";
60
+ state.last = state.i + 2;
61
+ } else state.str += state.char;
62
+ else if (state.char === "\"") state.quoted = true;
63
+ else if (state.char === "{") {
64
+ state.last = ++state.i;
65
+ result.push(parsePostgresArrayLoop(state, input, parser, typarray));
66
+ } else if (state.char === "}") {
67
+ state.quoted = false;
68
+ if (state.last < state.i) result.push(parseArrayValue(input.slice(state.last, state.i), parser));
69
+ state.last = state.i + 1;
70
+ break;
71
+ } else if (state.char === delimiter && state.p !== "}" && state.p !== "\"") {
72
+ result.push(parseArrayValue(input.slice(state.last, state.i), parser));
73
+ state.last = state.i + 1;
74
+ }
75
+ state.p = state.char;
76
+ }
77
+ if (state.last < state.i) result.push(parseArrayValue(input.slice(state.last, state.i + 1), parser));
78
+ return result;
79
+ };
80
+ const parseArrayValue = (input, parser) => {
81
+ return input === "NULL" ? null : parser ? parser(input) : input;
82
+ };
20
83
  const createDb = (options) => {
21
84
  return createDbWithAdapter({
22
85
  ...options,
@@ -99,6 +162,7 @@ const PostgresJsAdapter = {
99
162
  let sql;
100
163
  if (config.databaseURL) sql = postgres(config.databaseURL, config);
101
164
  else sql = postgres(config);
165
+ patchPostgresJsArrayParsers(sql);
102
166
  return sql;
103
167
  },
104
168
  async queryClient(client, text, values, arraysMode) {