@shivaedev/sql 0.32.0 → 0.33.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/CHANGELOG.md +8 -0
- package/README.md +51 -14
- package/dist/conditionalUpsert.d.ts +4 -3
- package/dist/conditionalUpsert.d.ts.map +1 -1
- package/dist/conditionalUpsert.js +1 -1
- package/dist/conditionalUpsert.js.map +1 -1
- package/dist/conflictWrites.d.ts +6 -5
- package/dist/conflictWrites.d.ts.map +1 -1
- package/dist/conflictWrites.js +1 -1
- package/dist/conflictWrites.js.map +1 -1
- package/dist/inValues.d.ts +5 -0
- package/dist/inValues.d.ts.map +1 -0
- package/dist/inValues.js +10 -0
- package/dist/inValues.js.map +1 -0
- package/dist/int4Array.d.ts +5 -0
- package/dist/int4Array.d.ts.map +1 -0
- package/dist/int4Array.js +10 -0
- package/dist/int4Array.js.map +1 -0
- package/dist/int8.d.ts +5 -0
- package/dist/int8.d.ts.map +1 -0
- package/dist/int8.js +9 -0
- package/dist/int8.js.map +1 -0
- package/dist/listenForChanges.js +2 -2
- package/dist/listenForChanges.js.map +1 -1
- package/dist/makeConflictClause.d.ts +2 -1
- package/dist/makeConflictClause.d.ts.map +1 -1
- package/dist/makeConflictClause.js +12 -4
- package/dist/makeConflictClause.js.map +1 -1
- package/dist/upsertColumns.d.ts +16 -0
- package/dist/upsertColumns.d.ts.map +1 -0
- package/dist/upsertColumns.js +2 -0
- package/dist/upsertColumns.js.map +1 -0
- package/package.json +6 -6
- package/src/conditionalUpsert.ts +4 -3
- package/src/conflictWrites.ts +11 -7
- package/src/inValues.ts +11 -0
- package/src/int4Array.ts +14 -0
- package/src/int8.ts +14 -0
- package/src/listenForChanges.ts +2 -2
- package/src/makeConflictClause.ts +22 -6
- package/src/upsertColumns.ts +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.33.0 - 2026-11-02
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Repository `upsert` and `upsertMany` accept per-field `add` and `keepOnNull` modes in `updateColumns`, including conditional upserts. Counter additions run atomically in SQL, while null incoming values can preserve stored values; record and bucket changes still publish after commit.
|
|
8
|
+
- `inValues(column, values)` supplies a native SQL predicate that matches nothing for an empty list, including qualified columns in `SqlSchema` queries.
|
|
9
|
+
- `int8(field)` and `int4Array(field)` preserve field schemas while encoding native PostgreSQL storage parameters for bigint values and integer arrays, including empty arrays.
|
|
10
|
+
|
|
3
11
|
## 0.32.0 - 2026-11-02
|
|
4
12
|
|
|
5
13
|
### Added
|
package/README.md
CHANGED
|
@@ -129,27 +129,24 @@ const createdAt = Model.Field({
|
|
|
129
129
|
|
|
130
130
|
This field is absent from insert and update. A PostgreSQL `timestamptz` default supplies a `Date` on the database boundary, while the JSON codec encodes a string. Choose each field's schema for the values its driver or transport actually returns.
|
|
131
131
|
|
|
132
|
-
For
|
|
132
|
+
For PostgreSQL `int8` and one-dimensional `int4[]` columns, wrap the field's value schema with a storage codec:
|
|
133
133
|
|
|
134
134
|
```ts
|
|
135
|
-
import
|
|
136
|
-
import {
|
|
135
|
+
import { int8 } from "@shivaedev/sql/int8.ts";
|
|
136
|
+
import { int4Array } from "@shivaedev/sql/int4Array.ts";
|
|
137
137
|
|
|
138
138
|
const Integers = Schema.Array(Schema.Int);
|
|
139
|
-
const StoredIntegers =
|
|
140
|
-
Schema.decodeTo(Integers, {
|
|
141
|
-
decode: SchemaGetter.transformEffect((value) => SchemaParser.decodeUnknownEffect(Integers)(PgTypes.isParameter(value) ? value.value : value)),
|
|
142
|
-
encode: SchemaGetter.transform((values) => Result.getOrThrow(PgTypes.array(values, PgTypes.OID.int4))),
|
|
143
|
-
}),
|
|
144
|
-
);
|
|
139
|
+
const StoredIntegers = int4Array(Integers);
|
|
145
140
|
|
|
146
141
|
class Sample extends Model.Class<Sample>("Sample")({
|
|
147
|
-
id: Schema.
|
|
142
|
+
id: int8(Schema.BigInt),
|
|
148
143
|
values: Model.Field({ insert: StoredIntegers, select: StoredIntegers, update: StoredIntegers, json: Integers }),
|
|
149
144
|
}) {}
|
|
150
145
|
```
|
|
151
146
|
|
|
152
|
-
|
|
147
|
+
`int8(field)` keeps bigint values exact beyond `Number.MAX_SAFE_INTEGER` and encodes native `PgTypes.int8` parameters. The native driver returns `bigint`; no conversion through a JS number occurs. `int4Array(field)` encodes a native array parameter with the `int4` element OID, including for an empty array. Both take the field schema, preserve its validation, and unwrap their native parameters when repository writes decode returned rows. PostgreSQL still enforces its integer ranges.
|
|
148
|
+
|
|
149
|
+
Use the array storage codec on select, insert and update so equality filters encode empty arrays too. Keep an ordinary array schema for JSON. A bigint field transported as JSON likewise needs an explicit transport codec in its JSON variant; these helpers describe database storage.
|
|
153
150
|
|
|
154
151
|
For a PostgreSQL `jsonb` column, wrap the value schema with `jsonb`:
|
|
155
152
|
|
|
@@ -346,6 +343,29 @@ Here `archive` is another unversioned `InvoiceLine` repository with its own tabl
|
|
|
346
343
|
|
|
347
344
|
A repository configured with `conflictColumns` also exposes `insertFromSelectOrIgnore(source, columns)`. It uses the same conflict columns and optional `conflictWhere` predicate as `insertOrIgnore`, skips existing keys, and returns only inserted rows. An empty source returns `[]`. Both writes join `transact` and roll back with it. Source filter encoding services and target result decoding services remain in the write's Effect environment.
|
|
348
345
|
|
|
346
|
+
### Native SQL list predicates
|
|
347
|
+
|
|
348
|
+
`inValues(column, values)` from `@shivaedev/sql/inValues.ts` returns an Effect requiring the native `SqlClient`. It builds a native SQL fragment: an empty list matches nothing, and a non-empty list binds each value as a parameter. Pass a column name or a native fragment for a qualified column. Keep request encoding, result decoding and the SQL itself in native `SqlSchema`:
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
import { SqlClient, SqlSchema } from "effect/sql";
|
|
352
|
+
import { inValues } from "@shivaedev/sql/inValues.ts";
|
|
353
|
+
|
|
354
|
+
const sql = yield* SqlClient.SqlClient;
|
|
355
|
+
const paymentsBySequence = SqlSchema.findAll({
|
|
356
|
+
Request: Schema.Array(Payment.fields.sequence),
|
|
357
|
+
Result: Schema.Struct({ sequence: Payment.fields.sequence }),
|
|
358
|
+
execute: (sequences) => Effect.gen(function* () {
|
|
359
|
+
const predicate = yield* inValues(sql`p.${sql("sequence")}`, sequences);
|
|
360
|
+
return yield* sql`select p.sequence from payments p where ${predicate}`;
|
|
361
|
+
}),
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const rows = yield* paymentsBySequence([]);
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
`rows` is empty even when the table contains payments. The helper takes its column explicitly and leaves native `SqlSchema` visible. Use native SQL with composed schemas for joins; this helper adds no query layer or typed join.
|
|
368
|
+
|
|
349
369
|
### Composite keys and idempotent writes
|
|
350
370
|
|
|
351
371
|
A generated app can ingest the same reading more than once. Declare the table's primary key with an `idColumn` tuple and its unique conflict key with `conflictColumns`:
|
|
@@ -384,7 +404,7 @@ The application creates `readings` with `PRIMARY KEY (source, sequence)`; `seque
|
|
|
384
404
|
| `insertManyOrIgnore` | Readonly array of model insert inputs | Decoded inserted models; conflicting rows are omitted. |
|
|
385
405
|
| `upsertMany` | Readonly array of model insert inputs and `{ updateColumns: [...] }` | An array of `{ row, inserted }` results. |
|
|
386
406
|
|
|
387
|
-
All four methods encode with the model's insert schema and retain its codec services. `upsert` and `upsertMany` require a nonempty list of inserted, updateable fields; primary-key, conflict-key and generated fields are excluded.
|
|
407
|
+
All four methods encode with the model's insert schema and retain its codec services. `upsert` and `upsertMany` require a nonempty list of inserted, updateable fields; primary-key, conflict-key and generated fields are excluded. String entries replace those columns with their incoming encoded values on conflict. Other stored values stay intact. A selected optional field must be present in every encoded input. Unknown, empty, protected or absent update columns fail with `SchemaError`. A violation of another unique constraint remains a native `SqlError`.
|
|
388
408
|
|
|
389
409
|
For a partial unique index such as `CREATE UNIQUE INDEX ON entries (a, b) WHERE kind = 'x'`, add `conflictWhere` beside `conflictColumns`:
|
|
390
410
|
|
|
@@ -401,6 +421,20 @@ const inserted = yield* entries.insertManyOrIgnore(inputs);
|
|
|
401
421
|
|
|
402
422
|
All four conflict methods use this target, producing `ON CONFLICT (a, b) WHERE kind = $n` before `DO NOTHING` or `DO UPDATE SET ...`, followed by `RETURNING`. `conflictWhere` uses typed equality entries like `findMany.where`: decoded field values pass through their field codecs and remain bound parameters. Rows outside the index predicate can insert with the same key. A target that matches no unique index fails with native `SqlError` in the error channel. Use native `SqlClient` and `SqlSchema` for SQL expressions or other conflict policies.
|
|
403
423
|
|
|
424
|
+
Declare conflict behavior per field in the same `updateColumns` list:
|
|
425
|
+
|
|
426
|
+
```ts
|
|
427
|
+
const saved = yield* counters.upsert(incoming, {
|
|
428
|
+
updateColumns: [
|
|
429
|
+
{ column: "count", mode: "add" },
|
|
430
|
+
{ column: "label", mode: "keepOnNull" },
|
|
431
|
+
"note",
|
|
432
|
+
],
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
`add` computes the stored column plus its incoming encoded value inside the conflict update, so concurrent increments from separate PostgreSQL connections all count. Its model field must decode to a number, bigint or `BigDecimal`; choose a storage codec and SQL column that support native addition. `keepOnNull` uses the incoming value when it is non-null and keeps the stored value when it is SQL `NULL`. A string entry still replaces the field. Inserts use the incoming values directly. These entries also work in `upsertMany` and with `updateWhere`, and publish the same record and old/new bucket keys as other repository writes.
|
|
437
|
+
|
|
404
438
|
On PostgreSQL, pass `updateWhere` to conditionally apply the update branch:
|
|
405
439
|
|
|
406
440
|
```ts
|
|
@@ -668,7 +702,7 @@ const delivery = postgresChanges({
|
|
|
668
702
|
|
|
669
703
|
`pg` is the application's `@effect/sql-pg` client; the binding accepts its native SQL and `listen` methods without creating another pool. Optional `listenerClient` supplies a different native client for LISTEN; the application client still owns write notifications and heartbeat publication. Both clients must reach the same database. LISTEN requires a direct or session-mode connection. With one shared client, reserve one session connection for LISTEN and another for writes and heartbeats; use a pool client with at least two connections. With separate clients, the listener needs one connection of its own. Compose `delivery` into the Layer that provides feature services using `transact`, alongside the existing SQL and Reactivity services. The [reference server](https://github.com/ShivaeDev/platform/blob/main/packages/react/src/test-support/postgres-example/server.ts) shows the complete composition. The binding sends `select pg_notify(...)` through the writing transaction's `SqlClient`, so a rollback wakes no process. Its transaction sink leaves delivery to the listener, including in the writing process. Unframed `invalidateOnCommit` calls retain local invalidation; cross-process writes must use `transact`.
|
|
670
704
|
|
|
671
|
-
`PostgresChangesOptions` takes `channel`, `client`, `resync`, optional `listenerClient` and `connectionSetting` (a diagnostic label, default `"client"`), and optional `heartbeatInterval`, `heartbeatTimeout` and `retryDelay` Effect durations. The defaults are 5 seconds, 10 seconds and 1 second. Acquisition waits for LISTEN and then a heartbeat received through it, each within `heartbeatTimeout`. A deadline without a heartbeat fails startup with `PostgresListenerError` from `@shivaedev/sql/PostgresListenerError.ts`, whose `connectionSetting` and message identify the connection to fix. Native SQL failures still fail startup with `SqlError`. Established listeners reconnect after a loss. Loss and reconnect
|
|
705
|
+
`PostgresChangesOptions` takes `channel`, `client`, `resync`, optional `listenerClient` and `connectionSetting` (a diagnostic label, default `"client"`), and optional `heartbeatInterval`, `heartbeatTimeout` and `retryDelay` Effect durations. The defaults are 5 seconds, 10 seconds and 1 second. Acquisition waits for LISTEN and then a heartbeat received through it, each within `heartbeatTimeout`. A deadline without a heartbeat fails startup with `PostgresListenerError` from `@shivaedev/sql/PostgresListenerError.ts`, whose `connectionSetting` and message identify the connection to fix. Native SQL failures still fail startup with `SqlError`. Established listeners reconnect after a loss. Loss warnings and reconnect debug logs omit database causes. A missing heartbeat or a stream failure resyncs streams before listener cleanup; a successful reconnection resyncs again. Listener cleanup runs in a parallel sub-scope bounded by `heartbeatTimeout`, so stalled listener cleanup cannot delay native connection release, a fresh subscription or scope shutdown. The heartbeat detects a listener that stops delivering without failing. `resync` is an infallible `Effect.Effect<number>` returning the number of open live streams it marked for reconciliation. `makeLiveServer.resync` provides this count and stops counting a stream when its scope closes. Direct bindings with another stream owner must return that owner's count. Provide the Layer for the process lifetime so scope release closes the listener.
|
|
672
706
|
|
|
673
707
|
NOTIFY is a wake-up signal, not a durable log. Transaction payloads contain only string or finite-number invalidation keys, with no row values. PostgreSQL requires each payload to be smaller than 8,000 bytes in the default configuration. The binding splits JSON arrays by their UTF-8 byte length; one key that cannot fit, or a nonserializable key type, fails with `SqlError` before commit and rolls back the write. Heartbeats use a separate control payload on the same channel. Applications choose a channel shared only by their cooperating processes. LISTEN requires a session connection; PgBouncer transaction pooling needs another delivery adapter. Missed notifications are reconciled by querying again on resync, with no replay guarantee.
|
|
674
708
|
|
|
@@ -676,6 +710,9 @@ NOTIFY is a wake-up signal, not a durable log. Transaction payloads contain only
|
|
|
676
710
|
|
|
677
711
|
Import the module that defines the name; there is no root entry.
|
|
678
712
|
- `@shivaedev/sql/clientOptions.ts`: `clientOptions(options, { snakeCase? })`, `SqlNameTransforms` — Add default native name transforms to driver or app host options; opt out with `snakeCase: false`.
|
|
713
|
+
- `@shivaedev/sql/inValues.ts`: `inValues(column, values)` — Native list predicate with match-nothing semantics for an empty list; requires `SqlClient`.
|
|
714
|
+
- `@shivaedev/sql/int8.ts`: `int8(field)` — PostgreSQL bigint storage codec using the supplied field schema.
|
|
715
|
+
- `@shivaedev/sql/int4Array.ts`: `int4Array(field)` — PostgreSQL integer-array storage codec, including typed empty arrays.
|
|
679
716
|
- `@shivaedev/sql/repository.ts`: `makeRepository(model, options)` — `tableName`, scalar or composite `idColumn`, `spanPrefix`, optional `versionColumn`, `conflictColumns` and `conflictWhere`, and `collection` required for bucket models; requires native `SqlClient`.
|
|
680
717
|
- `@shivaedev/sql/repository.ts`: `OptimisticConcurrencyError` — Typed stale or missing-row failure for versioned writes, with `tableName`, `id`, `expectedVersion`, `reason: "missing" | "stale"`.
|
|
681
718
|
- `@shivaedev/sql/tupleIn.ts`: `tupleIn(model, fields, tuples, types)` — Filter entry matching two or more fields together against a list of tuples, for `where` in reads and unversioned deletes.
|
|
@@ -747,7 +784,7 @@ The mapper handles named unique violations and PostgreSQL foreign-key and check
|
|
|
747
784
|
|
|
748
785
|
Recover outside `transact` so earlier writes roll back before handling a mapped domain error. A losing unique-key insert can then catch `NameTaken` and read the winner's row without a private transaction error. See the [constraint-failures guide](https://github.com/ShivaeDev/platform/blob/main/docs/framework/constraint-errors.md).
|
|
749
786
|
|
|
750
|
-
For the native PostgreSQL driver's default representations, use precise numeric strings with `Schema.BigDecimalFromString`, `int8` values with `Schema.BigInt`, `date` values as `YYYY-MM-DD` strings with `Schema.String`, instants with `Schema.Date`, nullable text and generated values. A persisted value that violates its schema fails decoding; a write and read inside the enclosing transaction roll back together when that failure escapes.
|
|
787
|
+
For the native PostgreSQL driver's default representations, use precise numeric strings with `Schema.BigDecimalFromString`, `int8` values with `int8(Schema.BigInt)`, `date` values as `YYYY-MM-DD` strings with `Schema.String`, instants with `Schema.Date`, nullable text and generated values. A persisted value that violates its schema fails decoding; a write and read inside the enclosing transaction roll back together when that failure escapes.
|
|
751
788
|
|
|
752
789
|
JSON and JSONB columns are not supported. A repository write of a plain object to one fails with `SqlError` and writes nothing. Give structured data its own columns, or its own table when it repeats, so PostgreSQL constraints and the model both describe it.
|
|
753
790
|
|
|
@@ -2,9 +2,10 @@ import { Effect, Schema } from "effect";
|
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
3
|
import type { SqlClient } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
|
+
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
5
6
|
import type { Comparisons, FindManyFilter } from "#repositoryFilter.ts";
|
|
6
|
-
import type {
|
|
7
|
-
import { type UpsertRow } from "
|
|
7
|
+
import type { UpsertAssignment } from "#upsertColumns.ts";
|
|
8
|
+
import { type UpsertRow } from "#upsertResult.ts";
|
|
8
9
|
type Fields<TModel extends Model.Any> = Schema.Struct.Type<TModel["fields"]>;
|
|
9
10
|
interface Incoming<TModel extends Model.Any, TValue> {
|
|
10
11
|
readonly excluded: {
|
|
@@ -49,7 +50,7 @@ export declare function makeConditionalUpsert(model: Model.Any, sql: SqlClient.S
|
|
|
49
50
|
readonly conflictWhere?: Readonly<Record<string, unknown>>;
|
|
50
51
|
readonly idColumns: readonly string[];
|
|
51
52
|
}): (inputs: readonly unknown[], settings: {
|
|
52
|
-
readonly updateColumns: readonly
|
|
53
|
+
readonly updateColumns: readonly UpsertAssignment[];
|
|
53
54
|
readonly updateWhere: Readonly<Record<string, unknown>>;
|
|
54
55
|
}) => Effect.Effect<({
|
|
55
56
|
readonly _tag: "Unchanged";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditionalUpsert.d.ts","sourceRoot":"","sources":["../src/conditionalUpsert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"conditionalUpsert.d.ts","sourceRoot":"","sources":["../src/conditionalUpsert.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import { makeConflictClause } from "#makeConflictClause.ts";
|
|
3
|
-
import { makeUpsertDecoder, upsertReturning } from "
|
|
3
|
+
import { makeUpsertDecoder, upsertReturning } from "#upsertResult.ts";
|
|
4
4
|
export function makeConditionalUpsert(model, sql, options) {
|
|
5
5
|
const encode = Schema.encodeEffect(model.insert);
|
|
6
6
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conditionalUpsert.js","sourceRoot":"","sources":["../src/conditionalUpsert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"conditionalUpsert.js","sourceRoot":"","sources":["../src/conditionalUpsert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAI5D,OAAO,EAAE,iBAAiB,EAAkB,eAAe,EAAE,MAAM,kBAAkB,CAAC;AA+CtF,MAAM,UAAU,qBAAqB,CACpC,KAAgB,EAChB,GAAwB,EACxB,OAOC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACvD,OAAO,CACN,MAA0B,EAC1B,QAA0H,EACzH,EAAE,CACH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAC1D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAChD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;YAChF,OAAO,GAAG,CAAA,eAAe,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,cAAc,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC7I,CAAC,CAAC,CACF,CAAC;QACF,MAAM,WAAW,GAAwC,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,EAAE,CAC/D,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;YAC9B,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;YAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO,EAAE,IAAI,EAAE,WAAW,EAAW,CAAC;YACvC,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAClC,OAAO,MAAM,CAAC,QAAQ;gBACrB,CAAC,CAAE,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAY;gBAC5D,CAAC,CAAE,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAY,CAAC;QAC/D,CAAC,CAAC,CACF,CAAC;QACF,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC;IAChB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,UAAU,oBAAoB,CAAC,CAAC,CAAC;AAC7F,CAAC"}
|
package/dist/conflictWrites.d.ts
CHANGED
|
@@ -5,13 +5,14 @@ import type { SqlError } from "effect/sql/SqlError";
|
|
|
5
5
|
import { type InsertMany } from "#batchWrites.ts";
|
|
6
6
|
import { type ConditionalUpsert, type ConditionalUpsertMany } from "#conditionalUpsert.ts";
|
|
7
7
|
import { type InsertFromSelect } from "#insertFromSelect.ts";
|
|
8
|
-
import type { RepositoryChanges } from "
|
|
8
|
+
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
9
|
+
import type { UpsertAssignment, UpsertColumn } from "#upsertColumns.ts";
|
|
9
10
|
export type InsertColumn<TModel extends Model.Any> = Extract<keyof TModel["insert"]["Type"] & keyof TModel["fields"], string>;
|
|
10
11
|
export type ConflictColumns<TModel extends Model.Any> = readonly [InsertColumn<TModel>, ...InsertColumn<TModel>[]];
|
|
11
12
|
interface UpdateOptions<TModel extends Model.Any, TExcluded extends PropertyKey> {
|
|
12
13
|
readonly updateColumns: readonly [
|
|
13
|
-
Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded
|
|
14
|
-
...Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded
|
|
14
|
+
UpsertColumn<TModel, Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded>>,
|
|
15
|
+
...UpsertColumn<TModel, Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded>>[]
|
|
15
16
|
];
|
|
16
17
|
}
|
|
17
18
|
export interface ConflictWrites<TModel extends Model.Any, TExcluded extends PropertyKey, TFilterServices = never> {
|
|
@@ -33,7 +34,7 @@ export declare function makeConflictWrites(model: Model.Any, sql: SqlClient.SqlC
|
|
|
33
34
|
insertManyOrIgnore: (inputs: readonly unknown[]) => Effect.Effect<unknown[], Schema.SchemaError | SqlError, unknown>;
|
|
34
35
|
insertOrIgnore: (input: unknown) => Effect.Effect<Option.None<unknown> | Option.Some<unknown>, Schema.SchemaError | SqlError, unknown>;
|
|
35
36
|
upsert: (input: unknown, settings: {
|
|
36
|
-
readonly updateColumns: readonly
|
|
37
|
+
readonly updateColumns: readonly UpsertAssignment[];
|
|
37
38
|
readonly updateWhere?: Readonly<Record<string, unknown>>;
|
|
38
39
|
}) => Effect.Effect<{
|
|
39
40
|
inserted: boolean;
|
|
@@ -50,7 +51,7 @@ export declare function makeConflictWrites(model: Model.Any, sql: SqlClient.SqlC
|
|
|
50
51
|
readonly inserted: false;
|
|
51
52
|
} | undefined, Schema.SchemaError | SqlError, unknown>;
|
|
52
53
|
upsertMany: (inputs: readonly unknown[], settings: {
|
|
53
|
-
readonly updateColumns: readonly
|
|
54
|
+
readonly updateColumns: readonly UpsertAssignment[];
|
|
54
55
|
readonly updateWhere?: Readonly<Record<string, unknown>>;
|
|
55
56
|
}) => Effect.Effect<unknown[], Schema.SchemaError | SqlError, unknown>;
|
|
56
57
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conflictWrites.d.ts","sourceRoot":"","sources":["../src/conflictWrites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,KAAK,UAAU,EAAkB,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAyB,MAAM,uBAAuB,CAAC;AAClH,OAAO,EAAE,KAAK,gBAAgB,EAAwB,MAAM,sBAAsB,CAAC;AAEnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"conflictWrites.d.ts","sourceRoot":"","sources":["../src/conflictWrites.ts"],"names":[],"mappings":"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"}
|
package/dist/conflictWrites.js
CHANGED
|
@@ -3,7 +3,7 @@ import { makeInsertMany } from "#batchWrites.ts";
|
|
|
3
3
|
import { makeConditionalUpsert } from "#conditionalUpsert.ts";
|
|
4
4
|
import { makeInsertFromSelect } from "#insertFromSelect.ts";
|
|
5
5
|
import { makeConflictClause } from "#makeConflictClause.ts";
|
|
6
|
-
import { makeUpsertDecoder, upsertReturning } from "
|
|
6
|
+
import { makeUpsertDecoder, upsertReturning } from "#upsertResult.ts";
|
|
7
7
|
export function makeConflictWrites(model, sql, options) {
|
|
8
8
|
const { tableName, spanPrefix } = options;
|
|
9
9
|
const encode = Schema.encodeEffect(model.insert);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conflictWrites.js","sourceRoot":"","sources":["../src/conflictWrites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhD,OAAO,EAAmB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAsD,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAClH,OAAO,EAAyB,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"conflictWrites.js","sourceRoot":"","sources":["../src/conflictWrites.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import type { Fragment } from "effect/sql/Statement";
|
|
4
|
+
export declare const inValues: (column: string | Fragment, values: readonly unknown[]) => Effect.Effect<import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>, never, SqlClient.SqlClient>;
|
|
5
|
+
//# sourceMappingURL=inValues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inValues.d.ts","sourceRoot":"","sources":["../src/inValues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,eAAO,MAAM,QAAQ,wLAMnB,CAAC"}
|
package/dist/inValues.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
export const inValues = Effect.fnUntraced(function* (column, values) {
|
|
4
|
+
const sql = yield* SqlClient.SqlClient;
|
|
5
|
+
if (values.length === 0) {
|
|
6
|
+
return sql `1 = 0`;
|
|
7
|
+
}
|
|
8
|
+
return sql `${typeof column === "string" ? sql(column) : column} in ${sql.in(values)}`;
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=inValues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inValues.js","sourceRoot":"","sources":["../src/inValues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAyB,EAAE,MAA0B;IACzG,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,CAAA,OAAO,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAA,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;AACvF,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare function int4Array<TField extends Schema.Top & {
|
|
3
|
+
readonly Encoded: readonly number[];
|
|
4
|
+
}>(field: TField): Schema.compose<TField, Schema.decodeTo<Schema.$Array<Schema.Int>, Schema.Unknown, never, never>>;
|
|
5
|
+
//# sourceMappingURL=int4Array.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"int4Array.d.ts","sourceRoot":"","sources":["../src/int4Array.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,MAAM,EAA8B,MAAM,QAAQ,CAAC;AAIpE,wBAAgB,SAAS,CAAC,MAAM,SAAS,MAAM,CAAC,GAAG,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,KAAK,EAAE,MAAM,oGAQ3G"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as PgTypes from "@effect/sql-pg/PgTypes";
|
|
2
|
+
import { Result, Schema, SchemaGetter, SchemaParser } from "effect";
|
|
3
|
+
const Integers = Schema.Array(Schema.Int);
|
|
4
|
+
export function int4Array(field) {
|
|
5
|
+
return Schema.Unknown.pipe(Schema.decodeTo(Integers, {
|
|
6
|
+
decode: SchemaGetter.transformEffect((value) => SchemaParser.decodeUnknownEffect(Integers)(PgTypes.isParameter(value) ? value.value : value)),
|
|
7
|
+
encode: SchemaGetter.transform((values) => Result.getOrThrow(PgTypes.array(values, PgTypes.OID.int4))),
|
|
8
|
+
}), Schema.decodeTo(field));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=int4Array.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"int4Array.js","sourceRoot":"","sources":["../src/int4Array.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEpE,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAE1C,MAAM,UAAU,SAAS,CAAsE,KAAa;IAC3G,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CACzB,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACzB,MAAM,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC7I,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;KACtG,CAAC,EACF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CACtB,CAAC;AACH,CAAC"}
|
package/dist/int8.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"int8.d.ts","sourceRoot":"","sources":["../src/int8.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA8B,MAAM,QAAQ,CAAC;AAE5D,wBAAgB,IAAI,CAAC,MAAM,SAAS,MAAM,CAAC,GAAG,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,MAAM,wFAU3F"}
|
package/dist/int8.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as PgTypes from "@effect/sql-pg/PgTypes";
|
|
2
|
+
import { Schema, SchemaGetter, SchemaParser } from "effect";
|
|
3
|
+
export function int8(field) {
|
|
4
|
+
return Schema.Unknown.pipe(Schema.decodeTo(Schema.BigInt, {
|
|
5
|
+
decode: SchemaGetter.transformEffect((value) => SchemaParser.decodeUnknownEffect(Schema.BigInt)(PgTypes.isParameter(value) ? value.value : value)),
|
|
6
|
+
encode: SchemaGetter.transform(PgTypes.int8),
|
|
7
|
+
}), Schema.decodeTo(field));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=int8.js.map
|
package/dist/int8.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"int8.js","sourceRoot":"","sources":["../src/int8.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE5D,MAAM,UAAU,IAAI,CAA2D,KAAa;IAC3F,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CACzB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;QAC9B,MAAM,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9C,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CACjG;QACD,MAAM,EAAE,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;KAC5C,CAAC,EACF,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CACtB,CAAC;AACH,CAAC"}
|
package/dist/listenForChanges.js
CHANGED
|
@@ -67,11 +67,11 @@ export const listenForChanges = Effect.fn("PostgresChanges.listenForChanges")(fu
|
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
if (lostAt !== undefined) {
|
|
70
|
-
yield* Effect.logDebug("PostgreSQL change listener reconnect failed; retrying"
|
|
70
|
+
yield* Effect.logDebug("PostgreSQL change listener reconnect failed; retrying");
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
lostAt = yield* Clock.currentTimeMillis;
|
|
74
|
-
yield* Effect.logWarning("PostgreSQL change listener lost; resynchronizing live streams"
|
|
74
|
+
yield* Effect.logWarning("PostgreSQL change listener lost; resynchronizing live streams");
|
|
75
75
|
}).pipe(Effect.andThen(Effect.sleep(options.retryDelay ?? "1 second")))))).pipe(Effect.forkScoped);
|
|
76
76
|
yield* Deferred.await(ready);
|
|
77
77
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listenForChanges.js","sourceRoot":"","sources":["../src/listenForChanges.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"listenForChanges.js","sourceRoot":"","sources":["../src/listenForChanges.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
3
|
import type { SqlClient } from "effect/sql";
|
|
4
|
+
import type { UpsertAssignment } from "#upsertColumns.ts";
|
|
4
5
|
export declare function makeConflictClause(model: Model.Any, sql: SqlClient.SqlClient, options: {
|
|
5
6
|
readonly tableName: string;
|
|
6
7
|
readonly conflictColumns: readonly string[];
|
|
7
8
|
readonly conflictWhere?: Readonly<Record<string, unknown>>;
|
|
8
9
|
readonly idColumns: readonly string[];
|
|
9
|
-
}): (encoded: Readonly<Record<string, unknown>>, updateColumns?: readonly
|
|
10
|
+
}): (encoded: Readonly<Record<string, unknown>>, updateColumns?: readonly UpsertAssignment[], updateWhere?: Readonly<Record<string, unknown>>) => Effect.Effect<import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>, Schema.SchemaError, unknown>;
|
|
10
11
|
//# sourceMappingURL=makeConflictClause.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeConflictClause.d.ts","sourceRoot":"","sources":["../src/makeConflictClause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAA0B,MAAM,QAAQ,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"makeConflictClause.d.ts","sourceRoot":"","sources":["../src/makeConflictClause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAA0B,MAAM,QAAQ,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,KAAK,CAAC,GAAG,EAChB,GAAG,EAAE,SAAS,CAAC,SAAS,EACxB,OAAO,EAAE;IACR,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,aAiCS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kBAC1B,SAAS,gBAAgB,EAAE,gBAC7B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kIAmBhD"}
|
|
@@ -21,17 +21,25 @@ export function makeConflictClause(model, sql, options) {
|
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
+
function assignment(entry) {
|
|
25
|
+
const column = typeof entry === "string" ? entry : entry.column;
|
|
26
|
+
const incoming = sql `excluded.${sql(column)}`;
|
|
27
|
+
const stored = sql `${sql(options.tableName)}.${sql(column)}`;
|
|
28
|
+
let value = incoming;
|
|
29
|
+
if (typeof entry !== "string") {
|
|
30
|
+
value = entry.mode === "add" ? sql `${stored} + ${incoming}` : sql `coalesce(${incoming}, ${stored})`;
|
|
31
|
+
}
|
|
32
|
+
return sql `${sql(column)} = ${value}`;
|
|
33
|
+
}
|
|
24
34
|
function clause(encoded, updateColumns, updateWhere) {
|
|
25
35
|
return Effect.gen(function* () {
|
|
26
36
|
yield* validateColumns(encoded, conflictColumns);
|
|
27
37
|
if (updateColumns !== undefined) {
|
|
28
|
-
yield* validateColumns(encoded, updateColumns, [...idColumns, ...conflictColumns, ...immutable]);
|
|
38
|
+
yield* validateColumns(encoded, updateColumns.map((entry) => (typeof entry === "string" ? entry : entry.column)), [...idColumns, ...conflictColumns, ...immutable]);
|
|
29
39
|
}
|
|
30
40
|
const conflict = sql.csv(conflictColumns.map((column) => sql `${sql(column)}`));
|
|
31
41
|
const where = options.conflictWhere === undefined ? sql `` : sql `where ${yield* filter.where(options.conflictWhere)}`;
|
|
32
|
-
const action = updateColumns === undefined
|
|
33
|
-
? sql `do nothing`
|
|
34
|
-
: sql `do update set ${sql.csv(updateColumns.map((column) => sql `${sql(column)} = excluded.${sql(column)}`))}`;
|
|
42
|
+
const action = updateColumns === undefined ? sql `do nothing` : sql `do update set ${sql.csv(updateColumns.map(assignment))}`;
|
|
35
43
|
const condition = updateWhere === undefined ? sql `` : sql `where ${yield* updateFilter.where(updateWhere, true, true)}`;
|
|
36
44
|
return sql `on conflict (${conflict}) ${where} ${action} ${condition}`;
|
|
37
45
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeConflictClause.js","sourceRoot":"","sources":["../src/makeConflictClause.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGhE,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"makeConflictClause.js","sourceRoot":"","sources":["../src/makeConflictClause.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BigDecimal } from "effect";
|
|
2
|
+
import type { Model } from "effect/schema";
|
|
3
|
+
export type UpsertColumn<TModel extends Model.Any, TColumn extends keyof TModel["fields"]> = TColumn | {
|
|
4
|
+
readonly column: TColumn;
|
|
5
|
+
readonly mode: "keepOnNull";
|
|
6
|
+
} | {
|
|
7
|
+
[TKey in TColumn]: NonNullable<TModel["fields"][TKey]["Type"]> extends number | bigint | BigDecimal.BigDecimal ? {
|
|
8
|
+
readonly column: TKey;
|
|
9
|
+
readonly mode: "add";
|
|
10
|
+
} : never;
|
|
11
|
+
}[TColumn];
|
|
12
|
+
export type UpsertAssignment = string | {
|
|
13
|
+
readonly column: string;
|
|
14
|
+
readonly mode: "add" | "keepOnNull";
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=upsertColumns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsertColumns.d.ts","sourceRoot":"","sources":["../src/upsertColumns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,MAAM,YAAY,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,OAAO,SAAS,MAAM,MAAM,CAAC,QAAQ,CAAC,IACtF,OAAO,GACP;IACA,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC3B,GACD;KACC,IAAI,IAAI,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC,UAAU,GAC3G;QAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAA;KAAE,GAC/C,KAAK;CACP,CAAC,OAAO,CAAC,CAAC;AAEd,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,YAAY,CAAA;CAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsertColumns.js","sourceRoot":"","sources":["../src/upsertColumns.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/sql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "Schema-derived repositories over native Effect SQL",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect"
|
|
@@ -43,17 +43,17 @@
|
|
|
43
43
|
"README.md"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@shivaedev/changes": "0.
|
|
46
|
+
"@shivaedev/changes": "0.8.0",
|
|
47
47
|
"@shivaedev/service": "0.6.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@effect/platform-node": "4.0.6",
|
|
51
51
|
"@effect/sql-pg": "4.0.6",
|
|
52
52
|
"@effect/sql-sqlite-node": "4.0.6",
|
|
53
|
-
"@shivaedev/jobs": "0.
|
|
54
|
-
"@shivaedev/quality": "0.
|
|
55
|
-
"@shivaedev/test-sql": "0.16.
|
|
56
|
-
"@shivaedev/test-story": "0.
|
|
53
|
+
"@shivaedev/jobs": "0.30.0",
|
|
54
|
+
"@shivaedev/quality": "0.56.0",
|
|
55
|
+
"@shivaedev/test-sql": "0.16.2",
|
|
56
|
+
"@shivaedev/test-story": "0.34.0",
|
|
57
57
|
"@types/node": "24.19.2",
|
|
58
58
|
"effect": "4.0.6",
|
|
59
59
|
"typescript": "7.0.2",
|
package/src/conditionalUpsert.ts
CHANGED
|
@@ -3,9 +3,10 @@ import type { Model } from "effect/schema";
|
|
|
3
3
|
import type { SqlClient } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
5
|
import { makeConflictClause } from "#makeConflictClause.ts";
|
|
6
|
+
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
6
7
|
import type { Comparisons, FindManyFilter } from "#repositoryFilter.ts";
|
|
7
|
-
import type {
|
|
8
|
-
import { makeUpsertDecoder, type UpsertRow, upsertReturning } from "
|
|
8
|
+
import type { UpsertAssignment } from "#upsertColumns.ts";
|
|
9
|
+
import { makeUpsertDecoder, type UpsertRow, upsertReturning } from "#upsertResult.ts";
|
|
9
10
|
|
|
10
11
|
type Fields<TModel extends Model.Any> = Schema.Struct.Type<TModel["fields"]>;
|
|
11
12
|
interface Incoming<TModel extends Model.Any, TValue> {
|
|
@@ -70,7 +71,7 @@ export function makeConditionalUpsert(
|
|
|
70
71
|
const clause = makeConflictClause(model, sql, options);
|
|
71
72
|
return (
|
|
72
73
|
inputs: readonly unknown[],
|
|
73
|
-
settings: { readonly updateColumns: readonly
|
|
74
|
+
settings: { readonly updateColumns: readonly UpsertAssignment[]; readonly updateWhere: Readonly<Record<string, unknown>> },
|
|
74
75
|
) =>
|
|
75
76
|
Effect.gen(function* () {
|
|
76
77
|
const statements = yield* Effect.forEach(inputs, (input) =>
|
package/src/conflictWrites.ts
CHANGED
|
@@ -6,15 +6,16 @@ import { type InsertMany, makeInsertMany } from "#batchWrites.ts";
|
|
|
6
6
|
import { type ConditionalUpsert, type ConditionalUpsertMany, makeConditionalUpsert } from "#conditionalUpsert.ts";
|
|
7
7
|
import { type InsertFromSelect, makeInsertFromSelect } from "#insertFromSelect.ts";
|
|
8
8
|
import { makeConflictClause } from "#makeConflictClause.ts";
|
|
9
|
-
import type { RepositoryChanges } from "
|
|
10
|
-
import {
|
|
9
|
+
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
10
|
+
import type { UpsertAssignment, UpsertColumn } from "#upsertColumns.ts";
|
|
11
|
+
import { makeUpsertDecoder, upsertReturning } from "#upsertResult.ts";
|
|
11
12
|
|
|
12
13
|
export type InsertColumn<TModel extends Model.Any> = Extract<keyof TModel["insert"]["Type"] & keyof TModel["fields"], string>;
|
|
13
14
|
export type ConflictColumns<TModel extends Model.Any> = readonly [InsertColumn<TModel>, ...InsertColumn<TModel>[]];
|
|
14
15
|
interface UpdateOptions<TModel extends Model.Any, TExcluded extends PropertyKey> {
|
|
15
16
|
readonly updateColumns: readonly [
|
|
16
|
-
Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded
|
|
17
|
-
...Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded
|
|
17
|
+
UpsertColumn<TModel, Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded>>,
|
|
18
|
+
...UpsertColumn<TModel, Exclude<InsertColumn<TModel> & keyof TModel["update"]["Type"], TExcluded>>[],
|
|
18
19
|
];
|
|
19
20
|
}
|
|
20
21
|
export interface ConflictWrites<TModel extends Model.Any, TExcluded extends PropertyKey, TFilterServices = never> {
|
|
@@ -58,7 +59,7 @@ export function makeConflictWrites(
|
|
|
58
59
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
59
60
|
const conditional = makeConditionalUpsert(model, sql, options);
|
|
60
61
|
const clause = makeConflictClause(model, sql, options);
|
|
61
|
-
function statement(input: unknown, updateColumns?: readonly
|
|
62
|
+
function statement(input: unknown, updateColumns?: readonly UpsertAssignment[]) {
|
|
62
63
|
return Effect.gen(function* () {
|
|
63
64
|
const encoded = yield* record(yield* encode(input));
|
|
64
65
|
const suffix = yield* clause(encoded, updateColumns);
|
|
@@ -76,7 +77,10 @@ export function makeConflictWrites(
|
|
|
76
77
|
yield* options.changes.record(rows);
|
|
77
78
|
return rows.length === 0 ? Option.none() : Option.some(yield* decode(rows[0]));
|
|
78
79
|
}).pipe(options.changes.write, Effect.withSpan(`${spanPrefix}.insertOrIgnore`)),
|
|
79
|
-
upsert: (
|
|
80
|
+
upsert: (
|
|
81
|
+
input: unknown,
|
|
82
|
+
settings: { readonly updateColumns: readonly UpsertAssignment[]; readonly updateWhere?: Readonly<Record<string, unknown>> },
|
|
83
|
+
) =>
|
|
80
84
|
settings.updateWhere === undefined
|
|
81
85
|
? Effect.gen(function* () {
|
|
82
86
|
const rows = yield* yield* statement(input, settings.updateColumns);
|
|
@@ -86,7 +90,7 @@ export function makeConflictWrites(
|
|
|
86
90
|
: conditional([input], { ...settings, updateWhere: settings.updateWhere }).pipe(Effect.map((results) => results[0])),
|
|
87
91
|
upsertMany: (
|
|
88
92
|
inputs: readonly unknown[],
|
|
89
|
-
settings: { readonly updateColumns: readonly
|
|
93
|
+
settings: { readonly updateColumns: readonly UpsertAssignment[]; readonly updateWhere?: Readonly<Record<string, unknown>> },
|
|
90
94
|
) =>
|
|
91
95
|
settings.updateWhere === undefined
|
|
92
96
|
? makeInsertMany(model, sql, options, "upsertMany", (row) => clause(row, settings.updateColumns), true)(inputs)
|
package/src/inValues.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import type { Fragment } from "effect/sql/Statement";
|
|
4
|
+
|
|
5
|
+
export const inValues = Effect.fnUntraced(function* (column: string | Fragment, values: readonly unknown[]) {
|
|
6
|
+
const sql = yield* SqlClient.SqlClient;
|
|
7
|
+
if (values.length === 0) {
|
|
8
|
+
return sql`1 = 0`;
|
|
9
|
+
}
|
|
10
|
+
return sql`${typeof column === "string" ? sql(column) : column} in ${sql.in(values)}`;
|
|
11
|
+
});
|
package/src/int4Array.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as PgTypes from "@effect/sql-pg/PgTypes";
|
|
2
|
+
import { Result, Schema, SchemaGetter, SchemaParser } from "effect";
|
|
3
|
+
|
|
4
|
+
const Integers = Schema.Array(Schema.Int);
|
|
5
|
+
|
|
6
|
+
export function int4Array<TField extends Schema.Top & { readonly Encoded: readonly number[] }>(field: TField) {
|
|
7
|
+
return Schema.Unknown.pipe(
|
|
8
|
+
Schema.decodeTo(Integers, {
|
|
9
|
+
decode: SchemaGetter.transformEffect((value) => SchemaParser.decodeUnknownEffect(Integers)(PgTypes.isParameter(value) ? value.value : value)),
|
|
10
|
+
encode: SchemaGetter.transform((values) => Result.getOrThrow(PgTypes.array(values, PgTypes.OID.int4))),
|
|
11
|
+
}),
|
|
12
|
+
Schema.decodeTo(field),
|
|
13
|
+
);
|
|
14
|
+
}
|
package/src/int8.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as PgTypes from "@effect/sql-pg/PgTypes";
|
|
2
|
+
import { Schema, SchemaGetter, SchemaParser } from "effect";
|
|
3
|
+
|
|
4
|
+
export function int8<TField extends Schema.Top & { readonly Encoded: bigint }>(field: TField) {
|
|
5
|
+
return Schema.Unknown.pipe(
|
|
6
|
+
Schema.decodeTo(Schema.BigInt, {
|
|
7
|
+
decode: SchemaGetter.transformEffect((value) =>
|
|
8
|
+
SchemaParser.decodeUnknownEffect(Schema.BigInt)(PgTypes.isParameter(value) ? value.value : value),
|
|
9
|
+
),
|
|
10
|
+
encode: SchemaGetter.transform(PgTypes.int8),
|
|
11
|
+
}),
|
|
12
|
+
Schema.decodeTo(field),
|
|
13
|
+
);
|
|
14
|
+
}
|
package/src/listenForChanges.ts
CHANGED
|
@@ -89,11 +89,11 @@ export const listenForChanges = Effect.fn("PostgresChanges.listenForChanges")(fu
|
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
if (lostAt !== undefined) {
|
|
92
|
-
yield* Effect.logDebug("PostgreSQL change listener reconnect failed; retrying"
|
|
92
|
+
yield* Effect.logDebug("PostgreSQL change listener reconnect failed; retrying");
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
95
95
|
lostAt = yield* Clock.currentTimeMillis;
|
|
96
|
-
yield* Effect.logWarning("PostgreSQL change listener lost; resynchronizing live streams"
|
|
96
|
+
yield* Effect.logWarning("PostgreSQL change listener lost; resynchronizing live streams");
|
|
97
97
|
}).pipe(Effect.andThen(Effect.sleep(options.retryDelay ?? "1 second"))),
|
|
98
98
|
),
|
|
99
99
|
),
|
|
@@ -2,6 +2,7 @@ import { Effect, Schema, SchemaAST, SchemaIssue } from "effect";
|
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
3
|
import type { SqlClient } from "effect/sql";
|
|
4
4
|
import { makeFilter } from "#repositoryFilter.ts";
|
|
5
|
+
import type { UpsertAssignment } from "#upsertColumns.ts";
|
|
5
6
|
|
|
6
7
|
export function makeConflictClause(
|
|
7
8
|
model: Model.Any,
|
|
@@ -33,18 +34,33 @@ export function makeConflictClause(
|
|
|
33
34
|
}
|
|
34
35
|
});
|
|
35
36
|
}
|
|
36
|
-
function
|
|
37
|
+
function assignment(entry: UpsertAssignment) {
|
|
38
|
+
const column = typeof entry === "string" ? entry : entry.column;
|
|
39
|
+
const incoming = sql`excluded.${sql(column)}`;
|
|
40
|
+
const stored = sql`${sql(options.tableName)}.${sql(column)}`;
|
|
41
|
+
let value = incoming;
|
|
42
|
+
if (typeof entry !== "string") {
|
|
43
|
+
value = entry.mode === "add" ? sql`${stored} + ${incoming}` : sql`coalesce(${incoming}, ${stored})`;
|
|
44
|
+
}
|
|
45
|
+
return sql`${sql(column)} = ${value}`;
|
|
46
|
+
}
|
|
47
|
+
function clause(
|
|
48
|
+
encoded: Readonly<Record<string, unknown>>,
|
|
49
|
+
updateColumns?: readonly UpsertAssignment[],
|
|
50
|
+
updateWhere?: Readonly<Record<string, unknown>>,
|
|
51
|
+
) {
|
|
37
52
|
return Effect.gen(function* () {
|
|
38
53
|
yield* validateColumns(encoded, conflictColumns);
|
|
39
54
|
if (updateColumns !== undefined) {
|
|
40
|
-
yield* validateColumns(
|
|
55
|
+
yield* validateColumns(
|
|
56
|
+
encoded,
|
|
57
|
+
updateColumns.map((entry) => (typeof entry === "string" ? entry : entry.column)),
|
|
58
|
+
[...idColumns, ...conflictColumns, ...immutable],
|
|
59
|
+
);
|
|
41
60
|
}
|
|
42
61
|
const conflict = sql.csv(conflictColumns.map((column) => sql`${sql(column)}`));
|
|
43
62
|
const where = options.conflictWhere === undefined ? sql`` : sql`where ${yield* filter.where(options.conflictWhere)}`;
|
|
44
|
-
const action =
|
|
45
|
-
updateColumns === undefined
|
|
46
|
-
? sql`do nothing`
|
|
47
|
-
: sql`do update set ${sql.csv(updateColumns.map((column) => sql`${sql(column)} = excluded.${sql(column)}`))}`;
|
|
63
|
+
const action = updateColumns === undefined ? sql`do nothing` : sql`do update set ${sql.csv(updateColumns.map(assignment))}`;
|
|
48
64
|
const condition = updateWhere === undefined ? sql`` : sql`where ${yield* updateFilter.where(updateWhere, true, true)}`;
|
|
49
65
|
return sql`on conflict (${conflict}) ${where} ${action} ${condition}`;
|
|
50
66
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { BigDecimal } from "effect";
|
|
2
|
+
import type { Model } from "effect/schema";
|
|
3
|
+
|
|
4
|
+
export type UpsertColumn<TModel extends Model.Any, TColumn extends keyof TModel["fields"]> =
|
|
5
|
+
| TColumn
|
|
6
|
+
| {
|
|
7
|
+
readonly column: TColumn;
|
|
8
|
+
readonly mode: "keepOnNull";
|
|
9
|
+
}
|
|
10
|
+
| {
|
|
11
|
+
[TKey in TColumn]: NonNullable<TModel["fields"][TKey]["Type"]> extends number | bigint | BigDecimal.BigDecimal
|
|
12
|
+
? { readonly column: TKey; readonly mode: "add" }
|
|
13
|
+
: never;
|
|
14
|
+
}[TColumn];
|
|
15
|
+
|
|
16
|
+
export type UpsertAssignment = string | { readonly column: string; readonly mode: "add" | "keepOnNull" };
|