@shivaedev/sql 0.34.0 → 0.36.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +3 -3
- package/dist/aggregateColumn.d.ts +3 -3
- package/dist/aggregateColumn.d.ts.map +1 -1
- package/dist/aggregateColumn.js +4 -2
- package/dist/aggregateColumn.js.map +1 -1
- package/dist/batchWrites.d.ts +4 -4
- package/dist/batchWrites.d.ts.map +1 -1
- package/dist/batchWrites.js +8 -5
- package/dist/batchWrites.js.map +1 -1
- package/dist/batchedDelete.js +1 -1
- package/dist/batchedDelete.js.map +1 -1
- package/dist/compositeRepository.d.ts +9 -5
- package/dist/compositeRepository.d.ts.map +1 -1
- package/dist/compositeRepository.js +12 -9
- package/dist/compositeRepository.js.map +1 -1
- package/dist/conditionalUpsert.d.ts +4 -4
- package/dist/conditionalUpsert.d.ts.map +1 -1
- package/dist/conditionalUpsert.js +7 -4
- package/dist/conditionalUpsert.js.map +1 -1
- package/dist/conflictWrites.d.ts +4 -4
- package/dist/conflictWrites.d.ts.map +1 -1
- package/dist/conflictWrites.js +11 -8
- package/dist/conflictWrites.js.map +1 -1
- package/dist/coordinateWorkerRelease.d.ts.map +1 -1
- package/dist/coordinateWorkerRelease.js +7 -1
- package/dist/coordinateWorkerRelease.js.map +1 -1
- package/dist/insertFromSelect.d.ts +3 -3
- package/dist/insertFromSelect.d.ts.map +1 -1
- package/dist/insertFromSelect.js +5 -3
- package/dist/insertFromSelect.js.map +1 -1
- package/dist/latestPerGroup.d.ts +2 -2
- package/dist/latestPerGroup.d.ts.map +1 -1
- package/dist/latestPerGroup.js +5 -4
- package/dist/latestPerGroup.js.map +1 -1
- package/dist/makeAggregate.d.ts +4 -3
- package/dist/makeAggregate.d.ts.map +1 -1
- package/dist/makeAggregate.js +35 -31
- package/dist/makeAggregate.js.map +1 -1
- package/dist/makeConflictClause.d.ts +3 -3
- package/dist/makeConflictClause.d.ts.map +1 -1
- package/dist/makeConflictClause.js +6 -4
- package/dist/makeConflictClause.js.map +1 -1
- package/dist/makeQueryClauses.d.ts +3 -3
- package/dist/makeQueryClauses.d.ts.map +1 -1
- package/dist/makeQueryClauses.js +5 -3
- package/dist/makeQueryClauses.js.map +1 -1
- package/dist/pinnedGroups.d.ts +3 -4
- package/dist/pinnedGroups.d.ts.map +1 -1
- package/dist/pinnedGroups.js +8 -10
- package/dist/pinnedGroups.js.map +1 -1
- package/dist/releaseWorkers.d.ts.map +1 -1
- package/dist/releaseWorkers.js +10 -4
- package/dist/releaseWorkers.js.map +1 -1
- package/dist/repository.d.ts +1 -1
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +7 -9
- package/dist/repository.js.map +1 -1
- package/dist/repositoryChanges.d.ts +2 -2
- package/dist/repositoryChanges.d.ts.map +1 -1
- package/dist/repositoryChanges.js +2 -1
- package/dist/repositoryChanges.js.map +1 -1
- package/dist/repositoryFilter.d.ts +4 -4
- package/dist/repositoryFilter.d.ts.map +1 -1
- package/dist/repositoryFilter.js +5 -3
- package/dist/repositoryFilter.js.map +1 -1
- package/dist/repositoryQueries.d.ts +3 -3
- package/dist/repositoryQueries.d.ts.map +1 -1
- package/dist/repositoryQueries.js +45 -41
- package/dist/repositoryQueries.js.map +1 -1
- package/dist/repositoryWrites.d.ts +9 -5
- package/dist/repositoryWrites.d.ts.map +1 -1
- package/dist/repositoryWrites.js +8 -7
- package/dist/repositoryWrites.js.map +1 -1
- package/dist/testing/WorkerRelease.d.ts +13 -0
- package/dist/testing/WorkerRelease.d.ts.map +1 -0
- package/dist/testing/WorkerRelease.js +4 -0
- package/dist/testing/WorkerRelease.js.map +1 -0
- package/dist/tupleIn.d.ts +1 -2
- package/dist/tupleIn.d.ts.map +1 -1
- package/dist/tupleIn.js +16 -17
- package/dist/tupleIn.js.map +1 -1
- package/dist/upsertResult.d.ts +2 -2
- package/dist/upsertResult.d.ts.map +1 -1
- package/dist/upsertResult.js +4 -2
- package/dist/upsertResult.js.map +1 -1
- package/dist/versionedRepository.d.ts +5 -5
- package/dist/versionedRepository.d.ts.map +1 -1
- package/dist/versionedRepository.js +5 -3
- package/dist/versionedRepository.js.map +1 -1
- package/dist/versionedStatements.d.ts +3 -3
- package/dist/versionedStatements.d.ts.map +1 -1
- package/dist/versionedStatements.js +12 -9
- package/dist/versionedStatements.js.map +1 -1
- package/package.json +8 -7
- package/src/aggregateColumn.ts +4 -3
- package/src/batchWrites.ts +10 -10
- package/src/batchedDelete.ts +1 -1
- package/src/compositeRepository.ts +15 -15
- package/src/conditionalUpsert.ts +7 -6
- package/src/conflictWrites.ts +14 -10
- package/src/coordinateWorkerRelease.ts +7 -1
- package/src/insertFromSelect.ts +6 -6
- package/src/latestPerGroup.ts +5 -4
- package/src/makeAggregate.ts +48 -47
- package/src/makeConflictClause.ts +6 -6
- package/src/makeQueryClauses.ts +6 -6
- package/src/pinnedGroups.ts +10 -14
- package/src/releaseWorkers.ts +16 -4
- package/src/repository.ts +8 -9
- package/src/repositoryChanges.ts +2 -6
- package/src/repositoryFilter.ts +5 -4
- package/src/repositoryQueries.ts +57 -55
- package/src/repositoryWrites.ts +9 -9
- package/src/testing/WorkerRelease.ts +13 -0
- package/src/tupleIn.ts +16 -18
- package/src/upsertResult.ts +4 -3
- package/src/versionedRepository.ts +6 -6
- package/src/versionedStatements.ts +15 -15
- package/dist/testing.d.ts +0 -27
- package/dist/testing.d.ts.map +0 -1
- package/dist/testing.js +0 -75
- package/dist/testing.js.map +0 -1
- package/src/testing.ts +0 -103
package/dist/tupleIn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tupleIn.js","sourceRoot":"","sources":["../src/tupleIn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA4B9C,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAajD,MAAM,UAAU,OAAO,CACtB,KAAa,EACb,MAAe,EACf,MAAuF,EACvF,KAAyD;IAEzD,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;AAClH,CAAC;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"tupleIn.js","sourceRoot":"","sources":["../src/tupleIn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA4B9C,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AAajD,MAAM,UAAU,OAAO,CACtB,KAAa,EACb,MAAe,EACf,MAAuF,EACvF,KAAyD;IAEzD,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAsB,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;AAClH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EACxD,KAAsC,EACtC,OAA8E;IAE9E,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAChE,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;IACzE,MAAM,IAAI,GAAoC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5G,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAA,OAAO,CAAC;IACnB,CAAC;IACD,IAAI,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAClE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7G,OAAO,GAAG,CAAA,IAAI,OAAO,uBAAuB,QAAQ,GAAG,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAA,IAAI,OAAO,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,CAAA,GAAG,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACvG,CAAC,CAAC,CAAC"}
|
package/dist/upsertResult.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
4
|
export interface UpsertRow<TRow> {
|
|
5
5
|
readonly inserted: boolean;
|
|
6
6
|
readonly row: TRow;
|
|
7
7
|
}
|
|
8
|
-
export declare
|
|
8
|
+
export declare const upsertReturning: () => Effect.Effect<import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>, never, SqlClient.SqlClient>;
|
|
9
9
|
export declare function makeUpsertDecoder(model: Model.Any): (row: Readonly<Record<string, unknown>> | undefined) => Effect.Effect<{
|
|
10
10
|
inserted: boolean;
|
|
11
11
|
row: unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upsertResult.d.ts","sourceRoot":"","sources":["../src/upsertResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"upsertResult.d.ts","sourceRoot":"","sources":["../src/upsertResult.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,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,WAAW,SAAS,CAAC,IAAI;IAC9B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,eAAe,mIAG1B,CAAC;AAEH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,SAEpC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS;;;gCAE1D"}
|
package/dist/upsertResult.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
-
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
export const upsertReturning = Effect.fnUntraced(function* () {
|
|
4
|
+
const sql = yield* SqlClient.SqlClient;
|
|
3
5
|
return sql `*, (xmax = 0) as ${sql("effectSqlInserted")}`;
|
|
4
|
-
}
|
|
6
|
+
});
|
|
5
7
|
export function makeUpsertDecoder(model) {
|
|
6
8
|
const decode = Schema.decodeUnknownEffect(model);
|
|
7
9
|
return (row) => Effect.map(decode(row), (decoded) => ({ inserted: row?.effectSqlInserted === true, row: decoded }));
|
package/dist/upsertResult.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upsertResult.js","sourceRoot":"","sources":["../src/upsertResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"upsertResult.js","sourceRoot":"","sources":["../src/upsertResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAOvC,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC;IACvC,OAAO,GAAG,CAAA,oBAAoB,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;AAC1D,CAAC,CAAC,CAAC;AAEH,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,GAAkD,EAAE,EAAE,CAC7D,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,iBAAiB,KAAK,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;AACtG,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Effect, Option, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient, type SqlModel } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
5
|
import type { PrimaryKey, Repository } from "#compositeRepository.ts";
|
|
6
6
|
import type { OptimisticConcurrencyError } from "#repository.ts";
|
|
7
|
+
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
7
8
|
import type { UpdateInput } from "#repositoryUpdate.ts";
|
|
8
9
|
import { type VersionedOptions } from "#versionedStatements.ts";
|
|
9
|
-
import type { RepositoryChanges } from "./repositoryChanges.ts";
|
|
10
10
|
export type IdColumn<TModel extends Model.Any> = keyof TModel["Type"] & keyof TModel["update"]["Type"] & keyof TModel["fields"];
|
|
11
11
|
export type VersionColumn<TModel extends Model.Any, TId extends PrimaryKey<TModel>> = {
|
|
12
12
|
[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 {
|
|
@@ -23,16 +23,16 @@ export interface VersionedWrites<TModel extends Model.Any, TId extends PrimaryKe
|
|
|
23
23
|
readonly update: (input: UpdateInput<TModel>) => Effect.Effect<TModel["Type"], WriteError, TModel["update"]["EncodingServices"] | TModel["DecodingServices"]>;
|
|
24
24
|
readonly updateVoid: (input: UpdateInput<TModel>) => Effect.Effect<void, WriteError, TModel["update"]["EncodingServices"]>;
|
|
25
25
|
}
|
|
26
|
-
export declare
|
|
26
|
+
export declare const makeVersionedWrites: (model: Model.Any, options: VersionedOptions & {
|
|
27
27
|
readonly changes: RepositoryChanges;
|
|
28
28
|
readonly spanPrefix: string;
|
|
29
|
-
})
|
|
29
|
+
}) => Effect.Effect<{
|
|
30
30
|
delete: (id: unknown, expected: number) => Effect.Effect<undefined, OptimisticConcurrencyError | Schema.SchemaError | SqlError, unknown>;
|
|
31
31
|
insert: (input: unknown) => Effect.Effect<unknown, Schema.SchemaError | SqlError, unknown>;
|
|
32
32
|
insertVoid: (input: unknown) => Effect.Effect<void, Schema.SchemaError | SqlError, unknown>;
|
|
33
33
|
update: (input: Readonly<Record<string, unknown>>) => Effect.Effect<unknown, OptimisticConcurrencyError | Schema.SchemaError | SqlError, unknown>;
|
|
34
34
|
updateVoid: (input: Readonly<Record<string, unknown>>) => Effect.Effect<undefined, OptimisticConcurrencyError | Schema.SchemaError | SqlError, unknown>;
|
|
35
35
|
insertOrIgnore?: (input: unknown) => Effect.Effect<Option.None<unknown> | Option.Some<unknown>, Schema.SchemaError | SqlError, unknown>;
|
|
36
|
-
}
|
|
36
|
+
}, never, SqlClient.SqlClient>;
|
|
37
37
|
export {};
|
|
38
38
|
//# sourceMappingURL=versionedRepository.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versionedRepository.d.ts","sourceRoot":"","sources":["../src/versionedRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"versionedRepository.d.ts","sourceRoot":"","sources":["../src/versionedRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,KAAK,gBAAgB,EAAuB,MAAM,yBAAyB,CAAC;AAErF,MAAM,MAAM,QAAQ,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,IAAI,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChI,MAAM,MAAM,aAAa,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,SAAS,UAAU,CAAC,MAAM,CAAC,IAAI;KACpF,IAAI,IAAI,OAAO,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,eAAe,CACxI,MAAM,EACN,MAAM,EACN,KAAK,EACL,KAAK,CACL,GACE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS;QAAE,QAAQ,EAAE,MAAM,IAAI,IAAI,GAAG,MAAM;KAAE,GACrE,IAAI,GACJ,KAAK,GACN,KAAK;CACR,CAAC,OAAO,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC,GAC1E,OAAO,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,SAAS,WAAW,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAE5H,MAAM,MAAM,gBAAgB,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,SAAS,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CACpG,UAAU,CAAC,OAAO,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CACvD,CAAC;AACF,KAAK,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,0BAA0B,CAAC;AAC7E,KAAK,SAAS,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,SAAS,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,SAAS,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,GAC/G,GAAG,CAAC,MAAM,CAAC,GACX,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;AAClC,MAAM,WAAW,eAAe,CAAC,MAAM,SAAS,KAAK,CAAC,GAAG,EAAE,GAAG,SAAS,UAAU,CAAC,MAAM,CAAC;IACxF,QAAQ,CAAC,MAAM,EAAE,CAChB,EAAE,EAAE,GAAG,SAAS,SAAS,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAC1I,eAAe,EAAE,MAAM,KACnB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACnG,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IACnD,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;IAC3D,QAAQ,CAAC,MAAM,EAAE,CAChB,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,KACtB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAClH,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC;CAC3H;AAED,eAAO,MAAM,mBAAmB;sBAEiB,iBAAiB;yBAAuB,MAAM;;iBAkDvE,OAAO,YAAY,MAAM;oBA5CzB,OAAO;wBAQH,OAAO;oBAeX,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;wBAW7B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;6BAnB7B,OAAO;8BAwCrC,CAAC"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Effect, Option, Schema } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
2
3
|
import { versionedStatements } from "#versionedStatements.ts";
|
|
3
|
-
export
|
|
4
|
+
export const makeVersionedWrites = Effect.fnUntraced(function* (model, options) {
|
|
5
|
+
const sql = yield* SqlClient.SqlClient;
|
|
4
6
|
const { spanPrefix, changes } = options;
|
|
5
|
-
const statements = versionedStatements(model,
|
|
7
|
+
const statements = yield* versionedStatements(model, options);
|
|
6
8
|
const decodeRow = Schema.decodeUnknownEffect(model);
|
|
7
9
|
function insert(input) {
|
|
8
10
|
return Effect.gen(function* () {
|
|
@@ -59,5 +61,5 @@ export function makeVersionedWrites(model, sql, options) {
|
|
|
59
61
|
}).pipe(changes.write, Effect.withSpan(`${spanPrefix}.delete`));
|
|
60
62
|
}
|
|
61
63
|
return { delete: deleteRow, insert, insertVoid, update, updateVoid, ...(options.conflictColumns === undefined ? {} : { insertOrIgnore }) };
|
|
62
|
-
}
|
|
64
|
+
});
|
|
63
65
|
//# sourceMappingURL=versionedRepository.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versionedRepository.js","sourceRoot":"","sources":["../src/versionedRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"versionedRepository.js","sourceRoot":"","sources":["../src/versionedRepository.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
4
|
import type { OptimisticConcurrencyError } from "#repository.ts";
|
|
5
5
|
export interface VersionedOptions {
|
|
6
6
|
readonly conflict: (id: unknown, expectedVersion: number, reason: "missing" | "stale") => OptimisticConcurrencyError;
|
|
@@ -10,7 +10,7 @@ export interface VersionedOptions {
|
|
|
10
10
|
readonly tableName: string;
|
|
11
11
|
readonly versionColumn: string;
|
|
12
12
|
}
|
|
13
|
-
export declare
|
|
13
|
+
export declare const versionedStatements: (model: Model.Any, options: VersionedOptions) => Effect.Effect<{
|
|
14
14
|
insert: (input: unknown, ignore?: boolean) => Effect.Effect<import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>, Schema.SchemaError | import("effect/sql/SqlError").SqlError, unknown>;
|
|
15
15
|
remove: (id: unknown, expected: number) => Effect.Effect<{
|
|
16
16
|
classify: () => Effect.Effect<never, OptimisticConcurrencyError | import("effect/sql/SqlError").SqlError, never>;
|
|
@@ -20,5 +20,5 @@ export declare function versionedStatements(model: Model.Any, sql: SqlClient.Sql
|
|
|
20
20
|
classify: () => Effect.Effect<never, OptimisticConcurrencyError | import("effect/sql/SqlError").SqlError, never>;
|
|
21
21
|
statement: import("effect/sql/Statement").Statement<import("effect/sql/SqlConnection").Row>;
|
|
22
22
|
}, Schema.SchemaError, unknown>;
|
|
23
|
-
}
|
|
23
|
+
}, never, SqlClient.SqlClient>;
|
|
24
24
|
//# sourceMappingURL=versionedStatements.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versionedStatements.d.ts","sourceRoot":"","sources":["../src/versionedStatements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,
|
|
1
|
+
{"version":3,"file":"versionedStatements.d.ts","sourceRoot":"","sources":["../src/versionedStatements.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,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAGjE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,KAAK,0BAA0B,CAAC;IACrH,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,mBAAmB;oBAsCR,OAAO;iBAsBV,OAAO,YAAY,MAAM;;;;oBAftB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;8BA2BvD,CAAC"}
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
2
3
|
import { makeConflictClause } from "#makeConflictClause.ts";
|
|
3
4
|
const Version = Schema.Number.check(Schema.isInt(), Schema.isGreaterThanOrEqualTo(0));
|
|
4
|
-
export
|
|
5
|
+
export const versionedStatements = Effect.fnUntraced(function* (model, options) {
|
|
6
|
+
const sql = yield* SqlClient.SqlClient;
|
|
5
7
|
const { tableName, idColumns, versionColumn, conflict } = options;
|
|
6
|
-
const
|
|
8
|
+
const entries = [];
|
|
9
|
+
for (const column of idColumns) {
|
|
7
10
|
const field = model.fields[column];
|
|
8
11
|
if (field === undefined) {
|
|
9
|
-
|
|
12
|
+
return yield* Effect.die(new Error(`Unknown ID column: ${column}`));
|
|
10
13
|
}
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
const encodeKey = Schema.encodeEffect(Schema.Struct(
|
|
14
|
+
entries.push([column, field]);
|
|
15
|
+
}
|
|
16
|
+
const encodeKey = Schema.encodeEffect(Schema.Struct(Object.fromEntries(entries)));
|
|
14
17
|
const versionSchema = model.fields[versionColumn];
|
|
15
18
|
if (versionSchema === undefined) {
|
|
16
|
-
|
|
19
|
+
return yield* Effect.die(new Error(`Unknown version column: ${versionColumn}`));
|
|
17
20
|
}
|
|
18
21
|
const encodeVersion = Schema.encodeEffect(versionSchema);
|
|
19
22
|
const encodeInsert = Schema.encodeEffect(model.insert);
|
|
20
23
|
const encodeUpdate = Schema.encodeEffect(model.update);
|
|
21
24
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
22
25
|
const validateVersion = Schema.decodeUnknownEffect(Version);
|
|
23
|
-
const clause = options.conflictColumns === undefined ? undefined : makeConflictClause(model,
|
|
26
|
+
const clause = options.conflictColumns === undefined ? undefined : yield* makeConflictClause(model, { ...options, conflictColumns: options.conflictColumns });
|
|
24
27
|
function key(input) {
|
|
25
28
|
return idColumns.length === 1 ? { [idColumns[0] ?? ""]: input } : input;
|
|
26
29
|
}
|
|
@@ -70,5 +73,5 @@ export function versionedStatements(model, sql, options) {
|
|
|
70
73
|
});
|
|
71
74
|
}
|
|
72
75
|
return { insert, remove, update };
|
|
73
|
-
}
|
|
76
|
+
});
|
|
74
77
|
//# sourceMappingURL=versionedStatements.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versionedStatements.js","sourceRoot":"","sources":["../src/versionedStatements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"versionedStatements.js","sourceRoot":"","sources":["../src/versionedStatements.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/sql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.1",
|
|
4
4
|
"description": "Schema-derived repositories over native Effect SQL",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"effect"
|
|
@@ -44,17 +44,18 @@
|
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@shivaedev/changes": "0.9.0",
|
|
47
|
-
"@shivaedev/service": "0.6.
|
|
47
|
+
"@shivaedev/service": "0.6.2"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@effect/platform-node": "4.0.6",
|
|
51
51
|
"@effect/sql-pg": "4.0.6",
|
|
52
52
|
"@effect/sql-sqlite-node": "4.0.6",
|
|
53
|
-
"@shivaedev/contract": "0.
|
|
54
|
-
"@shivaedev/jobs": "0.
|
|
55
|
-
"@shivaedev/quality": "0.
|
|
56
|
-
"@shivaedev/test-
|
|
57
|
-
"@shivaedev/test-
|
|
53
|
+
"@shivaedev/contract": "0.34.0",
|
|
54
|
+
"@shivaedev/jobs": "0.34.0",
|
|
55
|
+
"@shivaedev/quality": "0.58.0",
|
|
56
|
+
"@shivaedev/test-kits": "0.2.1",
|
|
57
|
+
"@shivaedev/test-sql": "0.18.2",
|
|
58
|
+
"@shivaedev/test-story": "0.37.0",
|
|
58
59
|
"@types/node": "24.19.2",
|
|
59
60
|
"effect": "4.0.6",
|
|
60
61
|
"typescript": "7.0.2",
|
package/src/aggregateColumn.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect, Schema, SchemaAST } from "effect";
|
|
2
|
-
import
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
3
|
|
|
4
4
|
const Expression = Schema.Tuple([Schema.Tuple([Schema.Literals(["count", "sum", "avg", "min", "max", "boolOr", "boolAnd"]), Schema.String])]);
|
|
5
5
|
const functions = { avg: "avg", boolAnd: "bool_and", boolOr: "bool_or", count: "count", max: "max", min: "min", sum: "sum" };
|
|
@@ -31,7 +31,8 @@ function resultSchema(operation: Operation, field: Schema.Constraint): Schema.Co
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export
|
|
34
|
+
export const aggregateColumn = Effect.fnUntraced(function* (fieldAt: (key: string) => Effect.Effect<Schema.Constraint, Schema.SchemaError>) {
|
|
35
|
+
const sql = yield* SqlClient.SqlClient;
|
|
35
36
|
return Effect.fnUntraced(function* (name: string, expression: object) {
|
|
36
37
|
const [[operation, key]] = yield* Schema.decodeUnknownEffect(Expression)(Object.entries(expression));
|
|
37
38
|
const countRows = operation === "count" && key === "*";
|
|
@@ -46,4 +47,4 @@ export function aggregateColumn(sql: SqlClient.SqlClient, fieldAt: (key: string)
|
|
|
46
47
|
schema: operation === "count" ? Result : Schema.NullOr(Result),
|
|
47
48
|
};
|
|
48
49
|
});
|
|
49
|
-
}
|
|
50
|
+
});
|
package/src/batchWrites.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
5
|
import type { Fragment } from "effect/sql/Statement";
|
|
6
|
-
import type { RepositoryChanges } from "
|
|
7
|
-
import { makeUpsertDecoder, upsertReturning } from "
|
|
6
|
+
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
7
|
+
import { makeUpsertDecoder, upsertReturning } from "#upsertResult.ts";
|
|
8
8
|
|
|
9
9
|
export type InsertMany<TModel extends Model.Any, TServices = never> = (
|
|
10
10
|
inputs: readonly TModel["insert"]["Type"][],
|
|
@@ -14,20 +14,20 @@ export interface BatchWrites<TModel extends Model.Any> {
|
|
|
14
14
|
readonly insertMany: InsertMany<TModel>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function
|
|
17
|
+
export const makeInsertMany = Effect.fnUntraced(function* <TServices = never>(
|
|
18
18
|
model: Model.Any,
|
|
19
|
-
sql: SqlClient.SqlClient,
|
|
20
19
|
options: { readonly tableName: string; readonly spanPrefix: string; readonly changes: RepositoryChanges },
|
|
21
20
|
operation: string,
|
|
22
|
-
prepare
|
|
23
|
-
Effect.succeed(sql``),
|
|
21
|
+
prepare?: (row: Readonly<Record<string, unknown>>) => Effect.Effect<Fragment, SqlError | Schema.SchemaError, TServices>,
|
|
24
22
|
upsert = false,
|
|
25
23
|
) {
|
|
24
|
+
const sql = yield* SqlClient.SqlClient;
|
|
25
|
+
const prepareRow = prepare ?? (() => Effect.succeed(sql``));
|
|
26
26
|
const encode = Schema.encodeEffect(model.insert);
|
|
27
27
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
28
28
|
const decode = Schema.decodeUnknownEffect(Schema.Array(model));
|
|
29
29
|
const decodeUpsert = makeUpsertDecoder(model);
|
|
30
|
-
const returning = options.changes.returning(upsert ? upsertReturning(
|
|
30
|
+
const returning = options.changes.returning(upsert ? yield* upsertReturning() : sql`*`);
|
|
31
31
|
return (inputs: readonly unknown[]) =>
|
|
32
32
|
Effect.gen(function* () {
|
|
33
33
|
if (inputs.length === 0) {
|
|
@@ -57,7 +57,7 @@ export function makeInsertMany<TServices = never>(
|
|
|
57
57
|
for (const row of rows) {
|
|
58
58
|
const value = sql`(${sql.csv(columns.map((column) => (Object.hasOwn(row, column) ? sql`${row[column]}` : sql`default`)))})`;
|
|
59
59
|
const size = value.compile()[1].length;
|
|
60
|
-
const prepared = yield*
|
|
60
|
+
const prepared = yield* prepareRow(row);
|
|
61
61
|
const suffixSize = sql`${prepared}`.compile()[1].length;
|
|
62
62
|
// Bound native fragment size as well as PostgreSQL's 65,535 bind parameters.
|
|
63
63
|
if (chunk.length > 0 && (chunk.length === chunkSize || parameters + size + suffixSize > 10_000)) {
|
|
@@ -71,4 +71,4 @@ export function makeInsertMany<TServices = never>(
|
|
|
71
71
|
yield* options.changes.record(changedRows);
|
|
72
72
|
return results;
|
|
73
73
|
}).pipe(options.changes.write, Effect.withSpan(`${options.spanPrefix}.${operation}`));
|
|
74
|
-
}
|
|
74
|
+
});
|
package/src/batchedDelete.ts
CHANGED
|
@@ -69,7 +69,7 @@ export const makeBatchedDelete = Effect.fnUntraced(function* (
|
|
|
69
69
|
changes: RepositoryChanges,
|
|
70
70
|
) {
|
|
71
71
|
const sql = yield* SqlClient.SqlClient;
|
|
72
|
-
const { where } = makeFilter(model
|
|
72
|
+
const { where } = yield* makeFilter(model);
|
|
73
73
|
function deleteBatch(predicate: Fragment, limit: number) {
|
|
74
74
|
const count = SqlSchema.findOne({
|
|
75
75
|
execute: (batchLimit) => sql`with removed as (
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Cause } from "effect";
|
|
2
2
|
import { Effect, Schema } from "effect";
|
|
3
3
|
import type { Model } from "effect/schema";
|
|
4
|
-
import {
|
|
4
|
+
import { SqlClient, SqlSchema } from "effect/sql";
|
|
5
5
|
import type { SqlError } from "effect/sql/SqlError";
|
|
6
6
|
import type { BatchedDelete } from "#batchedDelete.ts";
|
|
7
7
|
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
@@ -41,9 +41,8 @@ export type Repository<TModel extends Model.Any, TId extends PrimaryKey<TModel>>
|
|
|
41
41
|
}
|
|
42
42
|
: never);
|
|
43
43
|
|
|
44
|
-
export
|
|
44
|
+
export const makeCompositeCrud = Effect.fnUntraced(function* (
|
|
45
45
|
model: Model.Any,
|
|
46
|
-
sql: SqlClient.SqlClient,
|
|
47
46
|
options: {
|
|
48
47
|
readonly columns: readonly string[];
|
|
49
48
|
readonly tableName: string;
|
|
@@ -51,19 +50,20 @@ export function makeCompositeCrud(
|
|
|
51
50
|
},
|
|
52
51
|
changes: RepositoryChanges,
|
|
53
52
|
) {
|
|
53
|
+
const sql = yield* SqlClient.SqlClient;
|
|
54
54
|
const { columns, tableName, spanPrefix } = options;
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
);
|
|
55
|
+
const entries: [string, Schema.Constraint][] = [];
|
|
56
|
+
for (const column of columns) {
|
|
57
|
+
const field = model.fields[column];
|
|
58
|
+
if (field === undefined) {
|
|
59
|
+
return yield* Effect.die(new Error(`Unknown ID column: ${column}`));
|
|
60
|
+
}
|
|
61
|
+
entries.push([column, field]);
|
|
62
|
+
}
|
|
63
|
+
const fields = Object.fromEntries(entries);
|
|
64
64
|
const Key = columns.length === 1 ? model.fields[columns[0] ?? ""] : Schema.Struct(fields);
|
|
65
65
|
if (Key === undefined) {
|
|
66
|
-
|
|
66
|
+
return yield* Effect.die(new Error("Unknown repository ID column"));
|
|
67
67
|
}
|
|
68
68
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
69
69
|
function predicate(input: Readonly<Record<string, unknown>>) {
|
|
@@ -80,7 +80,7 @@ export function makeCompositeCrud(
|
|
|
80
80
|
});
|
|
81
81
|
|
|
82
82
|
return {
|
|
83
|
-
...repositoryWrites(model,
|
|
83
|
+
...(yield* repositoryWrites(model, { ...options, idColumns: columns }, changes)),
|
|
84
84
|
findById: (id: unknown) => find(id).pipe(Effect.withSpan(`${spanPrefix}.findById`)),
|
|
85
85
|
};
|
|
86
|
-
}
|
|
86
|
+
});
|
package/src/conditionalUpsert.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
5
|
import { makeConflictClause } from "#makeConflictClause.ts";
|
|
6
6
|
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
@@ -53,9 +53,8 @@ export interface ConditionalUpsertMany<TModel extends Model.Any, TOptions, TServ
|
|
|
53
53
|
): Effect.Effect<UpsertRow<TModel["Type"]>[], SqlError | Schema.SchemaError, TServices>;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
export
|
|
56
|
+
export const makeConditionalUpsert = Effect.fnUntraced(function* (
|
|
57
57
|
model: Model.Any,
|
|
58
|
-
sql: SqlClient.SqlClient,
|
|
59
58
|
options: {
|
|
60
59
|
readonly tableName: string;
|
|
61
60
|
readonly spanPrefix: string;
|
|
@@ -65,10 +64,12 @@ export function makeConditionalUpsert(
|
|
|
65
64
|
readonly idColumns: readonly string[];
|
|
66
65
|
},
|
|
67
66
|
) {
|
|
67
|
+
const sql = yield* SqlClient.SqlClient;
|
|
68
|
+
const returning = yield* upsertReturning();
|
|
68
69
|
const encode = Schema.encodeEffect(model.insert);
|
|
69
70
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
70
71
|
const decode = makeUpsertDecoder(model);
|
|
71
|
-
const clause = makeConflictClause(model,
|
|
72
|
+
const clause = yield* makeConflictClause(model, options);
|
|
72
73
|
return (
|
|
73
74
|
inputs: readonly unknown[],
|
|
74
75
|
settings: { readonly updateColumns: readonly UpsertAssignment[]; readonly updateWhere: Readonly<Record<string, unknown>> },
|
|
@@ -78,7 +79,7 @@ export function makeConditionalUpsert(
|
|
|
78
79
|
Effect.gen(function* () {
|
|
79
80
|
const row = yield* record(yield* encode(input));
|
|
80
81
|
const suffix = yield* clause(row, settings.updateColumns, settings.updateWhere);
|
|
81
|
-
return sql`insert into ${sql(options.tableName)} ${sql.insert(row)} ${suffix} returning ${options.changes.returning(
|
|
82
|
+
return sql`insert into ${sql(options.tableName)} ${sql.insert(row)} ${suffix} returning ${options.changes.returning(returning)}`;
|
|
82
83
|
}),
|
|
83
84
|
);
|
|
84
85
|
const changedRows: Readonly<Record<string, unknown>>[] = [];
|
|
@@ -99,4 +100,4 @@ export function makeConditionalUpsert(
|
|
|
99
100
|
yield* options.changes.record(changedRows);
|
|
100
101
|
return results;
|
|
101
102
|
}).pipe(options.changes.write, Effect.withSpan(`${options.spanPrefix}.conditionalUpsert`));
|
|
102
|
-
}
|
|
103
|
+
});
|
package/src/conflictWrites.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Option, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
5
|
import { type InsertMany, makeInsertMany } from "#batchWrites.ts";
|
|
6
6
|
import { type ConditionalUpsert, type ConditionalUpsertMany, makeConditionalUpsert } from "#conditionalUpsert.ts";
|
|
@@ -40,9 +40,8 @@ export interface ConflictWrites<TModel extends Model.Any, TExcluded extends Prop
|
|
|
40
40
|
>;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
export
|
|
43
|
+
export const makeConflictWrites = Effect.fnUntraced(function* (
|
|
44
44
|
model: Model.Any,
|
|
45
|
-
sql: SqlClient.SqlClient,
|
|
46
45
|
options: {
|
|
47
46
|
readonly changes: RepositoryChanges;
|
|
48
47
|
readonly tableName: string;
|
|
@@ -52,25 +51,27 @@ export function makeConflictWrites(
|
|
|
52
51
|
readonly idColumns: readonly string[];
|
|
53
52
|
},
|
|
54
53
|
) {
|
|
54
|
+
const sql = yield* SqlClient.SqlClient;
|
|
55
55
|
const { tableName, spanPrefix } = options;
|
|
56
|
+
const returning = yield* upsertReturning();
|
|
56
57
|
const encode = Schema.encodeEffect(model.insert);
|
|
57
58
|
const decode = Schema.decodeUnknownEffect(model);
|
|
58
59
|
const decodeUpsert = makeUpsertDecoder(model);
|
|
59
60
|
const record = Schema.decodeUnknownEffect(Schema.Record(Schema.String, Schema.Unknown));
|
|
60
|
-
const conditional = makeConditionalUpsert(model,
|
|
61
|
-
const clause = makeConflictClause(model,
|
|
61
|
+
const conditional = yield* makeConditionalUpsert(model, options);
|
|
62
|
+
const clause = yield* makeConflictClause(model, options);
|
|
62
63
|
function statement(input: unknown, updateColumns?: readonly UpsertAssignment[]) {
|
|
63
64
|
return Effect.gen(function* () {
|
|
64
65
|
const encoded = yield* record(yield* encode(input));
|
|
65
66
|
const suffix = yield* clause(encoded, updateColumns);
|
|
66
|
-
return sql`insert into ${sql(tableName)} ${sql.insert(encoded)} ${suffix} returning ${options.changes.returning(updateColumns === undefined ? sql`*` :
|
|
67
|
+
return sql`insert into ${sql(tableName)} ${sql.insert(encoded)} ${suffix} returning ${options.changes.returning(updateColumns === undefined ? sql`*` : returning)}`;
|
|
67
68
|
});
|
|
68
69
|
}
|
|
69
70
|
return {
|
|
70
|
-
insertFromSelectOrIgnore: makeInsertFromSelect(model,
|
|
71
|
+
insertFromSelectOrIgnore: yield* makeInsertFromSelect(model, options, "insertFromSelectOrIgnore", (columns) =>
|
|
71
72
|
clause(Object.fromEntries(columns.map((key) => [key, undefined]))),
|
|
72
73
|
),
|
|
73
|
-
insertManyOrIgnore: makeInsertMany(model,
|
|
74
|
+
insertManyOrIgnore: yield* makeInsertMany(model, options, "insertManyOrIgnore", (row) => clause(row)),
|
|
74
75
|
insertOrIgnore: (input: unknown) =>
|
|
75
76
|
Effect.gen(function* () {
|
|
76
77
|
const rows = yield* yield* statement(input);
|
|
@@ -93,7 +94,10 @@ export function makeConflictWrites(
|
|
|
93
94
|
settings: { readonly updateColumns: readonly UpsertAssignment[]; readonly updateWhere?: Readonly<Record<string, unknown>> },
|
|
94
95
|
) =>
|
|
95
96
|
settings.updateWhere === undefined
|
|
96
|
-
?
|
|
97
|
+
? Effect.flatMap(
|
|
98
|
+
makeInsertMany(model, options, "upsertMany", (row) => clause(row, settings.updateColumns), true),
|
|
99
|
+
(insertMany) => insertMany(inputs),
|
|
100
|
+
).pipe(Effect.provideService(SqlClient.SqlClient, sql))
|
|
97
101
|
: conditional(inputs, { ...settings, updateWhere: settings.updateWhere }),
|
|
98
102
|
};
|
|
99
|
-
}
|
|
103
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { Duration, Effect, Exit, Predicate, Schedule, Scope } from "effect";
|
|
1
|
+
import { Duration, Effect, Exit, Option, Predicate, Schedule, Scope } from "effect";
|
|
2
2
|
import { isSqlError } from "effect/sql/SqlError";
|
|
3
|
+
import { WorkerReleaseTesting } from "#testing/WorkerRelease.ts";
|
|
3
4
|
import { readPostgresRelease } from "./postgresRelease.ts";
|
|
4
5
|
import { releaseWorkers } from "./releaseWorkers.ts";
|
|
5
6
|
import { makeWorkerRelease } from "./WorkerRelease.ts";
|
|
@@ -65,5 +66,10 @@ export const coordinateWorkerRelease = Effect.fn("EffectSql.coordinateWorkerRele
|
|
|
65
66
|
yield* loop("heartbeat", rows.heartbeat);
|
|
66
67
|
yield* tick("poll", poll).pipe(Scope.provide(scope));
|
|
67
68
|
yield* loop("poll", poll);
|
|
69
|
+
const testing = yield* Effect.serviceOption(WorkerReleaseTesting);
|
|
70
|
+
if (Option.isSome(testing)) {
|
|
71
|
+
const context = yield* Effect.context<Effect.Services<typeof poll>>();
|
|
72
|
+
yield* testing.value.register({ heartbeat: rows.heartbeat, poll: poll.pipe(Effect.provideContext(context)) }).pipe(Scope.provide(scope));
|
|
73
|
+
}
|
|
68
74
|
return gate.service;
|
|
69
75
|
});
|
package/src/insertFromSelect.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effect, Schema } from "effect";
|
|
2
2
|
import type { Model } from "effect/schema";
|
|
3
|
-
import
|
|
3
|
+
import { SqlClient } from "effect/sql";
|
|
4
4
|
import type { SqlError } from "effect/sql/SqlError";
|
|
5
5
|
import type { Fragment } from "effect/sql/Statement";
|
|
6
6
|
import type { RepositoryChanges } from "#repositoryChanges.ts";
|
|
@@ -24,24 +24,24 @@ export interface SelectWrites<TModel extends Model.Any> {
|
|
|
24
24
|
readonly insertFromSelect: InsertFromSelect<TModel>;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export function
|
|
27
|
+
export const makeInsertFromSelect = Effect.fnUntraced(function* <TServices = never>(
|
|
28
28
|
model: Model.Any,
|
|
29
|
-
sql: SqlClient.SqlClient,
|
|
30
29
|
options: { readonly tableName: string; readonly spanPrefix: string; readonly changes: RepositoryChanges },
|
|
31
30
|
operation: string,
|
|
32
|
-
prepare
|
|
31
|
+
prepare?: (columns: readonly string[]) => Effect.Effect<Fragment, SqlError | Schema.SchemaError, TServices>,
|
|
33
32
|
) {
|
|
33
|
+
const sql = yield* SqlClient.SqlClient;
|
|
34
34
|
const decode = Schema.decodeUnknownEffect(Schema.Array(model));
|
|
35
35
|
return (source: RepositorySelect<Schema.Struct.Fields, unknown>, columns: Readonly<Record<string, string>>) =>
|
|
36
36
|
Effect.gen(function* () {
|
|
37
37
|
const names = Object.keys(columns);
|
|
38
38
|
const selected = sql.csv(Object.values(columns).map((column) => sql`${sql(column)}`));
|
|
39
39
|
const target = sql.csv(names.map((column) => sql`${sql(column)}`));
|
|
40
|
-
const suffix = yield* prepare(names);
|
|
40
|
+
const suffix = yield* prepare?.(names) ?? Effect.succeed(sql``);
|
|
41
41
|
const statement = yield* source.statement;
|
|
42
42
|
const rows =
|
|
43
43
|
yield* sql`insert into ${sql(options.tableName)} (${target}) select ${selected} from (${statement}) as ${sql("source")} where true ${suffix} returning ${options.changes.returning()}`;
|
|
44
44
|
yield* options.changes.record(rows);
|
|
45
45
|
return yield* decode(rows);
|
|
46
46
|
}).pipe(options.changes.write, Effect.withSpan(`${options.spanPrefix}.${operation}`));
|
|
47
|
-
}
|
|
47
|
+
});
|