@effect/sql-pg 0.46.0 → 0.48.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.
- package/dist/cjs/PgClient.js +143 -100
- package/dist/cjs/PgClient.js.map +1 -1
- package/dist/dts/PgClient.d.ts +11 -62
- package/dist/dts/PgClient.d.ts.map +1 -1
- package/dist/esm/PgClient.js +143 -100
- package/dist/esm/PgClient.js.map +1 -1
- package/package.json +7 -6
- package/src/PgClient.ts +155 -183
package/src/PgClient.ts
CHANGED
|
@@ -7,19 +7,23 @@ import type { Connection } from "@effect/sql/SqlConnection"
|
|
|
7
7
|
import { SqlError } from "@effect/sql/SqlError"
|
|
8
8
|
import type { Custom, Fragment, Primitive } from "@effect/sql/Statement"
|
|
9
9
|
import * as Statement from "@effect/sql/Statement"
|
|
10
|
+
import * as Arr from "effect/Array"
|
|
10
11
|
import * as Chunk from "effect/Chunk"
|
|
11
12
|
import * as Config from "effect/Config"
|
|
12
|
-
import type
|
|
13
|
+
import type * as ConfigError from "effect/ConfigError"
|
|
13
14
|
import * as Context from "effect/Context"
|
|
14
15
|
import * as Duration from "effect/Duration"
|
|
15
16
|
import * as Effect from "effect/Effect"
|
|
17
|
+
import * as Fiber from "effect/Fiber"
|
|
16
18
|
import * as Layer from "effect/Layer"
|
|
19
|
+
import * as Option from "effect/Option"
|
|
20
|
+
import * as RcRef from "effect/RcRef"
|
|
17
21
|
import * as Redacted from "effect/Redacted"
|
|
18
|
-
import
|
|
22
|
+
import * as Scope from "effect/Scope"
|
|
19
23
|
import * as Stream from "effect/Stream"
|
|
20
|
-
import type * as NodeStream from "node:stream"
|
|
21
24
|
import type { ConnectionOptions } from "node:tls"
|
|
22
|
-
import
|
|
25
|
+
import * as Pg from "pg"
|
|
26
|
+
import Cursor from "pg-cursor"
|
|
23
27
|
|
|
24
28
|
const ATTR_DB_SYSTEM_NAME = "db.system.name"
|
|
25
29
|
const ATTR_DB_NAMESPACE = "db.namespace"
|
|
@@ -30,13 +34,13 @@ const ATTR_SERVER_PORT = "server.port"
|
|
|
30
34
|
* @category type ids
|
|
31
35
|
* @since 1.0.0
|
|
32
36
|
*/
|
|
33
|
-
export const TypeId:
|
|
37
|
+
export const TypeId: TypeId = "~@effect/sql-pg/PgClient"
|
|
34
38
|
|
|
35
39
|
/**
|
|
36
40
|
* @category type ids
|
|
37
41
|
* @since 1.0.0
|
|
38
42
|
*/
|
|
39
|
-
export type TypeId =
|
|
43
|
+
export type TypeId = "~@effect/sql-pg/PgClient"
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
46
|
* @category models
|
|
@@ -46,7 +50,6 @@ export interface PgClient extends Client.SqlClient {
|
|
|
46
50
|
readonly [TypeId]: TypeId
|
|
47
51
|
readonly config: PgClientConfig
|
|
48
52
|
readonly json: (_: unknown) => Fragment
|
|
49
|
-
readonly array: (_: ReadonlyArray<Primitive>) => Fragment
|
|
50
53
|
readonly listen: (channel: string) => Stream.Stream<string, SqlError>
|
|
51
54
|
readonly notify: (channel: string, payload: string) => Effect.Effect<void, SqlError>
|
|
52
55
|
}
|
|
@@ -72,33 +75,11 @@ export interface PgClientConfig {
|
|
|
72
75
|
readonly username?: string | undefined
|
|
73
76
|
readonly password?: Redacted.Redacted | undefined
|
|
74
77
|
|
|
75
|
-
/**
|
|
76
|
-
* A function returning a custom socket to use. This parameter is not documented
|
|
77
|
-
* in the postgres.js's type signature. See their
|
|
78
|
-
* [readme](https://github.com/porsager/postgres?tab=readme-ov-file#connection-details) instead.
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```ts
|
|
82
|
-
* import { AuthTypes, Connector } from "@google-cloud/cloud-sql-connector";
|
|
83
|
-
* import { PgClient } from "@effect/sql-pg";
|
|
84
|
-
* import { Config, Effect, Layer } from "effect"
|
|
85
|
-
*
|
|
86
|
-
* const layer = Effect.gen(function*() {
|
|
87
|
-
* const connector = new Connector();
|
|
88
|
-
* const clientOpts = yield* Effect.promise(() => connector.getOptions({
|
|
89
|
-
* instanceConnectionName: "project:region:instance",
|
|
90
|
-
* authType: AuthTypes.IAM,
|
|
91
|
-
* }));
|
|
92
|
-
* return PgClient.layer({ socket: clientOpts.stream, username: "iam-user" });
|
|
93
|
-
* }).pipe(Layer.unwrapEffect)
|
|
94
|
-
* ```
|
|
95
|
-
*/
|
|
96
|
-
readonly socket?: (() => NodeStream.Duplex) | undefined
|
|
97
|
-
|
|
98
78
|
readonly idleTimeout?: Duration.DurationInput | undefined
|
|
99
79
|
readonly connectTimeout?: Duration.DurationInput | undefined
|
|
100
80
|
|
|
101
81
|
readonly maxConnections?: number | undefined
|
|
82
|
+
readonly minConnections?: number | undefined
|
|
102
83
|
readonly connectionTTL?: Duration.DurationInput | undefined
|
|
103
84
|
|
|
104
85
|
readonly applicationName?: string | undefined
|
|
@@ -107,31 +88,7 @@ export interface PgClientConfig {
|
|
|
107
88
|
readonly transformResultNames?: ((str: string) => string) | undefined
|
|
108
89
|
readonly transformQueryNames?: ((str: string) => string) | undefined
|
|
109
90
|
readonly transformJson?: boolean | undefined
|
|
110
|
-
readonly
|
|
111
|
-
readonly prepare?: boolean | undefined
|
|
112
|
-
/**
|
|
113
|
-
* A callback when postgres has a notice, see
|
|
114
|
-
* [readme](https://github.com/porsager/postgres?tab=readme-ov-file#connection-details).
|
|
115
|
-
* By default, postgres.js logs these with console.log.
|
|
116
|
-
* To silence notices, see the following example:
|
|
117
|
-
* @example
|
|
118
|
-
* ```ts
|
|
119
|
-
* import { PgClient } from "@effect/sql-pg";
|
|
120
|
-
* import { Config, Layer } from "effect"
|
|
121
|
-
*
|
|
122
|
-
* const layer = PgClient.layer({ onnotice: Config.succeed(() => {}) })
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
readonly onnotice?: (notice: postgres.Notice) => void
|
|
126
|
-
readonly types?: Record<string, postgres.PostgresType> | undefined
|
|
127
|
-
|
|
128
|
-
readonly debug?: postgres.Options<{}>["debug"] | undefined
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
type PartialWithUndefined<T> = { [K in keyof T]?: T[K] | undefined }
|
|
132
|
-
|
|
133
|
-
interface PostgresOptions extends postgres.Options<{}> {
|
|
134
|
-
readonly socket?: (() => NodeStream.Duplex) | undefined
|
|
91
|
+
readonly types?: Pg.CustomTypesConfig | undefined
|
|
135
92
|
}
|
|
136
93
|
|
|
137
94
|
/**
|
|
@@ -153,53 +110,39 @@ export const make = (
|
|
|
153
110
|
).array :
|
|
154
111
|
undefined
|
|
155
112
|
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
? Math.round(
|
|
160
|
-
Duration.toMillis(Duration.decode(options.connectionTTL)) / 1000
|
|
161
|
-
)
|
|
162
|
-
: undefined,
|
|
163
|
-
idle_timeout: options.idleTimeout
|
|
164
|
-
? Math.round(
|
|
165
|
-
Duration.toMillis(Duration.decode(options.idleTimeout)) / 1000
|
|
166
|
-
)
|
|
167
|
-
: undefined,
|
|
168
|
-
connect_timeout: options.connectTimeout
|
|
169
|
-
? Math.round(
|
|
170
|
-
Duration.toMillis(Duration.decode(options.connectTimeout)) / 1000
|
|
171
|
-
)
|
|
172
|
-
: undefined,
|
|
173
|
-
|
|
113
|
+
const pool = new Pg.Pool({
|
|
114
|
+
connectionString: options.url ? Redacted.value(options.url) : undefined,
|
|
115
|
+
user: options.username,
|
|
174
116
|
host: options.host,
|
|
175
|
-
port: options.port,
|
|
176
|
-
ssl: options.ssl,
|
|
177
|
-
path: options.path,
|
|
178
117
|
database: options.database,
|
|
179
|
-
username: options.username,
|
|
180
118
|
password: options.password ? Redacted.value(options.password) : undefined,
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
119
|
+
ssl: options.ssl,
|
|
120
|
+
port: options.port,
|
|
121
|
+
connectionTimeoutMillis: options.connectTimeout
|
|
122
|
+
? Duration.toMillis(options.connectTimeout)
|
|
123
|
+
: undefined,
|
|
124
|
+
idleTimeoutMillis: options.idleTimeout
|
|
125
|
+
? Duration.toMillis(options.idleTimeout)
|
|
126
|
+
: undefined,
|
|
127
|
+
max: options.maxConnections,
|
|
128
|
+
min: options.minConnections,
|
|
129
|
+
maxLifetimeSeconds: options.connectionTTL
|
|
130
|
+
? Duration.toSeconds(options.connectionTTL)
|
|
131
|
+
: undefined,
|
|
132
|
+
application_name: options.applicationName ?? "@effect/sql-pg",
|
|
133
|
+
types: options.types
|
|
134
|
+
})
|
|
191
135
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
: postgres(opts as any)
|
|
136
|
+
pool.on("error", (_err) => {
|
|
137
|
+
})
|
|
195
138
|
|
|
196
139
|
yield* Effect.acquireRelease(
|
|
197
140
|
Effect.tryPromise({
|
|
198
|
-
try: () =>
|
|
141
|
+
try: () => pool.query("SELECT 1"),
|
|
199
142
|
catch: (cause) => new SqlError({ cause, message: "PgClient: Failed to connect" })
|
|
200
143
|
}),
|
|
201
144
|
() =>
|
|
202
|
-
Effect.promise(() =>
|
|
145
|
+
Effect.promise(() => pool.end()).pipe(
|
|
203
146
|
Effect.interruptible,
|
|
204
147
|
Effect.timeoutOption(1000)
|
|
205
148
|
)
|
|
@@ -215,15 +158,20 @@ export const make = (
|
|
|
215
158
|
)
|
|
216
159
|
|
|
217
160
|
class ConnectionImpl implements Connection {
|
|
218
|
-
|
|
161
|
+
readonly pg: Pg.Pool | Pg.PoolClient
|
|
162
|
+
constructor(pg: Pg.Pool | Pg.PoolClient) {
|
|
163
|
+
this.pg = pg
|
|
164
|
+
}
|
|
219
165
|
|
|
220
|
-
private run(query:
|
|
166
|
+
private run(query: string, params: ReadonlyArray<Primitive>) {
|
|
221
167
|
return Effect.async<ReadonlyArray<any>, SqlError>((resume) => {
|
|
222
|
-
query
|
|
223
|
-
(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
168
|
+
this.pg.query(query, params as any, (err, result) => {
|
|
169
|
+
if (err) {
|
|
170
|
+
resume(Effect.fail(new SqlError({ cause: err, message: "Failed to execute statement" })))
|
|
171
|
+
} else {
|
|
172
|
+
resume(Effect.succeed(result.rows))
|
|
173
|
+
}
|
|
174
|
+
})
|
|
227
175
|
})
|
|
228
176
|
}
|
|
229
177
|
|
|
@@ -233,17 +181,40 @@ export const make = (
|
|
|
233
181
|
transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined
|
|
234
182
|
) {
|
|
235
183
|
return transformRows
|
|
236
|
-
? Effect.map(this.run(
|
|
237
|
-
: this.run(
|
|
184
|
+
? Effect.map(this.run(sql, params), transformRows)
|
|
185
|
+
: this.run(sql, params)
|
|
238
186
|
}
|
|
239
187
|
executeRaw(sql: string, params: ReadonlyArray<Primitive>) {
|
|
240
|
-
return
|
|
188
|
+
return Effect.async<Pg.Result, SqlError>((resume) => {
|
|
189
|
+
this.pg.query(sql, params as any, (err, result) => {
|
|
190
|
+
if (err) {
|
|
191
|
+
resume(Effect.fail(new SqlError({ cause: err, message: "Failed to execute statement" })))
|
|
192
|
+
} else {
|
|
193
|
+
resume(Effect.succeed(result))
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
})
|
|
241
197
|
}
|
|
242
198
|
executeWithoutTransform(sql: string, params: ReadonlyArray<Primitive>) {
|
|
243
|
-
return this.run(
|
|
199
|
+
return this.run(sql, params)
|
|
244
200
|
}
|
|
245
201
|
executeValues(sql: string, params: ReadonlyArray<Primitive>) {
|
|
246
|
-
return
|
|
202
|
+
return Effect.async<ReadonlyArray<any>, SqlError>((resume) => {
|
|
203
|
+
this.pg.query(
|
|
204
|
+
{
|
|
205
|
+
text: sql,
|
|
206
|
+
rowMode: "array",
|
|
207
|
+
values: params as Array<string>
|
|
208
|
+
},
|
|
209
|
+
(err, result) => {
|
|
210
|
+
if (err) {
|
|
211
|
+
resume(Effect.fail(new SqlError({ cause: err, message: "Failed to execute statement" })))
|
|
212
|
+
} else {
|
|
213
|
+
resume(Effect.succeed(result.rows))
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
})
|
|
247
218
|
}
|
|
248
219
|
executeUnprepared(
|
|
249
220
|
sql: string,
|
|
@@ -257,38 +228,59 @@ export const make = (
|
|
|
257
228
|
params: ReadonlyArray<Primitive>,
|
|
258
229
|
transformRows: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined
|
|
259
230
|
) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
(
|
|
266
|
-
)
|
|
267
|
-
|
|
231
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
232
|
+
const self = this
|
|
233
|
+
return Effect.gen(function*() {
|
|
234
|
+
const cursor = yield* Effect.acquireRelease(
|
|
235
|
+
Effect.sync(() => self.pg.query(new Cursor(sql, params as any))),
|
|
236
|
+
(cursor) => Effect.sync(() => cursor.close())
|
|
237
|
+
)
|
|
238
|
+
const pull = Effect.async<Chunk.Chunk<any>, Option.Option<SqlError>>((resume) => {
|
|
239
|
+
cursor.read(128, (err, rows) => {
|
|
240
|
+
if (err) {
|
|
241
|
+
resume(Effect.fail(Option.some(new SqlError({ cause: err, message: "Failed to execute statement" }))))
|
|
242
|
+
} else if (Arr.isNonEmptyArray(rows)) {
|
|
243
|
+
resume(Effect.succeed(Chunk.unsafeFromArray(transformRows ? transformRows(rows) as any : rows)))
|
|
244
|
+
} else {
|
|
245
|
+
resume(Effect.fail(Option.none()))
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
})
|
|
249
|
+
return Stream.repeatEffectChunkOption(pull)
|
|
250
|
+
}).pipe(
|
|
251
|
+
Stream.unwrapScoped
|
|
268
252
|
)
|
|
269
253
|
}
|
|
270
254
|
}
|
|
271
255
|
|
|
256
|
+
const reserveRaw = Effect.async<Pg.PoolClient, SqlError, Scope.Scope>((resume) => {
|
|
257
|
+
const fiber = Option.getOrThrow(Fiber.getCurrentFiber())
|
|
258
|
+
const scope = Context.unsafeGet(fiber.currentContext, Scope.Scope)
|
|
259
|
+
pool.connect((err, client, release) => {
|
|
260
|
+
if (err) {
|
|
261
|
+
resume(Effect.fail(new SqlError({ cause: err, message: "Failed to acquire connection for transaction" })))
|
|
262
|
+
} else {
|
|
263
|
+
resume(Effect.as(Scope.addFinalizer(scope, Effect.sync(release)), client!))
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
})
|
|
267
|
+
const reserve = Effect.map(reserveRaw, (client) => new ConnectionImpl(client))
|
|
268
|
+
|
|
269
|
+
const listenClient = yield* RcRef.make({
|
|
270
|
+
acquire: reserveRaw
|
|
271
|
+
})
|
|
272
|
+
|
|
272
273
|
return Object.assign(
|
|
273
274
|
yield* Client.make({
|
|
274
|
-
acquirer: Effect.succeed(new ConnectionImpl(
|
|
275
|
-
transactionAcquirer:
|
|
276
|
-
Effect.acquireRelease(
|
|
277
|
-
Effect.tryPromise({
|
|
278
|
-
try: () => client.reserve(),
|
|
279
|
-
catch: (cause) => new SqlError({ cause, message: "Failed to reserve connection" })
|
|
280
|
-
}),
|
|
281
|
-
(pg) => Effect.sync(() => pg.release())
|
|
282
|
-
),
|
|
283
|
-
(_) => new ConnectionImpl(_)
|
|
284
|
-
),
|
|
275
|
+
acquirer: Effect.succeed(new ConnectionImpl(pool)),
|
|
276
|
+
transactionAcquirer: reserve,
|
|
285
277
|
compiler,
|
|
286
278
|
spanAttributes: [
|
|
287
279
|
...(options.spanAttributes ? Object.entries(options.spanAttributes) : []),
|
|
288
280
|
[ATTR_DB_SYSTEM_NAME, "postgresql"],
|
|
289
|
-
[ATTR_DB_NAMESPACE,
|
|
290
|
-
[ATTR_SERVER_ADDRESS,
|
|
291
|
-
[ATTR_SERVER_PORT,
|
|
281
|
+
[ATTR_DB_NAMESPACE, options.database ?? options.username ?? "postgres"],
|
|
282
|
+
[ATTR_SERVER_ADDRESS, options.host ?? "localhost"],
|
|
283
|
+
[ATTR_SERVER_PORT, options.port ?? 5432]
|
|
292
284
|
],
|
|
293
285
|
transformRows
|
|
294
286
|
}),
|
|
@@ -296,28 +288,42 @@ export const make = (
|
|
|
296
288
|
[TypeId]: TypeId as TypeId,
|
|
297
289
|
config: {
|
|
298
290
|
...options,
|
|
299
|
-
host:
|
|
300
|
-
port:
|
|
301
|
-
username:
|
|
302
|
-
password:
|
|
303
|
-
database:
|
|
291
|
+
host: pool.options.host,
|
|
292
|
+
port: pool.options.port,
|
|
293
|
+
username: pool.options.user,
|
|
294
|
+
password: typeof pool.options.password === "string" ? Redacted.make(pool.options.password) : undefined,
|
|
295
|
+
database: pool.options.database
|
|
304
296
|
},
|
|
305
297
|
json: (_: unknown) => PgJson(_),
|
|
306
|
-
array: (_: ReadonlyArray<Primitive>) => PgArray(_),
|
|
307
298
|
listen: (channel: string) =>
|
|
308
|
-
Stream.asyncPush<string, SqlError>((emit)
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
|
|
299
|
+
Stream.asyncPush<string, SqlError>(Effect.fnUntraced(function*(emit) {
|
|
300
|
+
const client = yield* RcRef.get(listenClient)
|
|
301
|
+
function onNotification(msg: Pg.Notification) {
|
|
302
|
+
if (msg.channel === channel && msg.payload) {
|
|
303
|
+
emit.single(msg.payload)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
yield* Effect.addFinalizer(() =>
|
|
307
|
+
Effect.promise(() => {
|
|
308
|
+
client.off("notification", onNotification)
|
|
309
|
+
return client.query(`UNLISTEN ${Pg.escapeIdentifier(channel)}`)
|
|
310
|
+
})
|
|
315
311
|
)
|
|
316
|
-
|
|
312
|
+
yield* Effect.tryPromise({
|
|
313
|
+
try: () => client.query(`LISTEN ${Pg.escapeIdentifier(channel)}`),
|
|
314
|
+
catch: (cause) => new SqlError({ cause, message: "Failed to listen" })
|
|
315
|
+
})
|
|
316
|
+
client.on("notification", onNotification)
|
|
317
|
+
})),
|
|
317
318
|
notify: (channel: string, payload: string) =>
|
|
318
|
-
Effect.
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
Effect.async<void, SqlError>((resume) => {
|
|
320
|
+
pool.query(`NOTIFY ${Pg.escapeIdentifier(channel)}, $1`, [payload], (err) => {
|
|
321
|
+
if (err) {
|
|
322
|
+
resume(Effect.fail(new SqlError({ cause: err, message: "Failed to notify" })))
|
|
323
|
+
} else {
|
|
324
|
+
resume(Effect.void)
|
|
325
|
+
}
|
|
326
|
+
})
|
|
321
327
|
})
|
|
322
328
|
}
|
|
323
329
|
)
|
|
@@ -329,7 +335,7 @@ export const make = (
|
|
|
329
335
|
*/
|
|
330
336
|
export const layerConfig = (
|
|
331
337
|
config: Config.Config.Wrap<PgClientConfig>
|
|
332
|
-
): Layer.Layer<PgClient | Client.SqlClient, ConfigError | SqlError> =>
|
|
338
|
+
): Layer.Layer<PgClient | Client.SqlClient, ConfigError.ConfigError | SqlError> =>
|
|
333
339
|
Layer.scopedContext(
|
|
334
340
|
Config.unwrap(config).pipe(
|
|
335
341
|
Effect.flatMap(make),
|
|
@@ -347,7 +353,7 @@ export const layerConfig = (
|
|
|
347
353
|
*/
|
|
348
354
|
export const layer = (
|
|
349
355
|
config: PgClientConfig
|
|
350
|
-
): Layer.Layer<PgClient | Client.SqlClient,
|
|
356
|
+
): Layer.Layer<PgClient | Client.SqlClient, SqlError> =>
|
|
351
357
|
Layer.scopedContext(
|
|
352
358
|
Effect.map(make(config), (client) =>
|
|
353
359
|
Context.make(PgClient, client).pipe(
|
|
@@ -363,8 +369,6 @@ export const makeCompiler = (
|
|
|
363
369
|
transform?: (_: string) => string,
|
|
364
370
|
transformJson = true
|
|
365
371
|
): Statement.Compiler => {
|
|
366
|
-
const pg = postgres({ max: 0 })
|
|
367
|
-
|
|
368
372
|
const transformValue = transformJson && transform
|
|
369
373
|
? Statement.defaultTransforms(transform).value
|
|
370
374
|
: undefined
|
|
@@ -393,33 +397,12 @@ export const makeCompiler = (
|
|
|
393
397
|
return [
|
|
394
398
|
placeholder(undefined),
|
|
395
399
|
[
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
: transformValue(type.i0)
|
|
400
|
-
) as any
|
|
400
|
+
withoutTransform || transformValue === undefined
|
|
401
|
+
? type.i0
|
|
402
|
+
: transformValue(type.i0)
|
|
401
403
|
]
|
|
402
404
|
]
|
|
403
405
|
}
|
|
404
|
-
case "PgArray": {
|
|
405
|
-
const param = pg.array(type.i0 as any) as any
|
|
406
|
-
const first = type.i0[0]
|
|
407
|
-
switch (typeof first) {
|
|
408
|
-
case "boolean": {
|
|
409
|
-
param.type = 1000
|
|
410
|
-
break
|
|
411
|
-
}
|
|
412
|
-
case "number": {
|
|
413
|
-
param.type = 1022
|
|
414
|
-
break
|
|
415
|
-
}
|
|
416
|
-
default: {
|
|
417
|
-
param.type = 1009
|
|
418
|
-
break
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
return [placeholder(undefined), [param]]
|
|
422
|
-
}
|
|
423
406
|
}
|
|
424
407
|
}
|
|
425
408
|
})
|
|
@@ -431,7 +414,7 @@ const escape = Statement.defaultEscape("\"")
|
|
|
431
414
|
* @category custom types
|
|
432
415
|
* @since 1.0.0
|
|
433
416
|
*/
|
|
434
|
-
export type PgCustom = PgJson
|
|
417
|
+
export type PgCustom = PgJson
|
|
435
418
|
|
|
436
419
|
/**
|
|
437
420
|
* @category custom types
|
|
@@ -443,14 +426,3 @@ interface PgJson extends Custom<"PgJson", unknown> {}
|
|
|
443
426
|
* @since 1.0.0
|
|
444
427
|
*/
|
|
445
428
|
const PgJson = Statement.custom<PgJson>("PgJson")
|
|
446
|
-
|
|
447
|
-
/**
|
|
448
|
-
* @category custom types
|
|
449
|
-
* @since 1.0.0
|
|
450
|
-
*/
|
|
451
|
-
interface PgArray extends Custom<"PgArray", ReadonlyArray<Primitive>> {}
|
|
452
|
-
/**
|
|
453
|
-
* @category custom types
|
|
454
|
-
* @since 1.0.0
|
|
455
|
-
*/
|
|
456
|
-
const PgArray = Statement.custom<PgArray>("PgArray")
|