@shivaedev/sql 0.29.0 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +101 -1
- package/dist/applyLowMemoryPostgres.d.ts +7 -0
- package/dist/applyLowMemoryPostgres.d.ts.map +1 -0
- package/dist/applyLowMemoryPostgres.js +24 -0
- package/dist/applyLowMemoryPostgres.js.map +1 -0
- package/dist/batchedDelete.d.ts +33 -0
- package/dist/batchedDelete.d.ts.map +1 -0
- package/dist/batchedDelete.js +64 -0
- package/dist/batchedDelete.js.map +1 -0
- package/dist/compositeRepository.d.ts +14 -13
- package/dist/compositeRepository.d.ts.map +1 -1
- package/dist/compositeRepository.js.map +1 -1
- package/dist/jsonb.d.ts +3 -0
- package/dist/jsonb.d.ts.map +1 -0
- package/dist/jsonb.js +9 -0
- package/dist/jsonb.js.map +1 -0
- package/dist/repository.d.ts.map +1 -1
- package/dist/repository.js +19 -17
- package/dist/repository.js.map +1 -1
- package/dist/repositoryChanges.d.ts +1 -0
- package/dist/repositoryChanges.d.ts.map +1 -1
- package/dist/repositoryChanges.js +9 -1
- package/dist/repositoryChanges.js.map +1 -1
- package/dist/repositoryUpdate.d.ts +31 -0
- package/dist/repositoryUpdate.d.ts.map +1 -0
- package/dist/repositoryUpdate.js +16 -0
- package/dist/repositoryUpdate.js.map +1 -0
- package/dist/repositoryWrites.d.ts +5 -2
- package/dist/repositoryWrites.d.ts.map +1 -1
- package/dist/repositoryWrites.js +19 -4
- package/dist/repositoryWrites.js.map +1 -1
- package/dist/tryPurgeLock.d.ts +4 -0
- package/dist/tryPurgeLock.d.ts.map +1 -0
- package/dist/tryPurgeLock.js +15 -0
- package/dist/tryPurgeLock.js.map +1 -0
- package/dist/versionedRepository.d.ts +3 -2
- package/dist/versionedRepository.d.ts.map +1 -1
- package/dist/versionedRepository.js.map +1 -1
- package/package.json +4 -4
- package/src/applyLowMemoryPostgres.ts +28 -0
- package/src/batchedDelete.ts +93 -0
- package/src/compositeRepository.ts +25 -34
- package/src/jsonb.ts +12 -0
- package/src/repository.ts +19 -17
- package/src/repositoryChanges.ts +9 -1
- package/src/repositoryUpdate.ts +65 -0
- package/src/repositoryWrites.ts +19 -4
- package/src/tryPurgeLock.ts +18 -0
- package/src/versionedRepository.ts +3 -2
package/src/repositoryWrites.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Model } from "effect/schema";
|
|
|
3
3
|
import { type SqlClient, SqlSchema } from "effect/sql";
|
|
4
4
|
import type { RepositoryChanges } from "./repositoryChanges.ts";
|
|
5
5
|
import { makeFilter } from "./repositoryFilter.ts";
|
|
6
|
+
import { selectedUpdate } from "./repositoryUpdate.ts";
|
|
6
7
|
|
|
7
8
|
export function repositoryWrites(
|
|
8
9
|
model: Model.Any,
|
|
@@ -36,6 +37,15 @@ export function repositoryWrites(
|
|
|
36
37
|
const insertVoid = SqlSchema.void({ execute: insert, Request: model.insert });
|
|
37
38
|
const updateRow = SqlSchema.findOne({ execute: update, Request: model.update, Result: model });
|
|
38
39
|
const updateVoid = SqlSchema.void({ execute: update, Request: model.update });
|
|
40
|
+
function selected(input: unknown, columns: readonly string[], returning: boolean) {
|
|
41
|
+
return Effect.gen(function* () {
|
|
42
|
+
const row = yield* record(input);
|
|
43
|
+
const Request = yield* selectedUpdate(model, columns, idColumns, row);
|
|
44
|
+
return yield* returning
|
|
45
|
+
? SqlSchema.findOne({ execute: update, Request, Result: model })(row)
|
|
46
|
+
: SqlSchema.void({ execute: update, Request })(row);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
39
49
|
const idColumn = idColumns[0] ?? "";
|
|
40
50
|
const key = model.fields[idColumn];
|
|
41
51
|
if (key === undefined) {
|
|
@@ -63,10 +73,15 @@ export function repositoryWrites(
|
|
|
63
73
|
insert: (input: unknown) =>
|
|
64
74
|
changes.write(insertRow(input).pipe(Effect.catchTag("NoSuchElementError", Effect.die))).pipe(Effect.withSpan(`${spanPrefix}.insert`)),
|
|
65
75
|
insertVoid: (input: unknown) => changes.write(insertVoid(input)).pipe(Effect.withSpan(`${spanPrefix}.insertVoid`)),
|
|
66
|
-
update: (input: unknown, settings?: { readonly onMissing
|
|
76
|
+
update: (input: unknown, settings?: { readonly onMissing?: "fail"; readonly columns?: readonly string[] }) => {
|
|
77
|
+
const result = settings?.columns === undefined ? updateRow(input) : selected(input, settings.columns, true);
|
|
78
|
+
return changes
|
|
79
|
+
.write(settings?.onMissing === "fail" ? result : result.pipe(Effect.catchTag("NoSuchElementError", Effect.die)))
|
|
80
|
+
.pipe(Effect.withSpan(`${spanPrefix}.update`));
|
|
81
|
+
},
|
|
82
|
+
updateVoid: (input: unknown, settings?: { readonly columns: readonly string[] }) =>
|
|
67
83
|
changes
|
|
68
|
-
.write(settings
|
|
69
|
-
.pipe(Effect.withSpan(`${spanPrefix}.
|
|
70
|
-
updateVoid: (input: unknown) => changes.write(updateVoid(input)).pipe(Effect.withSpan(`${spanPrefix}.updateVoid`)),
|
|
84
|
+
.write(settings === undefined ? updateVoid(input) : selected(input, settings.columns, false))
|
|
85
|
+
.pipe(Effect.withSpan(`${spanPrefix}.updateVoid`)),
|
|
71
86
|
};
|
|
72
87
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { SqlClient } from "effect/sql";
|
|
3
|
+
import type { Statement } from "effect/sql/Statement";
|
|
4
|
+
|
|
5
|
+
export const tryPurgeLock = Effect.fnUntraced(function* (tableName: string) {
|
|
6
|
+
const sql = yield* SqlClient.SqlClient;
|
|
7
|
+
const [identifier] = sql`${sql(tableName)}`.compile();
|
|
8
|
+
const key = sql`hashtextextended('@shivaedev/sql/deleteBatched:' || ${identifier}::regclass::oid::text, 0)`;
|
|
9
|
+
const connection = yield* sql.reserve;
|
|
10
|
+
function execute(statement: Statement<Readonly<Record<string, unknown>>>) {
|
|
11
|
+
const [text, parameters] = statement.compile();
|
|
12
|
+
return connection.execute(text, parameters, undefined);
|
|
13
|
+
}
|
|
14
|
+
const [lock] = yield* Effect.acquireRelease(execute(sql`select pg_try_advisory_lock(${key}) as acquired`), (rows) =>
|
|
15
|
+
rows[0]?.acquired === true ? Effect.orDie(execute(sql`select pg_advisory_unlock(${key})`)) : Effect.void,
|
|
16
|
+
);
|
|
17
|
+
return lock?.acquired === true;
|
|
18
|
+
});
|
|
@@ -4,6 +4,7 @@ import type { SqlClient, 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 { UpdateInput } from "#repositoryUpdate.ts";
|
|
7
8
|
import { type VersionedOptions, versionedStatements } from "#versionedStatements.ts";
|
|
8
9
|
import type { RepositoryChanges } from "./repositoryChanges.ts";
|
|
9
10
|
|
|
@@ -37,9 +38,9 @@ export interface VersionedWrites<TModel extends Model.Any, TId extends PrimaryKe
|
|
|
37
38
|
readonly insert: Repository<TModel, TId>["insert"];
|
|
38
39
|
readonly insertVoid: Repository<TModel, TId>["insertVoid"];
|
|
39
40
|
readonly update: (
|
|
40
|
-
input: TModel
|
|
41
|
+
input: UpdateInput<TModel>,
|
|
41
42
|
) => Effect.Effect<TModel["Type"], WriteError, TModel["update"]["EncodingServices"] | TModel["DecodingServices"]>;
|
|
42
|
-
readonly updateVoid: (input: TModel
|
|
43
|
+
readonly updateVoid: (input: UpdateInput<TModel>) => Effect.Effect<void, WriteError, TModel["update"]["EncodingServices"]>;
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
export function makeVersionedWrites(
|