@effect/sql-pg 0.0.0-snapshot-189d4cae80e186661241002ad9d729628096520f
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/Client/package.json +6 -0
- package/LICENSE +21 -0
- package/Migrator/package.json +6 -0
- package/README.md +5 -0
- package/dist/cjs/Client.js +196 -0
- package/dist/cjs/Client.js.map +1 -0
- package/dist/cjs/Migrator.js +125 -0
- package/dist/cjs/Migrator.js.map +1 -0
- package/dist/cjs/index.js +44 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/dts/Client.d.ts +96 -0
- package/dist/dts/Client.d.ts.map +1 -0
- package/dist/dts/Migrator.d.ts +23 -0
- package/dist/dts/Migrator.d.ts.map +1 -0
- package/dist/dts/index.d.ts +28 -0
- package/dist/dts/index.d.ts.map +1 -0
- package/dist/esm/Client.js +156 -0
- package/dist/esm/Client.js.map +1 -0
- package/dist/esm/Migrator.js +77 -0
- package/dist/esm/Migrator.js.map +1 -0
- package/dist/esm/index.js +28 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +4 -0
- package/package.json +51 -0
- package/src/Client.ts +290 -0
- package/src/Migrator.ts +113 -0
- package/src/index.ts +33 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Client from "@effect/sql/Client";
|
|
5
|
+
import { SqlError } from "@effect/sql/Error";
|
|
6
|
+
import * as Statement from "@effect/sql/Statement";
|
|
7
|
+
import * as Chunk from "effect/Chunk";
|
|
8
|
+
import * as Config from "effect/Config";
|
|
9
|
+
import * as Context from "effect/Context";
|
|
10
|
+
import * as Duration from "effect/Duration";
|
|
11
|
+
import * as Effect from "effect/Effect";
|
|
12
|
+
import * as Layer from "effect/Layer";
|
|
13
|
+
import * as Secret from "effect/Secret";
|
|
14
|
+
import * as Stream from "effect/Stream";
|
|
15
|
+
import postgres from "postgres";
|
|
16
|
+
/**
|
|
17
|
+
* @category tags
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
*/
|
|
20
|
+
export const PgClient = /*#__PURE__*/Context.GenericTag("@effect/sql-pg/PgClient");
|
|
21
|
+
const escape = /*#__PURE__*/Statement.defaultEscape("\"");
|
|
22
|
+
/**
|
|
23
|
+
* @category constructors
|
|
24
|
+
* @since 1.0.0
|
|
25
|
+
*/
|
|
26
|
+
export const make = options => Effect.gen(function* (_) {
|
|
27
|
+
const compiler = makeCompiler(options.transformQueryNames, options.transformJson);
|
|
28
|
+
const transformRows = Client.defaultTransforms(options.transformResultNames, options.transformJson).array;
|
|
29
|
+
const opts = {
|
|
30
|
+
max: options.maxConnections ?? 10,
|
|
31
|
+
max_lifetime: options.connectionTTL ? Math.round(Duration.toMillis(Duration.decode(options.connectionTTL)) / 1000) : undefined,
|
|
32
|
+
idle_timeout: options.idleTimeout ? Math.round(Duration.toMillis(Duration.decode(options.idleTimeout)) / 1000) : undefined,
|
|
33
|
+
connect_timeout: options.connectTimeout ? Math.round(Duration.toMillis(Duration.decode(options.connectTimeout)) / 1000) : undefined,
|
|
34
|
+
host: options.host,
|
|
35
|
+
port: options.port,
|
|
36
|
+
ssl: options.ssl,
|
|
37
|
+
path: options.path,
|
|
38
|
+
database: options.database,
|
|
39
|
+
username: options.username,
|
|
40
|
+
password: options.password ? Secret.value(options.password) : undefined,
|
|
41
|
+
fetch_types: options.fetchTypes ?? true,
|
|
42
|
+
debug: options.debug
|
|
43
|
+
};
|
|
44
|
+
const client = options.url ? postgres(Secret.value(options.url), opts) : postgres(opts);
|
|
45
|
+
yield* _(Effect.addFinalizer(() => Effect.promise(() => client.end())));
|
|
46
|
+
class ConnectionImpl {
|
|
47
|
+
pg;
|
|
48
|
+
constructor(pg) {
|
|
49
|
+
this.pg = pg;
|
|
50
|
+
}
|
|
51
|
+
run(query) {
|
|
52
|
+
return Effect.async(resume => {
|
|
53
|
+
query.then(_ => resume(Effect.succeed(_)), error => resume(new SqlError({
|
|
54
|
+
error
|
|
55
|
+
})));
|
|
56
|
+
return Effect.sync(() => query.cancel());
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
runTransform(query) {
|
|
60
|
+
return options.transformResultNames ? Effect.map(this.run(query), transformRows) : this.run(query);
|
|
61
|
+
}
|
|
62
|
+
execute(sql, params) {
|
|
63
|
+
return this.runTransform(this.pg.unsafe(sql, params));
|
|
64
|
+
}
|
|
65
|
+
executeWithoutTransform(sql, params) {
|
|
66
|
+
return this.run(this.pg.unsafe(sql, params));
|
|
67
|
+
}
|
|
68
|
+
executeValues(sql, params) {
|
|
69
|
+
return this.run(this.pg.unsafe(sql, params).values());
|
|
70
|
+
}
|
|
71
|
+
executeRaw(sql, params) {
|
|
72
|
+
return this.runTransform(this.pg.unsafe(sql, params));
|
|
73
|
+
}
|
|
74
|
+
executeStream(sql, params) {
|
|
75
|
+
return Stream.mapChunks(Stream.fromAsyncIterable(this.pg.unsafe(sql, params).cursor(16), error => new SqlError({
|
|
76
|
+
error
|
|
77
|
+
})), Chunk.flatMap(rows => Chunk.unsafeFromArray(options.transformResultNames ? transformRows(rows) : rows)));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return Object.assign(Client.make({
|
|
81
|
+
acquirer: Effect.succeed(new ConnectionImpl(client)),
|
|
82
|
+
transactionAcquirer: Effect.map(Effect.acquireRelease(Effect.tryPromise({
|
|
83
|
+
try: () => client.reserve(),
|
|
84
|
+
catch: error => new SqlError({
|
|
85
|
+
error
|
|
86
|
+
})
|
|
87
|
+
}), pg => Effect.sync(() => pg.release())), _ => new ConnectionImpl(_)),
|
|
88
|
+
compiler
|
|
89
|
+
}), {
|
|
90
|
+
config: options,
|
|
91
|
+
json: _ => PgJson(_),
|
|
92
|
+
array: _ => PgArray(_)
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* @category constructor
|
|
97
|
+
* @since 1.0.0
|
|
98
|
+
*/
|
|
99
|
+
export const layer = config => Layer.scoped(PgClient, Effect.flatMap(Config.unwrap(config), make));
|
|
100
|
+
/**
|
|
101
|
+
* @category constructor
|
|
102
|
+
* @since 1.0.0
|
|
103
|
+
*/
|
|
104
|
+
export const makeCompiler = (transform, transformJson = true) => {
|
|
105
|
+
const pg = postgres({
|
|
106
|
+
max: 0
|
|
107
|
+
});
|
|
108
|
+
const transformValue = transformJson && transform ? Client.defaultTransforms(transform).value : undefined;
|
|
109
|
+
return Statement.makeCompiler({
|
|
110
|
+
placeholder: _ => `$${_}`,
|
|
111
|
+
onIdentifier: transform ? _ => escape(transform(_)) : escape,
|
|
112
|
+
onRecordUpdate: (placeholders, valueAlias, valueColumns, values) => [`(values ${placeholders}) AS ${valueAlias}${valueColumns}`, values.flat()],
|
|
113
|
+
onCustom: (type, placeholder) => {
|
|
114
|
+
switch (type.kind) {
|
|
115
|
+
case "PgJson":
|
|
116
|
+
{
|
|
117
|
+
return [placeholder(), [pg.json(transformValue !== undefined ? transformValue(type.i0) : type.i0)]];
|
|
118
|
+
}
|
|
119
|
+
case "PgArray":
|
|
120
|
+
{
|
|
121
|
+
const param = pg.array(type.i0);
|
|
122
|
+
const first = type.i0[0];
|
|
123
|
+
switch (typeof first) {
|
|
124
|
+
case "boolean":
|
|
125
|
+
{
|
|
126
|
+
param.type = 1000;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
case "number":
|
|
130
|
+
{
|
|
131
|
+
param.type = 1022;
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
default:
|
|
135
|
+
{
|
|
136
|
+
param.type = 1009;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return [placeholder(), [param]];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* @category custom types
|
|
148
|
+
* @since 1.0.0
|
|
149
|
+
*/
|
|
150
|
+
const PgJson = /*#__PURE__*/Statement.custom("PgJson");
|
|
151
|
+
/**
|
|
152
|
+
* @category custom types
|
|
153
|
+
* @since 1.0.0
|
|
154
|
+
*/
|
|
155
|
+
const PgArray = /*#__PURE__*/Statement.custom("PgArray");
|
|
156
|
+
//# sourceMappingURL=Client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Client.js","names":["Client","SqlError","Statement","Chunk","Config","Context","Duration","Effect","Layer","Secret","Stream","postgres","PgClient","GenericTag","escape","defaultEscape","make","options","gen","_","compiler","makeCompiler","transformQueryNames","transformJson","transformRows","defaultTransforms","transformResultNames","array","opts","max","maxConnections","max_lifetime","connectionTTL","Math","round","toMillis","decode","undefined","idle_timeout","idleTimeout","connect_timeout","connectTimeout","host","port","ssl","path","database","username","password","value","fetch_types","fetchTypes","debug","client","url","addFinalizer","promise","end","ConnectionImpl","pg","constructor","run","query","async","resume","then","succeed","error","sync","cancel","runTransform","map","execute","sql","params","unsafe","executeWithoutTransform","executeValues","values","executeRaw","executeStream","mapChunks","fromAsyncIterable","cursor","flatMap","rows","unsafeFromArray","Object","assign","acquirer","transactionAcquirer","acquireRelease","tryPromise","try","reserve","catch","release","config","json","PgJson","PgArray","layer","scoped","unwrap","transform","transformValue","placeholder","onIdentifier","onRecordUpdate","placeholders","valueAlias","valueColumns","flat","onCustom","type","kind","i0","param","first","custom"],"sources":["../../src/Client.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Command from "@effect/platform/Command";
|
|
5
|
+
import { FileSystem } from "@effect/platform/FileSystem";
|
|
6
|
+
import { Path } from "@effect/platform/Path";
|
|
7
|
+
import * as Migrator from "@effect/sql/Migrator";
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as Layer from "effect/Layer";
|
|
10
|
+
import * as Secret from "effect/Secret";
|
|
11
|
+
import * as Client from "./Client.js";
|
|
12
|
+
/**
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
*/
|
|
15
|
+
export * from "@effect/sql/Migrator";
|
|
16
|
+
/**
|
|
17
|
+
* @category constructor
|
|
18
|
+
* @since 1.0.0
|
|
19
|
+
*/
|
|
20
|
+
export const run = /*#__PURE__*/Migrator.make({
|
|
21
|
+
getClient: Client.PgClient,
|
|
22
|
+
ensureTable(sql, table) {
|
|
23
|
+
return Effect.catchAll(sql`select ${table}::regclass`, () => sql`
|
|
24
|
+
CREATE TABLE ${sql(table)} (
|
|
25
|
+
migration_id integer primary key,
|
|
26
|
+
created_at timestamp with time zone not null default now(),
|
|
27
|
+
name text not null
|
|
28
|
+
)
|
|
29
|
+
`);
|
|
30
|
+
},
|
|
31
|
+
lockTable(sql, table) {
|
|
32
|
+
return sql`
|
|
33
|
+
LOCK TABLE ${sql(table)} IN ACCESS EXCLUSIVE MODE
|
|
34
|
+
`;
|
|
35
|
+
},
|
|
36
|
+
dumpSchema(sql, path, table) {
|
|
37
|
+
const pgDump = args => Effect.gen(function* (_) {
|
|
38
|
+
const dump = yield* _(Command.make("pg_dump", ...args, "--no-owner", "--no-privileges"), Command.env({
|
|
39
|
+
PATH: globalThis.process?.env.PATH,
|
|
40
|
+
PGHOST: sql.config.host,
|
|
41
|
+
PGPORT: sql.config.port?.toString(),
|
|
42
|
+
PGUSER: sql.config.username,
|
|
43
|
+
PGPASSWORD: sql.config.password ? Secret.value(sql.config.password) : undefined,
|
|
44
|
+
PGDATABASE: sql.config.database,
|
|
45
|
+
PGSSLMODE: sql.config.ssl ? "require" : "prefer"
|
|
46
|
+
}), Command.string);
|
|
47
|
+
return dump.replace(/^--.*$/gm, "").replace(/^SET .*$/gm, "").replace(/^SELECT pg_catalog\..*$/gm, "").replace(/\n{2,}/gm, "\n\n").trim();
|
|
48
|
+
}).pipe(Effect.mapError(error => new Migrator.MigrationError({
|
|
49
|
+
reason: "failed",
|
|
50
|
+
message: error.message
|
|
51
|
+
})));
|
|
52
|
+
const pgDumpSchema = pgDump(["--schema-only"]);
|
|
53
|
+
const pgDumpMigrations = pgDump(["--column-inserts", "--data-only", `--table=${table}`]);
|
|
54
|
+
const pgDumpAll = Effect.map(Effect.all([pgDumpSchema, pgDumpMigrations], {
|
|
55
|
+
concurrency: 2
|
|
56
|
+
}), ([schema, migrations]) => schema + "\n\n" + migrations);
|
|
57
|
+
const pgDumpFile = path => Effect.gen(function* (_) {
|
|
58
|
+
const fs = yield* _(FileSystem);
|
|
59
|
+
const path_ = yield* _(Path);
|
|
60
|
+
const dump = yield* _(pgDumpAll);
|
|
61
|
+
yield* _(fs.makeDirectory(path_.dirname(path), {
|
|
62
|
+
recursive: true
|
|
63
|
+
}));
|
|
64
|
+
yield* _(fs.writeFileString(path, dump));
|
|
65
|
+
}).pipe(Effect.mapError(error => new Migrator.MigrationError({
|
|
66
|
+
reason: "failed",
|
|
67
|
+
message: error.message
|
|
68
|
+
})));
|
|
69
|
+
return pgDumpFile(path);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
/**
|
|
73
|
+
* @category layers
|
|
74
|
+
* @since 1.0.0
|
|
75
|
+
*/
|
|
76
|
+
export const layer = options => Layer.effectDiscard(run(options));
|
|
77
|
+
//# sourceMappingURL=Migrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Migrator.js","names":["Command","FileSystem","Path","Migrator","Effect","Layer","Secret","Client","run","make","getClient","PgClient","ensureTable","sql","table","catchAll","lockTable","dumpSchema","path","pgDump","args","gen","_","dump","env","PATH","globalThis","process","PGHOST","config","host","PGPORT","port","toString","PGUSER","username","PGPASSWORD","password","value","undefined","PGDATABASE","database","PGSSLMODE","ssl","string","replace","trim","pipe","mapError","error","MigrationError","reason","message","pgDumpSchema","pgDumpMigrations","pgDumpAll","map","all","concurrency","schema","migrations","pgDumpFile","fs","path_","makeDirectory","dirname","recursive","writeFileString","layer","options","effectDiscard"],"sources":["../../src/Migrator.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* @since 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
export * as client from "./Client.js";
|
|
8
|
+
/**
|
|
9
|
+
* @since 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
export * as error from "@effect/sql/Error";
|
|
12
|
+
/**
|
|
13
|
+
* @since 1.0.0
|
|
14
|
+
*/
|
|
15
|
+
export * as migrator from "./Migrator.js";
|
|
16
|
+
/**
|
|
17
|
+
* @since 1.0.0
|
|
18
|
+
*/
|
|
19
|
+
export * as resolver from "@effect/sql/Resolver";
|
|
20
|
+
/**
|
|
21
|
+
* @since 1.0.0
|
|
22
|
+
*/
|
|
23
|
+
export * as schema from "@effect/sql/Schema";
|
|
24
|
+
/**
|
|
25
|
+
* @since 1.0.0
|
|
26
|
+
*/
|
|
27
|
+
export * as statement from "@effect/sql/Statement";
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["client","error","migrator","resolver","schema","statement"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":"AAAA;;;AAIA;;;AAGA,OAAO,KAAKA,MAAM,MAAM,aAAa;AAErC;;;AAGA,OAAO,KAAKC,KAAK,MAAM,mBAAmB;AAE1C;;;AAGA,OAAO,KAAKC,QAAQ,MAAM,eAAe;AAEzC;;;AAGA,OAAO,KAAKC,QAAQ,MAAM,sBAAsB;AAEhD;;;AAGA,OAAO,KAAKC,MAAM,MAAM,oBAAoB;AAE5C;;;AAGA,OAAO,KAAKC,SAAS,MAAM,uBAAuB","ignoreList":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@effect/sql-pg",
|
|
3
|
+
"version": "0.0.0-snapshot-189d4cae80e186661241002ad9d729628096520f",
|
|
4
|
+
"description": "A Postgresql toolkit for Effect",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/effect-ts/effect.git",
|
|
9
|
+
"directory": "packages/sql-pg"
|
|
10
|
+
},
|
|
11
|
+
"sideEffects": [],
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"postgres": "^3.4.4"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@effect/platform": "^0.0.0-snapshot-189d4cae80e186661241002ad9d729628096520f",
|
|
17
|
+
"@effect/sql": "^0.0.0-snapshot-189d4cae80e186661241002ad9d729628096520f",
|
|
18
|
+
"effect": "^0.0.0-snapshot-189d4cae80e186661241002ad9d729628096520f"
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/cjs/index.js",
|
|
21
|
+
"module": "./dist/esm/index.js",
|
|
22
|
+
"types": "./dist/dts/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
"./package.json": "./package.json",
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/dts/index.d.ts",
|
|
27
|
+
"import": "./dist/esm/index.js",
|
|
28
|
+
"default": "./dist/cjs/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./Client": {
|
|
31
|
+
"types": "./dist/dts/Client.d.ts",
|
|
32
|
+
"import": "./dist/esm/Client.js",
|
|
33
|
+
"default": "./dist/cjs/Client.js"
|
|
34
|
+
},
|
|
35
|
+
"./Migrator": {
|
|
36
|
+
"types": "./dist/dts/Migrator.d.ts",
|
|
37
|
+
"import": "./dist/esm/Migrator.js",
|
|
38
|
+
"default": "./dist/cjs/Migrator.js"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"typesVersions": {
|
|
42
|
+
"*": {
|
|
43
|
+
"Client": [
|
|
44
|
+
"./dist/dts/Client.d.ts"
|
|
45
|
+
],
|
|
46
|
+
"Migrator": [
|
|
47
|
+
"./dist/dts/Migrator.d.ts"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/Client.ts
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Client from "@effect/sql/Client"
|
|
5
|
+
import type { Connection } from "@effect/sql/Connection"
|
|
6
|
+
import { SqlError } from "@effect/sql/Error"
|
|
7
|
+
import type { Custom, Fragment, Primitive } from "@effect/sql/Statement"
|
|
8
|
+
import * as Statement from "@effect/sql/Statement"
|
|
9
|
+
import * as Chunk from "effect/Chunk"
|
|
10
|
+
import * as Config from "effect/Config"
|
|
11
|
+
import type { ConfigError } from "effect/ConfigError"
|
|
12
|
+
import * as Context from "effect/Context"
|
|
13
|
+
import * as Duration from "effect/Duration"
|
|
14
|
+
import * as Effect from "effect/Effect"
|
|
15
|
+
import * as Layer from "effect/Layer"
|
|
16
|
+
import type { Scope } from "effect/Scope"
|
|
17
|
+
import * as Secret from "effect/Secret"
|
|
18
|
+
import * as Stream from "effect/Stream"
|
|
19
|
+
import type { PendingQuery, PendingValuesQuery } from "postgres"
|
|
20
|
+
import postgres from "postgres"
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @category models
|
|
24
|
+
* @since 1.0.0
|
|
25
|
+
*/
|
|
26
|
+
export interface PgClient extends Client.Client {
|
|
27
|
+
readonly config: PgClientConfig
|
|
28
|
+
readonly json: (_: unknown) => Fragment
|
|
29
|
+
readonly array: (_: ReadonlyArray<Primitive>) => Fragment
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @category tags
|
|
34
|
+
* @since 1.0.0
|
|
35
|
+
*/
|
|
36
|
+
export const PgClient: Context.Tag<PgClient, PgClient> = Context.GenericTag<PgClient>("@effect/sql-pg/PgClient")
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @category constructors
|
|
40
|
+
* @since 1.0.0
|
|
41
|
+
*/
|
|
42
|
+
export interface PgClientConfig {
|
|
43
|
+
readonly url?: Secret.Secret | undefined
|
|
44
|
+
|
|
45
|
+
readonly host?: string | undefined
|
|
46
|
+
readonly port?: number | undefined
|
|
47
|
+
readonly path?: string | undefined
|
|
48
|
+
readonly ssl?: boolean | undefined
|
|
49
|
+
readonly database?: string | undefined
|
|
50
|
+
readonly username?: string | undefined
|
|
51
|
+
readonly password?: Secret.Secret | undefined
|
|
52
|
+
|
|
53
|
+
readonly idleTimeout?: Duration.DurationInput | undefined
|
|
54
|
+
readonly connectTimeout?: Duration.DurationInput | undefined
|
|
55
|
+
|
|
56
|
+
readonly maxConnections?: number | undefined
|
|
57
|
+
readonly connectionTTL?: Duration.DurationInput | undefined
|
|
58
|
+
|
|
59
|
+
readonly transformResultNames?: ((str: string) => string) | undefined
|
|
60
|
+
readonly transformQueryNames?: ((str: string) => string) | undefined
|
|
61
|
+
readonly transformJson?: boolean | undefined
|
|
62
|
+
readonly fetchTypes?: boolean | undefined
|
|
63
|
+
|
|
64
|
+
readonly debug?: postgres.Options<{}>["debug"] | undefined
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const escape = Statement.defaultEscape("\"")
|
|
68
|
+
|
|
69
|
+
type PartialWithUndefined<T> = { [K in keyof T]?: T[K] | undefined }
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* @category constructors
|
|
73
|
+
* @since 1.0.0
|
|
74
|
+
*/
|
|
75
|
+
export const make = (
|
|
76
|
+
options: PgClientConfig
|
|
77
|
+
): Effect.Effect<PgClient, never, Scope> =>
|
|
78
|
+
Effect.gen(function*(_) {
|
|
79
|
+
const compiler = makeCompiler(
|
|
80
|
+
options.transformQueryNames,
|
|
81
|
+
options.transformJson
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
const transformRows = Client.defaultTransforms(
|
|
85
|
+
options.transformResultNames!,
|
|
86
|
+
options.transformJson
|
|
87
|
+
).array
|
|
88
|
+
|
|
89
|
+
const opts: PartialWithUndefined<postgres.Options<{}>> = {
|
|
90
|
+
max: options.maxConnections ?? 10,
|
|
91
|
+
max_lifetime: options.connectionTTL
|
|
92
|
+
? Math.round(
|
|
93
|
+
Duration.toMillis(Duration.decode(options.connectionTTL)) / 1000
|
|
94
|
+
)
|
|
95
|
+
: undefined,
|
|
96
|
+
idle_timeout: options.idleTimeout
|
|
97
|
+
? Math.round(
|
|
98
|
+
Duration.toMillis(Duration.decode(options.idleTimeout)) / 1000
|
|
99
|
+
)
|
|
100
|
+
: undefined,
|
|
101
|
+
connect_timeout: options.connectTimeout
|
|
102
|
+
? Math.round(
|
|
103
|
+
Duration.toMillis(Duration.decode(options.connectTimeout)) / 1000
|
|
104
|
+
)
|
|
105
|
+
: undefined,
|
|
106
|
+
|
|
107
|
+
host: options.host,
|
|
108
|
+
port: options.port,
|
|
109
|
+
ssl: options.ssl,
|
|
110
|
+
path: options.path,
|
|
111
|
+
database: options.database,
|
|
112
|
+
username: options.username,
|
|
113
|
+
password: options.password ? Secret.value(options.password) : undefined,
|
|
114
|
+
fetch_types: options.fetchTypes ?? true,
|
|
115
|
+
debug: options.debug
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const client = options.url
|
|
119
|
+
? postgres(Secret.value(options.url), opts as any)
|
|
120
|
+
: postgres(opts as any)
|
|
121
|
+
|
|
122
|
+
yield* _(Effect.addFinalizer(() => Effect.promise(() => client.end())))
|
|
123
|
+
|
|
124
|
+
class ConnectionImpl implements Connection {
|
|
125
|
+
constructor(private readonly pg: postgres.Sql<{}>) {}
|
|
126
|
+
|
|
127
|
+
private run(query: PendingQuery<any> | PendingValuesQuery<any>) {
|
|
128
|
+
return Effect.async<ReadonlyArray<any>, SqlError>((resume) => {
|
|
129
|
+
query.then(
|
|
130
|
+
(_) => resume(Effect.succeed(_)),
|
|
131
|
+
(error) => resume(new SqlError({ error }))
|
|
132
|
+
)
|
|
133
|
+
return Effect.sync(() => query.cancel())
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private runTransform(query: PendingQuery<any>) {
|
|
138
|
+
return options.transformResultNames
|
|
139
|
+
? Effect.map(this.run(query), transformRows)
|
|
140
|
+
: this.run(query)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
execute(sql: string, params: ReadonlyArray<Primitive>) {
|
|
144
|
+
return this.runTransform(this.pg.unsafe(sql, params as any))
|
|
145
|
+
}
|
|
146
|
+
executeWithoutTransform(sql: string, params: ReadonlyArray<Primitive>) {
|
|
147
|
+
return this.run(this.pg.unsafe(sql, params as any))
|
|
148
|
+
}
|
|
149
|
+
executeValues(sql: string, params: ReadonlyArray<Primitive>) {
|
|
150
|
+
return this.run(this.pg.unsafe(sql, params as any).values())
|
|
151
|
+
}
|
|
152
|
+
executeRaw(sql: string, params?: ReadonlyArray<Primitive>) {
|
|
153
|
+
return this.runTransform(this.pg.unsafe(sql, params as any))
|
|
154
|
+
}
|
|
155
|
+
executeStream(sql: string, params: ReadonlyArray<Primitive>) {
|
|
156
|
+
return Stream.mapChunks(
|
|
157
|
+
Stream.fromAsyncIterable(
|
|
158
|
+
this.pg.unsafe(sql, params as any).cursor(16) as AsyncIterable<
|
|
159
|
+
Array<any>
|
|
160
|
+
>,
|
|
161
|
+
(error) => new SqlError({ error })
|
|
162
|
+
),
|
|
163
|
+
Chunk.flatMap((rows) =>
|
|
164
|
+
Chunk.unsafeFromArray(
|
|
165
|
+
options.transformResultNames ? transformRows(rows) : rows
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return Object.assign(
|
|
173
|
+
Client.make({
|
|
174
|
+
acquirer: Effect.succeed(new ConnectionImpl(client)),
|
|
175
|
+
transactionAcquirer: Effect.map(
|
|
176
|
+
Effect.acquireRelease(
|
|
177
|
+
Effect.tryPromise({
|
|
178
|
+
try: () => client.reserve(),
|
|
179
|
+
catch: (error) => new SqlError({ error })
|
|
180
|
+
}),
|
|
181
|
+
(pg) => Effect.sync(() => pg.release())
|
|
182
|
+
),
|
|
183
|
+
(_) => new ConnectionImpl(_)
|
|
184
|
+
),
|
|
185
|
+
compiler
|
|
186
|
+
}),
|
|
187
|
+
{
|
|
188
|
+
config: options,
|
|
189
|
+
json: (_: unknown) => PgJson(_),
|
|
190
|
+
array: (_: ReadonlyArray<Primitive>) => PgArray(_)
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* @category constructor
|
|
197
|
+
* @since 1.0.0
|
|
198
|
+
*/
|
|
199
|
+
export const layer: (
|
|
200
|
+
config: Config.Config.Wrap<PgClientConfig>
|
|
201
|
+
) => Layer.Layer<PgClient, ConfigError> = (
|
|
202
|
+
config: Config.Config.Wrap<PgClientConfig>
|
|
203
|
+
) => Layer.scoped(PgClient, Effect.flatMap(Config.unwrap(config), make))
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @category constructor
|
|
207
|
+
* @since 1.0.0
|
|
208
|
+
*/
|
|
209
|
+
export const makeCompiler = (
|
|
210
|
+
transform?: (_: string) => string,
|
|
211
|
+
transformJson = true
|
|
212
|
+
): Statement.Compiler => {
|
|
213
|
+
const pg = postgres({ max: 0 })
|
|
214
|
+
|
|
215
|
+
const transformValue = transformJson && transform
|
|
216
|
+
? Client.defaultTransforms(transform).value
|
|
217
|
+
: undefined
|
|
218
|
+
|
|
219
|
+
return Statement.makeCompiler<PgCustom>({
|
|
220
|
+
placeholder: (_) => `$${_}`,
|
|
221
|
+
onIdentifier: transform ? (_) => escape(transform(_)) : escape,
|
|
222
|
+
onRecordUpdate: (placeholders, valueAlias, valueColumns, values) => [
|
|
223
|
+
`(values ${placeholders}) AS ${valueAlias}${valueColumns}`,
|
|
224
|
+
values.flat()
|
|
225
|
+
],
|
|
226
|
+
onCustom: (type, placeholder) => {
|
|
227
|
+
switch (type.kind) {
|
|
228
|
+
case "PgJson": {
|
|
229
|
+
return [
|
|
230
|
+
placeholder(),
|
|
231
|
+
[
|
|
232
|
+
pg.json(
|
|
233
|
+
transformValue !== undefined
|
|
234
|
+
? transformValue(type.i0)
|
|
235
|
+
: type.i0
|
|
236
|
+
) as any
|
|
237
|
+
]
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
case "PgArray": {
|
|
241
|
+
const param = pg.array(type.i0 as any) as any
|
|
242
|
+
const first = type.i0[0]
|
|
243
|
+
switch (typeof first) {
|
|
244
|
+
case "boolean": {
|
|
245
|
+
param.type = 1000
|
|
246
|
+
break
|
|
247
|
+
}
|
|
248
|
+
case "number": {
|
|
249
|
+
param.type = 1022
|
|
250
|
+
break
|
|
251
|
+
}
|
|
252
|
+
default: {
|
|
253
|
+
param.type = 1009
|
|
254
|
+
break
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return [placeholder(), [param]]
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* @category custom types
|
|
266
|
+
* @since 1.0.0
|
|
267
|
+
*/
|
|
268
|
+
export type PgCustom = PgJson | PgArray
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* @category custom types
|
|
272
|
+
* @since 1.0.0
|
|
273
|
+
*/
|
|
274
|
+
interface PgJson extends Custom<"PgJson", unknown> {}
|
|
275
|
+
/**
|
|
276
|
+
* @category custom types
|
|
277
|
+
* @since 1.0.0
|
|
278
|
+
*/
|
|
279
|
+
const PgJson = Statement.custom<PgJson>("PgJson")
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @category custom types
|
|
283
|
+
* @since 1.0.0
|
|
284
|
+
*/
|
|
285
|
+
interface PgArray extends Custom<"PgArray", ReadonlyArray<Primitive>> {}
|
|
286
|
+
/**
|
|
287
|
+
* @category custom types
|
|
288
|
+
* @since 1.0.0
|
|
289
|
+
*/
|
|
290
|
+
const PgArray = Statement.custom<PgArray>("PgArray")
|