@shivaedev/sql 0.32.0 → 0.34.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 +34 -0
- package/README.md +153 -23
- package/dist/MigrationStartedAt.d.ts.map +1 -0
- package/dist/{internal/MigrationStartedAt.js → MigrationStartedAt.js} +1 -1
- package/dist/MigrationStartedAt.js.map +1 -0
- package/dist/batchWrites.d.ts +1 -1
- package/dist/batchWrites.d.ts.map +1 -1
- package/dist/batchWrites.js.map +1 -1
- package/dist/batchedDelete.d.ts +9 -2
- package/dist/batchedDelete.d.ts.map +1 -1
- package/dist/batchedDelete.js +34 -35
- package/dist/batchedDelete.js.map +1 -1
- package/dist/changes.d.ts +8 -0
- package/dist/changes.d.ts.map +1 -0
- package/dist/changes.js +7 -0
- package/dist/changes.js.map +1 -0
- 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/deleteGroupsBatched.d.ts +13 -0
- package/dist/deleteGroupsBatched.d.ts.map +1 -0
- package/dist/deleteGroupsBatched.js +23 -0
- package/dist/deleteGroupsBatched.js.map +1 -0
- 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/insertFromSelect.d.ts +1 -1
- package/dist/insertFromSelect.d.ts.map +1 -1
- package/dist/insertFromSelect.js.map +1 -1
- 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/invalidationKeys.d.ts +8 -0
- package/dist/invalidationKeys.d.ts.map +1 -0
- package/dist/invalidationKeys.js +15 -0
- package/dist/invalidationKeys.js.map +1 -0
- package/dist/keysetPage.d.ts +26 -0
- package/dist/keysetPage.d.ts.map +1 -0
- package/dist/keysetPage.js +23 -0
- package/dist/keysetPage.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 +36 -6
- package/dist/makeConflictClause.js.map +1 -1
- package/dist/migrationLock.d.ts.map +1 -0
- package/dist/migrationLock.js.map +1 -0
- package/dist/migrations.d.ts +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +18 -9
- package/dist/migrations.js.map +1 -1
- package/dist/postgresChanges.d.ts.map +1 -1
- package/dist/postgresChanges.js +8 -4
- package/dist/postgresChanges.js.map +1 -1
- package/dist/postgresLayer.d.ts +2 -1
- package/dist/postgresLayer.d.ts.map +1 -1
- package/dist/postgresLayer.js +1 -1
- package/dist/postgresLayer.js.map +1 -1
- package/dist/postgresRelease.js +1 -1
- package/dist/postgresRelease.js.map +1 -1
- package/dist/repositoryChanges.d.ts.map +1 -1
- package/dist/repositoryChanges.js +4 -3
- package/dist/repositoryChanges.js.map +1 -1
- package/dist/transact.d.ts +13 -5
- package/dist/transact.d.ts.map +1 -1
- package/dist/transact.js +45 -19
- package/dist/transact.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/dist/versionedStatements.d.ts +1 -1
- package/package.json +7 -6
- package/src/{internal/MigrationStartedAt.ts → MigrationStartedAt.ts} +1 -1
- package/src/batchWrites.ts +2 -1
- package/src/batchedDelete.ts +53 -40
- package/src/changes.ts +12 -0
- package/src/conditionalUpsert.ts +4 -3
- package/src/conflictWrites.ts +11 -7
- package/src/deleteGroupsBatched.ts +41 -0
- package/src/inValues.ts +11 -0
- package/src/insertFromSelect.ts +1 -1
- package/src/int4Array.ts +14 -0
- package/src/int8.ts +14 -0
- package/src/invalidationKeys.ts +24 -0
- package/src/keysetPage.ts +54 -0
- package/src/listenForChanges.ts +2 -2
- package/src/makeConflictClause.ts +53 -8
- package/src/migrations.ts +21 -10
- package/src/postgresChanges.ts +13 -4
- package/src/postgresLayer.ts +1 -1
- package/src/postgresRelease.ts +1 -1
- package/src/repositoryChanges.ts +4 -3
- package/src/transact.ts +61 -24
- package/src/upsertColumns.ts +16 -0
- package/dist/internal/CommandRecovery.d.ts +0 -3
- package/dist/internal/CommandRecovery.d.ts.map +0 -1
- package/dist/internal/CommandRecovery.js +0 -5
- package/dist/internal/CommandRecovery.js.map +0 -1
- package/dist/internal/MigrationStartedAt.d.ts.map +0 -1
- package/dist/internal/MigrationStartedAt.js.map +0 -1
- package/dist/internal/migrationLock.d.ts.map +0 -1
- package/dist/internal/migrationLock.js.map +0 -1
- package/src/internal/CommandRecovery.ts +0 -5
- /package/dist/{internal/MigrationStartedAt.d.ts → MigrationStartedAt.d.ts} +0 -0
- /package/dist/{internal/migrationLock.d.ts → migrationLock.d.ts} +0 -0
- /package/dist/{internal/migrationLock.js → migrationLock.js} +0 -0
- /package/src/{internal/migrationLock.ts → migrationLock.ts} +0 -0
package/src/transact.ts
CHANGED
|
@@ -1,45 +1,78 @@
|
|
|
1
|
-
import { Effect } from "effect";
|
|
1
|
+
import { Context, Effect } from "effect";
|
|
2
2
|
import { dual } from "effect/Function";
|
|
3
3
|
import type { ReadonlyRecord } from "effect/Record";
|
|
4
4
|
import * as Reactivity from "effect/reactivity/Reactivity";
|
|
5
5
|
import { SqlClient } from "effect/sql";
|
|
6
6
|
import { isSqlError, type SqlError } from "effect/sql/SqlError";
|
|
7
|
-
import { makeChannel } from "@shivaedev/changes/channel.ts";
|
|
8
|
-
import {
|
|
7
|
+
import { type BeforeCommit as CommitHook, makeChannel } from "@shivaedev/changes/channel.ts";
|
|
8
|
+
import { type Observation, type Observer, unobserved } from "@shivaedev/changes/observe.ts";
|
|
9
|
+
import type { Publish } from "@shivaedev/changes/publish.ts";
|
|
10
|
+
import { flatten, type Invalidation, keysOf } from "#invalidationKeys.ts";
|
|
9
11
|
|
|
10
12
|
export type InvalidationKeys = readonly unknown[] | ReadonlyRecord<string, readonly unknown[]>;
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
export interface AnnouncementOptions {
|
|
15
|
+
readonly publication?: "local" | "shared";
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
type Services = SqlClient.SqlClient | Reactivity.Reactivity;
|
|
19
|
+
|
|
20
|
+
export const ChangeObserver = Context.Reference<Observer<unknown>>("@shivaedev/sql/ChangeObserver", { defaultValue: () => unobserved });
|
|
21
|
+
export const BeforeCommit = Context.Reference<CommitHook<unknown, SqlError, Services>>("@shivaedev/sql/BeforeCommit", {
|
|
22
|
+
defaultValue: () => () => Effect.void,
|
|
23
|
+
});
|
|
24
|
+
export const CommittedSink = Context.Reference<Publish<unknown, Services> | undefined>("@shivaedev/sql/CommittedSink", {
|
|
25
|
+
defaultValue: () => undefined,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function observe(event: Observation<Invalidation>) {
|
|
29
|
+
return Effect.flatMap(ChangeObserver, (observer) => observer({ ...event, changes: keysOf(event.changes) }));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function invalidate(keys: readonly unknown[]) {
|
|
33
|
+
return Reactivity.Reactivity.use((reactivity) => Effect.sync(() => reactivity.invalidateUnsafe(keys)));
|
|
18
34
|
}
|
|
19
35
|
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
36
|
+
const committed = Effect.fnUntraced(function* (changes: readonly Invalidation[]) {
|
|
37
|
+
const sink = yield* CommittedSink;
|
|
38
|
+
if (sink === undefined) {
|
|
39
|
+
return yield* invalidate(keysOf(changes));
|
|
40
|
+
}
|
|
41
|
+
const shared = keysOf(changes.filter((change) => change.publication === "shared"));
|
|
42
|
+
const sharedKeys = new Set(shared);
|
|
43
|
+
const local = keysOf(changes.filter((change) => change.publication === "local" && !sharedKeys.has(change.key)));
|
|
44
|
+
if (local.length > 0) {
|
|
45
|
+
yield* invalidate(local);
|
|
46
|
+
}
|
|
47
|
+
if (shared.length > 0) {
|
|
48
|
+
yield* sink(shared);
|
|
27
49
|
}
|
|
28
50
|
});
|
|
29
51
|
|
|
30
|
-
const invalidations = makeChannel<
|
|
52
|
+
const invalidations = makeChannel<Invalidation, Services, SqlError>({
|
|
53
|
+
beforeCommit: (changes) => {
|
|
54
|
+
const shared = keysOf(changes.filter((change) => change.publication === "shared"));
|
|
55
|
+
return shared.length === 0 ? Effect.void : Effect.flatMap(BeforeCommit, (hook) => hook(shared));
|
|
56
|
+
},
|
|
57
|
+
key: (change) => (change.publication === "shared" ? change.key : change),
|
|
31
58
|
name: "@shivaedev/sql/transact",
|
|
32
59
|
owner: Effect.map(SqlClient.SqlClient, (sql) => sql.transactionService),
|
|
33
|
-
publish: (
|
|
34
|
-
unowned:
|
|
60
|
+
publish: (changes) => invalidate(keysOf(changes)),
|
|
61
|
+
unowned: Effect.gen(function* () {
|
|
62
|
+
const sql = yield* SqlClient.SqlClient;
|
|
63
|
+
const native = yield* Effect.serviceOption(sql.transactionService);
|
|
64
|
+
if (native._tag === "Some") {
|
|
65
|
+
return yield* Effect.die(
|
|
66
|
+
new Error("transact cannot announce changes after a transaction it does not own; begin the outer transaction with transact"),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}),
|
|
35
70
|
});
|
|
36
71
|
|
|
37
|
-
export const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
export const invalidateOnCommit = Effect.fn("Transact.invalidateOnCommit")(function* (keys: InvalidationKeys) {
|
|
42
|
-
yield* invalidations.record(flatten(keys));
|
|
72
|
+
export const invalidateOnCommit = Effect.fn("Transact.invalidateOnCommit")(function* (keys: InvalidationKeys, options?: AnnouncementOptions) {
|
|
73
|
+
yield* invalidations
|
|
74
|
+
.record(flatten(keys).map((key) => ({ key, publication: options?.publication ?? "shared" })))
|
|
75
|
+
.pipe(Effect.provideService(invalidations.Observer, observe));
|
|
43
76
|
});
|
|
44
77
|
|
|
45
78
|
export interface TransactOptions<TError> {
|
|
@@ -65,6 +98,10 @@ export const transact: {
|
|
|
65
98
|
? sql.withTransaction(body)
|
|
66
99
|
: boundary.restore(sql.withTransaction(Effect.tap(body, () => sql.afterCommit(boundary.committed)))),
|
|
67
100
|
)(effect)
|
|
68
|
-
.pipe(
|
|
101
|
+
.pipe(
|
|
102
|
+
Effect.provideService(invalidations.Observer, observe),
|
|
103
|
+
Effect.provideService(invalidations.CommittedSink, committed),
|
|
104
|
+
Effect.catchIf(isSqlError, (error) => Effect.fail(options.onSqlError(error))),
|
|
105
|
+
);
|
|
69
106
|
}),
|
|
70
107
|
);
|
|
@@ -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" };
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CommandRecovery.d.ts","sourceRoot":"","sources":["../../src/internal/CommandRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,eAAO,MAAM,eAAe,sDAE1B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"CommandRecovery.js","sourceRoot":"","sources":["../../src/internal/CommandRecovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEzC,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,CAAsB,gCAAgC,EAAE;IACvG,YAAY,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI;CAC/B,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationStartedAt.d.ts","sourceRoot":"","sources":["../../src/internal/MigrationStartedAt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,eAAO,MAAM,kBAAkB,uCAE7B,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationStartedAt.js","sourceRoot":"","sources":["../../src/internal/MigrationStartedAt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEjC,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC,SAAS,CAAqB,4CAA4C,EAAE;IACrH,YAAY,EAAE,GAAG,EAAE,CAAC,SAAS;CAC7B,CAAC,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrationLock.d.ts","sourceRoot":"","sources":["../../src/internal/migrationLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,eAAO,MAAM,aAAa,qJAexB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrationLock.js","sourceRoot":"","sources":["../../src/internal/migrationLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAa,EAAE,OAAe;IACvF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IACtC,SAAS,OAAO,CAAC,SAAuD;QACvE,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;QAC/C,OAAO,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAA,mDAAmD,CAAC,CAAC;IAC1F,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAA,qCAAqC,OAAO,UAAU,CAAC,EAAE,GAAG,EAAE,CACrG,OAAO,CAAC,GAAG,CAAA,qCAAqC,QAAQ,EAAE,OAAO,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAC/F,CAAC;IACF,MAAM,GAAG,GAAG,yBAAyB,KAAK,EAAE,CAAC;IAC7C,yGAAyG;IACzG,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA,8CAA8C,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1H,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAA,4CAA4C,GAAG,OAAO,CAAC,CAAC;AAC3E,CAAC,CAAC,CAAC"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|