@shivaedev/sql 0.0.0 → 0.22.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 +275 -0
  2. package/LICENSE +21 -0
  3. package/README.md +613 -1
  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 +71 -4
  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,6 @@
1
+ import { Effect } from "effect";
2
+ import { Migrator } from "effect/sql";
3
+ export function runSchemaComponent(name, effect) {
4
+ return effect.pipe(Effect.mapError((cause) => new Migrator.MigrationError({ cause, kind: "Failed", message: `Schema component ${name} failed.` })));
5
+ }
6
+ //# sourceMappingURL=SchemaComponent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaComponent.js","sourceRoot":"","sources":["../src/SchemaComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAkB,MAAM,YAAY,CAAC;AAQtD,MAAM,UAAU,kBAAkB,CAAO,IAAY,EAAE,MAAoC;IAC1F,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,oBAAoB,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AACrJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { Context, Effect, type Scope } from "effect";
2
+ declare const WorkerRelease_base: Context.ServiceClass<WorkerRelease, "@shivaedev/sql/WorkerRelease", {
3
+ readonly register: <E>(control: (active: boolean) => Effect.Effect<void, E>) => Effect.Effect<void, E, Scope.Scope>;
4
+ }>;
5
+ export declare class WorkerRelease extends WorkerRelease_base {
6
+ }
7
+ export declare const makeWorkerRelease: () => Effect.Effect<{
8
+ service: {
9
+ readonly register: <E>(control: (active: boolean) => Effect.Effect<void, E>) => Effect.Effect<void, E, Scope.Scope>;
10
+ };
11
+ setActive: (next: boolean) => Effect.Effect<void, unknown, never>;
12
+ }, never, never>;
13
+ export {};
14
+ //# sourceMappingURL=WorkerRelease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkerRelease.d.ts","sourceRoot":"","sources":["../src/WorkerRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,KAAK,EAAa,MAAM,QAAQ,CAAC;;uBAK3C,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;;AAHrH,qBAAa,aAAc,SAAQ,kBAKA;CAAG;AAEtC,eAAO,MAAM,iBAAiB;;2BAJT,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC;;sBAqBjG,OAAO;gBAWzB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { Context, Effect, Semaphore } from "effect";
2
+ export class WorkerRelease extends Context.Service()("@shivaedev/sql/WorkerRelease") {
3
+ }
4
+ export const makeWorkerRelease = Effect.fn("EffectSql.makeWorkerRelease")(function* () {
5
+ const mutex = Semaphore.makeUnsafe(1);
6
+ const controls = new Set();
7
+ let active = false;
8
+ const locked = mutex.withPermits(1);
9
+ function register(control) {
10
+ const attach = Effect.gen(function* () {
11
+ controls.add(control);
12
+ yield* control(active);
13
+ });
14
+ const detach = Effect.sync(() => {
15
+ controls.delete(control);
16
+ });
17
+ return Effect.acquireRelease(locked(attach), () => locked(detach));
18
+ }
19
+ return {
20
+ service: WorkerRelease.of({ register }),
21
+ setActive: (next) => locked(Effect.gen(function* () {
22
+ if (next === active) {
23
+ return;
24
+ }
25
+ active = next;
26
+ yield* Effect.forEach(controls, (control) => control(active), { concurrency: "unbounded", discard: true });
27
+ })).pipe(Effect.uninterruptible),
28
+ };
29
+ });
30
+ //# sourceMappingURL=WorkerRelease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WorkerRelease.js","sourceRoot":"","sources":["../src/WorkerRelease.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAc,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEhE,MAAM,OAAO,aAAc,SAAQ,OAAO,CAAC,OAAO,EAK/C,CAAC,8BAA8B,CAAC;CAAG;AAEtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,QAAQ,CAAC;IAClF,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAqD,CAAC;IAC9E,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACpC,SAAS,QAAQ,CAAI,OAAoD;QACxE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YAC/B,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO;QACN,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC;QACvC,SAAS,EAAE,CAAC,IAAa,EAAE,EAAE,CAC5B,MAAM,CACL,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACnB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACrB,OAAO;YACR,CAAC;YACD,MAAM,GAAG,IAAI,CAAC;YACd,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5G,CAAC,CAAC,CACF,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC;KAC/B,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ declare const AdvisoryLockOutsideTransaction_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 & {
4
+ readonly _tag: "AdvisoryLockOutsideTransaction";
5
+ } & Readonly<A>;
6
+ export declare class AdvisoryLockOutsideTransaction extends AdvisoryLockOutsideTransaction_base {
7
+ }
8
+ export declare const advisoryXactLock: (key: string | bigint) => Effect.Effect<undefined, AdvisoryLockOutsideTransaction | import("effect/sql/SqlError").SqlError, SqlClient.SqlClient>;
9
+ export {};
10
+ //# sourceMappingURL=advisoryXactLock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advisoryXactLock.d.ts","sourceRoot":"","sources":["../src/advisoryXactLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAU,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;;;;AAEvC,qBAAa,8BAA+B,SAAQ,mCAAkD;CAAG;AAEzG,eAAO,MAAM,gBAAgB,kJAW3B,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { Data, Effect, Option } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ export class AdvisoryLockOutsideTransaction extends Data.TaggedError("AdvisoryLockOutsideTransaction") {
4
+ }
5
+ export const advisoryXactLock = Effect.fn("EffectSql.advisoryXactLock")(function* (key) {
6
+ const sql = yield* SqlClient.SqlClient;
7
+ const transaction = yield* Effect.serviceOption(sql.transactionService);
8
+ if (Option.isNone(transaction)) {
9
+ return yield* new AdvisoryLockOutsideTransaction();
10
+ }
11
+ if (typeof key === "string") {
12
+ yield* sql `select pg_advisory_xact_lock(hashtextextended(${key}, 0))`;
13
+ }
14
+ else {
15
+ yield* sql `select pg_advisory_xact_lock(${String(key)}::bigint)`;
16
+ }
17
+ });
18
+ //# sourceMappingURL=advisoryXactLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advisoryXactLock.js","sourceRoot":"","sources":["../src/advisoryXactLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,OAAO,8BAA+B,SAAQ,IAAI,CAAC,WAAW,CAAC,gCAAgC,CAAC;CAAG;AAEzG,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,EAAE,CAAC,4BAA4B,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAoB;IACtG,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACxE,IAAI,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC,CAAC,IAAI,8BAA8B,EAAE,CAAC;IACpD,CAAC;IACD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC7B,KAAK,CAAC,CAAC,GAAG,CAAA,iDAAiD,GAAG,OAAO,CAAC;IACvE,CAAC;SAAM,CAAC;QACP,KAAK,CAAC,CAAC,GAAG,CAAA,gCAAgC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;IAClE,CAAC;AACF,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { SqlClient } from "effect/sql";
3
+ export declare function aggregateColumn(sql: SqlClient.SqlClient, fieldAt: (key: string) => Effect.Effect<Schema.Constraint, Schema.SchemaError>): (name: string, expression: object) => Effect.Effect<{
4
+ column: import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>;
5
+ order: import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>;
6
+ schema: Schema.Constraint;
7
+ }, Schema.SchemaError, never>;
8
+ //# sourceMappingURL=aggregateColumn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregateColumn.d.ts","sourceRoot":"","sources":["../src/aggregateColumn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAa,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgC5C,wBAAgB,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC;;;;8BAevI"}
@@ -0,0 +1,44 @@
1
+ import { Effect, Schema, SchemaAST } from "effect";
2
+ const Expression = Schema.Tuple([Schema.Tuple([Schema.Literals(["count", "sum", "avg", "min", "max", "boolOr", "boolAnd"]), Schema.String])]);
3
+ const functions = { avg: "avg", boolAnd: "bool_and", boolOr: "bool_or", count: "count", max: "max", min: "min", sum: "sum" };
4
+ function isNumber(ast) {
5
+ if (ast._tag === "Union") {
6
+ return ast.types.some(isNumber);
7
+ }
8
+ if (ast._tag === "Suspend") {
9
+ return isNumber(ast.thunk());
10
+ }
11
+ return ast._tag === "Number" || (ast._tag === "Literal" && typeof ast.literal === "number");
12
+ }
13
+ function resultSchema(operation, field) {
14
+ switch (operation) {
15
+ case "count":
16
+ return Schema.NumberFromString;
17
+ case "sum":
18
+ case "avg":
19
+ return isNumber(SchemaAST.toType(field.ast)) ? Schema.NumberFromString : Schema.BigDecimalFromString;
20
+ case "boolOr":
21
+ case "boolAnd":
22
+ return Schema.Boolean;
23
+ case "min":
24
+ case "max":
25
+ return field;
26
+ }
27
+ }
28
+ export function aggregateColumn(sql, fieldAt) {
29
+ return Effect.fnUntraced(function* (name, expression) {
30
+ const [[operation, key]] = yield* Schema.decodeUnknownEffect(Expression)(Object.entries(expression));
31
+ const countRows = operation === "count" && key === "*";
32
+ const field = countRows ? Schema.Number : yield* fieldAt(key);
33
+ const operand = countRows ? sql `*` : sql `${sql(key)}`;
34
+ const aggregate = sql `${sql.literal(functions[operation])}(${operand})`;
35
+ const text = operation === "count" || operation === "sum" || operation === "avg";
36
+ const Result = resultSchema(operation, field);
37
+ return {
38
+ column: sql `${text ? sql `cast(${aggregate} as text)` : aggregate} as ${sql(name)}`,
39
+ order: aggregate,
40
+ schema: operation === "count" ? Result : Schema.NullOr(Result),
41
+ };
42
+ });
43
+ }
44
+ //# sourceMappingURL=aggregateColumn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregateColumn.js","sourceRoot":"","sources":["../src/aggregateColumn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { BigDecimal, Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlError } from "effect/sql/SqlError";
4
+ import type { FindManyFilter, OrderedValue } from "#repositoryFilter.ts";
5
+ type Row<T extends Model.Any> = Schema.Struct.Type<T["fields"]>;
6
+ type Key<T extends Model.Any> = Extract<keyof T["fields"] & keyof Row<T>, string>;
7
+ type FieldsOfType<T extends Model.Any, TValue> = {
8
+ [TKey in Key<T>]: [NonNullable<Row<T>[TKey]>] extends [TValue] ? TKey : never;
9
+ }[Key<T>];
10
+ interface Operands<T extends Model.Any> {
11
+ avg: FieldsOfType<T, number | BigDecimal.BigDecimal>;
12
+ boolAnd: FieldsOfType<T, boolean>;
13
+ boolOr: FieldsOfType<T, boolean>;
14
+ count: "*" | Key<T>;
15
+ max: FieldsOfType<T, OrderedValue>;
16
+ min: FieldsOfType<T, OrderedValue>;
17
+ sum: FieldsOfType<T, number | BigDecimal.BigDecimal>;
18
+ }
19
+ export type AggregateExpression<T extends Model.Any> = {
20
+ [TOperation in keyof Operands<T>]: {
21
+ readonly [TKey in TOperation]: Operands<T>[TKey];
22
+ } & {
23
+ readonly [TKey in Exclude<keyof Operands<T>, TOperation>]?: never;
24
+ };
25
+ }[keyof Operands<T>];
26
+ type AggregateValue<T extends Model.Any, TExpression> = TExpression extends {
27
+ readonly count: unknown;
28
+ } ? number : TExpression extends {
29
+ readonly boolOr: unknown;
30
+ } | {
31
+ readonly boolAnd: unknown;
32
+ } ? boolean | null : TExpression extends {
33
+ readonly [TKey in infer TOperation]: infer TField;
34
+ } ? TOperation extends "sum" | "avg" | "min" | "max" ? TField extends Key<T> ? Row<T>[TField] | null : never : never : never;
35
+ export interface AggregateQuery<T extends Model.Any, TGroup extends readonly Key<T>[], TAggregates> {
36
+ readonly aggregates: TAggregates & {
37
+ readonly [TKey in TGroup[number]]?: never;
38
+ };
39
+ readonly groupBy: TGroup;
40
+ readonly limit?: number;
41
+ readonly orderBy?: readonly {
42
+ readonly field: TGroup[number] | Extract<keyof TAggregates, string>;
43
+ readonly direction: "asc" | "desc";
44
+ }[];
45
+ readonly where?: FindManyFilter<T>;
46
+ }
47
+ export type Aggregate<T extends Model.Any> = <const TGroup extends readonly [Key<T>, ...Key<T>[]], const TAggregates extends Readonly<Record<string, AggregateExpression<T>>>>(query: AggregateQuery<T, TGroup, TAggregates>) => Effect.Effect<Array<{
48
+ readonly [TName in TGroup[number] | keyof TAggregates]: TName extends TGroup[number] ? Row<T>[TName] : AggregateValue<T, TAggregates[TName]>;
49
+ }>, SqlError | Schema.SchemaError, T["fields"][Key<T>]["EncodingServices"] | T["fields"][Key<T>]["DecodingServices"]>;
50
+ export {};
51
+ //# sourceMappingURL=aggregateQuery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregateQuery.d.ts","sourceRoot":"","sources":["../src/aggregateQuery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=aggregateQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregateQuery.js","sourceRoot":"","sources":["../src/aggregateQuery.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import { Effect } from "effect";
2
+ import { Migrator } from "effect/sql";
3
+ import type { PostgresMigrationOptions } from "./migrations.ts";
4
+ import { type PendingPostgresMigrations } from "./pendingPostgresMigrations.ts";
5
+ export declare const assertPostgresMigrations: <R>(options: Pick<PostgresMigrationOptions<R>, "components" | "loader" | "release" | "table">) => Effect.Effect<undefined, Migrator.MigrationError | import("effect/sql/SqlError").SqlError, R | import("effect/sql/SqlClient").SqlClient>;
6
+ export declare function postgresMigrationError(pending: PendingPostgresMigrations): Migrator.MigrationError;
7
+ //# sourceMappingURL=assertPostgresMigrations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertPostgresMigrations.d.ts","sourceRoot":"","sources":["../src/assertPostgresMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,yBAAyB,EAA6B,MAAM,gCAAgC,CAAC;AAE3G,eAAO,MAAM,wBAAwB,GAA8D,CAAC,wOAOlG,CAAC;AAEH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,yBAAyB,2BASxE"}
@@ -0,0 +1,20 @@
1
+ import { Effect } from "effect";
2
+ import { Migrator } from "effect/sql";
3
+ import { pendingPostgresMigrations } from "./pendingPostgresMigrations.js";
4
+ export const assertPostgresMigrations = Effect.fn("EffectSql.assertPostgresMigrations")(function* (options) {
5
+ const pending = yield* pendingPostgresMigrations(options);
6
+ if (pending.migrations.length > 0 || pending.components.length > 0) {
7
+ return yield* Effect.fail(postgresMigrationError(pending));
8
+ }
9
+ });
10
+ export function postgresMigrationError(pending) {
11
+ const details = [
12
+ ...pending.migrations.map(({ id, name }) => `migration ${id} (${name})`),
13
+ ...pending.components.map(({ name, detail }) => `component ${name}: ${detail}`),
14
+ ];
15
+ return new Migrator.MigrationError({
16
+ kind: "BadState",
17
+ message: `Database migrations are not current: ${details.join("; ")}. Run the deployment migration command.`,
18
+ });
19
+ }
20
+ //# sourceMappingURL=assertPostgresMigrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assertPostgresMigrations.js","sourceRoot":"","sources":["../src/assertPostgresMigrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,EAAkC,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3G,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,EAAE,CAAC,oCAAoC,CAAC,CAAC,QAAQ,CAAC,EAChG,OAAyF;IAEzF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;IAC1D,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpE,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,MAAM,UAAU,sBAAsB,CAAC,OAAkC;IACxE,MAAM,OAAO,GAAG;QACf,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,aAAa,EAAE,KAAK,IAAI,GAAG,CAAC;QACxE,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,aAAa,IAAI,KAAK,MAAM,EAAE,CAAC;KAC/E,CAAC;IACF,OAAO,IAAI,QAAQ,CAAC,cAAc,CAAC;QAClC,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,wCAAwC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,yCAAyC;KAC5G,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlClient } from "effect/sql";
4
+ import type { SqlError } from "effect/sql/SqlError";
5
+ import type { Fragment } from "effect/sql/Statement";
6
+ import type { RepositoryChanges } from "./repositoryChanges.ts";
7
+ export type InsertMany<TModel extends Model.Any, TServices = never> = (inputs: readonly TModel["insert"]["Type"][]) => Effect.Effect<TModel["Type"][], SqlError | Schema.SchemaError, TModel["insert"]["EncodingServices"] | TModel["DecodingServices"] | TServices>;
8
+ export interface BatchWrites<TModel extends Model.Any> {
9
+ readonly insertMany: InsertMany<TModel>;
10
+ }
11
+ export declare function makeInsertMany<TServices = never>(model: Model.Any, sql: SqlClient.SqlClient, options: {
12
+ readonly tableName: string;
13
+ readonly spanPrefix: string;
14
+ readonly changes: RepositoryChanges;
15
+ }, operation: string, prepare?: (row: Readonly<Record<string, unknown>>) => Effect.Effect<Fragment, Schema.SchemaError, TServices>): (inputs: readonly unknown[]) => Effect.Effect<unknown[], Schema.SchemaError | SqlError, unknown>;
16
+ //# sourceMappingURL=batchWrites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batchWrites.d.ts","sourceRoot":"","sources":["../src/batchWrites.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;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,MAAM,MAAM,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,SAAS,GAAG,KAAK,IAAI,CACrE,MAAM,EAAE,SAAS,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,KACvC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,SAAS,CAAC,CAAC;AAEnJ,MAAM,WAAW,WAAW,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG;IACpD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;CACxC;AAED,wBAAgB,cAAc,CAAC,SAAS,GAAG,KAAK,EAC/C,KAAK,EAAE,KAAK,CAAC,GAAG,EAChB,GAAG,EAAE,SAAS,CAAC,SAAS,EACxB,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,EACzG,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,SAAS,CAA+B,YAKzH,SAAS,OAAO,EAAE,sEA2ClC"}
@@ -0,0 +1,49 @@
1
+ import { Effect, Schema } from "effect";
2
+ export function makeInsertMany(model, sql, options, operation, prepare = () => Effect.succeed(sql ``)) {
3
+ const encode = Schema.encodeEffect(model.insert);
4
+ const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
5
+ const decode = Schema.decodeUnknownEffect(Schema.Array(model));
6
+ return (inputs) => Effect.gen(function* () {
7
+ if (inputs.length === 0) {
8
+ return [];
9
+ }
10
+ const rows = yield* Effect.forEach(inputs, (input) => Effect.flatMap(encode(input), record));
11
+ const columns = [...new Set(rows.flatMap(Object.keys))];
12
+ if (columns.length === 0) {
13
+ columns.push(...Object.keys(model.fields).slice(0, 1));
14
+ }
15
+ const names = sql.csv(columns.map((column) => sql `${sql(column)}`));
16
+ const chunkSize = Math.max(1, Math.min(1000, Math.floor(10_000 / columns.length)));
17
+ const results = [];
18
+ const changedRows = [];
19
+ let chunk = [];
20
+ let parameters = 0;
21
+ let suffix = sql ``;
22
+ const flush = Effect.gen(function* () {
23
+ const returned = yield* sql `insert into ${sql(options.tableName)} (${names}) values ${sql.csv(chunk)} ${suffix} returning *`;
24
+ changedRows.push(...returned);
25
+ for (const row of yield* decode(returned)) {
26
+ results.push(row);
27
+ }
28
+ chunk = [];
29
+ parameters = 0;
30
+ });
31
+ for (const row of rows) {
32
+ const value = sql `(${sql.csv(columns.map((column) => (Object.hasOwn(row, column) ? sql `${row[column]}` : sql `default`)))})`;
33
+ const size = value.compile()[1].length;
34
+ const prepared = yield* prepare(row);
35
+ const suffixSize = sql `${prepared}`.compile()[1].length;
36
+ // Bound native fragment size as well as PostgreSQL's 65,535 bind parameters.
37
+ if (chunk.length > 0 && (chunk.length === chunkSize || parameters + size + suffixSize > 10_000)) {
38
+ yield* flush;
39
+ }
40
+ suffix = prepared;
41
+ chunk.push(value);
42
+ parameters += size;
43
+ }
44
+ yield* flush;
45
+ yield* options.changes.record(changedRows);
46
+ return results;
47
+ }).pipe(options.changes.write, Effect.withSpan(`${options.spanPrefix}.${operation}`));
48
+ }
49
+ //# sourceMappingURL=batchWrites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batchWrites.js","sourceRoot":"","sources":["../src/batchWrites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export interface SqlNameTransforms {
2
+ readonly transformQueryNames?: ((name: string) => string) | undefined;
3
+ readonly transformResultNames?: ((name: string) => string) | undefined;
4
+ }
5
+ export declare function clientOptions<TOptions extends object>(options: TOptions, { snakeCase }?: {
6
+ readonly snakeCase?: boolean;
7
+ }): TOptions & SqlNameTransforms;
8
+ //# sourceMappingURL=clientOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientOptions.d.ts","sourceRoot":"","sources":["../src/clientOptions.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;IACtE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CACvE;AAED,wBAAgB,aAAa,CAAC,QAAQ,SAAS,MAAM,EACpD,OAAO,EAAE,QAAQ,EACjB,EAAE,SAAgB,EAAE,GAAE;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAO,GACzD,QAAQ,GAAG,iBAAiB,CAK9B"}
@@ -0,0 +1,8 @@
1
+ import { camelToSnake, snakeToCamel } from "effect/String";
2
+ export function clientOptions(options, { snakeCase = true } = {}) {
3
+ return {
4
+ ...(snakeCase ? { transformQueryNames: camelToSnake, transformResultNames: snakeToCamel } : {}),
5
+ ...options,
6
+ };
7
+ }
8
+ //# sourceMappingURL=clientOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clientOptions.js","sourceRoot":"","sources":["../src/clientOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAO3D,MAAM,UAAU,aAAa,CAC5B,OAAiB,EACjB,EAAE,SAAS,GAAG,IAAI,EAAE,GAAqC,EAAE;IAE3D,OAAO;QACN,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,mBAAmB,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,GAAG,OAAO;KACV,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { Cause } from "effect";
2
+ import { Effect, Schema } from "effect";
3
+ import type { Model } from "effect/schema";
4
+ import { type SqlClient } from "effect/sql";
5
+ import type { SqlError } from "effect/sql/SqlError";
6
+ import { type RepositoryChanges } from "#repositoryChanges.ts";
7
+ import type { RepositoryListFilter } from "#repositoryFilter.ts";
8
+ import type { IdColumn, NativeRepository } from "#versionedRepository.ts";
9
+ export type CompositeKey<TModel extends Model.Any> = readonly [IdColumn<TModel>, IdColumn<TModel>, ...IdColumn<TModel>[]];
10
+ export type PrimaryKey<TModel extends Model.Any> = IdColumn<TModel> | CompositeKey<TModel>;
11
+ type DeleteWhere<TModel extends Model.Any> = (where: RepositoryListFilter<TModel>) => Effect.Effect<void, SqlError | Schema.SchemaError, TModel["fields"][keyof TModel["fields"]]["EncodingServices"]>;
12
+ interface Update<TModel extends Model.Any> {
13
+ (input: TModel["update"]["Type"], options: {
14
+ readonly onMissing: "fail";
15
+ }): Effect.Effect<TModel["Type"], SqlError | Schema.SchemaError | Cause.NoSuchElementError, TModel["update"]["EncodingServices"] | TModel["DecodingServices"]>;
16
+ (input: TModel["update"]["Type"]): Effect.Effect<TModel["Type"], SqlError | Schema.SchemaError, TModel["update"]["EncodingServices"] | TModel["DecodingServices"]>;
17
+ }
18
+ export type Repository<TModel extends Model.Any, TId extends PrimaryKey<TModel>> = [TId] extends [IdColumn<TModel>] ? Omit<NativeRepository<TModel, Extract<TId, IdColumn<TModel>>>, "delete" | "update"> & {
19
+ readonly delete: NativeRepository<TModel, Extract<TId, IdColumn<TModel>>>["delete"] & DeleteWhere<TModel>;
20
+ readonly update: Update<TModel>;
21
+ } : TId extends CompositeKey<TModel> ? Omit<NativeRepository<TModel, TId[number]>, "findById" | "delete" | "update"> & {
22
+ readonly update: Update<TModel>;
23
+ readonly findById: (id: Pick<TModel["Type"], TId[number]>) => Effect.Effect<TModel["Type"], SqlError | Schema.SchemaError | Cause.NoSuchElementError, TModel["DecodingServices"] | TModel["fields"][TId[number]]["EncodingServices"]>;
24
+ readonly delete: ((id: Pick<TModel["Type"], TId[number]>) => Effect.Effect<void, SqlError | Schema.SchemaError, TModel["fields"][TId[number]]["EncodingServices"]>) & DeleteWhere<TModel>;
25
+ } : never;
26
+ export declare function makeCompositeCrud(model: Model.Any, sql: SqlClient.SqlClient, options: {
27
+ readonly columns: readonly string[];
28
+ readonly tableName: string;
29
+ readonly spanPrefix: string;
30
+ }, supplied?: RepositoryChanges): {
31
+ delete: (id: unknown) => Effect.Effect<void, Schema.SchemaError | SqlError, unknown>;
32
+ insert: (input: unknown) => Effect.Effect<unknown, Schema.SchemaError | SqlError, unknown>;
33
+ insertVoid: (input: unknown) => Effect.Effect<void, Schema.SchemaError | SqlError, unknown>;
34
+ update: (input: unknown, settings?: {
35
+ readonly onMissing: "fail";
36
+ }) => Effect.Effect<unknown, Cause.NoSuchElementError | Schema.SchemaError | SqlError, unknown>;
37
+ updateVoid: (input: unknown) => Effect.Effect<void, Schema.SchemaError | SqlError, unknown>;
38
+ findById: (id: unknown) => Effect.Effect<unknown, Cause.NoSuchElementError | Schema.SchemaError | SqlError, unknown>;
39
+ };
40
+ export {};
41
+ //# sourceMappingURL=compositeRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compositeRepository.d.ts","sourceRoot":"","sources":["../src/compositeRepository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,KAAK,iBAAiB,EAAqB,MAAM,uBAAuB,CAAC;AAClF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE1E,MAAM,MAAM,YAAY,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAC1H,MAAM,MAAM,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAC3F,KAAK,WAAW,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,CAC5C,KAAK,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAEtH,UAAU,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG;IACxC,CACC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAC/B,OAAO,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GACrC,MAAM,CAAC,MAAM,CACf,MAAM,CAAC,MAAM,CAAC,EACd,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,kBAAkB,EACxD,MAAM,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,CACjE,CAAC;IACF,CACC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;CACnI;AAED,MAAM,MAAM,UAAU,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,SAAS,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAChH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAAG;IACtF,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1G,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;CAChC,GACA,GAAG,SAAS,YAAY,CAAC,MAAM,CAAC,GAC/B,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAC,GAAG;IAChF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,CAClB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,KACjC,MAAM,CAAC,MAAM,CACjB,MAAM,CAAC,MAAM,CAAC,EACd,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,kBAAkB,EACxD,MAAM,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAC9E,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE,CAAC,CACjB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,KACjC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,GAC1G,WAAW,CAAC,MAAM,CAAC,CAAC;CACrB,GACA,KAAK,CAAC;AAEV,wBAAgB,iBAAiB,CAChC,KAAK,EAAE,KAAK,CAAC,GAAG,EAChB,GAAG,EAAE,SAAS,CAAC,SAAS,EACxB,OAAO,EAAE;IACR,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B,EACD,QAAQ,CAAC,EAAE,iBAAiB;;;;;;;;mBAsCZ,OAAO;EAEvB"}
@@ -0,0 +1,38 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { SqlSchema } from "effect/sql";
3
+ import { repositoryChanges } from "#repositoryChanges.ts";
4
+ import { repositoryWrites } from "#repositoryWrites.ts";
5
+ export function makeCompositeCrud(model, sql, options, supplied) {
6
+ const { columns, tableName, spanPrefix } = options;
7
+ const fields = Object.fromEntries(columns.map((column) => {
8
+ const field = model.fields[column];
9
+ if (field === undefined) {
10
+ throw new Error(`Unknown ID column: ${column}`);
11
+ }
12
+ return [column, field];
13
+ }));
14
+ const Key = columns.length === 1 ? model.fields[columns[0] ?? ""] : Schema.Struct(fields);
15
+ if (Key === undefined) {
16
+ throw new Error("Unknown repository ID column");
17
+ }
18
+ const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
19
+ function predicate(input) {
20
+ return sql.and(columns.map((column) => sql `${sql(column)} = ${input[column]}`));
21
+ }
22
+ const find = SqlSchema.findOne({
23
+ execute: (input) => Effect.flatMap(record(columns.length === 1 ? { [columns[0] ?? ""]: input } : input), (key) => sql `select * from ${sql(tableName)} where ${predicate(key)}`),
24
+ Request: Key,
25
+ Result: model,
26
+ });
27
+ const changes = supplied ?? {
28
+ record: (rows) => Effect.flatMap(repositoryChanges(sql, tableName, columns), (boundary) => boundary.record(rows)),
29
+ write(effect) {
30
+ return Effect.flatMap(repositoryChanges(sql, tableName, columns), (boundary) => boundary.write(effect));
31
+ },
32
+ };
33
+ return {
34
+ ...repositoryWrites(model, sql, { ...options, idColumns: columns }, changes),
35
+ findById: (id) => find(id).pipe(Effect.withSpan(`${spanPrefix}.findById`)),
36
+ };
37
+ }
38
+ //# sourceMappingURL=compositeRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compositeRepository.js","sourceRoot":"","sources":["../src/compositeRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlClient } from "effect/sql";
4
+ import type { SqlError } from "effect/sql/SqlError";
5
+ import type { Comparisons, FindManyFilter } from "#repositoryFilter.ts";
6
+ import type { RepositoryChanges } from "./repositoryChanges.ts";
7
+ type Fields<TModel extends Model.Any> = Schema.Struct.Type<TModel["fields"]>;
8
+ interface Incoming<TModel extends Model.Any, TValue> {
9
+ readonly excluded: {
10
+ [TKey in keyof Fields<TModel>]: [Fields<TModel>[TKey]] extends [TValue] ? TKey : never;
11
+ }[keyof Fields<TModel>];
12
+ }
13
+ export type UpsertFilter<TModel extends Model.Any> = {
14
+ readonly [TKey in keyof Fields<TModel>]?: FindManyFilter<TModel>[TKey] | Incoming<TModel, Fields<TModel>[TKey]> | Comparisons<Fields<TModel>[TKey], NonNullable<Fields<TModel>[TKey]> | Incoming<TModel, NonNullable<Fields<TModel>[TKey]>>>;
15
+ };
16
+ export type UpsertResult<TRow> = {
17
+ readonly _tag: "Inserted";
18
+ readonly row: TRow;
19
+ } | {
20
+ readonly _tag: "Updated";
21
+ readonly row: TRow;
22
+ } | {
23
+ readonly _tag: "Unchanged";
24
+ };
25
+ export interface ConditionalUpsert<TModel extends Model.Any, TOptions, TServices> {
26
+ (input: TModel["insert"]["Type"], options: TOptions & {
27
+ readonly updateWhere: UpsertFilter<TModel>;
28
+ }): Effect.Effect<UpsertResult<TModel["Type"]>, SqlError | Schema.SchemaError, TServices | TModel["fields"][keyof TModel["fields"]]["EncodingServices"]>;
29
+ (input: TModel["insert"]["Type"], options: TOptions & {
30
+ readonly updateWhere?: never;
31
+ }): Effect.Effect<TModel["Type"], SqlError | Schema.SchemaError, TServices>;
32
+ }
33
+ export interface ConditionalUpsertMany<TModel extends Model.Any, TOptions, TServices> {
34
+ (inputs: readonly TModel["insert"]["Type"][], options: TOptions & {
35
+ readonly updateWhere: UpsertFilter<TModel>;
36
+ }): Effect.Effect<UpsertResult<TModel["Type"]>[], SqlError | Schema.SchemaError, TServices | TModel["fields"][keyof TModel["fields"]]["EncodingServices"]>;
37
+ (inputs: readonly TModel["insert"]["Type"][], options: TOptions & {
38
+ readonly updateWhere?: never;
39
+ }): Effect.Effect<TModel["Type"][], SqlError | Schema.SchemaError, TServices>;
40
+ }
41
+ export declare function makeConditionalUpsert(model: Model.Any, sql: SqlClient.SqlClient, options: {
42
+ readonly tableName: string;
43
+ readonly spanPrefix: string;
44
+ readonly changes: RepositoryChanges;
45
+ readonly conflictColumns: readonly string[];
46
+ readonly conflictWhere?: Readonly<Record<string, unknown>>;
47
+ readonly idColumns: readonly string[];
48
+ }): (inputs: readonly unknown[], settings: {
49
+ readonly updateColumns: readonly string[];
50
+ readonly updateWhere: Readonly<Record<string, unknown>>;
51
+ }) => Effect.Effect<({
52
+ readonly _tag: "Unchanged";
53
+ readonly row?: never;
54
+ } | {
55
+ readonly _tag: "Inserted" | "Updated";
56
+ readonly row: unknown;
57
+ })[], Schema.SchemaError | SqlError, unknown>;
58
+ export {};
59
+ //# sourceMappingURL=conditionalUpsert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditionalUpsert.d.ts","sourceRoot":"","sources":["../src/conditionalUpsert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { makeConflictClause } from "#makeConflictClause.ts";
3
+ export function makeConditionalUpsert(model, sql, options) {
4
+ const encode = Schema.encodeEffect(model.insert);
5
+ const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
6
+ const decode = Schema.decodeUnknownEffect(model);
7
+ const clause = makeConflictClause(model, sql, options);
8
+ return (inputs, settings) => Effect.gen(function* () {
9
+ const statements = yield* Effect.forEach(inputs, (input) => Effect.gen(function* () {
10
+ const row = yield* record(yield* encode(input));
11
+ const suffix = yield* clause(row, settings.updateColumns, settings.updateWhere);
12
+ return sql `insert into ${sql(options.tableName)} ${sql.insert(row)} ${suffix} returning *, (xmax = 0) as ${sql("effectSqlInserted")}`;
13
+ }));
14
+ const changedRows = [];
15
+ const results = yield* Effect.forEach(statements, (statement) => Effect.gen(function* () {
16
+ const rows = yield* statement;
17
+ changedRows.push(...rows);
18
+ const row = rows[0];
19
+ if (row === undefined) {
20
+ return { _tag: "Unchanged" };
21
+ }
22
+ return { _tag: row.effectSqlInserted ? "Inserted" : "Updated", row: yield* decode(row) };
23
+ }));
24
+ yield* options.changes.record(changedRows);
25
+ return results;
26
+ }).pipe(options.changes.write, Effect.withSpan(`${options.spanPrefix}.conditionalUpsert`));
27
+ }
28
+ //# sourceMappingURL=conditionalUpsert.js.map
@@ -0,0 +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;AAiD5D,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,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACvD,OAAO,CACN,MAA0B,EAC1B,QAAgH,EAC/G,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,+BAA+B,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACvI,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,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAW,CAAC;QACnG,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"}