@kairos-es/store-postgres 1.0.0-alpha.4 → 1.0.0-alpha.6

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.
Files changed (86) hide show
  1. package/README.md +54 -29
  2. package/dist/cjs/clients.js +34 -24
  3. package/dist/cjs/clients.js.map +1 -1
  4. package/dist/cjs/config.js +9 -15
  5. package/dist/cjs/config.js.map +1 -1
  6. package/dist/cjs/ensureSchema.js +2 -2
  7. package/dist/cjs/ensureSchema.js.map +1 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/internal/matchSql.js +15 -4
  10. package/dist/cjs/internal/matchSql.js.map +1 -1
  11. package/dist/cjs/internal/readPlan.js +25 -1
  12. package/dist/cjs/internal/readPlan.js.map +1 -1
  13. package/dist/cjs/internal/transport.js +17 -13
  14. package/dist/cjs/internal/transport.js.map +1 -1
  15. package/dist/cjs/store.js +30 -25
  16. package/dist/cjs/store.js.map +1 -1
  17. package/dist/dts-cjs/clients.d.ts +66 -0
  18. package/dist/dts-cjs/clients.d.ts.map +1 -0
  19. package/dist/{dts → dts-cjs}/config.d.ts +9 -19
  20. package/dist/{dts → dts-cjs}/config.d.ts.map +1 -1
  21. package/dist/{dts → dts-cjs}/ensureSchema.d.ts +2 -2
  22. package/dist/dts-cjs/ensureSchema.d.ts.map +1 -0
  23. package/dist/{dts → dts-cjs}/index.d.ts +4 -3
  24. package/dist/dts-cjs/index.d.ts.map +1 -0
  25. package/dist/{dts → dts-cjs}/internal/ddl.d.ts +1 -1
  26. package/dist/{dts → dts-cjs}/internal/ddl.d.ts.map +1 -1
  27. package/dist/{dts → dts-cjs}/internal/matchSql.d.ts.map +1 -1
  28. package/dist/{dts → dts-cjs}/internal/readPlan.d.ts +1 -1
  29. package/dist/{dts → dts-cjs}/internal/readPlan.d.ts.map +1 -1
  30. package/dist/{dts → dts-cjs}/internal/transport.d.ts +20 -15
  31. package/dist/dts-cjs/internal/transport.d.ts.map +1 -0
  32. package/dist/dts-cjs/package.json +3 -0
  33. package/dist/dts-cjs/store.d.ts.map +1 -0
  34. package/dist/dts-esm/clients.d.ts +66 -0
  35. package/dist/dts-esm/clients.d.ts.map +1 -0
  36. package/dist/dts-esm/config.d.ts +48 -0
  37. package/dist/dts-esm/config.d.ts.map +1 -0
  38. package/dist/dts-esm/ensureSchema.d.ts +40 -0
  39. package/dist/dts-esm/ensureSchema.d.ts.map +1 -0
  40. package/dist/dts-esm/index.d.ts +42 -0
  41. package/dist/dts-esm/index.d.ts.map +1 -0
  42. package/dist/dts-esm/internal/ddl.d.ts +174 -0
  43. package/dist/dts-esm/internal/ddl.d.ts.map +1 -0
  44. package/dist/dts-esm/internal/matchSql.d.ts +164 -0
  45. package/dist/dts-esm/internal/matchSql.d.ts.map +1 -0
  46. package/dist/dts-esm/internal/readPlan.d.ts +72 -0
  47. package/dist/dts-esm/internal/readPlan.d.ts.map +1 -0
  48. package/dist/dts-esm/internal/transport.d.ts +131 -0
  49. package/dist/dts-esm/internal/transport.d.ts.map +1 -0
  50. package/dist/dts-esm/package.json +3 -0
  51. package/dist/dts-esm/store.d.ts +17 -0
  52. package/dist/dts-esm/store.d.ts.map +1 -0
  53. package/dist/esm/clients.js +34 -24
  54. package/dist/esm/clients.js.map +1 -1
  55. package/dist/esm/config.js +9 -15
  56. package/dist/esm/config.js.map +1 -1
  57. package/dist/esm/ensureSchema.js +2 -2
  58. package/dist/esm/ensureSchema.js.map +1 -1
  59. package/dist/esm/index.js +4 -3
  60. package/dist/esm/index.js.map +1 -1
  61. package/dist/esm/internal/matchSql.js +15 -4
  62. package/dist/esm/internal/matchSql.js.map +1 -1
  63. package/dist/esm/internal/readPlan.js +24 -1
  64. package/dist/esm/internal/readPlan.js.map +1 -1
  65. package/dist/esm/internal/transport.js +18 -14
  66. package/dist/esm/internal/transport.js.map +1 -1
  67. package/dist/esm/store.js +30 -25
  68. package/dist/esm/store.js.map +1 -1
  69. package/package.json +13 -11
  70. package/src/clients.ts +43 -31
  71. package/src/config.ts +12 -13
  72. package/src/ensureSchema.ts +2 -2
  73. package/src/index.ts +4 -3
  74. package/src/internal/ddl.ts +1 -1
  75. package/src/internal/matchSql.ts +15 -4
  76. package/src/internal/readPlan.ts +3 -2
  77. package/src/internal/transport.ts +28 -20
  78. package/src/store.ts +35 -28
  79. package/dist/dts/clients.d.ts +0 -34
  80. package/dist/dts/clients.d.ts.map +0 -1
  81. package/dist/dts/ensureSchema.d.ts.map +0 -1
  82. package/dist/dts/index.d.ts.map +0 -1
  83. package/dist/dts/internal/transport.d.ts.map +0 -1
  84. package/dist/dts/store.d.ts.map +0 -1
  85. /package/dist/{dts → dts-cjs}/internal/matchSql.d.ts +0 -0
  86. /package/dist/{dts → dts-cjs}/store.d.ts +0 -0
package/README.md CHANGED
@@ -13,20 +13,17 @@ database without interference.
13
13
 
14
14
  ## Installation
15
15
 
16
- `@kairos-es/core`, `effect`, and the Effect SQL/Postgres stack are peer
17
- dependencies (so the app owns the single shared Effect + `SqlClient` instance,
18
- per ADR-0003):
16
+ `@kairos-es/core`, `effect`, and `@effect/sql-pg` are peer dependencies (so
17
+ the app owns the single shared Effect + `SqlClient` instance, per ADR-0003):
19
18
 
20
19
  ```sh
21
20
  pnpm add @kairos-es/store-postgres@alpha @kairos-es/core@alpha \
22
- @effect/sql@^0.52.0 @effect/sql-pg@^0.53.0 @effect/platform@^0.97.0 \
23
- @effect/experimental@^0.61.0 effect@^3.22.0
21
+ @effect/sql-pg@^4.0.5 effect@^4.0.5
24
22
  ```
25
23
 
26
- `@effect/platform` and `@effect/experimental` are pulled in because
27
- `@effect/sql-pg` requires them (the pooled client's `Reactivity` service lives in
28
- `@effect/experimental`); declaring them here keeps the peer graph resolvable for
29
- consumers.
24
+ The generic SQL modules (`SqlClient`, `Migrator`, `SqlError`) and the
25
+ `Reactivity` service the pooled client requires ship inside `effect` itself, as
26
+ `effect/sql` and `effect/reactivity`, so nothing else has to be installed.
30
27
 
31
28
  ## Schema: `ensureSchema` as a migration
32
29
 
@@ -37,17 +34,24 @@ replaces its append functions. Every statement is `CREATE … IF NOT EXISTS` or
37
34
  **orchestration** is yours; the package only provides the idempotent **payload**.
38
35
 
39
36
  **Upgrading.** A re-run replaces the append functions but never alters an existing
40
- table. So when a release adds a column, its release notes give the `ALTER TABLE`
41
- statement, and an upgrade is that statement followed by this version's
42
- `ensureSchema` again, registered as a NEW migration: a migrator never re-runs one
43
- it has already applied, and an append function left behind silently ignores the
44
- new column.
37
+ table. So register this version's `ensureSchema` again as a NEW migration on every
38
+ upgrade, even one that adds no column: a migrator never re-runs one it has already
39
+ applied, and an append function left behind keeps the older version's body. When a
40
+ release adds a column, its release notes give the `ALTER TABLE` statement, and it
41
+ runs before that `ensureSchema`; an append function left behind silently ignores
42
+ the new column.
45
43
 
46
- Drop it straight into an `@effect/sql` migrator as a one-liner:
44
+ **One statement per call.** `@effect/sql-pg` 4 has no simple-query path: every
45
+ statement goes through the extended protocol, which takes one command. So a string
46
+ holding several statements, such as a SQL migration file, fails with `cannot insert
47
+ multiple commands into a prepared statement`, and `prepare: false` does not change
48
+ that. Split the file and run each statement on its own.
49
+
50
+ Drop it straight into an `effect/sql` migrator as a one-liner:
47
51
 
48
52
  ```ts
49
- import { Migrator } from '@effect/sql'
50
53
  import { ensureSchema } from '@kairos-es/store-postgres'
54
+ import { Migrator } from 'effect/sql'
51
55
 
52
56
  const config = { schema: 'public', tablePrefix: 'dcb_events' }
53
57
 
@@ -56,14 +60,13 @@ const migrations = Migrator.fromRecord({
56
60
  })
57
61
  ```
58
62
 
59
- Because `ensureSchema` requires the **generic** `SqlClient` tag (not the
60
- store-owned client tags), it slots into any migrator or boot sequence that
63
+ Because `ensureSchema` requires the **generic** `SqlClient` service (not the
64
+ store-owned client services), it slots into any migrator or boot sequence that
61
65
  already provides a `SqlClient`.
62
66
 
63
67
  Or run it directly once at boot, over whatever `SqlClient` you have wired:
64
68
 
65
69
  ```ts
66
- import { SqlClient } from '@effect/sql'
67
70
  import { PgClient } from '@effect/sql-pg'
68
71
  import { ensureSchema } from '@kairos-es/store-postgres'
69
72
  import { Effect, Layer, Redacted } from 'effect'
@@ -78,24 +81,34 @@ await Effect.runPromise(program.pipe(Effect.provide(SqlLive)))
78
81
  ```
79
82
 
80
83
  `ensureSchema` must have run before the store `layer` is used; the `layer` itself
81
- performs no DDL and depends only on the two client tags.
84
+ performs no DDL and depends only on the two client services.
82
85
 
83
86
  ## Two-endpoint wiring (Neon)
84
87
 
85
- `@effect/sql-pg` exposes a single `PgClient`/`SqlClient` tag, so this package
86
- defines **two distinct tags**, each holding a `PgClient` value:
88
+ `@effect/sql-pg` exposes a single `PgClient`/`SqlClient` service, so this
89
+ package defines **two distinct services**, each holding a `PgClient` value:
87
90
 
88
91
  - `PgClientPooled` — reads, the append function, and `NOTIFY`. Point it at your
89
92
  pooled endpoint.
90
93
  - `PgClientDirect` — used **only** by `subscribe`'s `LISTEN`. Point it at a
91
94
  **direct** (non-pooler) endpoint.
92
95
 
93
- Why the split matters on Neon: the built-in `listen` constructs a standalone
94
- connection inheriting the pool's host. A Neon **pooled** endpoint
95
- (`…-pooler…`) lands that connection on the PgBouncer front door, which
96
- **silently drops `LISTEN`/`NOTIFY`** — the subscription would simply never wake.
97
- Pointing `PgClientDirect` at Neon's direct endpoint fixes it. `subscribe` is the
98
- only method that touches `PgClientDirect`.
96
+ Why the split matters on Neon: the built-in `listen` reserves a connection from
97
+ its own client's pool, so it listens on whatever host that client was given. A
98
+ Neon **pooled** endpoint (`…-pooler…`) lands that connection on the PgBouncer
99
+ front door, which **silently drops `LISTEN`/`NOTIFY`** — the subscription would
100
+ never wake, and would deliver only at the poll interval. Pointing
101
+ `PgClientDirect` at Neon's direct endpoint fixes it. `subscribe` is the only
102
+ method that touches `PgClientDirect`.
103
+
104
+ Each live subscription holds one `PgClientDirect` connection for as long as it
105
+ runs, so that client's `maxConnections` (default 10) is how many subscriptions
106
+ can be listening at once. One past it still delivers, at the poll interval,
107
+ until a connection frees up. Size `directLayer` for your subscriber count:
108
+
109
+ ```ts
110
+ directLayer({ url, maxConnections: 50 })
111
+ ```
99
112
 
100
113
  ```ts
101
114
  import {
@@ -117,7 +130,19 @@ const clients = Layer.merge(
117
130
  const store = layer(config).pipe(Layer.provide(clients))
118
131
  ```
119
132
 
120
- On a plain (non-Neon) Postgres, point both tags at the **same** URL — the split
133
+ Both layers take `@effect/sql-pg`'s own pool config, so its options pass
134
+ straight through. That driver caches named prepared statements by default, and a
135
+ transaction-mode pooler, such as the PgBouncer behind Neon's `-pooler` endpoint,
136
+ may run each statement on a different server connection from the one that
137
+ prepared it. Behind such a pooler, unless it documents support for
138
+ protocol-level prepared statements, pass `prepare: false` to the client pointed
139
+ at it:
140
+
141
+ ```ts
142
+ pooledLayer({ url: Redacted.make(process.env.NEON_POOLED_URL!), prepare: false })
143
+ ```
144
+
145
+ On a plain (non-Neon) Postgres, point both services at the **same** URL — the split
121
146
  costs nothing there:
122
147
 
123
148
  ```ts
@@ -4,59 +4,69 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.pooledLayer = exports.directLayer = exports.PgClientPooled = exports.PgClientDirect = void 0;
7
- var _experimental = require("@effect/experimental");
8
7
  var _sqlPg = require("@effect/sql-pg");
9
8
  var _effect = require("effect");
9
+ var _reactivity = require("effect/reactivity");
10
10
  /**
11
11
  * The TWO store-owned Postgres clients — the "Neon trap" mitigation (ADR-0002).
12
12
  *
13
- * `@effect/sql-pg` exposes a single `PgClient` (and `SqlClient`) tag; a
13
+ * `@effect/sql-pg` exposes a single `PgClient` (and `SqlClient`) service; a
14
14
  * `PgClient.layer` claims BOTH. If we built two `PgClient.layer`s they would
15
- * collide on that one tag — the second would shadow the first. So instead we
16
- * define two DISTINCT `Context.Tag`s, each HOLDING a `PgClient` value:
15
+ * collide on that one key — the second would shadow the first. So instead we
16
+ * define two DISTINCT `Context.Service`s, each HOLDING a `PgClient` value:
17
17
  *
18
18
  * - `PgClientPooled` — the pooled client used for reads, the append function,
19
- * and `notify`. Backed by a `pg.Pool`; connections are recycled per query.
19
+ * and `notify`. Its statements borrow a connection from the client's pool per
20
+ * query.
20
21
  * - `PgClientDirect` — a client used ONLY by `subscribe`'s `listen`. Its
21
- * built-in `listen` constructs a STANDALONE `pg.Client` from the pool's
22
- * `options`, inheriting the pool's host. On a Neon POOLED endpoint
23
- * (`…-pooler…`) that standalone connection lands on the PgBouncer front door,
24
- * which SILENTLY DROPS `LISTEN`/`NOTIFY` — the subscription would simply never
22
+ * built-in `listen` RESERVES a connection from that client's own pool and
23
+ * holds it for the life of the subscription, so the listening session lives
24
+ * on whatever host the client was configured with. On a Neon POOLED endpoint
25
+ * (`…-pooler…`) that session is a PgBouncer front-door connection, which
26
+ * SILENTLY DROPS `LISTEN`/`NOTIFY` — the subscription would simply never
25
27
  * wake. Pointing `PgClientDirect` at Neon's DIRECT (non-pooler) endpoint fixes
26
28
  * it. `subscribe` is the ONLY method that touches `PgClientDirect`.
27
29
  *
28
- * For a plain (non-Neon) Postgres both tags point at the same URL; the split
29
- * costs nothing there. The two-tag design is what makes the Neon fix a
30
+ * Because each live subscription holds one of `PgClientDirect`'s pooled
31
+ * connections until it closes, that client's `maxConnections` is also the number
32
+ * of subscriptions that can be listening at once. A subscription past it waits
33
+ * for a connection on its wake fibre only — delivery still proceeds at the poll
34
+ * rate meanwhile (see `store.ts`) — so size the direct client for the expected
35
+ * subscriber count rather than for query throughput.
36
+ *
37
+ * For a plain (non-Neon) Postgres both services point at the same URL; the split
38
+ * costs nothing there. The two-service design is what makes the Neon fix a
30
39
  * deployment-time wiring choice rather than a code change.
31
40
  */
32
41
 
33
42
  /**
34
- * The pooled client tag: reads, the append function, and `notify`. Holds a
43
+ * The pooled client service: reads, the append function, and `notify`. Holds a
35
44
  * `PgClient` value rather than being a `PgClient.layer`, so it never collides
36
- * with the direct client on the shared `PgClient`/`SqlClient` tag.
45
+ * with the direct client on the shared `PgClient`/`SqlClient` key.
37
46
  */
38
- class PgClientPooled extends /*#__PURE__*/_effect.Context.Tag('@kairos-es/store-postgres/PgClientPooled')() {}
47
+ class PgClientPooled extends /*#__PURE__*/_effect.Context.Service()('@kairos-es/store-postgres/PgClientPooled') {}
39
48
  /**
40
- * The direct (non-pooler) client tag: the `subscribe` listener ONLY. Point this
41
- * at a direct endpoint on Neon so `LISTEN`/`NOTIFY` is not dropped by the pooler.
49
+ * The direct (non-pooler) client service: the `subscribe` listener ONLY. Point
50
+ * this at a direct endpoint on Neon so `LISTEN`/`NOTIFY` is not dropped by the
51
+ * pooler.
42
52
  */
43
53
  exports.PgClientPooled = PgClientPooled;
44
- class PgClientDirect extends /*#__PURE__*/_effect.Context.Tag('@kairos-es/store-postgres/PgClientDirect')() {}
54
+ class PgClientDirect extends /*#__PURE__*/_effect.Context.Service()('@kairos-es/store-postgres/PgClientDirect') {}
45
55
  /**
46
- * Build a `PgClientPooled` layer from a `PgClient` config. We construct the
47
- * client via `PgClient.make` (scoped) and place it in our OWN tag, then provide
48
- * `Reactivity.layer` (which `PgClient.make` requires) — exactly what the
56
+ * Build a `PgClientPooled` layer from a `PgClient` pool config. We construct the
57
+ * client via `PgClient.make` (scoped) and place it in our OWN service, then
58
+ * provide `Reactivity.layer` (which `PgClient.make` requires) — exactly what the
49
59
  * built-in `PgClient.layer` does internally, minus the collision-prone claim on
50
- * the shared `PgClient` tag.
60
+ * the shared `PgClient` key.
51
61
  */
52
62
  exports.PgClientDirect = PgClientDirect;
53
- const pooledLayer = config => _effect.Layer.scoped(PgClientPooled, _sqlPg.PgClient.make(config)).pipe(_effect.Layer.provide(_experimental.Reactivity.layer));
63
+ const pooledLayer = config => _effect.Layer.effect(PgClientPooled, _sqlPg.PgClient.make(config)).pipe(_effect.Layer.provide(_reactivity.Reactivity.layer));
54
64
  /**
55
- * Build a `PgClientDirect` layer from a `PgClient` config. Same construction as
65
+ * Build a `PgClientDirect` layer from a `PgClient` pool config. Same construction as
56
66
  * `pooledLayer`; the two differ only in which endpoint the caller points them
57
67
  * at (and that only matters on Neon).
58
68
  */
59
69
  exports.pooledLayer = pooledLayer;
60
- const directLayer = config => _effect.Layer.scoped(PgClientDirect, _sqlPg.PgClient.make(config)).pipe(_effect.Layer.provide(_experimental.Reactivity.layer));
70
+ const directLayer = config => _effect.Layer.effect(PgClientDirect, _sqlPg.PgClient.make(config)).pipe(_effect.Layer.provide(_reactivity.Reactivity.layer));
61
71
  exports.directLayer = directLayer;
62
72
  //# sourceMappingURL=clients.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"clients.js","names":["_experimental","require","_sqlPg","_effect","PgClientPooled","Context","Tag","exports","PgClientDirect","pooledLayer","config","Layer","scoped","PgClient","make","pipe","provide","Reactivity","layer","directLayer"],"sources":["../../src/clients.ts"],"sourcesContent":[null],"mappings":";;;;;;AAsBA,IAAAA,aAAA,GAAAC,OAAA;AAEA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AAzBA;;;;;;;;;;;;;;;;;;;;;;;AA2BA;;;;;AAKM,MAAOG,cAAe,sBAAQC,eAAO,CAACC,GAAG,CAC7C,0CAA0C,CAC3C,EAAqC;AAEtC;;;;AAAAC,OAAA,CAAAH,cAAA,GAAAA,cAAA;AAIM,MAAOI,cAAe,sBAAQH,eAAO,CAACC,GAAG,CAC7C,0CAA0C,CAC3C,EAAqC;AAEtC;;;;;;;AAAAC,OAAA,CAAAC,cAAA,GAAAA,cAAA;AAOO,MAAMC,WAAW,GACtBC,MAA+B,IAE/BC,aAAK,CAACC,MAAM,CAACR,cAAc,EAAES,eAAQ,CAACC,IAAI,CAACJ,MAAM,CAAC,CAAC,CAACK,IAAI,CACtDJ,aAAK,CAACK,OAAO,CAACC,wBAAU,CAACC,KAAK,CAAC,CAChC;AAEH;;;;;AAAAX,OAAA,CAAAE,WAAA,GAAAA,WAAA;AAKO,MAAMU,WAAW,GACtBT,MAA+B,IAE/BC,aAAK,CAACC,MAAM,CAACJ,cAAc,EAAEK,eAAQ,CAACC,IAAI,CAACJ,MAAM,CAAC,CAAC,CAACK,IAAI,CACtDJ,aAAK,CAACK,OAAO,CAACC,wBAAU,CAACC,KAAK,CAAC,CAChC;AAAAX,OAAA,CAAAY,WAAA,GAAAA,WAAA","ignoreList":[]}
1
+ {"version":3,"file":"clients.js","names":["_sqlPg","require","_effect","_reactivity","PgClientPooled","Context","Service","exports","PgClientDirect","pooledLayer","config","Layer","effect","PgClient","make","pipe","provide","Reactivity","layer","directLayer"],"sources":["../../src/clients.ts"],"sourcesContent":[null],"mappings":";;;;;;AA+BA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,WAAA,GAAAF,OAAA;AAjCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA;;;;;AAKM,MAAOG,cAAe,sBAAQC,eAAO,CAACC,OAAO,EAGhD,CAAC,0CAA0C,CAAC;AAE/C;;;;;AAAAC,OAAA,CAAAH,cAAA,GAAAA,cAAA;AAKM,MAAOI,cAAe,sBAAQH,eAAO,CAACC,OAAO,EAGhD,CAAC,0CAA0C,CAAC;AAE/C;;;;;;;AAAAC,OAAA,CAAAC,cAAA,GAAAA,cAAA;AAOO,MAAMC,WAAW,GACtBC,MAA6B,IAE7BC,aAAK,CAACC,MAAM,CAACR,cAAc,EAAES,eAAQ,CAACC,IAAI,CAACJ,MAAM,CAAC,CAAC,CAACK,IAAI,CACtDJ,aAAK,CAACK,OAAO,CAACC,sBAAU,CAACC,KAAK,CAAC,CAChC;AAEH;;;;;AAAAX,OAAA,CAAAE,WAAA,GAAAA,WAAA;AAKO,MAAMU,WAAW,GACtBT,MAA6B,IAE7BC,aAAK,CAACC,MAAM,CAACJ,cAAc,EAAEK,eAAQ,CAACC,IAAI,CAACJ,MAAM,CAAC,CAAC,CAACK,IAAI,CACtDJ,aAAK,CAACK,OAAO,CAACC,sBAAU,CAACC,KAAK,CAAC,CAChC;AAAAX,OAAA,CAAAY,WAAA,GAAAA,WAAA","ignoreList":[]}
@@ -34,7 +34,7 @@ var _ddl = require("./internal/ddl.js");
34
34
  * `sql(identifier)` dot-splits, so an embedded dot would silently re-partition
35
35
  * the name into the wrong schema/object.
36
36
  */
37
- const IdentifierAtom = /*#__PURE__*/_effect.Schema.String.pipe(/*#__PURE__*/_effect.Schema.nonEmptyString(), /*#__PURE__*/_effect.Schema.pattern(/^[^.]+$/, {
37
+ const IdentifierAtom = /*#__PURE__*/_effect.Schema.String.check(/*#__PURE__*/_effect.Schema.isNonEmpty(), /*#__PURE__*/_effect.Schema.isPattern(/^[^.]+$/, {
38
38
  identifier: 'PostgresIdentifierAtom',
39
39
  description: 'a non-empty identifier atom containing no "."'
40
40
  }));
@@ -65,29 +65,23 @@ const IdentifierAtom = /*#__PURE__*/_effect.Schema.String.pipe(/*#__PURE__*/_eff
65
65
  * fetches before looping.
66
66
  */
67
67
  const PostgresStoreConfig = exports.PostgresStoreConfig = /*#__PURE__*/_effect.Schema.Struct({
68
- // `exact: true` keeps the decoded type at `key?: T` (never `T | undefined`),
68
+ // `optionalKey` keeps the decoded type at `key?: T` (never `T | undefined`),
69
69
  // matching the repo's `exactOptionalPropertyTypes` discipline — an absent key,
70
70
  // not an explicit `undefined`.
71
- schema: _effect.Schema.optionalWith(IdentifierAtom, {
72
- exact: true
73
- }),
74
- tablePrefix: _effect.Schema.optionalWith(IdentifierAtom, {
75
- exact: true
76
- }),
77
- lockTimeout: _effect.Schema.optionalWith(_effect.Schema.Number.pipe(_effect.Schema.nonNegative(), _effect.Schema.finite()), {
78
- exact: true
79
- }),
71
+ schema: _effect.Schema.optionalKey(IdentifierAtom),
72
+ tablePrefix: _effect.Schema.optionalKey(IdentifierAtom),
73
+ lockTimeout: _effect.Schema.optionalKey(_effect.Schema.Number.check(_effect.Schema.isGreaterThanOrEqualTo(0), _effect.Schema.isFinite())),
80
74
  // The two subscribe knobs are core's field definitions, not this engine's: see
81
75
  // `subscriptionTuningFields`.
82
76
  ..._core.subscriptionTuningFields
83
- }).pipe(/*#__PURE__*/
77
+ }).check(/*#__PURE__*/
84
78
  // Cross-field guard: the derived table/index/function/channel names must all
85
79
  // fit Postgres's 63-byte identifier limit. Returning the message string fails
86
- // the decode with it; `undefined`/`true` passes.
87
- _effect.Schema.filter(config => (0, _ddl.oversizedIdentifier)(config) ?? true));
80
+ // the decode with it; `undefined` passes.
81
+ _effect.Schema.makeFilter(config => (0, _ddl.oversizedIdentifier)(config)));
88
82
  /**
89
83
  * Decode an unknown value into a validated `PostgresStoreConfig`, throwing a
90
- * `ParseError` on any violation. Used by `layer`/`ensureSchema` so a bad config
84
+ * `SchemaError` on any violation. Used by `layer`/`ensureSchema` so a bad config
91
85
  * fails at construction time.
92
86
  */
93
87
  const decodePostgresStoreConfig = exports.decodePostgresStoreConfig = /*#__PURE__*/_effect.Schema.decodeUnknownSync(PostgresStoreConfig);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":["_core","require","_effect","_ddl","IdentifierAtom","Schema","String","pipe","nonEmptyString","pattern","identifier","description","PostgresStoreConfig","exports","Struct","schema","optionalWith","exact","tablePrefix","lockTimeout","Number","nonNegative","finite","subscriptionTuningFields","filter","config","oversizedIdentifier","decodePostgresStoreConfig","decodeUnknownSync"],"sources":["../../src/config.ts"],"sourcesContent":[null],"mappings":";;;;;;AAoBA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,IAAA,GAAAF,OAAA;AAtBA;;;;;;;;;;;;;;;;;;;;;AAwBA;;;;;;AAMA,MAAMG,cAAc,gBAAGC,cAAM,CAACC,MAAM,CAACC,IAAI,cACvCF,cAAM,CAACG,cAAc,EAAE,eACvBH,cAAM,CAACI,OAAO,CAAC,SAAS,EAAE;EACxBC,UAAU,EAAE,wBAAwB;EACpCC,WAAW,EAAE;CACd,CAAC,CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BO,MAAMC,mBAAmB,GAAAC,OAAA,CAAAD,mBAAA,gBAAGP,cAAM,CAACS,MAAM,CAAC;EAC/C;EACA;EACA;EACAC,MAAM,EAAEV,cAAM,CAACW,YAAY,CAACZ,cAAc,EAAE;IAAEa,KAAK,EAAE;EAAI,CAAE,CAAC;EAC5DC,WAAW,EAAEb,cAAM,CAACW,YAAY,CAACZ,cAAc,EAAE;IAAEa,KAAK,EAAE;EAAI,CAAE,CAAC;EACjEE,WAAW,EAAEd,cAAM,CAACW,YAAY,CAC9BX,cAAM,CAACe,MAAM,CAACb,IAAI,CAACF,cAAM,CAACgB,WAAW,EAAE,EAAEhB,cAAM,CAACiB,MAAM,EAAE,CAAC,EACzD;IAAEL,KAAK,EAAE;EAAI,CAAE,CAChB;EACD;EACA;EACA,GAAGM;CACJ,CAAC,CAAChB,IAAI;AACL;AACA;AACA;AACAF,cAAM,CAACmB,MAAM,CAAEC,MAAM,IAAK,IAAAC,wBAAmB,EAACD,MAAM,CAAC,IAAI,IAAI,CAAC,CAC/D;AAGD;;;;;AAKO,MAAME,yBAAyB,GAAAd,OAAA,CAAAc,yBAAA,gBACpCtB,cAAM,CAACuB,iBAAiB,CAAChB,mBAAmB,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"config.js","names":["_core","require","_effect","_ddl","IdentifierAtom","Schema","String","check","isNonEmpty","isPattern","identifier","description","PostgresStoreConfig","exports","Struct","schema","optionalKey","tablePrefix","lockTimeout","Number","isGreaterThanOrEqualTo","isFinite","subscriptionTuningFields","makeFilter","config","oversizedIdentifier","decodePostgresStoreConfig","decodeUnknownSync"],"sources":["../../src/config.ts"],"sourcesContent":[null],"mappings":";;;;;;AAoBA,IAAAA,KAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,IAAA,GAAAF,OAAA;AAtBA;;;;;;;;;;;;;;;;;;;;;AAwBA;;;;;;AAMA,MAAMG,cAAc,gBAAGC,cAAM,CAACC,MAAM,CAACC,KAAK,cACxCF,cAAM,CAACG,UAAU,EAAE,eACnBH,cAAM,CAACI,SAAS,CAAC,SAAS,EAAE;EAC1BC,UAAU,EAAE,wBAAwB;EACpCC,WAAW,EAAE;CACd,CAAC,CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;AA0BO,MAAMC,mBAAmB,GAAAC,OAAA,CAAAD,mBAAA,gBAAGP,cAAM,CAACS,MAAM,CAAC;EAC/C;EACA;EACA;EACAC,MAAM,EAAEV,cAAM,CAACW,WAAW,CAACZ,cAAc,CAAC;EAC1Ca,WAAW,EAAEZ,cAAM,CAACW,WAAW,CAACZ,cAAc,CAAC;EAC/Cc,WAAW,EAAEb,cAAM,CAACW,WAAW,CAC7BX,cAAM,CAACc,MAAM,CAACZ,KAAK,CAACF,cAAM,CAACe,sBAAsB,CAAC,CAAC,CAAC,EAAEf,cAAM,CAACgB,QAAQ,EAAE,CAAC,CACzE;EACD;EACA;EACA,GAAGC;CACJ,CAAC,CAACf,KAAK;AACN;AACA;AACA;AACAF,cAAM,CAACkB,UAAU,CAAEC,MAAM,IAAK,IAAAC,wBAAmB,EAACD,MAAM,CAAC,CAAC,CAC3D;AAGD;;;;;AAKO,MAAME,yBAAyB,GAAAb,OAAA,CAAAa,yBAAA,gBACpCrB,cAAM,CAACsB,iBAAiB,CAACf,mBAAmB,CAAC","ignoreList":[]}
@@ -4,8 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.ensureSchema = void 0;
7
- var _sql = require("@effect/sql");
8
7
  var _effect = require("effect");
8
+ var _sql = require("effect/sql");
9
9
  var _config = require("./config.js");
10
10
  var _ddl = require("./internal/ddl.js");
11
11
  /**
@@ -14,7 +14,7 @@ var _ddl = require("./internal/ddl.js");
14
14
  * This is deliberately NOT a migrator. It is a single `Effect<void, SqlError,
15
15
  * SqlClient>` that creates (or refreshes) every object a store owns: both
16
16
  * tables, both indexes, and both plpgsql functions. It requires the GENERIC
17
- * `SqlClient` tag — NOT `PgClientPooled` — precisely so a consumer can drop it
17
+ * `SqlClient` service — NOT `PgClientPooled` — precisely so a consumer can drop it
18
18
  * straight into THEIR OWN migrator, e.g.:
19
19
  *
20
20
  * ```ts
@@ -1 +1 @@
1
- {"version":3,"file":"ensureSchema.js","names":["_sql","require","_effect","_config","_ddl","ensureSchema","config","Effect","gen","sql","SqlClient","names","resolveNames","decodePostgresStoreConfig","all","runDdl","discard","exports"],"sources":["../../src/ensureSchema.ts"],"sourcesContent":[null],"mappings":";;;;;;AA8BA,IAAAA,IAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AACA,IAAAG,IAAA,GAAAH,OAAA;AAjCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA;;;;;AAKO,MAAMI,YAAY,GACvBC,MAA2B,IAE3BC,cAAM,CAACC,GAAG,CAAC,aAAS;EAClB,MAAMC,GAAG,GAAG,OAAOC,cAAS,CAACA,SAAS;EACtC;EACA;EACA,MAAMC,KAAK,GAAG,IAAAC,iBAAY,EAAC,IAAAC,iCAAyB,EAACP,MAAM,CAAC,CAAC;EAC7D;EACA,OAAOC,cAAM,CAACO,GAAG,CAAC,IAAAC,WAAM,EAACN,GAAG,EAAEE,KAAK,CAAC,EAAE;IAAEK,OAAO,EAAE;EAAI,CAAE,CAAC;AAC1D,CAAC,CAAC;AAAAC,OAAA,CAAAZ,YAAA,GAAAA,YAAA","ignoreList":[]}
1
+ {"version":3,"file":"ensureSchema.js","names":["_effect","require","_sql","_config","_ddl","ensureSchema","config","Effect","gen","sql","SqlClient","names","resolveNames","decodePostgresStoreConfig","all","runDdl","discard","exports"],"sources":["../../src/ensureSchema.ts"],"sourcesContent":[null],"mappings":";;;;;;AA8BA,IAAAA,OAAA,GAAAC,OAAA;AACA,IAAAC,IAAA,GAAAD,OAAA;AACA,IAAAE,OAAA,GAAAF,OAAA;AACA,IAAAG,IAAA,GAAAH,OAAA;AAjCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA;;;;;AAKO,MAAMI,YAAY,GACvBC,MAA2B,IAE3BC,cAAM,CAACC,GAAG,CAAC,aAAS;EAClB,MAAMC,GAAG,GAAG,OAAOC,cAAS,CAACA,SAAS;EACtC;EACA;EACA,MAAMC,KAAK,GAAG,IAAAC,iBAAY,EAAC,IAAAC,iCAAyB,EAACP,MAAM,CAAC,CAAC;EAC7D;EACA,OAAOC,cAAM,CAACO,GAAG,CAAC,IAAAC,WAAM,EAACN,GAAG,EAAEE,KAAK,CAAC,EAAE;IAAEK,OAAO,EAAE;EAAI,CAAE,CAAC;AAC1D,CAAC,CAAC;AAAAC,OAAA,CAAAZ,YAAA,GAAAA,YAAA","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_clients","require","_ensureSchema","_store"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,IAAAA,QAAA,GAAAC,OAAA;AAOA,IAAAC,aAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["_clients","require","_ensureSchema","_store"],"sources":["../../src/index.ts"],"sourcesContent":[null],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAAA,QAAA,GAAAC,OAAA;AAOA,IAAAC,aAAA,GAAAD,OAAA;AACA,IAAAE,MAAA,GAAAF,OAAA","ignoreList":[]}
@@ -66,9 +66,20 @@ const RECORDSET_ALIAS = exports.RECORDSET_ALIAS = 'ne';
66
66
  * Typed as a `Record` over `EventColumnName` so that adding a column to
67
67
  * `EVENT_COLUMNS` without saying where its value comes from is a COMPILE error,
68
68
  * rather than a column the insert silently leaves at its default. Every column but
69
- * `data` passes through as the recordset already types it — `text[]` tags,
70
- * `timestamptz`, `jsonb` metadata — because `jsonb_to_recordset` did the casting;
71
- * `data` crosses as base64 TEXT and is restored to `bytea` here, its one decode.
69
+ * `data` and `metadata` passes through as the recordset already types it — `text[]`
70
+ * tags, `timestamptz` — because `jsonb_to_recordset` did the casting; `data`
71
+ * crosses as base64 TEXT and is restored to `bytea` here, its one decode.
72
+ *
73
+ * `metadata` is wrapped in `COALESCE(…, '{}'::jsonb)`, for a caller this package's
74
+ * own client never is. `ensureSchema` replaces each append function with
75
+ * `CREATE OR REPLACE`, which keeps its argument signature, so a client from before
76
+ * the column existed (`1.0.0-alpha.3` and earlier) goes on calling the current body
77
+ * with events JSON that has no `metadata` key. `jsonb_to_recordset` reads an absent
78
+ * key as `NULL`, and an insert that names the column inserts that `NULL` rather than
79
+ * the column's `DEFAULT`, so `NOT NULL` would refuse every such append. The
80
+ * `COALESCE` gives that row the empty bag the `DEFAULT` would have, which is what
81
+ * makes "migrate, then deploy" a safe order from those versions. An event sent WITH
82
+ * a bag passes through unchanged, so what is stored for it does not move.
72
83
  */
73
84
  const EVENT_COLUMN_SOURCE = {
74
85
  type: `${RECORDSET_ALIAS}.type`,
@@ -76,7 +87,7 @@ const EVENT_COLUMN_SOURCE = {
76
87
  tags: `${RECORDSET_ALIAS}.tags`,
77
88
  uuid: `${RECORDSET_ALIAS}.uuid`,
78
89
  occurred_at: `${RECORDSET_ALIAS}.occurred_at`,
79
- metadata: `${RECORDSET_ALIAS}.metadata`
90
+ metadata: `COALESCE(${RECORDSET_ALIAS}.metadata, '{}'::jsonb)`
80
91
  };
81
92
  /**
82
93
  * The bare event column names — `type, data, tags, uuid, occurred_at, metadata` —
@@ -1 +1 @@
1
- {"version":3,"file":"matchSql.js","names":["EVENT_COLUMNS","eventRecordsetColumns","exports","map","name","type","join","readColumns","prefix","RECORDSET_ALIAS","EVENT_COLUMN_SOURCE","data","tags","uuid","occurred_at","metadata","eventColumnList","eventInsertSelectList","allowedTypesPredicate","typesCol","taggedMatchChain","tokens","queryItemsExpr","tag","afterExpr","qualifiedRows","main","wildcardReadSql","typeOnlyReadSql","taggedReadSql"],"sources":["../../../src/internal/matchSql.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"matchSql.js","names":["EVENT_COLUMNS","eventRecordsetColumns","exports","map","name","type","join","readColumns","prefix","RECORDSET_ALIAS","EVENT_COLUMN_SOURCE","data","tags","uuid","occurred_at","metadata","eventColumnList","eventInsertSelectList","allowedTypesPredicate","typesCol","taggedMatchChain","tokens","queryItemsExpr","tag","afterExpr","qualifiedRows","main","wildcardReadSql","typeOnlyReadSql","taggedReadSql"],"sources":["../../../src/internal/matchSql.ts"],"sourcesContent":[null],"mappings":"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","ignoreList":[]}
@@ -7,6 +7,30 @@ exports.runFetch = exports.compileFetchPlan = void 0;
7
7
  var _core = require("@kairos-es/core");
8
8
  var _matchSql = require("./matchSql.js");
9
9
  var _transport = require("./transport.js");
10
+ /**
11
+ * The read-plan compiler for the Postgres engine, extracted from `store.ts` so it
12
+ * is a self-contained unit depending only on the PRE-QUOTED table names — never on
13
+ * the SQL clients. `store.ts`'s `read` and its `subscribe` — the latter feeding the
14
+ * plan to core's subscribe machine as that machine's `fetch` seam — both compile a
15
+ * plan here and run it against whichever client they hold.
16
+ *
17
+ * `compileFetchPlan` turns a servable `Query` into prepared SQL text plus a
18
+ * cursor-only `bind`, so a long-lived subscription re-binds only the cursor rather
19
+ * than re-dispatching the shape and re-serialising the query JSON on every poll.
20
+ * Which shape a query IS is not decided here: core's `classifyServableQuery` owns
21
+ * that dispatch beside the grammar it dispatches over (`Query.ts`), including the
22
+ * degenerate empty item's routing. The JSON/JSONB transport shapes and
23
+ * (de)serialisers — `EventRow`, `jsonbText`, `toQueryItemsJson`, `rowToSequenced`
24
+ * — live in `internal/transport.ts`, and this module only compiles plans.
25
+ *
26
+ * A plan compiled here is therefore the one place the Postgres engine dispatches
27
+ * a shape in TypeScript, and the exhaustiveness below protects BOTH verbs that
28
+ * compile one — `read`, and the `subscribe` poll sharing its plan. What it cannot
29
+ * reach is the append: its conflict guard covers the same three shapes inside its
30
+ * plpgsql body, where no compiler follows, and `ddl.ts` owns what that rests on
31
+ * instead.
32
+ */
33
+
10
34
  /**
11
35
  * Compile a servable query into a `FetchPlan`. The SQL comes from the shared
12
36
  * `matchSql` builders (the tagged path composes the same emitted match chain as the
@@ -35,7 +59,7 @@ const compileFetchPlan = (tables, query) => {
35
59
  };
36
60
  case 'typeOnly':
37
61
  {
38
- // node-postgres binds a JS array param as a Postgres array literal, so
62
+ // `@effect/sql-pg` binds a JS array of strings as a `text[]` param, so
39
63
  // `type = ANY($2)` matches any of the item's types. A branded `EventType` IS
40
64
  // its string to the driver, so nothing has to be unwrapped — but the list is
41
65
  // COPIED here, at compile time. The driver serialises the array afresh on
@@ -1 +1 @@
1
- {"version":3,"file":"readPlan.js","names":["_core","require","_matchSql","_transport","compileFetchPlan","tables","query","shape","classifyServableQuery","kind","text","wildcardReadSql","main","bind","after","limit","types","typeOnlyReadSql","itemsJson","jsonbText","toQueryItemsJson","taggedReadSql","tag","exports","runFetch","sql","plan","unsafe","ORIGIN"],"sources":["../../../src/internal/readPlan.ts"],"sourcesContent":[null],"mappings":";;;;;;AAyBA,IAAAA,KAAA,GAAAC,OAAA;AAEA,IAAAC,SAAA,GAAAD,OAAA;AACA,IAAAE,UAAA,GAAAF,OAAA;AA0BA;;;;;;;;;;;;;;;;;;AAkBO,MAAMG,gBAAgB,GAAGA,CAC9BC,MAAkB,EAClBC,KAAY,KACC;EACb,MAAMC,KAAK,GAAG,IAAAC,2BAAqB,EAACF,KAAK,CAAC;EAC1C,QAAQC,KAAK,CAACE,IAAI;IAChB,KAAK,UAAU;MACb,OAAO;QACLC,IAAI,EAAE,IAAAC,yBAAe,EAACN,MAAM,CAACO,IAAI,CAAC;QAClCC,IAAI,EAAEA,CAACC,KAAK,EAAEC,KAAK,KAAK,CAACD,KAAK,EAAEC,KAAK;OACtC;IACH,KAAK,UAAU;MAAE;QACf;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,MAAMC,KAAK,GAAG,CAAC,GAAGT,KAAK,CAACS,KAAK,CAAC;QAC9B,OAAO;UACLN,IAAI,EAAE,IAAAO,yBAAe,EAACZ,MAAM,CAACO,IAAI,CAAC;UAClCC,IAAI,EAAEA,CAACC,KAAK,EAAEC,KAAK,KAAK,CAACD,KAAK,EAAEE,KAAK,EAAED,KAAK;SAC7C;MACH;IACA,KAAK,QAAQ;MAAE;QACb;QACA;QACA,MAAMG,SAAS,GAAG,IAAAC,oBAAS,EAAC,IAAAC,2BAAgB,EAACd,KAAK,CAAC,CAAC;QACpD,OAAO;UACLI,IAAI,EAAE,IAAAW,uBAAa,EAAChB,MAAM,CAACO,IAAI,EAAEP,MAAM,CAACiB,GAAG,CAAC;UAC5CT,IAAI,EAAEA,CAACC,KAAK,EAAEC,KAAK,KAAK,CAACG,SAAS,EAAEJ,KAAK,EAAEC,KAAK;SACjD;MACH;EACF;AACF,CAAC;AAED;;;;AAAAQ,OAAA,CAAAnB,gBAAA,GAAAA,gBAAA;AAIO,MAAMoB,QAAQ,GAAGA,CACtBC,GAAwB,EACxBC,IAAe,EACfZ,KAA2B,EAC3BC,KAA4B,KAE5BU,GAAG,CAACE,MAAM,CAAWD,IAAI,CAAChB,IAAI,EAAEgB,IAAI,CAACb,IAAI,CAACC,KAAK,IAAIc,YAAM,EAAEb,KAAK,IAAI,IAAI,CAAC,CAAC;AAAAQ,OAAA,CAAAC,QAAA,GAAAA,QAAA","ignoreList":[]}
1
+ {"version":3,"file":"readPlan.js","names":["_core","require","_matchSql","_transport","compileFetchPlan","tables","query","shape","classifyServableQuery","kind","text","wildcardReadSql","main","bind","after","limit","types","typeOnlyReadSql","itemsJson","jsonbText","toQueryItemsJson","taggedReadSql","tag","exports","runFetch","sql","plan","unsafe","ORIGIN"],"sources":["../../../src/internal/readPlan.ts"],"sourcesContent":[null],"mappings":";;;;;;AAyBA,IAAAA,KAAA,GAAAC,OAAA;AAGA,IAAAC,SAAA,GAAAD,OAAA;AACA,IAAAE,UAAA,GAAAF,OAAA;AA7BA;;;;;;;;;;;;;;;;;;;;;;;;AAuDA;;;;;;;;;;;;;;;;;;AAkBO,MAAMG,gBAAgB,GAAGA,CAC9BC,MAAkB,EAClBC,KAAY,KACC;EACb,MAAMC,KAAK,GAAG,IAAAC,2BAAqB,EAACF,KAAK,CAAC;EAC1C,QAAQC,KAAK,CAACE,IAAI;IAChB,KAAK,UAAU;MACb,OAAO;QACLC,IAAI,EAAE,IAAAC,yBAAe,EAACN,MAAM,CAACO,IAAI,CAAC;QAClCC,IAAI,EAAEA,CAACC,KAAK,EAAEC,KAAK,KAAK,CAACD,KAAK,EAAEC,KAAK;OACtC;IACH,KAAK,UAAU;MAAE;QACf;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,MAAMC,KAAK,GAAG,CAAC,GAAGT,KAAK,CAACS,KAAK,CAAC;QAC9B,OAAO;UACLN,IAAI,EAAE,IAAAO,yBAAe,EAACZ,MAAM,CAACO,IAAI,CAAC;UAClCC,IAAI,EAAEA,CAACC,KAAK,EAAEC,KAAK,KAAK,CAACD,KAAK,EAAEE,KAAK,EAAED,KAAK;SAC7C;MACH;IACA,KAAK,QAAQ;MAAE;QACb;QACA;QACA,MAAMG,SAAS,GAAG,IAAAC,oBAAS,EAAC,IAAAC,2BAAgB,EAACd,KAAK,CAAC,CAAC;QACpD,OAAO;UACLI,IAAI,EAAE,IAAAW,uBAAa,EAAChB,MAAM,CAACO,IAAI,EAAEP,MAAM,CAACiB,GAAG,CAAC;UAC5CT,IAAI,EAAEA,CAACC,KAAK,EAAEC,KAAK,KAAK,CAACG,SAAS,EAAEJ,KAAK,EAAEC,KAAK;SACjD;MACH;EACF;AACF,CAAC;AAED;;;;AAAAQ,OAAA,CAAAnB,gBAAA,GAAAA,gBAAA;AAIO,MAAMoB,QAAQ,GAAGA,CACtBC,GAAwB,EACxBC,IAAe,EACfZ,KAA2B,EAC3BC,KAA4B,KAE5BU,GAAG,CAACE,MAAM,CAAWD,IAAI,CAAChB,IAAI,EAAEgB,IAAI,CAACb,IAAI,CAACC,KAAK,IAAIc,YAAM,EAAEb,KAAK,IAAI,IAAI,CAAC,CAAC;AAAAQ,OAAA,CAAAC,QAAA,GAAAA,QAAA","ignoreList":[]}
@@ -5,18 +5,20 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.toQueryItemsJson = exports.toEventJson = exports.rowToSequenced = exports.jsonbText = void 0;
7
7
  var _effect = require("effect");
8
+ var _encoding = require("effect/encoding");
8
9
  /**
9
10
  * Serialise a value to a JSON STRING for transport as a `::jsonb`-cast bound
10
11
  * parameter.
11
12
  *
12
- * WHY not `sql.json(value)`: `@effect/sql-pg`'s `json` helper binds the RAW
13
- * value, and node-postgres serialises a JS *array* bound param as a Postgres
14
- * ARRAY literal (`{…}`), not JSON — so `sql.json([...])::jsonb` fails with a
15
- * `22P02` invalid-JSON error (an array literal is not valid JSON). Passing a
16
- * pre-stringified JSON string and casting `::jsonb` sends plain text that
17
- * Postgres parses as JSON, which round-trips reliably for both objects and
18
- * arrays. Kept as a named helper so every JSON-transport call site is consistent
19
- * and the reasoning lives in one place.
13
+ * WHY a string and not `sql.json(value)`: the read plan runs through
14
+ * `sql.unsafe(text, params)` with POSITIONAL parameters, and a positional
15
+ * parameter must be a plain scalar or a flat array of scalars — `@effect/sql-pg`
16
+ * cannot infer a Postgres type for an object or an array of objects, and a
17
+ * `sql.json` fragment is not a value that list can carry. A pre-stringified
18
+ * JSON string binds untyped and the `::jsonb` cast has Postgres parse it, which
19
+ * round-trips reliably for both objects and arrays on the positional path and
20
+ * the tagged-template path alike. Kept as a named helper so every
21
+ * JSON-transport call site is consistent and the reasoning lives in one place.
20
22
  */
21
23
  const jsonbText = value => JSON.stringify(value);
22
24
  /** Serialise a `Query`'s items into their transport JSON shape. */
@@ -29,9 +31,11 @@ const toQueryItemsJson = query => query.items.map(item => ({
29
31
  exports.toQueryItemsJson = toQueryItemsJson;
30
32
  const toEventJson = event => ({
31
33
  type: event.type,
32
- // `Encoding.encodeBase64` (from `effect`) keeps this dependency-free and pure
33
- // — no `Buffer`, so no `@types/node` and no browser/runtime coupling.
34
- data: _effect.Encoding.encodeBase64(event.data),
34
+ // `Base64.encode` (from `effect/encoding`) keeps this dependency-free and pure
35
+ // — no `Buffer`, so no `@types/node` and no browser/runtime coupling. It emits
36
+ // the standard RFC 4648 alphabet with `=` padding, which is what plpgsql's
37
+ // `decode(…, 'base64')` reads.
38
+ data: _encoding.Base64.encode(event.data),
35
39
  tags: [...event.tags],
36
40
  uuid: event.uuid,
37
41
  occurred_at: _effect.DateTime.formatIso(event.occurredAt),
@@ -59,7 +63,7 @@ const metadataFrom = value => {
59
63
  /**
60
64
  * Map a raw main-table row to a core `SequencedEvent`. `data` NULL → empty bytes
61
65
  * (a payload-less event round-trips to a zero-length `Uint8Array`); `occurred_at`
62
- * Date → `DateTime.Utc`; `id` string → branded `Position`; `metadata` through
66
+ * Date → `DateTime.Utc`; `id` → branded `Position`; `metadata` through
63
67
  * `metadataFrom`. The column is `NOT NULL DEFAULT '{}'`, so there is no absent
64
68
  * case to reconcile: an event appended with an empty bag reads back as `{}` on
65
69
  * this engine exactly as on the in-memory oracle.
@@ -80,7 +84,7 @@ const rowToSequenced = row => ({
80
84
  data: row.data ?? new Uint8Array(0),
81
85
  tags: row.tags,
82
86
  uuid: row.uuid,
83
- occurredAt: _effect.DateTime.unsafeFromDate(row.occurred_at),
87
+ occurredAt: _effect.DateTime.fromDateUnsafe(row.occurred_at),
84
88
  metadata: metadataFrom(row.metadata)
85
89
  },
86
90
  position: BigInt(row.id)
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","names":["_effect","require","jsonbText","value","JSON","stringify","exports","toQueryItemsJson","query","items","map","item","types","tags","toEventJson","event","type","data","Encoding","encodeBase64","uuid","occurred_at","DateTime","formatIso","occurredAt","metadata","metadataFrom","Array","isArray","Error","rowToSequenced","row","Uint8Array","unsafeFromDate","position","BigInt","id"],"sources":["../../../src/internal/transport.ts"],"sourcesContent":[null],"mappings":";;;;;;AA4BA,IAAAA,OAAA,GAAAC,OAAA;AAGA;;;;;;;;;;;;;AAaO,MAAMC,SAAS,GAAIC,KAAc,IAAaC,IAAI,CAACC,SAAS,CAACF,KAAK,CAAC;AAQ1E;AAAAG,OAAA,CAAAJ,SAAA,GAAAA,SAAA;AACO,MAAMK,gBAAgB,GAAIC,KAAY,IAC3CA,KAAK,CAACC,KAAK,CAACC,GAAG,CAAEC,IAAI,KAAM;EACzBC,KAAK,EAAE,CAAC,GAAGD,IAAI,CAACC,KAAK,CAAC;EACtBC,IAAI,EAAE,CAAC,GAAGF,IAAI,CAACE,IAAI;CACpB,CAAC,CAAC;AA+BL;AAAAP,OAAA,CAAAC,gBAAA,GAAAA,gBAAA;AACO,MAAMO,WAAW,GAAIC,KAAe,KAAiB;EAC1DC,IAAI,EAAED,KAAK,CAACC,IAAI;EAChB;EACA;EACAC,IAAI,EAAEC,gBAAQ,CAACC,YAAY,CAACJ,KAAK,CAACE,IAAI,CAAC;EACvCJ,IAAI,EAAE,CAAC,GAAGE,KAAK,CAACF,IAAI,CAAC;EACrBO,IAAI,EAAEL,KAAK,CAACK,IAAI;EAChBC,WAAW,EAAEC,gBAAQ,CAACC,SAAS,CAACR,KAAK,CAACS,UAAU,CAAC;EACjDC,QAAQ,EAAEV,KAAK,CAACU;CACjB,CAAC;AAgCF;;;;;;;;;;;;AAAAnB,OAAA,CAAAQ,WAAA,GAAAA,WAAA;AAYA,MAAMY,YAAY,GAAIvB,KAAc,IAAc;EAChD,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAIA,KAAK,KAAK,IAAI,IAAIwB,KAAK,CAACC,OAAO,CAACzB,KAAK,CAAC,EAAE;IACvE,MAAM,IAAI0B,KAAK,CACb,sFAAsFzB,IAAI,CAACC,SAAS,CAACF,KAAK,CAAC,IAAI,CAChH;EACH;EACA,OAAOA,KAAiB;AAC1B,CAAC;AAED;;;;;;;;;;;;;;;;;;AAkBO,MAAM2B,cAAc,GAAIC,GAAa,KAAsB;EAChEhB,KAAK,EAAE;IACLC,IAAI,EAAEe,GAAG,CAACf,IAAwB;IAClCC,IAAI,EAAEc,GAAG,CAACd,IAAI,IAAI,IAAIe,UAAU,CAAC,CAAC,CAAC;IACnCnB,IAAI,EAAEkB,GAAG,CAAClB,IAAmC;IAC7CO,IAAI,EAAEW,GAAG,CAACX,IAAwB;IAClCI,UAAU,EAAEF,gBAAQ,CAACW,cAAc,CAACF,GAAG,CAACV,WAAW,CAAC;IACpDI,QAAQ,EAAEC,YAAY,CAACK,GAAG,CAACN,QAAQ;GACpC;EACDS,QAAQ,EAAEC,MAAM,CAACJ,GAAG,CAACK,EAAE;CACxB,CAAC;AAAA9B,OAAA,CAAAwB,cAAA,GAAAA,cAAA","ignoreList":[]}
1
+ {"version":3,"file":"transport.js","names":["_effect","require","_encoding","jsonbText","value","JSON","stringify","exports","toQueryItemsJson","query","items","map","item","types","tags","toEventJson","event","type","data","Base64","encode","uuid","occurred_at","DateTime","formatIso","occurredAt","metadata","metadataFrom","Array","isArray","Error","rowToSequenced","row","Uint8Array","fromDateUnsafe","position","BigInt","id"],"sources":["../../../src/internal/transport.ts"],"sourcesContent":[null],"mappings":";;;;;;AA4BA,IAAAA,OAAA,GAAAC,OAAA;AACA,IAAAC,SAAA,GAAAD,OAAA;AAGA;;;;;;;;;;;;;;AAcO,MAAME,SAAS,GAAIC,KAAc,IAAaC,IAAI,CAACC,SAAS,CAACF,KAAK,CAAC;AAQ1E;AAAAG,OAAA,CAAAJ,SAAA,GAAAA,SAAA;AACO,MAAMK,gBAAgB,GAAIC,KAAY,IAC3CA,KAAK,CAACC,KAAK,CAACC,GAAG,CAAEC,IAAI,KAAM;EACzBC,KAAK,EAAE,CAAC,GAAGD,IAAI,CAACC,KAAK,CAAC;EACtBC,IAAI,EAAE,CAAC,GAAGF,IAAI,CAACE,IAAI;CACpB,CAAC,CAAC;AA+BL;AAAAP,OAAA,CAAAC,gBAAA,GAAAA,gBAAA;AACO,MAAMO,WAAW,GAAIC,KAAe,KAAiB;EAC1DC,IAAI,EAAED,KAAK,CAACC,IAAI;EAChB;EACA;EACA;EACA;EACAC,IAAI,EAAEC,gBAAM,CAACC,MAAM,CAACJ,KAAK,CAACE,IAAI,CAAC;EAC/BJ,IAAI,EAAE,CAAC,GAAGE,KAAK,CAACF,IAAI,CAAC;EACrBO,IAAI,EAAEL,KAAK,CAACK,IAAI;EAChBC,WAAW,EAAEC,gBAAQ,CAACC,SAAS,CAACR,KAAK,CAACS,UAAU,CAAC;EACjDC,QAAQ,EAAEV,KAAK,CAACU;CACjB,CAAC;AAoCF;;;;;;;;;;;;AAAAnB,OAAA,CAAAQ,WAAA,GAAAA,WAAA;AAYA,MAAMY,YAAY,GAAIvB,KAAc,IAAc;EAChD,IAAI,OAAOA,KAAK,KAAK,QAAQ,IAAIA,KAAK,KAAK,IAAI,IAAIwB,KAAK,CAACC,OAAO,CAACzB,KAAK,CAAC,EAAE;IACvE,MAAM,IAAI0B,KAAK,CACb,sFAAsFzB,IAAI,CAACC,SAAS,CAACF,KAAK,CAAC,IAAI,CAChH;EACH;EACA,OAAOA,KAAiB;AAC1B,CAAC;AAED;;;;;;;;;;;;;;;;;;AAkBO,MAAM2B,cAAc,GAAIC,GAAa,KAAsB;EAChEhB,KAAK,EAAE;IACLC,IAAI,EAAEe,GAAG,CAACf,IAAwB;IAClCC,IAAI,EAAEc,GAAG,CAACd,IAAI,IAAI,IAAIe,UAAU,CAAC,CAAC,CAAC;IACnCnB,IAAI,EAAEkB,GAAG,CAAClB,IAAmC;IAC7CO,IAAI,EAAEW,GAAG,CAACX,IAAwB;IAClCI,UAAU,EAAEF,gBAAQ,CAACW,cAAc,CAACF,GAAG,CAACV,WAAW,CAAC;IACpDI,QAAQ,EAAEC,YAAY,CAACK,GAAG,CAACN,QAAQ;GACpC;EACDS,QAAQ,EAAEC,MAAM,CAACJ,GAAG,CAACK,EAAE;CACxB,CAAC;AAAA9B,OAAA,CAAAwB,cAAA,GAAAA,cAAA","ignoreList":[]}