@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 @@
1
+ {"version":3,"file":"repositoryChanges.js","sourceRoot":"","sources":["../src/repositoryChanges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE5D,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B,SAAS,cAAc,CAAC,IAAY,EAAE,KAAc;IACnD,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1D,CAAC;AAID,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,GAAwB,EAAE,KAAa,EAAE,OAA0B;IAChI,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC;IACjF,SAAS,OAAO,CAAU,MAA4E;QACrG,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAC9E,MAAM,CAAC,IAAI,CACV,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,EAC/C,MAAM,CAAC,cAAc,CACpB,UAAU,CAAC,UAAU,EACrB,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,CACzC,CACD,CACD,CAAC;IACH,CAAC;IACD,SAAS,MAAM,CAAC,IAAkD;QACjE,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,cAAc,EAAE,CAAC;YAClC,OAAO,OAAO,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAC5B,OAAO,CAAC,MAAM,KAAK,CAAC;YACnB,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvB,CAAC,CAAC,IAAI,CAAC,SAAS,CACd,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EACpC,cAAc,CACd,CACH,CAAC;QACF,OAAO,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,SAAS,KAAK,CAAU,MAA8B;QACrD,OAAO,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlClient } from "effect/sql";
4
+ import { type TupleFilter } from "#tupleIn.ts";
5
+ export type RepositoryFilter<TModel extends Model.Any> = {
6
+ readonly [TField in keyof Schema.Struct.Type<TModel["fields"]>]?: Schema.Struct.Type<TModel["fields"]>[TField] | undefined;
7
+ };
8
+ export type RepositoryListFilter<TModel extends Model.Any> = Partial<TupleFilter<TModel>> & {
9
+ readonly [TField in keyof Schema.Struct.Type<TModel["fields"]>]?: Schema.Struct.Type<TModel["fields"]>[TField] | {
10
+ readonly in: readonly Schema.Struct.Type<TModel["fields"]>[TField][];
11
+ } | undefined;
12
+ };
13
+ declare const Ordered: Schema.Union<readonly [Schema.String, Schema.Number, Schema.BigInt, Schema.Date, Schema.BigDecimal, Schema.DateTimeUtc]>;
14
+ export type OrderedValue = typeof Ordered.Type;
15
+ export type Comparisons<T, TOperand = NonNullable<T>> = [NonNullable<T>] extends [OrderedValue] ? {
16
+ readonly gt?: TOperand;
17
+ readonly gte?: TOperand;
18
+ readonly lt?: TOperand;
19
+ readonly lte?: TOperand;
20
+ } : {
21
+ readonly gt?: never;
22
+ readonly gte?: never;
23
+ readonly lt?: never;
24
+ readonly lte?: never;
25
+ };
26
+ type Pattern<T> = [NonNullable<T>] extends [string] ? {
27
+ readonly like?: NonNullable<T>;
28
+ } : {
29
+ readonly like?: never;
30
+ };
31
+ export type FindManyFilter<TModel extends Model.Any> = Partial<TupleFilter<TModel>> & {
32
+ readonly [TField in keyof Schema.Struct.Type<TModel["fields"]>]?: Schema.Struct.Type<TModel["fields"]>[TField] | (Comparisons<Schema.Struct.Type<TModel["fields"]>[TField]> & Pattern<Schema.Struct.Type<TModel["fields"]>[TField]>) | {
33
+ readonly in: readonly Schema.Struct.Type<TModel["fields"]>[TField][];
34
+ } | undefined;
35
+ };
36
+ export declare function makeFilter<TModel extends Model.Any>(model: TModel, sql: SqlClient.SqlClient, references?: {
37
+ readonly tableName: string;
38
+ }): {
39
+ fieldAt: (key: string) => Effect.Effect<never, Schema.SchemaError, never> | Effect.Effect<Schema.Constraint, never, never>;
40
+ where: (input?: Readonly<Record<string, unknown>> & Partial<TupleFilter<Model.Any>>, allowIn?: boolean, allowComparisons?: boolean) => Effect.Effect<import("effect/sql/Statement").Fragment, Schema.SchemaError, unknown>;
41
+ };
42
+ export {};
43
+ //# sourceMappingURL=repositoryFilter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryFilter.d.ts","sourceRoot":"","sources":["../src/repositoryFilter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import { Effect, Schema, SchemaIssue } from "effect";
2
+ import { tuplePredicate } from "#tupleIn.ts";
3
+ const Ordered = Schema.Union([Schema.String, Schema.Number, Schema.BigInt, Schema.Date, Schema.BigDecimal, Schema.DateTimeUtc]);
4
+ const operators = { gt: ">", gte: ">=", like: "like", lt: "<", lte: "<=" };
5
+ function isOperator(key) {
6
+ return Object.hasOwn(operators, key);
7
+ }
8
+ export function makeFilter(model, sql, references) {
9
+ function fieldAt(key) {
10
+ const field = Object.hasOwn(model.fields, key) ? model.fields[key] : undefined;
11
+ return field === undefined
12
+ ? Effect.fail(new Schema.SchemaError(new SchemaIssue.Pointer([key], new SchemaIssue.UnexpectedKey(model.ast, key))))
13
+ : Effect.succeed(field);
14
+ }
15
+ function column(key) {
16
+ return references === undefined ? sql `${sql(key)}` : sql `${sql(references.tableName)}.${sql(key)}`;
17
+ }
18
+ function reference(value) {
19
+ return references !== undefined && typeof value === "object" && value !== null && "excluded" in value && typeof value.excluded === "string"
20
+ ? value.excluded
21
+ : undefined;
22
+ }
23
+ function comparison(key, field, operator, operand) {
24
+ if (!isOperator(operator)) {
25
+ return Effect.fail(new Schema.SchemaError(new SchemaIssue.Pointer([key, operator], new SchemaIssue.UnexpectedKey(model.ast, operator))));
26
+ }
27
+ const incoming = reference(operand);
28
+ if (incoming !== undefined) {
29
+ return Effect.as(fieldAt(incoming), sql `${column(key)} ${sql.literal(operators[operator])} excluded.${sql(incoming)}`);
30
+ }
31
+ const validate = Schema.decodeUnknownEffect(operator === "like" ? Schema.String : Ordered);
32
+ return Effect.flatMap(validate(operand), (decoded) => Effect.map(Schema.encodeEffect(field)(decoded), (encoded) => sql `${column(key)} ${sql.literal(operators[operator])} ${encoded}`));
33
+ }
34
+ function inPredicate(key, encoded) {
35
+ if (references === undefined) {
36
+ return sql.in(key, encoded);
37
+ }
38
+ return encoded.length === 0 ? sql `1 = 0` : sql `${column(key)} in ${sql.in(encoded)}`;
39
+ }
40
+ function predicate(key, value, allowIn, allowComparisons) {
41
+ return Effect.flatMap(fieldAt(key), (field) => {
42
+ const incoming = reference(value);
43
+ if (incoming !== undefined) {
44
+ return Effect.as(fieldAt(incoming), sql `${column(key)} = excluded.${sql(incoming)}`);
45
+ }
46
+ const encode = Schema.encodeEffect(field);
47
+ if (allowComparisons && typeof value === "object" && value !== null && Object.keys(value).some(isOperator)) {
48
+ return Effect.map(Effect.forEach(Object.entries(value), ([operator, operand]) => comparison(key, field, operator, operand)), (predicates) => sql.and(predicates));
49
+ }
50
+ return allowIn && typeof value === "object" && value !== null && "in" in value && Array.isArray(value.in)
51
+ ? Effect.map(Effect.forEach(value.in, (entry) => encode(entry)), (encoded) => inPredicate(key, encoded))
52
+ : Effect.map(encode(value), (encoded) => (encoded === null ? sql `${column(key)} is null` : sql `${column(key)} = ${encoded}`));
53
+ });
54
+ }
55
+ function where(input = {}, allowIn = false, allowComparisons = false) {
56
+ return Effect.gen(function* () {
57
+ const predicates = yield* Effect.forEach(Object.entries(input).filter(([, value]) => value !== undefined), ([key, value]) => predicate(key, value, allowIn, allowComparisons));
58
+ if (allowIn) {
59
+ const tuple = yield* tuplePredicate(input, sql, fieldAt);
60
+ if (tuple !== undefined) {
61
+ predicates.push(tuple);
62
+ }
63
+ }
64
+ return sql.and(predicates);
65
+ });
66
+ }
67
+ return { fieldAt, where };
68
+ }
69
+ //# sourceMappingURL=repositoryFilter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryFilter.js","sourceRoot":"","sources":["../src/repositoryFilter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
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 { Aggregate } from "#aggregateQuery.ts";
7
+ import type { FindMany, LatestPerGroup } from "#repository.ts";
8
+ type Key<TModel extends Model.Any> = Extract<keyof TModel["fields"] & keyof Row<TModel>, string>;
9
+ type Row<TModel extends Model.Any> = Schema.Struct.Type<TModel["fields"]>;
10
+ export interface RepositorySelect<TFields extends Schema.Struct.Fields, TServices = never> {
11
+ readonly fields: TFields;
12
+ readonly statement: Effect.Effect<Fragment, Schema.SchemaError, TServices>;
13
+ }
14
+ export interface Queries<TModel extends Model.Any> {
15
+ aggregate: Aggregate<TModel>;
16
+ count: (query?: Pick<FindMany<TModel, Key<TModel>>, "where">) => Effect.Effect<number, SqlError | Schema.SchemaError, TModel["fields"][Key<TModel>]["EncodingServices"]>;
17
+ findMany: <TKey extends Key<TModel> = Key<TModel>>(query?: FindMany<TModel, TKey>) => Effect.Effect<Pick<Row<TModel>, TKey>[], SqlError | Schema.SchemaError, TModel["fields"][Key<TModel>]["EncodingServices"] | TModel["fields"][TKey]["DecodingServices"]>;
18
+ latestPerGroup: (query: LatestPerGroup<TModel>) => Effect.Effect<Row<TModel>[], SqlError | Schema.SchemaError, TModel["fields"][Key<TModel>]["EncodingServices"] | TModel["fields"][Key<TModel>]["DecodingServices"]>;
19
+ select: <TKey extends Key<TModel> = Key<TModel>>(query?: FindMany<TModel, TKey>) => RepositorySelect<Pick<TModel["fields"], TKey>, TModel["fields"][Key<TModel>]["EncodingServices"]>;
20
+ }
21
+ export declare function makeQueries<TModel extends Model.Any>(model: TModel, sql: SqlClient.SqlClient, options: {
22
+ readonly tableName: string;
23
+ readonly spanPrefix: string;
24
+ }): Queries<TModel>;
25
+ export {};
26
+ //# sourceMappingURL=repositoryQueries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryQueries.d.ts","sourceRoot":"","sources":["../src/repositoryQueries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { latestPerGroup as makeLatestPerGroup } from "#latestPerGroup.ts";
3
+ import { makeAggregate } from "#makeAggregate.ts";
4
+ import { makeQueryClauses } from "#makeQueryClauses.ts";
5
+ import { makeFilter } from "#repositoryFilter.ts";
6
+ const CountResult = Schema.Tuple([Schema.Struct({ count: Schema.NumberFromString })]);
7
+ export function makeQueries(model, sql, options) {
8
+ const { fieldAt, where } = makeFilter(model, sql);
9
+ const readLatest = makeLatestPerGroup(model, sql, options.tableName);
10
+ const { decodeLimit, orderClause, limitClause } = makeQueryClauses(sql, fieldAt);
11
+ const aggregate = makeAggregate(model, sql, options);
12
+ function count(query = {}) {
13
+ return Effect.gen(function* () {
14
+ const predicate = yield* where(query.where, true, true);
15
+ const rows = yield* sql `select cast(count(*) as text) as count from ${sql(options.tableName)} where ${predicate}`;
16
+ const [result] = yield* Schema.decodeUnknownEffect(CountResult)(rows);
17
+ return result.count;
18
+ }).pipe(Effect.withSpan(`${options.spanPrefix}.count`));
19
+ }
20
+ function select(query = {}) {
21
+ const keys = query.select ?? Object.keys(model.fields);
22
+ const fields = Object.fromEntries(keys.map((key) => [key, model.fields[key]]));
23
+ const statement = Effect.gen(function* () {
24
+ yield* Effect.forEach(keys, fieldAt);
25
+ const predicate = yield* where(query.where, true, true);
26
+ const order = yield* orderClause(query.orderBy);
27
+ const limit = yield* limitClause(query.limit);
28
+ return sql `select ${sql.csv(keys.map((key) => sql `${sql(key)}`))} from ${sql(options.tableName)} where ${predicate} ${order} ${limit}`;
29
+ });
30
+ return { fields, statement };
31
+ }
32
+ // Object.fromEntries erases the selected key-to-schema correspondence, so the typed overload restates it.
33
+ function findMany(query = {}) {
34
+ return Effect.gen(function* () {
35
+ const selected = select(query);
36
+ const rows = yield* sql `${yield* selected.statement}`;
37
+ return yield* Schema.decodeUnknownEffect(Schema.Array(Schema.Struct(selected.fields)))(rows);
38
+ }).pipe(Effect.withSpan(`${options.spanPrefix}.findMany`));
39
+ }
40
+ function latestPerGroup(query) {
41
+ return Effect.gen(function* () {
42
+ const order = yield* orderClause(query.orderBy);
43
+ const rowLimit = yield* decodeLimit(query.limit);
44
+ return yield* readLatest(query, order, rowLimit);
45
+ }).pipe(Effect.withSpan(`${options.spanPrefix}.latestPerGroup`));
46
+ }
47
+ return { aggregate, count, findMany, latestPerGroup, select };
48
+ }
49
+ //# sourceMappingURL=repositoryQueries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryQueries.js","sourceRoot":"","sources":["../src/repositoryQueries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import { type SqlClient } from "effect/sql";
4
+ import type { RepositoryChanges } from "./repositoryChanges.ts";
5
+ export declare function repositoryWrites(model: Model.Any, sql: SqlClient.SqlClient, options: {
6
+ readonly idColumns: readonly string[];
7
+ readonly tableName: string;
8
+ readonly spanPrefix: string;
9
+ }, changes: RepositoryChanges): {
10
+ delete: (id: unknown) => Effect.Effect<void, Schema.SchemaError | import("effect/sql/SqlError").SqlError, unknown>;
11
+ insert: (input: unknown) => Effect.Effect<unknown, Schema.SchemaError | import("effect/sql/SqlError").SqlError, unknown>;
12
+ insertVoid: (input: unknown) => Effect.Effect<void, Schema.SchemaError | import("effect/sql/SqlError").SqlError, unknown>;
13
+ update: (input: unknown, settings?: {
14
+ readonly onMissing: "fail";
15
+ }) => Effect.Effect<unknown, import("effect/Cause").NoSuchElementError | Schema.SchemaError | import("effect/sql/SqlError").SqlError, unknown>;
16
+ updateVoid: (input: unknown) => Effect.Effect<void, Schema.SchemaError | import("effect/sql/SqlError").SqlError, unknown>;
17
+ };
18
+ //# sourceMappingURL=repositoryWrites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryWrites.d.ts","sourceRoot":"","sources":["../src/repositoryWrites.ts"],"names":[],"mappings":"AAAA,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,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,KAAK,CAAC,GAAG,EAChB,GAAG,EAAE,SAAS,CAAC,SAAS,EACxB,OAAO,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,EAC3G,OAAO,EAAE,iBAAiB;IAiDzB,MAAM,OAAO,OAAO;IACpB,MAAM,UAAU,OAAO;IAEvB,UAAU,UAAU,OAAO;IAC3B,MAAM,UAAU,OAAO,aAAa;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAIlE,UAAU,UAAU,OAAO;EAE5B"}
@@ -0,0 +1,49 @@
1
+ import { Effect, Schema } from "effect";
2
+ import { SqlSchema } from "effect/sql";
3
+ import { makeFilter } from "./repositoryFilter.js";
4
+ export function repositoryWrites(model, sql, options, changes) {
5
+ const { idColumns, tableName, spanPrefix } = options;
6
+ const { where } = makeFilter(model, sql);
7
+ const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
8
+ const filterRecord = Schema.decodeUnknownEffect(Schema.Record(Schema.PropertyKey, Schema.Unknown));
9
+ function predicate(input) {
10
+ return sql.and(idColumns.map((column) => sql `${sql(column)} = ${input[column]}`));
11
+ }
12
+ function insert(input) {
13
+ return Effect.flatMap(record(input), (row) => (Object.keys(row).length === 0
14
+ ? sql `insert into ${sql(tableName)} default values returning *`
15
+ : sql `insert into ${sql(tableName)} ${sql.insert(row)} returning *`).pipe(Effect.tap(changes.record)));
16
+ }
17
+ function update(input) {
18
+ return Effect.flatMap(record(input), (row) => sql `update ${sql(tableName)} set ${sql.update(row, idColumns)} where ${predicate(row)} returning *`.pipe(Effect.tap(changes.record)));
19
+ }
20
+ const insertRow = SqlSchema.findOne({ execute: insert, Request: model.insert, Result: model });
21
+ const insertVoid = SqlSchema.void({ execute: insert, Request: model.insert });
22
+ const updateRow = SqlSchema.findOne({ execute: update, Request: model.update, Result: model });
23
+ const updateVoid = SqlSchema.void({ execute: update, Request: model.update });
24
+ const idColumn = idColumns[0] ?? "";
25
+ const key = model.fields[idColumn];
26
+ if (key === undefined) {
27
+ throw new Error("Unknown repository ID column");
28
+ }
29
+ const isKey = Schema.is(key);
30
+ const removeByKey = SqlSchema.void({
31
+ execute: (id) => Effect.flatMap(record({ [idColumn]: id }), (encoded) => sql `delete from ${sql(tableName)} where ${predicate(encoded)} returning *`.pipe(Effect.tap(changes.record))),
32
+ Request: key,
33
+ });
34
+ function remove(input) {
35
+ return idColumns.length === 1 && isKey(input)
36
+ ? removeByKey(input)
37
+ : Effect.flatMap(filterRecord(input), (filter) => Effect.flatMap(where(filter, true), (clause) => sql `delete from ${sql(tableName)} where ${clause} returning *`.pipe(Effect.tap(changes.record), Effect.asVoid)));
38
+ }
39
+ return {
40
+ delete: (id) => changes.write(remove(id)).pipe(Effect.withSpan(`${spanPrefix}.delete`)),
41
+ insert: (input) => changes.write(insertRow(input).pipe(Effect.catchTag("NoSuchElementError", Effect.die))).pipe(Effect.withSpan(`${spanPrefix}.insert`)),
42
+ insertVoid: (input) => changes.write(insertVoid(input)).pipe(Effect.withSpan(`${spanPrefix}.insertVoid`)),
43
+ update: (input, settings) => changes
44
+ .write(settings?.onMissing === "fail" ? updateRow(input) : updateRow(input).pipe(Effect.catchTag("NoSuchElementError", Effect.die)))
45
+ .pipe(Effect.withSpan(`${spanPrefix}.update`)),
46
+ updateVoid: (input) => changes.write(updateVoid(input)).pipe(Effect.withSpan(`${spanPrefix}.updateVoid`)),
47
+ };
48
+ }
49
+ //# sourceMappingURL=repositoryWrites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositoryWrites.js","sourceRoot":"","sources":["../src/repositoryWrites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ declare const UnannouncedWrites_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: "UnannouncedWrites";
5
+ } & Readonly<A>;
6
+ export declare class UnannouncedWrites extends UnannouncedWrites_base<{
7
+ readonly tables: readonly string[];
8
+ }> {
9
+ }
10
+ export declare const withChangeCoverage: <A, E, R>(body: Effect.Effect<A, E, R>) => Effect.Effect<A, import("effect/sql/SqlError").SqlError | UnannouncedWrites | Exclude<E, import("effect/sql/SqlError").SqlError>, import("effect/reactivity/Reactivity").Reactivity | SqlClient.SqlClient | Exclude<R, never>>;
11
+ export {};
12
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;;;;AAGvC,qBAAa,iBAAkB,SAAQ,uBAAsC;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;CAAG;AAQvH,eAAO,MAAM,kBAAkB,GAAsD,CAAC,EAAE,CAAC,EAAE,CAAC,iQAyB1F,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { Data, Effect } from "effect";
2
+ import { SqlClient } from "effect/sql";
3
+ import { ChangeObserver, transact } from "./transact.js";
4
+ export class UnannouncedWrites extends Data.TaggedError("UnannouncedWrites") {
5
+ }
6
+ export const withChangeCoverage = Effect.fn("Changes.withChangeCoverage")(function* (body) {
7
+ const observer = yield* ChangeObserver;
8
+ const sql = yield* SqlClient.SqlClient;
9
+ const named = new Set();
10
+ const written = sql `select relid, relname, (n_tup_ins + n_tup_upd + n_tup_del)::int as writes from pg_stat_xact_user_tables`;
11
+ const checked = Effect.gen(function* () {
12
+ const before = new Map((yield* written).map((row) => [row.relid, row.writes]));
13
+ const result = yield* body;
14
+ const missing = (yield* written).filter((row) => row.writes > (before.get(row.relid) ?? 0) && !named.has(row.relname));
15
+ if (missing.length > 0) {
16
+ return yield* Effect.fail(new UnannouncedWrites({ tables: missing.map((row) => row.relname).sort() }));
17
+ }
18
+ return result;
19
+ });
20
+ return yield* checked.pipe(transact({ onSqlError: (error) => error }), Effect.provideService(ChangeObserver, (event) => {
21
+ if (event._tag === "Recorded") {
22
+ for (const key of event.changes) {
23
+ named.add(key);
24
+ }
25
+ }
26
+ return observer(event);
27
+ }));
28
+ });
29
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzD,MAAM,OAAO,iBAAkB,SAAQ,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAyC;CAAG;AAQvH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,EAAE,CAAC,4BAA4B,CAAC,CAAC,QAAQ,CAAC,EAAW,IAA4B;IACzH,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,cAAc,CAAC;IACvC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAW,CAAC;IACjC,MAAM,OAAO,GAAG,GAAG,CAAa,yGAAyG,CAAC;IAC1I,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC;QAC3B,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACvH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;QACxG,CAAC;QACD,OAAO,MAAM,CAAC;IACf,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CACzB,QAAQ,CAAC,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,CAAC,EAC1C,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC/B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACjC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACF,CAAC;QACD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC,CAAC,CACF,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { Effect } from "effect";
2
+ import type { ReadonlyRecord } from "effect/Record";
3
+ import * as Reactivity from "effect/reactivity/Reactivity";
4
+ import { SqlClient } from "effect/sql";
5
+ import { type SqlError } from "effect/sql/SqlError";
6
+ export type InvalidationKeys = readonly unknown[] | ReadonlyRecord<string, readonly unknown[]>;
7
+ export declare const ChangeObserver: import("effect/Context").Reference<import("@shivaedev/changes/observe.ts").Observer<unknown>>;
8
+ export declare const BeforeCommit: import("effect/Context").Reference<import("@shivaedev/changes/channel.ts").BeforeCommit<unknown, SqlError, Reactivity.Reactivity | SqlClient.SqlClient>>;
9
+ export declare const CommittedSink: import("effect/Context").Reference<import("@shivaedev/changes/publish.ts").Publish<unknown, Reactivity.Reactivity | SqlClient.SqlClient> | undefined>;
10
+ export declare const invalidateOnCommit: (keys: InvalidationKeys) => Effect.Effect<void, never, Reactivity.Reactivity | SqlClient.SqlClient>;
11
+ export interface TransactOptions<TError> {
12
+ readonly onSqlError: (error: SqlError) => TError;
13
+ }
14
+ export declare const transact: {
15
+ <TError>(options: TransactOptions<TError>): <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, Exclude<E, SqlError> | TError, R | SqlClient.SqlClient | Reactivity.Reactivity>;
16
+ <A, E, R, TError>(effect: Effect.Effect<A, E, R>, options: TransactOptions<TError>): Effect.Effect<A, Exclude<E, SqlError> | TError, R | SqlClient.SqlClient | Reactivity.Reactivity>;
17
+ };
18
+ //# sourceMappingURL=transact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transact.d.ts","sourceRoot":"","sources":["../src/transact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAQ,MAAM,QAAQ,CAAC;AAEtC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGhE,MAAM,MAAM,gBAAgB,GAAG,SAAS,OAAO,EAAE,GAAG,cAAc,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC;AAiC/F,eAAO,MAAM,cAAc,+FAAyB,CAAC;AACrD,eAAO,MAAM,YAAY,0JAA6B,CAAC;AACvD,eAAO,MAAM,aAAa,uJAA8B,CAAC;AAEzD,eAAO,MAAM,kBAAkB,qGAE7B,CAAC;AAEH,MAAM,WAAW,eAAe,CAAC,MAAM;IACtC,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,MAAM,CAAC;CACjD;AAED,eAAO,MAAM,QAAQ,EAAE;IACtB,CAAC,MAAM,EACN,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,GAC9B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACjJ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC9B,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,GAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,SAAS,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;CASpG,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { Effect, Hash } from "effect";
2
+ import { dual } from "effect/Function";
3
+ import * as Reactivity from "effect/reactivity/Reactivity";
4
+ import { SqlClient } from "effect/sql";
5
+ import { isSqlError } from "effect/sql/SqlError";
6
+ import { makeChannel } from "@shivaedev/changes/channel.ts";
7
+ function hashOf(value) {
8
+ return typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean"
9
+ ? String(value)
10
+ : Hash.hash(value);
11
+ }
12
+ function isList(keys) {
13
+ return Array.isArray(keys);
14
+ }
15
+ function flatten(keys) {
16
+ return isList(keys) ? keys : Object.entries(keys).flatMap(([name, ids]) => [name, ...ids.map((id) => `${name}:${hashOf(id)}`)]);
17
+ }
18
+ const guard = Effect.fn("Transact.guard")(function* () {
19
+ const sql = yield* SqlClient.SqlClient;
20
+ const native = yield* Effect.serviceOption(sql.transactionService);
21
+ if (native._tag === "Some") {
22
+ return yield* Effect.die(new Error("transact cannot announce changes after a transaction it does not own; begin the outer transaction with transact"));
23
+ }
24
+ });
25
+ const invalidations = makeChannel({
26
+ name: "@shivaedev/sql/transact",
27
+ owner: Effect.map(SqlClient.SqlClient, (sql) => sql.transactionService),
28
+ publish: (keys) => Reactivity.invalidate(keys),
29
+ unowned: guard(),
30
+ });
31
+ export const ChangeObserver = invalidations.Observer;
32
+ export const BeforeCommit = invalidations.BeforeCommit;
33
+ export const CommittedSink = invalidations.CommittedSink;
34
+ export const invalidateOnCommit = Effect.fn("Transact.invalidateOnCommit")(function* (keys) {
35
+ yield* invalidations.record(flatten(keys));
36
+ });
37
+ export const transact = dual(2, Effect.fn("Transact.transact")(function* (effect, options) {
38
+ const sql = yield* SqlClient.SqlClient;
39
+ return yield* invalidations
40
+ .within(sql.withTransaction)(effect)
41
+ .pipe(Effect.catchIf(isSqlError, (error) => Effect.fail(options.onSqlError(error))));
42
+ }));
43
+ //# sourceMappingURL=transact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transact.js","sourceRoot":"","sources":["../src/transact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { Effect, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlClient } from "effect/sql";
4
+ export declare const tupleFilter: unique symbol;
5
+ type Row<TModel extends Model.Any> = Schema.Struct.Type<TModel["fields"]>;
6
+ type Key<TModel extends Model.Any> = Extract<keyof Row<TModel>, string>;
7
+ export interface TupleFilter<TModel extends Model.Any> {
8
+ readonly [tupleFilter]: {
9
+ readonly model: TModel;
10
+ readonly fields: readonly Key<TModel>[];
11
+ readonly values: readonly (readonly unknown[])[];
12
+ };
13
+ }
14
+ export declare function tupleIn<TModel extends Model.Any, const TFields extends readonly [Key<TModel>, Key<TModel>, ...Key<TModel>[]]>(model: TModel, fields: TFields, values: readonly {
15
+ readonly [TIndex in keyof TFields]: Row<TModel>[TFields[TIndex]];
16
+ }[]): TupleFilter<TModel>;
17
+ export declare function tuplePredicate(input: Partial<TupleFilter<Model.Any>>, sql: SqlClient.SqlClient, fieldAt: (key: string) => Effect.Effect<Schema.Constraint, Schema.SchemaError>): Effect.Effect<undefined, never, never> | Effect.Effect<import("effect/sql/Statement").Fragment, Schema.SchemaError, unknown>;
18
+ export {};
19
+ //# sourceMappingURL=tupleIn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tupleIn.d.ts","sourceRoot":"","sources":["../src/tupleIn.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;AAE5C,eAAO,MAAM,WAAW,eAAwB,CAAC;AACjD,KAAK,GAAG,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1E,KAAK,GAAG,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;AAExE,MAAM,WAAW,WAAW,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG;IACpD,QAAQ,CAAC,CAAC,WAAW,CAAC,EAAE;QACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACxC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,OAAO,EAAE,CAAC,EAAE,CAAC;KACjD,CAAC;CACF;AAED,wBAAgB,OAAO,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,SAAS,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAC5H,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,SAAS;IAAE,QAAQ,EAAE,MAAM,IAAI,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;CAAE,EAAE,GACrF,WAAW,CAAC,MAAM,CAAC,CAErB;AAED,wBAAgB,cAAc,CAC7B,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EACtC,GAAG,EAAE,SAAS,CAAC,SAAS,EACxB,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,gIAgB9E"}
@@ -0,0 +1,20 @@
1
+ import { Effect, Schema } from "effect";
2
+ export const tupleFilter = Symbol("sql/tupleIn");
3
+ export function tupleIn(model, fields, values) {
4
+ return { [tupleFilter]: { fields, model, values } };
5
+ }
6
+ export function tuplePredicate(input, sql, fieldAt) {
7
+ const tuple = input[tupleFilter];
8
+ if (tuple === undefined) {
9
+ return Effect.succeed(undefined);
10
+ }
11
+ return Effect.gen(function* () {
12
+ const fields = yield* Effect.forEach(tuple.fields, fieldAt);
13
+ const encode = Schema.encodeUnknownEffect(Schema.Tuple(fields));
14
+ const columns = sql.csv(tuple.fields.map((field) => sql `${sql(field)}`));
15
+ // Row comparisons retain column type inference for string-encoded numerics without PostgreSQL's deeply nested row-IN rewrite.
16
+ const rows = yield* Effect.forEach(tuple.values, (value) => Effect.map(encode(value), (encoded) => sql `(${columns}) = (${sql.csv(encoded.map((entry) => sql `${entry}`))})`));
17
+ return rows.length === 0 ? sql `1 = 0` : sql.or(rows);
18
+ });
19
+ }
20
+ //# sourceMappingURL=tupleIn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tupleIn.js","sourceRoot":"","sources":["../src/tupleIn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIxC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAYjD,MAAM,UAAU,OAAO,CACtB,KAAa,EACb,MAAe,EACf,MAAuF;IAEvF,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,KAAsC,EACtC,GAAwB,EACxB,OAA8E;IAE9E,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAA,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,8HAA8H;QAC9H,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAC1D,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAA,IAAI,OAAO,QAAQ,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAA,GAAG,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAC/G,CAAC;QACF,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { Effect, Option, Schema } from "effect";
2
+ import type { Model } from "effect/schema";
3
+ import type { SqlClient, SqlModel } from "effect/sql";
4
+ import type { SqlError } from "effect/sql/SqlError";
5
+ import type { PrimaryKey, Repository } from "#compositeRepository.ts";
6
+ import type { OptimisticConcurrencyError } from "#repository.ts";
7
+ import { type VersionedOptions } from "#versionedStatements.ts";
8
+ import type { RepositoryChanges } from "./repositoryChanges.ts";
9
+ export type IdColumn<TModel extends Model.Any> = keyof TModel["Type"] & keyof TModel["update"]["Type"] & keyof TModel["fields"];
10
+ export type VersionColumn<TModel extends Model.Any, TId extends PrimaryKey<TModel>> = {
11
+ [TKey in Extract<keyof TModel["fields"] & keyof TModel["update"]["Type"], string>]: TModel["fields"][TKey] extends Schema.ConstraintCodec<number, number, never, never> ? TModel["update"]["Type"] extends {
12
+ readonly [TField in TKey]: number;
13
+ } ? TKey : never : never;
14
+ }[Extract<keyof TModel["fields"] & keyof TModel["update"]["Type"], string>] & Exclude<keyof TModel["fields"], (TId extends readonly PropertyKey[] ? TId[number] : TId) | keyof TModel["insert"]["Type"]>;
15
+ export type NativeRepository<TModel extends Model.Any, TId extends IdColumn<TModel>> = Effect.Success<ReturnType<typeof SqlModel.makeRepository<TModel, TId>>>;
16
+ type WriteError = SqlError | Schema.SchemaError | OptimisticConcurrencyError;
17
+ type KeyColumn<TModel extends Model.Any, TId extends PrimaryKey<TModel>> = TId extends readonly IdColumn<TModel>[] ? TId[number] : Extract<TId, IdColumn<TModel>>;
18
+ export interface VersionedWrites<TModel extends Model.Any, TId extends PrimaryKey<TModel>> {
19
+ readonly delete: (id: TId extends readonly IdColumn<TModel>[] ? Pick<TModel["Type"], TId[number]> : TModel["fields"][Extract<TId, IdColumn<TModel>>]["Type"], expectedVersion: number) => Effect.Effect<void, WriteError, TModel["fields"][KeyColumn<TModel, TId>]["EncodingServices"]>;
20
+ readonly insert: Repository<TModel, TId>["insert"];
21
+ readonly insertVoid: Repository<TModel, TId>["insertVoid"];
22
+ readonly update: (input: TModel["update"]["Type"]) => Effect.Effect<TModel["Type"], WriteError, TModel["update"]["EncodingServices"] | TModel["DecodingServices"]>;
23
+ readonly updateVoid: (input: TModel["update"]["Type"]) => Effect.Effect<void, WriteError, TModel["update"]["EncodingServices"]>;
24
+ }
25
+ export declare function makeVersionedWrites(model: Model.Any, sql: SqlClient.SqlClient, options: VersionedOptions & {
26
+ readonly changes: RepositoryChanges;
27
+ readonly spanPrefix: string;
28
+ }): {
29
+ delete: (id: unknown, expected: number) => Effect.Effect<undefined, OptimisticConcurrencyError | Schema.SchemaError | SqlError, unknown>;
30
+ insert: (input: unknown) => Effect.Effect<unknown, Schema.SchemaError | SqlError, unknown>;
31
+ insertVoid: (input: unknown) => Effect.Effect<void, Schema.SchemaError | SqlError, unknown>;
32
+ update: (input: Readonly<Record<string, unknown>>) => Effect.Effect<unknown, OptimisticConcurrencyError | Schema.SchemaError | SqlError, unknown>;
33
+ updateVoid: (input: Readonly<Record<string, unknown>>) => Effect.Effect<undefined, OptimisticConcurrencyError | Schema.SchemaError | SqlError, unknown>;
34
+ insertOrIgnore?: (input: unknown) => Effect.Effect<Option.None<unknown> | Option.Some<unknown>, Schema.SchemaError | SqlError, unknown>;
35
+ };
36
+ export {};
37
+ //# sourceMappingURL=versionedRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versionedRepository.d.ts","sourceRoot":"","sources":["../src/versionedRepository.ts"],"names":[],"mappings":"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"}