@effect/sql-pg 4.0.0-beta.7 → 4.0.0-beta.70

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/src/PgMigrator.ts CHANGED
@@ -1,94 +1,132 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * Utilities for applying Effect SQL migrations to PostgreSQL databases.
3
+ *
4
+ * This module re-exports the shared `Migrator` loaders and error types, then
5
+ * provides `run` and `layer` helpers for applying ordered migrations through
6
+ * the current PostgreSQL `SqlClient` and `PgClient`. It is typically used at
7
+ * application startup, during deployment, in integration tests that provision a
8
+ * temporary PostgreSQL database, or in layer graphs that must prepare the
9
+ * schema before dependent services are acquired.
10
+ *
11
+ * Migrations are recorded in `effect_sql_migrations` by default and are loaded
12
+ * using the shared `<id>_<name>` file or record-key convention. Only migrations
13
+ * with an id greater than the latest recorded id are applied, so concurrent
14
+ * application instances should coordinate startup against the same database and
15
+ * avoid racing to install the same changes. When `schemaDirectory` is enabled,
16
+ * this adapter shells out to `pg_dump` using the active `PgClient`
17
+ * configuration, so `pg_dump` must be available on `PATH` and the layer must
18
+ * provide child process, filesystem, and path services. The generated dumps
19
+ * intentionally strip comments, session settings, ownership, and privilege
20
+ * statements to keep schema snapshots portable across PostgreSQL environments.
21
+ *
22
+ * @since 4.0.0
3
23
  */
4
- import type * as Effect from "effect/Effect"
24
+ import * as Effect from "effect/Effect"
25
+ import * as FileSystem from "effect/FileSystem"
5
26
  import * as Layer from "effect/Layer"
27
+ import * as Path from "effect/Path"
28
+ import * as Redacted from "effect/Redacted"
29
+ import * as ChildProcess from "effect/unstable/process/ChildProcess"
30
+ import * as ChildProcessSpawner from "effect/unstable/process/ChildProcessSpawner"
6
31
  import * as Migrator from "effect/unstable/sql/Migrator"
7
- import type * as Client from "effect/unstable/sql/SqlClient"
32
+ import type { SqlClient } from "effect/unstable/sql/SqlClient"
8
33
  import type { SqlError } from "effect/unstable/sql/SqlError"
34
+ import { PgClient } from "./PgClient.ts"
9
35
 
10
36
  /**
11
- * @since 1.0.0
37
+ * @since 4.0.0
12
38
  */
13
39
  export * from "effect/unstable/sql/Migrator"
14
40
 
15
41
  /**
16
- * @category constructor
17
- * @since 1.0.0
42
+ * Runs PostgreSQL SQL migrations using the configured clients. Schema dumps use `pg_dump` and require child process, filesystem, and path services.
43
+ *
44
+ * @category constructors
45
+ * @since 4.0.0
18
46
  */
19
47
  export const run: <R2 = never>(
20
48
  options: Migrator.MigratorOptions<R2>
21
49
  ) => Effect.Effect<
22
50
  ReadonlyArray<readonly [id: number, name: string]>,
23
51
  Migrator.MigrationError | SqlError,
24
- Client.SqlClient | R2
52
+ | SqlClient
53
+ | PgClient
54
+ | ChildProcessSpawner.ChildProcessSpawner
55
+ | FileSystem.FileSystem
56
+ | Path.Path
57
+ | R2
25
58
  > = Migrator.make({
26
- // TODO: Wait for Command module
27
- // dumpSchema(path, table) {
28
- // const pgDump = (args: Array<string>) =>
29
- // Effect.gen(function*() {
30
- // const sql = yield* PgClient
31
- // const dump = yield* pipe(
32
- // Command.make("pg_dump", ...args, "--no-owner", "--no-privileges"),
33
- // Command.env({
34
- // PATH: (globalThis as any).process?.env.PATH,
35
- // PGHOST: sql.config.host,
36
- // PGPORT: sql.config.port?.toString(),
37
- // PGUSER: sql.config.username,
38
- // PGPASSWORD: sql.config.password
39
- // ? Redacted.value(sql.config.password)
40
- // : undefined,
41
- // PGDATABASE: sql.config.database,
42
- // PGSSLMODE: sql.config.ssl ? "require" : "prefer"
43
- // }),
44
- // Command.string
45
- // )
46
- //
47
- // return dump.replace(/^--.*$/gm, "")
48
- // .replace(/^SET .*$/gm, "")
49
- // .replace(/^SELECT pg_catalog\..*$/gm, "")
50
- // .replace(/\n{2,}/gm, "\n\n")
51
- // .trim()
52
- // }).pipe(
53
- // Effect.mapError((error) => new Migrator.MigrationError({ kind: "Failed", message: error.message }))
54
- // )
55
- //
56
- // const pgDumpSchema = pgDump(["--schema-only"])
57
- //
58
- // const pgDumpMigrations = pgDump([
59
- // "--column-inserts",
60
- // "--data-only",
61
- // `--table=${table}`
62
- // ])
63
- //
64
- // const pgDumpAll = Effect.map(
65
- // Effect.all([pgDumpSchema, pgDumpMigrations], { concurrency: 2 }),
66
- // ([schema, migrations]) => schema + "\n\n" + migrations
67
- // )
68
- //
69
- // const pgDumpFile = (path: string) =>
70
- // Effect.gen(function*() {
71
- // const fs = yield* FileSystem
72
- // const path_ = yield* Path
73
- // const dump = yield* pgDumpAll
74
- // yield* fs.makeDirectory(path_.dirname(path), { recursive: true })
75
- // yield* fs.writeFileString(path, dump)
76
- // }).pipe(
77
- // Effect.mapError((error) => new Migrator.MigrationError({ kind: "Failed", message: error.message }))
78
- // )
79
- //
80
- // return pgDumpFile(path)
81
- // }
59
+ dumpSchema(path, table) {
60
+ const pgDump = (args: Array<string>) =>
61
+ Effect.gen(function*() {
62
+ const sql = yield* PgClient
63
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner
64
+ const dump = yield* ChildProcess.make("pg_dump", [...args, "--no-owner", "--no-privileges"], {
65
+ env: {
66
+ PATH: (globalThis as any).process?.env.PATH,
67
+ PGHOST: sql.config.host,
68
+ PGPORT: sql.config.port?.toString(),
69
+ PGUSER: sql.config.username,
70
+ PGPASSWORD: sql.config.password
71
+ ? Redacted.value(sql.config.password)
72
+ : undefined,
73
+ PGDATABASE: sql.config.database,
74
+ PGSSLMODE: sql.config.ssl ? "require" : "prefer"
75
+ }
76
+ }).pipe(spawner.string)
77
+
78
+ return dump.replace(/^--.*$/gm, "")
79
+ .replace(/^SET .*$/gm, "")
80
+ .replace(/^SELECT pg_catalog\..*$/gm, "")
81
+ .replace(/\n{2,}/gm, "\n\n")
82
+ .trim();
83
+ }).pipe(
84
+ Effect.mapError((error) => new Migrator.MigrationError({ kind: "Failed", message: error.message }))
85
+ )
86
+
87
+ const pgDumpSchema = pgDump(["--schema-only"])
88
+
89
+ const pgDumpMigrations = pgDump([
90
+ "--column-inserts",
91
+ "--data-only",
92
+ `--table=${table}`
93
+ ])
94
+
95
+ const pgDumpAll = Effect.map(
96
+ Effect.all([pgDumpSchema, pgDumpMigrations], { concurrency: 2 }),
97
+ ([schema, migrations]) => schema + "\n\n" + migrations
98
+ )
99
+
100
+ const pgDumpFile = (path: string) =>
101
+ Effect.gen(function*() {
102
+ const fs = yield* FileSystem.FileSystem
103
+ const path_ = yield* Path.Path
104
+ const dump = yield* pgDumpAll
105
+ yield* fs.makeDirectory(path_.dirname(path), { recursive: true })
106
+ yield* fs.writeFileString(path, dump)
107
+ }).pipe(
108
+ Effect.mapError((error) => new Migrator.MigrationError({ kind: "Failed", message: error.message }))
109
+ )
110
+
111
+ return pgDumpFile(path)
112
+ }
82
113
  })
83
114
 
84
115
  /**
116
+ * Creates a layer that runs PostgreSQL migrations during layer construction, including `pg_dump`-based schema dump support when requested.
117
+ *
85
118
  * @category layers
86
- * @since 1.0.0
119
+ * @since 4.0.0
87
120
  */
88
121
  export const layer = <R>(
89
122
  options: Migrator.MigratorOptions<R>
90
123
  ): Layer.Layer<
91
124
  never,
92
125
  Migrator.MigrationError | SqlError,
93
- Client.SqlClient | R
126
+ | SqlClient
127
+ | PgClient
128
+ | ChildProcessSpawner.ChildProcessSpawner
129
+ | FileSystem.FileSystem
130
+ | Path.Path
131
+ | R
94
132
  > => Layer.effectDiscard(run(options))
package/src/index.ts CHANGED
@@ -1,15 +1,52 @@
1
1
  /**
2
- * @since 1.0.0
2
+ * @since 4.0.0
3
3
  */
4
4
 
5
5
  // @barrel: Auto-generated exports. Do not edit manually.
6
6
 
7
7
  /**
8
- * @since 1.0.0
8
+ * PostgreSQL client implementation for Effect SQL, backed by `pg`.
9
+ *
10
+ * This module exposes constructors for creating a scoped `PgClient` from a
11
+ * managed `pg` pool, a single managed `pg` client, or lower-level connection
12
+ * acquirers. The resulting service can be provided as both `PgClient` and the
13
+ * generic `SqlClient`, and is intended for application database access,
14
+ * migrations, transactional workflows, row streaming, JSON parameters, and
15
+ * PostgreSQL LISTEN/NOTIFY integration.
16
+ *
17
+ * Pool-backed clients acquire connections per operation and reserve dedicated
18
+ * connections for transactions and cursor streams. Clients built from one
19
+ * `pg.Client` serialize shared access; enable `acquireForStream` when streams
20
+ * or listeners need their own client instead of sharing the query connection.
21
+ * LISTEN uses a scoped long-lived client and automatically issues `UNLISTEN`
22
+ * when the stream scope closes, so listeners should be scoped for as long as
23
+ * notifications are needed.
24
+ *
25
+ * @since 4.0.0
9
26
  */
10
27
  export * as PgClient from "./PgClient.ts"
11
28
 
12
29
  /**
13
- * @since 1.0.0
30
+ * Utilities for applying Effect SQL migrations to PostgreSQL databases.
31
+ *
32
+ * This module re-exports the shared `Migrator` loaders and error types, then
33
+ * provides `run` and `layer` helpers for applying ordered migrations through
34
+ * the current PostgreSQL `SqlClient` and `PgClient`. It is typically used at
35
+ * application startup, during deployment, in integration tests that provision a
36
+ * temporary PostgreSQL database, or in layer graphs that must prepare the
37
+ * schema before dependent services are acquired.
38
+ *
39
+ * Migrations are recorded in `effect_sql_migrations` by default and are loaded
40
+ * using the shared `<id>_<name>` file or record-key convention. Only migrations
41
+ * with an id greater than the latest recorded id are applied, so concurrent
42
+ * application instances should coordinate startup against the same database and
43
+ * avoid racing to install the same changes. When `schemaDirectory` is enabled,
44
+ * this adapter shells out to `pg_dump` using the active `PgClient`
45
+ * configuration, so `pg_dump` must be available on `PATH` and the layer must
46
+ * provide child process, filesystem, and path services. The generated dumps
47
+ * intentionally strip comments, session settings, ownership, and privilege
48
+ * statements to keep schema snapshots portable across PostgreSQL environments.
49
+ *
50
+ * @since 4.0.0
14
51
  */
15
52
  export * as PgMigrator from "./PgMigrator.ts"