@shivaedev/sql 0.0.0-stage → 0.21.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.
Files changed (189) hide show
  1. package/CHANGELOG.md +269 -0
  2. package/LICENSE +21 -0
  3. package/README.md +614 -2
  4. package/dist/SchemaComponent.d.ts +9 -0
  5. package/dist/SchemaComponent.d.ts.map +1 -0
  6. package/dist/SchemaComponent.js +6 -0
  7. package/dist/SchemaComponent.js.map +1 -0
  8. package/dist/WorkerRelease.d.ts +14 -0
  9. package/dist/WorkerRelease.d.ts.map +1 -0
  10. package/dist/WorkerRelease.js +30 -0
  11. package/dist/WorkerRelease.js.map +1 -0
  12. package/dist/advisoryXactLock.d.ts +10 -0
  13. package/dist/advisoryXactLock.d.ts.map +1 -0
  14. package/dist/advisoryXactLock.js +18 -0
  15. package/dist/advisoryXactLock.js.map +1 -0
  16. package/dist/aggregateColumn.d.ts +8 -0
  17. package/dist/aggregateColumn.d.ts.map +1 -0
  18. package/dist/aggregateColumn.js +44 -0
  19. package/dist/aggregateColumn.js.map +1 -0
  20. package/dist/aggregateQuery.d.ts +51 -0
  21. package/dist/aggregateQuery.d.ts.map +1 -0
  22. package/dist/aggregateQuery.js +2 -0
  23. package/dist/aggregateQuery.js.map +1 -0
  24. package/dist/assertPostgresMigrations.d.ts +7 -0
  25. package/dist/assertPostgresMigrations.d.ts.map +1 -0
  26. package/dist/assertPostgresMigrations.js +20 -0
  27. package/dist/assertPostgresMigrations.js.map +1 -0
  28. package/dist/batchWrites.d.ts +16 -0
  29. package/dist/batchWrites.d.ts.map +1 -0
  30. package/dist/batchWrites.js +49 -0
  31. package/dist/batchWrites.js.map +1 -0
  32. package/dist/clientOptions.d.ts +8 -0
  33. package/dist/clientOptions.d.ts.map +1 -0
  34. package/dist/clientOptions.js +8 -0
  35. package/dist/clientOptions.js.map +1 -0
  36. package/dist/compositeRepository.d.ts +41 -0
  37. package/dist/compositeRepository.d.ts.map +1 -0
  38. package/dist/compositeRepository.js +38 -0
  39. package/dist/compositeRepository.js.map +1 -0
  40. package/dist/conditionalUpsert.d.ts +59 -0
  41. package/dist/conditionalUpsert.d.ts.map +1 -0
  42. package/dist/conditionalUpsert.js +28 -0
  43. package/dist/conditionalUpsert.js.map +1 -0
  44. package/dist/conflictWrites.d.ts +45 -0
  45. package/dist/conflictWrites.d.ts.map +1 -0
  46. package/dist/conflictWrites.js +40 -0
  47. package/dist/conflictWrites.js.map +1 -0
  48. package/dist/coordinateWorkerRelease.d.ts +5 -0
  49. package/dist/coordinateWorkerRelease.d.ts.map +1 -0
  50. package/dist/coordinateWorkerRelease.js +30 -0
  51. package/dist/coordinateWorkerRelease.js.map +1 -0
  52. package/dist/insertFromSelect.d.ts +24 -0
  53. package/dist/insertFromSelect.d.ts.map +1 -0
  54. package/dist/insertFromSelect.js +15 -0
  55. package/dist/insertFromSelect.js.map +1 -0
  56. package/dist/latestPerGroup.d.ts +11 -0
  57. package/dist/latestPerGroup.d.ts.map +1 -0
  58. package/dist/latestPerGroup.js +51 -0
  59. package/dist/latestPerGroup.js.map +1 -0
  60. package/dist/listenForChanges.d.ts +5 -0
  61. package/dist/listenForChanges.d.ts.map +1 -0
  62. package/dist/listenForChanges.js +75 -0
  63. package/dist/listenForChanges.js.map +1 -0
  64. package/dist/makeAggregate.d.ts +8 -0
  65. package/dist/makeAggregate.d.ts.map +1 -0
  66. package/dist/makeAggregate.js +38 -0
  67. package/dist/makeAggregate.js.map +1 -0
  68. package/dist/makeConflictClause.d.ts +10 -0
  69. package/dist/makeConflictClause.d.ts.map +1 -0
  70. package/dist/makeConflictClause.js +41 -0
  71. package/dist/makeConflictClause.js.map +1 -0
  72. package/dist/makeQueryClauses.d.ts +14 -0
  73. package/dist/makeQueryClauses.d.ts.map +1 -0
  74. package/dist/makeQueryClauses.js +20 -0
  75. package/dist/makeQueryClauses.js.map +1 -0
  76. package/dist/migrationConvention.d.ts +3 -0
  77. package/dist/migrationConvention.d.ts.map +1 -0
  78. package/dist/migrationConvention.js +3 -0
  79. package/dist/migrationConvention.js.map +1 -0
  80. package/dist/migrations.d.ts +12 -0
  81. package/dist/migrations.d.ts.map +1 -0
  82. package/dist/migrations.js +41 -0
  83. package/dist/migrations.js.map +1 -0
  84. package/dist/migrationsFromDirectory.d.ts +4 -0
  85. package/dist/migrationsFromDirectory.d.ts.map +1 -0
  86. package/dist/migrationsFromDirectory.js +7 -0
  87. package/dist/migrationsFromDirectory.js.map +1 -0
  88. package/dist/notifyPayload.d.ts +7 -0
  89. package/dist/notifyPayload.d.ts.map +1 -0
  90. package/dist/notifyPayload.js +31 -0
  91. package/dist/notifyPayload.js.map +1 -0
  92. package/dist/pendingPostgresMigrations.d.ts +24 -0
  93. package/dist/pendingPostgresMigrations.d.ts.map +1 -0
  94. package/dist/pendingPostgresMigrations.js +30 -0
  95. package/dist/pendingPostgresMigrations.js.map +1 -0
  96. package/dist/pinnedGroups.d.ts +22 -0
  97. package/dist/pinnedGroups.d.ts.map +1 -0
  98. package/dist/pinnedGroups.js +35 -0
  99. package/dist/pinnedGroups.js.map +1 -0
  100. package/dist/postgresChanges.d.ts +20 -0
  101. package/dist/postgresChanges.d.ts.map +1 -0
  102. package/dist/postgresChanges.js +26 -0
  103. package/dist/postgresChanges.js.map +1 -0
  104. package/dist/postgresRelease.d.ts +9 -0
  105. package/dist/postgresRelease.d.ts.map +1 -0
  106. package/dist/postgresRelease.js +39 -0
  107. package/dist/postgresRelease.js.map +1 -0
  108. package/dist/releaseWorkers.d.ts +8 -0
  109. package/dist/releaseWorkers.d.ts.map +1 -0
  110. package/dist/releaseWorkers.js +26 -0
  111. package/dist/releaseWorkers.js.map +1 -0
  112. package/dist/repository.d.ts +66 -0
  113. package/dist/repository.d.ts.map +1 -0
  114. package/dist/repository.js +43 -0
  115. package/dist/repository.js.map +1 -0
  116. package/dist/repositoryChanges.d.ts +9 -0
  117. package/dist/repositoryChanges.d.ts.map +1 -0
  118. package/dist/repositoryChanges.js +32 -0
  119. package/dist/repositoryChanges.js.map +1 -0
  120. package/dist/repositoryFilter.d.ts +43 -0
  121. package/dist/repositoryFilter.d.ts.map +1 -0
  122. package/dist/repositoryFilter.js +69 -0
  123. package/dist/repositoryFilter.js.map +1 -0
  124. package/dist/repositoryQueries.d.ts +26 -0
  125. package/dist/repositoryQueries.d.ts.map +1 -0
  126. package/dist/repositoryQueries.js +49 -0
  127. package/dist/repositoryQueries.js.map +1 -0
  128. package/dist/repositoryWrites.d.ts +18 -0
  129. package/dist/repositoryWrites.d.ts.map +1 -0
  130. package/dist/repositoryWrites.js +49 -0
  131. package/dist/repositoryWrites.js.map +1 -0
  132. package/dist/testing.d.ts +12 -0
  133. package/dist/testing.d.ts.map +1 -0
  134. package/dist/testing.js +29 -0
  135. package/dist/testing.js.map +1 -0
  136. package/dist/transact.d.ts +18 -0
  137. package/dist/transact.d.ts.map +1 -0
  138. package/dist/transact.js +43 -0
  139. package/dist/transact.js.map +1 -0
  140. package/dist/tupleIn.d.ts +19 -0
  141. package/dist/tupleIn.d.ts.map +1 -0
  142. package/dist/tupleIn.js +20 -0
  143. package/dist/tupleIn.js.map +1 -0
  144. package/dist/versionedRepository.d.ts +37 -0
  145. package/dist/versionedRepository.d.ts.map +1 -0
  146. package/dist/versionedRepository.js +63 -0
  147. package/dist/versionedRepository.js.map +1 -0
  148. package/dist/versionedStatements.d.ts +25 -0
  149. package/dist/versionedStatements.d.ts.map +1 -0
  150. package/dist/versionedStatements.js +75 -0
  151. package/dist/versionedStatements.js.map +1 -0
  152. package/package.json +74 -3
  153. package/src/SchemaComponent.ts +12 -0
  154. package/src/WorkerRelease.ts +38 -0
  155. package/src/advisoryXactLock.ts +17 -0
  156. package/src/aggregateColumn.ts +49 -0
  157. package/src/aggregateQuery.ts +57 -0
  158. package/src/assertPostgresMigrations.ts +24 -0
  159. package/src/batchWrites.ts +69 -0
  160. package/src/clientOptions.ts +16 -0
  161. package/src/compositeRepository.ts +101 -0
  162. package/src/conditionalUpsert.ts +97 -0
  163. package/src/conflictWrites.ts +93 -0
  164. package/src/coordinateWorkerRelease.ts +33 -0
  165. package/src/insertFromSelect.ts +47 -0
  166. package/src/latestPerGroup.ts +58 -0
  167. package/src/listenForChanges.ts +97 -0
  168. package/src/makeAggregate.ts +64 -0
  169. package/src/makeConflictClause.ts +53 -0
  170. package/src/makeQueryClauses.ts +36 -0
  171. package/src/migrationConvention.ts +2 -0
  172. package/src/migrations.ts +58 -0
  173. package/src/migrationsFromDirectory.ts +7 -0
  174. package/src/notifyPayload.ts +34 -0
  175. package/src/pendingPostgresMigrations.ts +42 -0
  176. package/src/pinnedGroups.ts +46 -0
  177. package/src/postgresChanges.ts +48 -0
  178. package/src/postgresRelease.ts +41 -0
  179. package/src/releaseWorkers.ts +32 -0
  180. package/src/repository.ts +147 -0
  181. package/src/repositoryChanges.ts +49 -0
  182. package/src/repositoryFilter.ts +108 -0
  183. package/src/repositoryQueries.ts +107 -0
  184. package/src/repositoryWrites.ts +70 -0
  185. package/src/testing.ts +38 -0
  186. package/src/transact.ts +70 -0
  187. package/src/tupleIn.ts +44 -0
  188. package/src/versionedRepository.ts +108 -0
  189. package/src/versionedStatements.ts +90 -0
@@ -0,0 +1,41 @@
1
+ import { Duration, Effect, Option } from "effect";
2
+ import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import { Migrator, SqlClient } from "effect/sql";
4
+ import { advisoryXactLock } from "./advisoryXactLock.js";
5
+ import { postgresRelease } from "./postgresRelease.js";
6
+ import { runSchemaComponent } from "./SchemaComponent.js";
7
+ import { transact } from "./transact.js";
8
+ const migrate = Migrator.make({});
9
+ export const migratePostgres = Effect.fn("EffectSql.migratePostgres")(function* ({ loader, components = [], table = "effect_sql_migrations", lockTimeout, release, }) {
10
+ const sql = yield* SqlClient.SqlClient;
11
+ const available = yield* Effect.serviceOption(Reactivity.Reactivity);
12
+ const reactivity = Option.isSome(available) ? available.value : yield* Reactivity.make;
13
+ const millis = Duration.toMillis(lockTimeout);
14
+ const timeout = millis === Number.POSITIVE_INFINITY ? "0" : `${Math.max(1, Math.ceil(millis))}ms`;
15
+ const appliedMigrations = yield* Effect.gen(function* () {
16
+ yield* sql `select set_config('lock_timeout', ${timeout}, true)`;
17
+ yield* advisoryXactLock(`effect_sql_migrations:${table}`).pipe(Effect.catchTag("AdvisoryLockOutsideTransaction", Effect.die));
18
+ yield* sql `create table if not exists ${sql(table)} (
19
+ migration_id integer primary key,
20
+ created_at timestamp with time zone not null default now(),
21
+ name text not null
22
+ )`;
23
+ const current = [...(yield* loader)].sort(([left], [right]) => left - right);
24
+ const applied = yield* sql `select migration_id as id from ${sql(table)}`.withoutTransform;
25
+ const appliedIds = new Set(applied.map(({ id }) => id));
26
+ const latest = applied.reduce((max, { id }) => Math.max(max, id), 0);
27
+ const missing = current.filter(([id]) => id <= latest && !appliedIds.has(id));
28
+ if (missing.length > 0) {
29
+ return yield* Effect.fail(new Migrator.MigrationError({
30
+ kind: "BadState",
31
+ message: `Migrations missing from the ledger at or below latest applied id ${latest}: ${missing.map(([id]) => id).join(", ")}`,
32
+ }));
33
+ }
34
+ return yield* migrate({ loader: Effect.succeed(current), table });
35
+ }).pipe(transact({ onSqlError: (error) => error }), Effect.provideService(Reactivity.Reactivity, reactivity));
36
+ for (const component of [...components, ...(release === undefined ? [] : [postgresRelease(release, table)])]) {
37
+ yield* runSchemaComponent(component.name, component.apply);
38
+ }
39
+ return appliedMigrations;
40
+ });
41
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../src/migrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Effect, Path } from "effect";
2
+ import { Migrator } from "effect/sql";
3
+ export declare function migrationsFromDirectory(root: string): Effect.Effect<readonly Migrator.ResolvedMigration[], Migrator.MigrationError, import("effect/FileSystem").FileSystem | Path.Path>;
4
+ //# sourceMappingURL=migrationsFromDirectory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrationsFromDirectory.d.ts","sourceRoot":"","sources":["../src/migrationsFromDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,qIAEnD"}
@@ -0,0 +1,7 @@
1
+ import { Effect, Path } from "effect";
2
+ import { Migrator } from "effect/sql";
3
+ import { MIGRATIONS_DIRECTORY } from "#migrationConvention.ts";
4
+ export function migrationsFromDirectory(root) {
5
+ return Effect.flatMap(Path.Path, (path) => Migrator.fromFileSystem(path.join(root, MIGRATIONS_DIRECTORY)));
6
+ }
7
+ //# sourceMappingURL=migrationsFromDirectory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrationsFromDirectory.js","sourceRoot":"","sources":["../src/migrationsFromDirectory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAE/D,MAAM,UAAU,uBAAuB,CAAC,IAAY;IACnD,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC5G,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { SqlError } from "effect/sql/SqlError";
3
+ export declare const NotificationKeys: Schema.$Array<Schema.Union<readonly [Schema.String, Schema.Finite]>>;
4
+ export declare const decodeKeys: (input: unknown, options?: import("effect/SchemaAST").ParseOptions) => Effect.Effect<readonly (string | number)[], Schema.SchemaError, never>;
5
+ export declare function notificationError(message: string, cause?: unknown): SqlError;
6
+ export declare const encodeKeys: (keys: readonly unknown[]) => Effect.Effect<string[], SqlError, never>;
7
+ //# sourceMappingURL=notifyPayload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifyPayload.d.ts","sourceRoot":"","sources":["../src/notifyPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAgB,MAAM,qBAAqB,CAAC;AAE7D,eAAO,MAAM,gBAAgB,sEAA6D,CAAC;AAC3F,eAAO,MAAM,UAAU,+IAAsE,CAAC;AAG9F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,OAAiB,YAE1E;AAED,eAAO,MAAM,UAAU,wEAsBrB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { SqlError, UnknownError } from "effect/sql/SqlError";
3
+ export const NotificationKeys = Schema.Array(Schema.Union([Schema.String, Schema.Finite]));
4
+ export const decodeKeys = Schema.decodeUnknownEffect(Schema.fromJsonString(NotificationKeys));
5
+ const encoder = new TextEncoder();
6
+ export function notificationError(message, cause = message) {
7
+ return new SqlError({ reason: new UnknownError({ cause, message, operation: "notify" }) });
8
+ }
9
+ export const encodeKeys = Effect.fn("PostgresChanges.encodeKeys")(function* (keys) {
10
+ const valid = yield* Schema.decodeUnknownEffect(NotificationKeys)(keys).pipe(Effect.mapError((cause) => notificationError("PostgreSQL invalidation keys must be strings or finite numbers", cause)));
11
+ const payloads = [];
12
+ let batch = [];
13
+ for (const key of valid) {
14
+ const next = [...batch, key];
15
+ if (encoder.encode(JSON.stringify(next)).length >= 8000) {
16
+ if (batch.length === 0 || encoder.encode(JSON.stringify([key])).length >= 8000) {
17
+ return yield* Effect.fail(notificationError("A PostgreSQL invalidation key exceeds the NOTIFY payload limit"));
18
+ }
19
+ payloads.push(JSON.stringify(batch));
20
+ batch = [key];
21
+ }
22
+ else {
23
+ batch = next;
24
+ }
25
+ }
26
+ if (batch.length > 0) {
27
+ payloads.push(JSON.stringify(batch));
28
+ }
29
+ return payloads;
30
+ });
31
+ //# sourceMappingURL=notifyPayload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifyPayload.js","sourceRoot":"","sources":["../src/notifyPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3F,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC9F,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,KAAK,GAAY,OAAO;IAC1E,OAAO,IAAI,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,YAAY,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,EAAE,CAAC,4BAA4B,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAwB;IACpG,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAC3E,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,gEAAgE,EAAE,KAAK,CAAC,CAAC,CACtH,CAAC;IACF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,KAAK,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7B,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;YACzD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC;gBAChF,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,gEAAgE,CAAC,CAAC,CAAC;YAChH,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACrC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;QACf,CAAC;aAAM,CAAC;YACP,KAAK,GAAG,IAAI,CAAC;QACd,CAAC;IACF,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import type { PostgresMigrationOptions } from "./migrations.ts";
4
+ export interface PendingPostgresMigrations {
5
+ readonly components: readonly {
6
+ readonly name: string;
7
+ readonly detail: string;
8
+ }[];
9
+ readonly migrations: readonly {
10
+ readonly id: number;
11
+ readonly name: string;
12
+ }[];
13
+ }
14
+ export declare const pendingPostgresMigrations: <R>(args_0: Pick<PostgresMigrationOptions<R>, "components" | "loader" | "release" | "table">) => Effect.Effect<{
15
+ components: {
16
+ name: string;
17
+ detail: string;
18
+ }[];
19
+ migrations: {
20
+ id: number;
21
+ name: string;
22
+ }[];
23
+ }, import("effect/sql/Migrator").MigrationError | import("effect/sql/SqlError").SqlError, R | SqlClient.SqlClient>;
24
+ //# sourceMappingURL=pendingPostgresMigrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pendingPostgresMigrations.d.ts","sourceRoot":"","sources":["../src/pendingPostgresMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAIhE,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnF,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/E;AAED,eAAO,MAAM,yBAAyB,GAA+D,CAAC;;cAsBpE,MAAM;gBAAU,MAAM;;;YAf/B,MAAM;cAAQ,MAAM;;kHAuB3C,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import { postgresRelease } from "./postgresRelease.js";
4
+ import { runSchemaComponent } from "./SchemaComponent.js";
5
+ export const pendingPostgresMigrations = Effect.fn("EffectSql.pendingPostgresMigrations")(function* ({ loader, components = [], table = "effect_sql_migrations", release, }) {
6
+ const expected = yield* loader;
7
+ const migrations = [];
8
+ if (expected.length > 0) {
9
+ const sql = yield* SqlClient.SqlClient;
10
+ const identifier = sql `${sql(table)}`.compile()[0];
11
+ const [ledger] = yield* sql `select to_regclass(${identifier})::text as name`.withoutTransform;
12
+ const applied = ledger === undefined || ledger.name === null
13
+ ? []
14
+ : yield* sql `select migration_id as id, name from ${sql(table)}`.withoutTransform;
15
+ for (const [id, name] of expected) {
16
+ if (!applied.some((row) => row.id === id && row.name === name)) {
17
+ migrations.push({ id, name });
18
+ }
19
+ }
20
+ }
21
+ const pendingComponents = [];
22
+ for (const component of [...components, ...(release === undefined ? [] : [postgresRelease(release, table)])]) {
23
+ const detail = yield* runSchemaComponent(component.name, component.pending);
24
+ if (detail !== undefined) {
25
+ pendingComponents.push({ detail, name: component.name });
26
+ }
27
+ }
28
+ return { components: pendingComponents, migrations };
29
+ });
30
+ //# sourceMappingURL=pendingPostgresMigrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pendingPostgresMigrations.js","sourceRoot":"","sources":["../src/pendingPostgresMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAO1D,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,EAAE,CAAC,qCAAqC,CAAC,CAAC,QAAQ,CAAC,EAAK,EACvG,MAAM,EACN,UAAU,GAAG,EAAE,EACf,KAAK,GAAG,uBAAuB,EAC/B,OAAO,GAC2E;IAClF,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC;IAC/B,MAAM,UAAU,GAAmC,EAAE,CAAC;IACtD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;QACvC,MAAM,UAAU,GAAG,GAAG,CAAA,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAyB,sBAAsB,UAAU,iBAAiB,CAAC,gBAAgB,CAAC;QACvH,MAAM,OAAO,GACZ,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;YAC3C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAA8B,wCAAwC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAAC;QAClH,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,QAAQ,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBAChE,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/B,CAAC;QACF,CAAC;IACF,CAAC;IACD,MAAM,iBAAiB,GAAuC,EAAE,CAAC;IACjE,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,UAAU,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9G,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QAC5E,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1B,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1D,CAAC;IACF,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,UAAU,EAAsC,CAAC;AAC1F,CAAC,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlClient } from "effect/sql";
4
+ import type { RepositoryListFilter } from "#repositoryFilter.ts";
5
+ import { tupleFilter } from "#tupleIn.ts";
6
+ export declare function pinnedGroups(model: Model.Any, sql: SqlClient.SqlClient, partitionBy: readonly string[], input?: RepositoryListFilter<Model.Any>): Effect.Effect<undefined, never, never> | Effect.Effect<{
7
+ groups: never[];
8
+ remaining: RepositoryListFilter<Model.Any>;
9
+ }, never, never> | Effect.Effect<{
10
+ groups: (readonly [])[];
11
+ remaining: {
12
+ [x: string]: unknown;
13
+ [x: number]: unknown;
14
+ [x: symbol]: unknown;
15
+ [tupleFilter]?: {
16
+ readonly model: Model.Any;
17
+ readonly fields: readonly string[];
18
+ readonly values: readonly (readonly unknown[])[];
19
+ };
20
+ };
21
+ }, Schema.SchemaError, unknown>;
22
+ //# sourceMappingURL=pinnedGroups.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinnedGroups.d.ts","sourceRoot":"","sources":["../src/pinnedGroups.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,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,wBAAgB,YAAY,CAC3B,KAAK,EAAE,KAAK,CAAC,GAAG,EAChB,GAAG,EAAE,SAAS,CAAC,SAAS,EACxB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,KAAK,GAAE,oBAAoB,CAAC,KAAK,CAAC,GAAG,CAAM;;;;;;;;;;;;;;;gCAkC3C"}
@@ -0,0 +1,35 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { makeFilter } from "#repositoryFilter.ts";
3
+ import { tupleFilter } from "#tupleIn.ts";
4
+ export function pinnedGroups(model, sql, partitionBy, input = {}) {
5
+ const tuple = input[tupleFilter];
6
+ if (tuple?.values.length === 0
7
+ || Object.values(input).some((value) => typeof value === "object" && value !== null && "in" in value && Array.isArray(value.in) && value.in.length === 0)) {
8
+ return Effect.succeed({ groups: [], remaining: input });
9
+ }
10
+ const exactTuple = tuple !== undefined && tuple.fields.length === partitionBy.length && partitionBy.every((key) => tuple.fields.includes(key));
11
+ let groups = [[]];
12
+ const remaining = { ...input };
13
+ if (exactTuple) {
14
+ groups = tuple.values.map((values) => partitionBy.map((key) => values[tuple.fields.indexOf(key)]));
15
+ delete remaining[tupleFilter];
16
+ }
17
+ else {
18
+ for (const key of partitionBy) {
19
+ const value = input[key];
20
+ if (value === undefined) {
21
+ return Effect.succeed(undefined);
22
+ }
23
+ const values = typeof value === "object" && value !== null && "in" in value && Array.isArray(value.in) ? value.in : [value];
24
+ groups = groups.flatMap((group) => values.map((entry) => [...group, entry]));
25
+ delete remaining[key];
26
+ }
27
+ }
28
+ const { fieldAt } = makeFilter(model, sql);
29
+ return Effect.gen(function* () {
30
+ const fields = yield* Effect.forEach(partitionBy, fieldAt);
31
+ const groupsEncoded = yield* Effect.forEach(groups, (group) => Schema.encodeUnknownEffect(Schema.Tuple(fields))(group));
32
+ return { groups: groupsEncoded, remaining };
33
+ });
34
+ }
35
+ //# sourceMappingURL=pinnedGroups.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pinnedGroups.js","sourceRoot":"","sources":["../src/pinnedGroups.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type Duration, Effect, Layer, type Queue, type Scope } from "effect";
2
+ import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import { SqlClient } from "effect/sql";
4
+ import type { SqlError } from "effect/sql/SqlError";
5
+ export interface PostgresNotification {
6
+ readonly payload: string;
7
+ }
8
+ export interface PostgresChangeClient extends SqlClient.SqlClient {
9
+ readonly listen: (channel: string) => Effect.Effect<Queue.Dequeue<PostgresNotification, SqlError>, SqlError, Scope.Scope>;
10
+ }
11
+ export interface PostgresChangesOptions {
12
+ readonly channel: string;
13
+ readonly client: PostgresChangeClient;
14
+ readonly heartbeatInterval?: Duration.Input;
15
+ readonly heartbeatTimeout?: Duration.Input;
16
+ readonly resync: Effect.Effect<number>;
17
+ readonly retryDelay?: Duration.Input;
18
+ }
19
+ export declare function postgresChanges(options: PostgresChangesOptions): Layer.Layer<never, never, Reactivity.Reactivity>;
20
+ //# sourceMappingURL=postgresChanges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresChanges.d.ts","sourceRoot":"","sources":["../src/postgresChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AACvF,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAKpD,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAqB,SAAQ,SAAS,CAAC,SAAS;IAChE,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,oBAAoB,EAAE,QAAQ,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;CAC1H;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC;CACrC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,oDAsB9D"}
@@ -0,0 +1,26 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import { SqlClient } from "effect/sql";
4
+ import { listenForChanges } from "./listenForChanges.js";
5
+ import { encodeKeys } from "./notifyPayload.js";
6
+ import { BeforeCommit, CommittedSink } from "./transact.js";
7
+ export function postgresChanges(options) {
8
+ return Layer.effectContext(Effect.gen(function* () {
9
+ yield* listenForChanges(options);
10
+ const notify = Effect.fn("PostgresChanges.notify")(function* (keys) {
11
+ const sql = yield* SqlClient.SqlClient;
12
+ if (sql.transactionService !== options.client.transactionService) {
13
+ return;
14
+ }
15
+ const payloads = yield* encodeKeys(keys);
16
+ for (const payload of payloads) {
17
+ yield* sql `select pg_notify(${options.channel}, ${payload})`;
18
+ }
19
+ });
20
+ function committed(keys) {
21
+ return Effect.flatMap(SqlClient.SqlClient, (sql) => sql.transactionService === options.client.transactionService ? Effect.void : Reactivity.invalidate(keys));
22
+ }
23
+ return Context.make(BeforeCommit, notify).pipe(Context.add(CommittedSink, committed));
24
+ }));
25
+ }
26
+ //# sourceMappingURL=postgresChanges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresChanges.js","sourceRoot":"","sources":["../src/postgresChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAiB,MAAM,EAAE,KAAK,EAA0B,MAAM,QAAQ,CAAC;AACvF,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAmB5D,MAAM,UAAU,eAAe,CAAC,OAA+B;IAC9D,OAAO,KAAK,CAAC,aAAa,CACzB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnB,KAAK,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAwB;YACrF,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;YACvC,IAAI,GAAG,CAAC,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAClE,OAAO;YACR,CAAC;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACzC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAChC,KAAK,CAAC,CAAC,GAAG,CAAA,oBAAoB,OAAO,CAAC,OAAO,KAAK,OAAO,GAAG,CAAC;YAC9D,CAAC;QACF,CAAC,CAAC,CAAC;QACH,SAAS,SAAS,CAAC,IAAwB;YAC1C,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAClD,GAAG,CAAC,kBAAkB,KAAK,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CACxG,CAAC;QACH,CAAC;QACD,OAAO,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC;IACvF,CAAC,CAAC,CACF,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import type { SchemaComponent } from "./SchemaComponent.ts";
4
+ export declare const readPostgresRelease: (table?: any) => Effect.Effect<{
5
+ release: string;
6
+ recordedAt: Date;
7
+ } | undefined, import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
8
+ export declare function postgresRelease(release: string, table?: string): SchemaComponent;
9
+ //# sourceMappingURL=postgresRelease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresRelease.d.ts","sourceRoot":"","sources":["../src/postgresRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,eAAO,MAAM,mBAAmB;aAQK,MAAM;gBAAc,IAAI;2EAE3D,CAAC;AAEH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,SAA0B,GAAG,eAAe,CAwBjG"}
@@ -0,0 +1,39 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ export const readPostgresRelease = Effect.fn("EffectSql.readPostgresRelease")(function* (table = "effect_sql_migrations") {
4
+ const sql = yield* SqlClient.SqlClient;
5
+ const name = `${table}_release`;
6
+ const identifier = sql `${sql(name)}`.compile()[0];
7
+ const [exists] = yield* sql `select to_regclass(${identifier})::text as name`.withoutTransform;
8
+ if (exists === undefined || exists.name === null) {
9
+ return undefined;
10
+ }
11
+ const [row] = yield* sql `select release, recorded_at as "recordedAt" from ${sql(name)}`.withoutTransform;
12
+ return row;
13
+ });
14
+ export function postgresRelease(release, table = "effect_sql_migrations") {
15
+ return {
16
+ apply: Effect.gen(function* () {
17
+ const sql = yield* SqlClient.SqlClient;
18
+ yield* sql `create table if not exists ${sql(`${table}_release`)} (
19
+ id boolean primary key default true check (id),
20
+ release text not null,
21
+ recorded_at timestamptz not null
22
+ )`;
23
+ yield* sql `create table if not exists ${sql(`${table}_workers`)} (
24
+ process_id text primary key,
25
+ release text not null,
26
+ heartbeat timestamptz not null
27
+ )`;
28
+ yield* sql `insert into ${sql(`${table}_release`)} (id, release, recorded_at)
29
+ values (true, ${release}, clock_timestamp())
30
+ on conflict (id) do update set release = excluded.release, recorded_at = excluded.recorded_at`;
31
+ }),
32
+ name: "database release",
33
+ pending: Effect.gen(function* () {
34
+ const current = yield* readPostgresRelease(table);
35
+ return current?.release === release ? undefined : `Expected release ${release}; recorded ${current?.release ?? "none"}`;
36
+ }),
37
+ };
38
+ }
39
+ //# sourceMappingURL=postgresRelease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgresRelease.js","sourceRoot":"","sources":["../src/postgresRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,CAAC,MAAM,mBAAmB,GAAG,MAAM,CAAC,EAAE,CAAC,+BAA+B,CAAC,CAAC,QAAQ,CAAC,EAAE,KAAK,GAAG,uBAAuB;IACvH,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,KAAK,UAAU,CAAC;IAChC,MAAM,UAAU,GAAG,GAAG,CAAA,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAyB,sBAAsB,UAAU,iBAAiB,CAAC,gBAAgB,CAAC;IACvH,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAClD,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAuC,oDAAoD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC;IAChJ,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC,CAAC;AAEH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,KAAK,GAAG,uBAAuB;IAC/E,OAAO;QACN,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC1B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;YACvC,KAAK,CAAC,CAAC,GAAG,CAAA,8BAA8B,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC;;;;KAI7D,CAAC;YACH,KAAK,CAAC,CAAC,GAAG,CAAA,8BAA8B,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC;;;;KAI7D,CAAC;YACH,KAAK,CAAC,CAAC,GAAG,CAAA,eAAe,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC;oBAC/B,OAAO;kGACuE,CAAC;QACjG,CAAC,CAAC;QACF,IAAI,EAAE,kBAAkB;QACxB,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAClD,OAAO,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB,OAAO,cAAc,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC;QACzH,CAAC,CAAC;KACF,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ export declare const releaseWorkers: (release: string, staleMillis: number, table?: any) => Effect.Effect<{
4
+ claim: Effect.Effect<boolean, import("effect/sql/SqlError").SqlError, never>;
5
+ heartbeat: Effect.Effect<void, import("effect/sql/SqlError").SqlError, never>;
6
+ remove: Effect.Effect<void, import("effect/sql/SqlError").SqlError, never>;
7
+ }, never, SqlClient.SqlClient>;
8
+ //# sourceMappingURL=releaseWorkers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"releaseWorkers.d.ts","sourceRoot":"","sources":["../src/releaseWorkers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,eAAO,MAAM,cAAc;;;;8BA4BzB,CAAC"}
@@ -0,0 +1,26 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ export const releaseWorkers = Effect.fn("EffectSql.releaseWorkers")(function* (release, staleMillis, table = "effect_sql_migrations") {
4
+ const sql = yield* SqlClient.SqlClient;
5
+ const processId = crypto.randomUUID();
6
+ const workers = `${table}_workers`;
7
+ return {
8
+ claim: sql.withTransaction(Effect.gen(function* () {
9
+ const [owner] = yield* sql `select release from ${sql(`${table}_release`)} where id = true for update`.withoutTransform;
10
+ if (owner?.release !== release) {
11
+ return false;
12
+ }
13
+ const others = yield* sql `select process_id from ${sql(workers)} where release <> ${release}
14
+ and heartbeat > clock_timestamp() - ${staleMillis} * interval '1 millisecond'`;
15
+ if (others.length > 0) {
16
+ return false;
17
+ }
18
+ yield* sql `insert into ${sql(workers)} (process_id, release, heartbeat) values (${processId}, ${release}, clock_timestamp())
19
+ on conflict (process_id) do update set heartbeat = excluded.heartbeat`;
20
+ return true;
21
+ })),
22
+ heartbeat: sql `update ${sql(workers)} set heartbeat = clock_timestamp() where process_id = ${processId}`.pipe(Effect.asVoid),
23
+ remove: sql `delete from ${sql(workers)} where process_id = ${processId}`.pipe(Effect.asVoid),
24
+ };
25
+ });
26
+ //# sourceMappingURL=releaseWorkers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"releaseWorkers.js","sourceRoot":"","sources":["../src/releaseWorkers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,EAAE,CAAC,0BAA0B,CAAC,CAAC,QAAQ,CAAC,EAC5E,OAAe,EACf,WAAmB,EACnB,KAAK,GAAG,uBAAuB;IAE/B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,GAAG,KAAK,UAAU,CAAC;IACnC,OAAO;QACN,KAAK,EAAE,GAAG,CAAC,eAAe,CACzB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAqB,uBAAuB,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC,6BAA6B,CAAC,gBAAgB,CAAC;YAC5I,IAAI,KAAK,EAAE,OAAO,KAAK,OAAO,EAAE,CAAC;gBAChC,OAAO,KAAK,CAAC;YACd,CAAC;YACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,GAAG,CAAA,0BAA0B,GAAG,CAAC,OAAO,CAAC,qBAAqB,OAAO;0CACrD,WAAW,6BAA6B,CAAC;YAC/E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,KAAK,CAAC;YACd,CAAC;YACD,KAAK,CAAC,CAAC,GAAG,CAAA,eAAe,GAAG,CAAC,OAAO,CAAC,6CAA6C,SAAS,KAAK,OAAO;0EACjC,CAAC;YACvE,OAAO,IAAI,CAAC;QACb,CAAC,CAAC,CACF;QACD,SAAS,EAAE,GAAG,CAAA,UAAU,GAAG,CAAC,OAAO,CAAC,yDAAyD,SAAS,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QAC5H,MAAM,EAAE,GAAG,CAAA,eAAe,GAAG,CAAC,OAAO,CAAC,uBAAuB,SAAS,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;KAC5F,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { Effect, type Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import { SqlClient } from "effect/sql";
4
+ import { type BatchWrites } from "#batchWrites.ts";
5
+ import { type PrimaryKey, type Repository } from "#compositeRepository.ts";
6
+ import { type ConflictColumns, type ConflictWrites } from "#conflictWrites.ts";
7
+ import { type SelectWrites } from "#insertFromSelect.ts";
8
+ import type { FindManyFilter, RepositoryFilter, RepositoryListFilter } from "#repositoryFilter.ts";
9
+ import { type Queries } from "#repositoryQueries.ts";
10
+ import { type VersionColumn, type VersionedWrites } from "#versionedRepository.ts";
11
+ type Key<TModel extends Model.Any> = Extract<keyof TModel["fields"] & keyof Row<TModel>, string>;
12
+ type Row<TModel extends Model.Any> = Schema.Struct.Type<TModel["fields"]>;
13
+ export interface OrderBy<TModel extends Model.Any> {
14
+ readonly direction: "asc" | "desc";
15
+ readonly field: Key<TModel>;
16
+ }
17
+ export interface FindMany<TModel extends Model.Any, TKey extends Key<TModel>> {
18
+ readonly limit?: number;
19
+ readonly orderBy?: OrderBy<TModel> | readonly [OrderBy<TModel>, ...OrderBy<TModel>[]];
20
+ readonly select?: readonly [TKey, ...TKey[]];
21
+ readonly where?: FindManyFilter<TModel>;
22
+ }
23
+ export interface LatestPerGroup<TModel extends Model.Any> {
24
+ readonly limit: number;
25
+ readonly orderBy: readonly [OrderBy<TModel>, ...OrderBy<TModel>[]];
26
+ readonly partitionBy: readonly [Key<TModel>, ...Key<TModel>[]];
27
+ readonly where?: RepositoryListFilter<TModel>;
28
+ }
29
+ declare const OptimisticConcurrencyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
30
+ readonly _tag: "OptimisticConcurrencyError";
31
+ } & Readonly<A>;
32
+ export declare class OptimisticConcurrencyError extends OptimisticConcurrencyError_base<{
33
+ readonly tableName: string;
34
+ readonly id: unknown;
35
+ readonly expectedVersion: number;
36
+ readonly reason: "missing" | "stale";
37
+ }> {
38
+ }
39
+ interface RepositoryOptions<TId> {
40
+ readonly idColumn: TId;
41
+ readonly spanPrefix: string;
42
+ readonly tableName: string;
43
+ }
44
+ type VersionedRepository<TModel extends Model.Any, TId extends PrimaryKey<TModel>> = Omit<Repository<TModel, TId>, keyof VersionedWrites<TModel, TId>> & VersionedWrites<TModel, TId> & Queries<TModel>;
45
+ export declare function makeRepository<TModel extends Model.Any, const TId extends PrimaryKey<TModel>, const TConflict extends ConflictColumns<TModel>, const TWhere extends keyof RepositoryFilter<TModel> = never>(model: TModel, options: RepositoryOptions<TId> & {
46
+ readonly versionColumn: VersionColumn<TModel, TId>;
47
+ readonly conflictColumns: TConflict;
48
+ readonly conflictWhere?: Pick<RepositoryFilter<TModel>, TWhere>;
49
+ }): Effect.Effect<VersionedRepository<TModel, TId> & Pick<ConflictWrites<TModel, never, TModel["fields"][Extract<TWhere, keyof TModel["fields"]>]["EncodingServices"]>, "insertOrIgnore">, never, SqlClient.SqlClient>;
50
+ export declare function makeRepository<TModel extends Model.Any, const TId extends PrimaryKey<TModel>>(model: TModel, options: RepositoryOptions<TId> & {
51
+ readonly versionColumn: VersionColumn<TModel, TId>;
52
+ readonly conflictColumns?: never;
53
+ readonly conflictWhere?: never;
54
+ }): Effect.Effect<VersionedRepository<TModel, TId>, never, SqlClient.SqlClient>;
55
+ export declare function makeRepository<TModel extends Model.Any, const TId extends PrimaryKey<TModel>, const TConflict extends ConflictColumns<TModel>, const TWhere extends keyof RepositoryFilter<TModel> = never>(model: TModel, options: RepositoryOptions<TId> & {
56
+ readonly versionColumn?: never;
57
+ readonly conflictColumns: TConflict;
58
+ readonly conflictWhere?: Pick<RepositoryFilter<TModel>, TWhere>;
59
+ }): Effect.Effect<Repository<TModel, TId> & BatchWrites<TModel> & SelectWrites<TModel> & Queries<TModel> & ConflictWrites<TModel, TConflict[number] | (TId extends readonly PropertyKey[] ? TId[number] : TId), TModel["fields"][Extract<TWhere, keyof TModel["fields"]>]["EncodingServices"]>, never, SqlClient.SqlClient>;
60
+ export declare function makeRepository<TModel extends Model.Any, const TId extends PrimaryKey<TModel>>(model: TModel, options: RepositoryOptions<TId> & {
61
+ readonly versionColumn?: never;
62
+ readonly conflictColumns?: never;
63
+ readonly conflictWhere?: never;
64
+ }): Effect.Effect<Repository<TModel, TId> & BatchWrites<TModel> & SelectWrites<TModel> & Queries<TModel>, never, SqlClient.SqlClient>;
65
+ export {};
66
+ //# sourceMappingURL=repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.d.ts","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { Data, Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import { makeInsertMany } from "#batchWrites.ts";
4
+ import { makeCompositeCrud } from "#compositeRepository.ts";
5
+ import { makeConflictWrites } from "#conflictWrites.ts";
6
+ import { makeInsertFromSelect } from "#insertFromSelect.ts";
7
+ import { repositoryChanges } from "#repositoryChanges.ts";
8
+ import { makeQueries } from "#repositoryQueries.ts";
9
+ import { makeVersionedWrites } from "#versionedRepository.ts";
10
+ export class OptimisticConcurrencyError extends Data.TaggedError("OptimisticConcurrencyError") {
11
+ }
12
+ export function makeRepository(model, options) {
13
+ return Effect.fnUntraced(function* () {
14
+ const sql = yield* SqlClient.SqlClient;
15
+ const composite = typeof options.idColumn === "object";
16
+ const idColumns = (composite ? options.idColumn : [options.idColumn]).map(String);
17
+ const changes = yield* repositoryChanges(sql, options.tableName, idColumns);
18
+ const crud = makeCompositeCrud(model, sql, { ...options, columns: idColumns }, changes);
19
+ const queries = makeQueries(model, sql, options);
20
+ return options.versionColumn === undefined
21
+ ? {
22
+ ...crud,
23
+ insertFromSelect: makeInsertFromSelect(model, sql, { ...options, changes }, "insertFromSelect"),
24
+ insertMany: makeInsertMany(model, sql, { ...options, changes }, "insertMany"),
25
+ ...(options.conflictColumns === undefined
26
+ ? {}
27
+ : makeConflictWrites(model, sql, { ...options, changes, conflictColumns: options.conflictColumns, idColumns })),
28
+ ...queries,
29
+ }
30
+ : {
31
+ ...crud,
32
+ ...makeVersionedWrites(model, sql, {
33
+ ...options,
34
+ changes,
35
+ conflict: (id, expectedVersion, reason) => new OptimisticConcurrencyError({ expectedVersion, id, reason, tableName: options.tableName }),
36
+ idColumns,
37
+ versionColumn: options.versionColumn,
38
+ }),
39
+ ...queries,
40
+ };
41
+ })();
42
+ }
43
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sourceRoot":"","sources":["../src/repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAe,MAAM,QAAQ,CAAC;AAEnD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAoB,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAoC,MAAM,yBAAyB,CAAC;AAC9F,OAAO,EAA6C,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACnG,OAAO,EAAE,oBAAoB,EAAqB,MAAM,sBAAsB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAiB,mBAAmB,EAA4C,MAAM,yBAAyB,CAAC;AAwBvH,MAAM,OAAO,0BAA2B,SAAQ,IAAI,CAAC,WAAW,CAAC,4BAA4B,CAK3F;CAAG;AAsEL,MAAM,UAAU,cAAc,CAC7B,KAAa,EACb,OAIC;IAED,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;QACjC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;QACvC,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;QACvD,MAAM,SAAS,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAClF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAG,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;QACxF,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;QACjD,OAAO,OAAO,CAAC,aAAa,KAAK,SAAS;YACzC,CAAC,CAAC;gBACA,GAAG,IAAI;gBACP,gBAAgB,EAAE,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,kBAAkB,CAAC;gBAC/F,UAAU,EAAE,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,YAAY,CAAC;gBAC7E,GAAG,CAAC,OAAO,CAAC,eAAe,KAAK,SAAS;oBACxC,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC;gBAChH,GAAG,OAAO;aACV;YACF,CAAC,CAAC;gBACA,GAAG,IAAI;gBACP,GAAG,mBAAmB,CAAC,KAAK,EAAE,GAAG,EAAE;oBAClC,GAAG,OAAO;oBACV,OAAO;oBACP,QAAQ,EAAE,CAAC,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,0BAA0B,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;oBACxI,SAAS;oBACT,aAAa,EAAE,OAAO,CAAC,aAAa;iBACpC,CAAC;gBACF,GAAG,OAAO;aACV,CAAC;IACL,CAAC,CAAC,EAAE,CAAC;AACN,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { Effect } from "effect";
2
+ import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import { SqlClient } from "effect/sql";
4
+ export type RepositoryChanges = Effect.Success<ReturnType<typeof repositoryChanges>>;
5
+ export declare const repositoryChanges: (sql: SqlClient.SqlClient, table: string, columns: readonly string[]) => Effect.Effect<{
6
+ record: (rows: readonly Readonly<Record<string, unknown>>[]) => Effect.Effect<void, never, never>;
7
+ write: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, import("effect/sql/SqlError").SqlError | Exclude<E, import("effect/sql/SqlError").SqlError>, Exclude<Exclude<R, SqlClient.SqlClient>, Reactivity.Reactivity>>;
8
+ }, never, never>;
9
+ //# sourceMappingURL=repositoryChanges.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryChanges.d.ts","sourceRoot":"","sources":["../src/repositoryChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AASvC,MAAM,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC,CAAC;AAErF,eAAO,MAAM,iBAAiB;mBAcP,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE;YAiBnD,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBAIrD,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { Effect, Option } from "effect";
2
+ import * as Reactivity from "effect/reactivity/Reactivity";
3
+ import { SqlClient } from "effect/sql";
4
+ import { invalidateOnCommit, transact } from "#transact.ts";
5
+ const ITEM_KEY_LIMIT = 1000;
6
+ function encodeKeyValue(_key, value) {
7
+ return typeof value === "bigint" ? String(value) : value;
8
+ }
9
+ export const repositoryChanges = Effect.fnUntraced(function* (sql, table, columns) {
10
+ const initial = yield* Effect.serviceOption(Reactivity.Reactivity);
11
+ const fallback = Option.isSome(initial) ? initial.value : yield* Reactivity.make;
12
+ function provide(effect) {
13
+ return Effect.flatMap(Effect.serviceOption(Reactivity.Reactivity), (current) => effect.pipe(Effect.provideService(SqlClient.SqlClient, sql), Effect.provideService(Reactivity.Reactivity, Option.getOrElse(current, () => fallback))));
14
+ }
15
+ function record(rows) {
16
+ if (rows.length === 0) {
17
+ return Effect.void;
18
+ }
19
+ if (rows.length > ITEM_KEY_LIMIT) {
20
+ return provide(invalidateOnCommit([table, `${table}:*`]));
21
+ }
22
+ const ids = rows.map((row) => columns.length === 1
23
+ ? row[columns[0] ?? ""]
24
+ : JSON.stringify(columns.map((column) => row[column]), encodeKeyValue));
25
+ return provide(invalidateOnCommit({ [table]: ids }));
26
+ }
27
+ function write(effect) {
28
+ return provide(transact(effect, { onSqlError: (error) => error }));
29
+ }
30
+ return { record, write };
31
+ });
32
+ //# sourceMappingURL=repositoryChanges.js.map