@shivaedev/effect-changes-prisma 0.4.0 → 0.5.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 +12 -0
- package/README.md +249 -87
- package/dist/changes.d.ts +8 -8
- package/dist/changes.d.ts.map +1 -1
- package/dist/changes.js +6 -4
- package/dist/changes.js.map +1 -1
- package/dist/coverage.d.ts.map +1 -1
- package/dist/coverage.js +6 -2
- package/dist/coverage.js.map +1 -1
- package/dist/expiry.d.ts +1 -1
- package/dist/expiry.d.ts.map +1 -1
- package/dist/expiry.js.map +1 -1
- package/dist/model.d.ts +20 -20
- package/dist/model.d.ts.map +1 -1
- package/dist/recording.d.ts +1 -1
- package/dist/recording.d.ts.map +1 -1
- package/dist/recording.js +17 -13
- package/dist/recording.js.map +1 -1
- package/dist/tables.d.ts.map +1 -1
- package/dist/tables.js.map +1 -1
- package/dist/transaction.d.ts +5 -5
- package/dist/transaction.d.ts.map +1 -1
- package/dist/transaction.js +12 -8
- package/dist/transaction.js.map +1 -1
- package/dist/write.d.ts.map +1 -1
- package/dist/write.js +16 -10
- package/dist/write.js.map +1 -1
- package/docs/north-star.md +43 -0
- package/docs/roadmap.md +22 -0
- package/package.json +15 -11
- package/src/changes.ts +19 -16
- package/src/coverage.ts +6 -4
- package/src/expiry.ts +3 -3
- package/src/model.ts +13 -13
- package/src/recording.ts +9 -6
- package/src/transaction.ts +24 -21
- package/src/write.ts +9 -5
package/dist/model.d.ts
CHANGED
|
@@ -3,33 +3,33 @@ export interface TransactionOptions {
|
|
|
3
3
|
readonly maxWait?: number;
|
|
4
4
|
readonly timeout?: number;
|
|
5
5
|
}
|
|
6
|
-
export interface Transactional<
|
|
7
|
-
$transaction: <
|
|
6
|
+
export interface Transactional<TTx> {
|
|
7
|
+
$transaction: <TX>(run: (tx: TTx) => Promise<TX>, options?: TransactionOptions) => PromiseLike<TX>;
|
|
8
8
|
}
|
|
9
|
-
type PayloadOf<
|
|
9
|
+
type PayloadOf<TDelegate> = TDelegate extends {
|
|
10
10
|
readonly [key: symbol]: {
|
|
11
11
|
readonly types: {
|
|
12
|
-
readonly payload: infer
|
|
12
|
+
readonly payload: infer TPayload;
|
|
13
13
|
};
|
|
14
14
|
};
|
|
15
|
-
} ?
|
|
16
|
-
type Delegates<
|
|
17
|
-
export type ModelName<
|
|
18
|
-
[
|
|
19
|
-
readonly name: infer
|
|
20
|
-
} ?
|
|
21
|
-
}[Delegates<
|
|
22
|
-
export type ModelRow<
|
|
23
|
-
[
|
|
24
|
-
readonly name:
|
|
25
|
-
readonly scalars: infer
|
|
26
|
-
} ?
|
|
27
|
-
}[Delegates<
|
|
15
|
+
} ? TPayload : never;
|
|
16
|
+
type Delegates<TClient> = Exclude<keyof TClient & string, `$${string}`>;
|
|
17
|
+
export type ModelName<TClient> = {
|
|
18
|
+
[TKey in Delegates<TClient>]: PayloadOf<TClient[TKey]> extends {
|
|
19
|
+
readonly name: infer TName extends string;
|
|
20
|
+
} ? TName : never;
|
|
21
|
+
}[Delegates<TClient>];
|
|
22
|
+
export type ModelRow<TClient, TModel extends string> = Extract<{
|
|
23
|
+
[TKey in Delegates<TClient>]: PayloadOf<TClient[TKey]> extends {
|
|
24
|
+
readonly name: TModel;
|
|
25
|
+
readonly scalars: infer TRow;
|
|
26
|
+
} ? TRow : never;
|
|
27
|
+
}[Delegates<TClient>], object>;
|
|
28
28
|
export type RowOperation = "create" | "update" | "upsert" | "delete" | "createManyAndReturn" | "updateManyAndReturn";
|
|
29
29
|
export type CountOperation = "createMany" | "updateMany" | "deleteMany";
|
|
30
|
-
export type ModelChanges<
|
|
31
|
-
export type ChangeMap<
|
|
32
|
-
readonly [
|
|
30
|
+
export type ModelChanges<TRow, A> = (row: TRow, operation: RowOperation) => Iterable<A>;
|
|
31
|
+
export type ChangeMap<TClient, A> = {
|
|
32
|
+
readonly [TModel in ModelName<TClient>]: ModelChanges<ModelRow<TClient, TModel>, A> | null;
|
|
33
33
|
};
|
|
34
34
|
export declare const rowOperations: ReadonlySet<string>;
|
|
35
35
|
export declare const countOperations: ReadonlySet<string>;
|
package/dist/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,GAAG,eAAe,GAAG,gBAAgB,GAAG,cAAc,CAAC;IAClG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,iBAAiB,GAAG,eAAe,GAAG,gBAAgB,GAAG,cAAc,CAAC;IAClG,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa,CAAC,GAAG;IACjC,YAAY,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,kBAAkB,KAAK,WAAW,CAAC,EAAE,CAAC,CAAC;CACnG;AAED,KAAK,SAAS,CAAC,SAAS,IAAI,SAAS,SAAS;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG;QAAE,QAAQ,CAAC,KAAK,EAAE;YAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,QAAQ,CAAA;SAAE,CAAA;KAAE,CAAA;CAAE,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEtJ,KAAK,SAAS,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,OAAO,GAAG,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC,CAAC;AAExE,MAAM,MAAM,SAAS,CAAC,OAAO,IAAI;KAC/B,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,MAAM,CAAA;KAAE,GAAG,KAAK,GAAG,KAAK;CAC5H,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;AAEtB,MAAM,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS,MAAM,IAAI,OAAO,CAC7D;KACE,IAAI,IAAI,SAAS,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;KAAE,GAAG,IAAI,GAAG,KAAK;CACrI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EACrB,MAAM,CACN,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,qBAAqB,GAAG,qBAAqB,CAAC;AAErH,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,YAAY,GAAG,YAAY,CAAC;AAExE,MAAM,MAAM,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC;AAExF,MAAM,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI;IACnC,QAAQ,EAAE,MAAM,IAAI,SAAS,CAAC,OAAO,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI;CAC1F,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,CAO5C,CAAC;AAEH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAAuE,CAAC;AAExH,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,MAA6D,CAAC"}
|
package/dist/recording.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LooseMap, Write } from "./write.ts";
|
|
2
2
|
export declare const isWriteOperation: (operation: string) => boolean;
|
|
3
3
|
export declare const delegatesOf: <A>(models: LooseMap<A>) => ReadonlyMap<string, string>;
|
|
4
|
-
export declare const recordingClient: <
|
|
4
|
+
export declare const recordingClient: <TClient extends object>(client: TClient, delegates: ReadonlyMap<string, string>, collect: (write: Write) => void) => TClient;
|
|
5
5
|
//# sourceMappingURL=recording.d.ts.map
|
package/dist/recording.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recording.d.ts","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,gBAAgB,
|
|
1
|
+
{"version":3,"file":"recording.d.ts","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAElD,eAAO,MAAM,gBAAgB,cAAe,MAAM,KAAG,OAAyE,CAAC;AAE/H,eAAO,MAAM,WAAW,GAAI,CAAC,UAAU,QAAQ,CAAC,CAAC,CAAC,KAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAK7E,CAAC;AAsBH,eAAO,MAAM,eAAe,GAAI,OAAO,SAAS,MAAM,UAC7C,OAAO,aACJ,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,WAC7B,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,KAC7B,OAUA,CAAC"}
|
package/dist/recording.js
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { countOperations, delegateOf, rowOperations } from "./model.js";
|
|
2
2
|
export const isWriteOperation = (operation) => rowOperations.has(operation) || countOperations.has(operation);
|
|
3
3
|
export const delegatesOf = (models) => new Map(Object.entries(models).flatMap(([model, changesOf]) => changesOf === undefined || changesOf === null ? [] : [[delegateOf(model), model]]));
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
function bound(value, target) {
|
|
5
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
6
|
+
}
|
|
7
|
+
function recordingDelegate(delegate, model, collect) {
|
|
8
|
+
return new Proxy(delegate, {
|
|
9
|
+
get: (target, key) => {
|
|
10
|
+
const value = Reflect.get(target, key);
|
|
11
|
+
if (typeof key !== "string" || typeof value !== "function" || !isWriteOperation(key)) {
|
|
12
|
+
return bound(value, target);
|
|
13
|
+
}
|
|
14
|
+
return (...args) => Promise.resolve(Reflect.apply(value, target, args)).then((result) => {
|
|
15
|
+
collect({ model, operation: key, result });
|
|
16
|
+
return result;
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
17
21
|
export const recordingClient = (client, delegates, collect) => new Proxy(client, {
|
|
18
22
|
get: (target, key) => {
|
|
19
23
|
const value = Reflect.get(target, key);
|
package/dist/recording.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recording.js","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAW,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAE/H,MAAM,CAAC,MAAM,WAAW,GAAG,CAAI,MAAmB,EAA+B,EAAE,CAClF,IAAI,GAAG,CACN,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,CACrD,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,CAAU,CAAC,CAC1F,CACD,CAAC;AAEH,
|
|
1
|
+
{"version":3,"file":"recording.js","sourceRoot":"","sources":["../src/recording.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAW,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAE/H,MAAM,CAAC,MAAM,WAAW,GAAG,CAAI,MAAmB,EAA+B,EAAE,CAClF,IAAI,GAAG,CACN,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,CACrD,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,KAAK,CAAU,CAAC,CAC1F,CACD,CAAC;AAEH,SAAS,KAAK,CAAC,KAAc,EAAE,MAAc;IAC5C,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACjE,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAgB,EAAE,KAAa,EAAE,OAA+B;IAC1F,OAAO,IAAI,KAAK,CAAC,QAAQ,EAAE;QAC1B,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;YACpB,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,UAAU,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtF,OAAO,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO,CAAC,GAAG,IAAwB,EAAE,EAAE,CACtC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAe,EAAE,EAAE;gBAC5E,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC3C,OAAO,MAAM,CAAC;YACf,CAAC,CAAC,CAAC;QACL,CAAC;KACD,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,MAAe,EACf,SAAsC,EACtC,OAA+B,EACrB,EAAE,CACZ,IAAI,KAAK,CAAC,MAAM,EAAE;IACjB,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;QACpB,MAAM,KAAK,GAAY,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACvE,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACxE,OAAO,iBAAiB,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAC7B,CAAC;CACD,CAAC,CAAC"}
|
package/dist/tables.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC,eAAO,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC,eAAO,MAAM,QAAQ,WAAY,MAAM,KAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAC4E,CAAC;AAEjJ,MAAM,WAAW,cAAc;IAC9B,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC,OAAO,CAAC,CAAC;CACzD;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAStD,eAAO,MAAM,WAAW,oFAQtB,CAAC;AAEH,eAAO,MAAM,aAAa,0GAGxB,CAAC"}
|
package/dist/tables.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,KAAK,GAAG,uDAAuD,CAAC;AACtE,MAAM,MAAM,GAAG,sCAAsC,CAAC;AACtD,MAAM,OAAO,GAAG,YAAY,CAAC;AAE7B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAA+B,EAAE,CACvE,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;AAQjJ,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAE/F,MAAM,OAAO,GACZ,wJAAwJ,CAAC;AAE1J,MAAM,IAAI,GAAgB,IAAI,GAAG,EAAE,CAAC;AAEpC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAsB;IAClG,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpI,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACzH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAA4B,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"tables.js","sourceRoot":"","sources":["../src/tables.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,KAAK,GAAG,uDAAuD,CAAC;AACtE,MAAM,MAAM,GAAG,sCAAsC,CAAC;AACtD,MAAM,OAAO,GAAG,YAAY,CAAC;AAE7B,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAA+B,EAAE,CACvE,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;AAQjJ,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;AAE/F,MAAM,OAAO,GACZ,wJAAwJ,CAAC;AAE1J,MAAM,IAAI,GAAgB,IAAI,GAAG,EAAE,CAAC;AAEpC,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,EAAE,CAAC,2BAA2B,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAsB;IAClG,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpI,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACzH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,MAA4B,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,EAAE,CAAC,6BAA6B,CAAC,CAAC,QAAQ,CAAC,EAAE,MAAsB,EAAE,KAAK,GAAgB,IAAI;IACjI,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACrG,CAAC,CAAC,CAAC"}
|
package/dist/transaction.d.ts
CHANGED
|
@@ -3,13 +3,13 @@ import type { Frame } from "@shivaedev/effect-changes/frame.ts";
|
|
|
3
3
|
import { PrismaError, TransactionExpired } from "./error.ts";
|
|
4
4
|
import { type Expire } from "./expiry.ts";
|
|
5
5
|
import type { Transactional, TransactionOptions } from "./model.ts";
|
|
6
|
-
export declare const runTransaction: <
|
|
7
|
-
readonly client:
|
|
8
|
-
readonly open: Effect.Effect<Frame, never,
|
|
9
|
-
readonly body: (tx:
|
|
6
|
+
export declare const runTransaction: <TTx extends Transactional<TTx>, TX, E, R, TOpenRequirements>(options: {
|
|
7
|
+
readonly client: TTx;
|
|
8
|
+
readonly open: Effect.Effect<Frame, never, TOpenRequirements>;
|
|
9
|
+
readonly body: (tx: TTx) => Effect.Effect<TX, E, R>;
|
|
10
10
|
readonly transaction: TransactionOptions | undefined;
|
|
11
11
|
readonly savepoint: boolean;
|
|
12
12
|
readonly deadline: number | undefined;
|
|
13
13
|
readonly Expiry: Context.Reference<Expire>;
|
|
14
|
-
}) => Effect.Effect<
|
|
14
|
+
}) => Effect.Effect<TX, E | TransactionExpired | PrismaError, R | TOpenRequirements>;
|
|
15
15
|
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,EAAQ,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAiC,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA6CpE,eAAO,MAAM,cAAc,GAAI,
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,EAAQ,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oCAAoC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,KAAK,MAAM,EAAiC,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA6CpE,eAAO,MAAM,cAAc,GAAI,GAAG,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,iBAAiB,WAAW;IACpG,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;IAC9D,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,WAAW,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;CAC3C,KAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,GAAG,WAAW,EAAE,CAAC,GAAG,iBAAiB,CA+B/E,CAAC"}
|
package/dist/transaction.js
CHANGED
|
@@ -3,10 +3,10 @@ import { PrismaError, TransactionExpired } from "./error.js";
|
|
|
3
3
|
import { expiring, isTransactionClosed } from "./expiry.js";
|
|
4
4
|
class BodyFailed {
|
|
5
5
|
}
|
|
6
|
-
|
|
6
|
+
function commit(client, options, savepoint, body, context, signal) {
|
|
7
7
|
let started = false;
|
|
8
8
|
let failed;
|
|
9
|
-
|
|
9
|
+
async function run(tx) {
|
|
10
10
|
started = true;
|
|
11
11
|
const exit = await Effect.runPromiseExitWith(context)(body(tx), { signal });
|
|
12
12
|
if (Exit.isSuccess(exit)) {
|
|
@@ -14,8 +14,8 @@ const commit = (client, options, savepoint, body, context, signal) => {
|
|
|
14
14
|
}
|
|
15
15
|
failed = exit;
|
|
16
16
|
throw new BodyFailed();
|
|
17
|
-
}
|
|
18
|
-
|
|
17
|
+
}
|
|
18
|
+
function rejected(cause) {
|
|
19
19
|
if (failed !== undefined) {
|
|
20
20
|
return { committed: false, exit: failed };
|
|
21
21
|
}
|
|
@@ -24,18 +24,22 @@ const commit = (client, options, savepoint, body, context, signal) => {
|
|
|
24
24
|
}
|
|
25
25
|
const closed = new TransactionExpired({ cause, message: "The transaction was closed before it could finish" });
|
|
26
26
|
return { closed, committed: false, exit: Exit.fail(closed) };
|
|
27
|
-
}
|
|
27
|
+
}
|
|
28
28
|
return Promise.resolve(client.$transaction(run, options)).then((value) => ({ committed: true, exit: Exit.succeed(value) }), rejected);
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
30
|
export const runTransaction = (options) => Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
|
|
31
31
|
const { client, savepoint, body, deadline, Expiry } = options;
|
|
32
32
|
const frame = yield* options.open;
|
|
33
33
|
const context = yield* Effect.context();
|
|
34
34
|
const abort = new AbortController();
|
|
35
|
-
|
|
35
|
+
function guarded(tx) {
|
|
36
|
+
return expiring(frame.provide(body(tx)), deadline, Expiry);
|
|
37
|
+
}
|
|
36
38
|
const outcome = commit(client, options.transaction, savepoint, guarded, context, abort.signal);
|
|
37
39
|
const expire = yield* Expiry;
|
|
38
|
-
|
|
40
|
+
function settle(settled) {
|
|
41
|
+
return Effect.andThen(settled.closed === undefined ? Effect.void : expire(settled.closed.cause), Effect.as(frame.settle(settled.committed ? "committed" : "rolledBack"), settled.exit));
|
|
42
|
+
}
|
|
39
43
|
const settled = yield* restore(Effect.promise(() => outcome)).pipe(Effect.onInterrupt(() => Effect.andThen(Effect.sync(() => abort.abort()), Effect.flatMap(Effect.promise(() => outcome), settle))));
|
|
40
44
|
return yield* Effect.flatten(settle(settled));
|
|
41
45
|
}));
|
package/dist/transaction.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEpD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAe,QAAQ,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AASzE,MAAM,UAAU;CAAG;AAEnB,
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../src/transaction.ts"],"names":[],"mappings":"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"}
|
package/dist/write.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAmB,KAAK,YAAY,EAAiB,MAAM,YAAY,CAAC;AAE/E,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,GACrB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACpF;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/G,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;AAEvF,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;CAC3C;
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAmB,KAAK,YAAY,EAAiB,MAAM,YAAY,CAAC;AAE/E,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,MAAM,YAAY,GACrB;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACpF;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/G,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/F,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;AAEvF,MAAM,WAAW,WAAW,CAAC,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;CAC3C;AA+BD,eAAO,MAAM,SAAS,GAAI,CAAC,UAAU,QAAQ,CAAC,CAAC,CAAC,SAAS,KAAK,KAAG,WAAW,CAAC,CAAC,CAwB7E,CAAC"}
|
package/dist/write.js
CHANGED
|
@@ -5,16 +5,22 @@ class MissingField {
|
|
|
5
5
|
this.field = field;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
function guarded(row) {
|
|
9
|
+
return new Proxy(row, {
|
|
10
|
+
get: (target, key, receiver) => {
|
|
11
|
+
if (typeof key === "string" && !(key in target)) {
|
|
12
|
+
throw new MissingField(key);
|
|
13
|
+
}
|
|
14
|
+
return Reflect.get(target, key, receiver);
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function isRowOperation(operation) {
|
|
19
|
+
return rowOperations.has(operation);
|
|
20
|
+
}
|
|
21
|
+
function rowsOf(result) {
|
|
22
|
+
return (Array.isArray(result) ? result : [result]).filter((row) => typeof row === "object" && row !== null);
|
|
23
|
+
}
|
|
18
24
|
const nothing = { changes: [], unnamed: undefined };
|
|
19
25
|
export const interpret = (models, write) => {
|
|
20
26
|
const { model, operation } = write;
|
package/dist/write.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAqB,aAAa,EAAE,MAAM,YAAY,CAAC;AAqB/E,MAAM,YAAY;IACR,KAAK,CAAS;IAEvB,YAAY,KAAa;QACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;CACD;AAED,
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../src/write.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAqB,aAAa,EAAE,MAAM,YAAY,CAAC;AAqB/E,MAAM,YAAY;IACR,KAAK,CAAS;IAEvB,YAAY,KAAa;QACxB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;CACD;AAED,SAAS,OAAO,CAAC,GAAW;IAC3B,OAAO,IAAI,KAAK,CAAC,GAAG,EAAE;QACrB,GAAG,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE;YAC9B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC;gBACjD,MAAM,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC;YAC7B,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC3C,CAAC;KACD,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB;IACxC,OAAO,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,MAAM,CAAC,MAAe;IAC9B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiB,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC;AAC5H,CAAC;AAED,MAAM,OAAO,GAAuB,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAExE,MAAM,CAAC,MAAM,SAAS,GAAG,CAAI,MAAmB,EAAE,KAAY,EAAkB,EAAE;IACjF,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACnC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACnD,OAAO,OAAO,CAAC;IAChB,CAAC;IACD,IAAI,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACpC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,OAAO,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,GAAQ,EAAE,CAAC;IACxB,IAAI,CAAC;QACJ,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;QACrD,CAAC;IACF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,IAAI,KAAK,YAAY,YAAY,EAAE,CAAC;YACnC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,CAAC;QAC/F,CAAC;QACD,MAAM,KAAK,CAAC;IACb,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACxC,CAAC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# North star
|
|
2
|
+
|
|
3
|
+
## The problem
|
|
4
|
+
|
|
5
|
+
A successful Prisma query says that its statement ran. A successful transaction body still does not say that COMMIT succeeded. A deferred constraint can reject the commit, a caller can be interrupted, or Prisma can expire the transaction while the Effect body has more work to do. If an application announces changes from its write methods or from the body's success, it can announce rows that rolled back, miss a commit that landed during interruption, or continue side effects after the database transaction closed.
|
|
6
|
+
|
|
7
|
+
The other half of the problem is knowing which writes need an announcement. An application often names changes by an owner, member or domain rather than a table. That meaning belongs to the application. Returned model rows can provide it; a count alone cannot. A test also needs evidence that its writes passed through this path, including SQL that bypasses ordinary model delegates.
|
|
8
|
+
|
|
9
|
+
## The ideal
|
|
10
|
+
|
|
11
|
+
An application on Prisma Classic and PostgreSQL has one path for commit-bound changes. It defines its change values and model mappings once, runs Prisma calls through `use`, and wraps an action in `transaction`. The adapter supplies the scoped client and translates the real driver's outcome into the shared effect-changes frame lifecycle. An application with an existing Effect wrapper can feed observed results through `recordWrite` without adopting another query wrapper.
|
|
12
|
+
|
|
13
|
+
A mapping classifies a model deliberately: a row names changes, or `null` says its writes need none. A count-only write or a returned row missing a field the mapping needs must be visible to a test rather than quietly producing an invented subject. A PostgreSQL test compares its written tables with `Recorded` observations and its own definition of which change covers a model.
|
|
14
|
+
|
|
15
|
+
## What good looks like
|
|
16
|
+
|
|
17
|
+
- COMMIT determines publication. Savepoint release determines merging into an enclosing frame; rollback determines discard.
|
|
18
|
+
- Interruption during a body stops that body and rolls back. Interruption during an in-flight COMMIT still waits for the database outcome, so a landed commit can publish.
|
|
19
|
+
- A started transaction expiring is distinct from one unable to start. Typed application failures remain available to callers.
|
|
20
|
+
- An expired body stops before later side effects. Wall-clock deadlines follow the current Prisma client's timeout rather than the test clock.
|
|
21
|
+
- Model meanings remain explicit and typed. An exhaustive map makes an added model require a classification.
|
|
22
|
+
- Tests take a baseline on their own transaction before checking table counters, so a reused connection does not give credit or blame for another transaction's writes.
|
|
23
|
+
|
|
24
|
+
## Trade-offs
|
|
25
|
+
|
|
26
|
+
When goals conflict, database outcome and interruption correctness win first, then reuse of the shared channel, then explicit application-owned meaning, then proof at the PostgreSQL boundary, then convenience.
|
|
27
|
+
|
|
28
|
+
**Commit correctness costs waiting.** A Prisma promise already in flight cannot be treated as rolled back just because the Effect caller stops waiting. The adapter must settle from the driver's result, including after interruption. A more convenient cancellation API cannot invent a different database outcome.
|
|
29
|
+
|
|
30
|
+
**Returned rows limit automatic naming.** The mapping uses the row a write returns. Count-only operations and missing fields need an explicit choice by the application; automatically fetching rows would add queries and its own consistency problem. Keep unsupported shapes visible before adding convenience.
|
|
31
|
+
|
|
32
|
+
**Coverage is deliberately coarse.** The coverage predicate connects a written table's model to recorded changes. One covering change satisfies that table check. This is a useful guard against a missed path, but subject-level correctness belongs in the application's tests.
|
|
33
|
+
|
|
34
|
+
**Prisma adaptation stays narrow.** The shared channel owns buffering, observation and publication policy. This package owns the Promise transaction boundary, the current client, returned-write interpretation and PostgreSQL table-counter helpers. Keep those responsibilities separate so improvements to a channel reach both Prisma and native SQL callers.
|
|
35
|
+
|
|
36
|
+
## What it leaves out
|
|
37
|
+
|
|
38
|
+
- A replacement Prisma client, repository layer or migration runner. effect-prisma owns the separate Prisma Next database facade, and effect-sql owns native Effect persistence and migrations.
|
|
39
|
+
- The shape of an application's change values, the meaning of their keys, or which subjects a write should name.
|
|
40
|
+
- A selected subscription transport, durable delivery policy or deployment topology. The application chooses those around its publication sink.
|
|
41
|
+
- Proof that every affected row or subject is announced. The coverage helper checks tables and unnamed writes; application behavior tests check the meaning of the announcements.
|
|
42
|
+
|
|
43
|
+
The [roadmap](roadmap.md) holds the unresolved support and API questions. The [framework roadmap](https://github.com/ShivaeDev/platform/blob/main/docs/framework/roadmap.md) owns adoption and delivery decisions that span packages.
|
package/docs/roadmap.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
## Built
|
|
4
|
+
|
|
5
|
+
- [x] A Prisma Classic/PostgreSQL binding over effect-changes, with typed model mappings, a scoped `Client`, `use` and an explicit `recordWrite` seam.
|
|
6
|
+
- [x] Publication after a successful COMMIT, discard after rollback or failed commit, nested savepoint merge and discard, and publication when COMMIT lands after caller interruption.
|
|
7
|
+
- [x] `TransactionExpired` and body interruption at an explicit or configured wall-clock timeout, including linked nested bodies and queries that find a transaction closed. A transaction unable to start remains a `PrismaError`.
|
|
8
|
+
- [x] Row-based recording, keyed deduplication, autocommit publication, explicit batches, and unnamed-write reporting for count-only writes and returned rows missing a mapping field.
|
|
9
|
+
- [x] Table/model extraction from schema text, PostgreSQL transaction-counter baselines, and a table-level coverage check over recorded observations and unnamed writes.
|
|
10
|
+
- [x] Pure, type and real PostgreSQL tests, plus a packed-consumer fixture for published module imports and basic execution. PostgreSQL tests skip without `PLATFORM_EFFECT_CHANGES_PRISMA_TEST_DATABASE_URL`.
|
|
11
|
+
|
|
12
|
+
## Next
|
|
13
|
+
|
|
14
|
+
No package implementation milestone has been selected. The next extension should come from a demonstrated Prisma consumer and a decision about the open questions below. Cross-package adoption, composed application validation and deployment delivery policy belong in the [framework roadmap](https://github.com/ShivaeDev/platform/blob/main/docs/framework/roadmap.md).
|
|
15
|
+
|
|
16
|
+
## Open questions
|
|
17
|
+
|
|
18
|
+
- How much independent support should this Prisma path receive as the framework's native persistence path develops? It serves Prisma applications; there is no decision here to replace it or retire it.
|
|
19
|
+
- Should recording stay at returned top-level model writes, with explicit `recordWrite` and coverage for other paths, or should the adapter observe more ORM behavior? Nested relation writes, cascades and trigger writes need dedicated tests before their coverage behavior is documented.
|
|
20
|
+
- Is table-level coverage the intended acceptance bar, or does a consumer need a check that proves every affected subject has a change?
|
|
21
|
+
- Should `recording.ts`, `expiry.ts`, `transaction.ts` and the interpretation helpers remain supported extension points? The module export pattern exposes them, while the primary usage path goes through `changes.ts`, `model.ts`, `write.ts`, `coverage.ts`, `tables.ts` and `error.ts`.
|
|
22
|
+
- Which PostgreSQL coverage edges need a supported contract: writes followed by TRUNCATE, or identical table names in several schemas? Dedicated tests are needed before either behavior can be promised.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shivaedev/effect-changes-prisma",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Commit-bound change channels for Prisma Classic on PostgreSQL only: automatic change recording, publish after $transaction commits, and a test-time coverage check",
|
|
5
5
|
"homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/effect-changes-prisma#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"sideEffects": false,
|
|
16
16
|
"type": "module",
|
|
17
17
|
"imports": {
|
|
18
|
-
"#test/*": "./test/*",
|
|
18
|
+
"#test/*": "./src/test-support/*",
|
|
19
19
|
"#*.ts": {
|
|
20
20
|
"source": "./src/*.ts",
|
|
21
21
|
"types": "./dist/*.d.ts",
|
|
@@ -34,27 +34,31 @@
|
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
36
|
"src",
|
|
37
|
+
"!src/**/*.test.ts",
|
|
38
|
+
"!src/**/*.spec.ts",
|
|
39
|
+
"!src/**/test-support",
|
|
40
|
+
"docs",
|
|
37
41
|
"CHANGELOG.md",
|
|
38
42
|
"README.md"
|
|
39
43
|
],
|
|
40
44
|
"dependencies": {
|
|
41
|
-
"@shivaedev/effect-changes": "0.
|
|
45
|
+
"@shivaedev/effect-changes": "0.3.0",
|
|
42
46
|
"@shivaedev/types": "0.2.0"
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"@prisma/adapter-pg": "7.10.0",
|
|
46
50
|
"@prisma/client": "7.10.0",
|
|
47
|
-
"@shivaedev/quality": "0.
|
|
48
|
-
"@types/node": "24.
|
|
51
|
+
"@shivaedev/quality": "0.20.0",
|
|
52
|
+
"@types/node": "24.19.1",
|
|
49
53
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
50
|
-
"effect": "4.0.
|
|
54
|
+
"effect": "4.0.4",
|
|
51
55
|
"prisma": "7.10.0",
|
|
52
56
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
53
|
-
"vitest": "
|
|
57
|
+
"vitest": "5.0.3"
|
|
54
58
|
},
|
|
55
59
|
"peerDependencies": {
|
|
56
60
|
"@prisma/client": "7.10.0",
|
|
57
|
-
"effect": "4.0.
|
|
61
|
+
"effect": "4.0.4"
|
|
58
62
|
},
|
|
59
63
|
"engines": {
|
|
60
64
|
"node": ">=24"
|
|
@@ -64,10 +68,10 @@
|
|
|
64
68
|
"provenance": true
|
|
65
69
|
},
|
|
66
70
|
"scripts": {
|
|
67
|
-
"build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" &&
|
|
71
|
+
"build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc --project tsconfig.build.json",
|
|
68
72
|
"ready": "pnpm typecheck && pnpm test && pnpm build",
|
|
69
73
|
"test": "pnpm test:prepare && vitest run",
|
|
70
|
-
"test:prepare": "prisma generate --config test/prisma.config.ts --no-hints",
|
|
71
|
-
"typecheck": "prisma generate --config test/prisma.config.ts --no-hints && tsc --noEmit"
|
|
74
|
+
"test:prepare": "prisma generate --config src/test-support/prisma.config.ts --no-hints",
|
|
75
|
+
"typecheck": "prisma generate --config src/test-support/prisma.config.ts --no-hints && tsc --noEmit"
|
|
72
76
|
}
|
|
73
77
|
}
|
package/src/changes.ts
CHANGED
|
@@ -9,37 +9,40 @@ import { interpret, type LooseMap, type UnnamedWrite, type Write } from "./write
|
|
|
9
9
|
|
|
10
10
|
export type UnnamedObserver = (write: UnnamedWrite) => Effect.Effect<void>;
|
|
11
11
|
|
|
12
|
-
export interface PrismaChangesOptions<
|
|
13
|
-
readonly client:
|
|
14
|
-
readonly models: Partial<ChangeMap<
|
|
12
|
+
export interface PrismaChangesOptions<TTx, A, R> extends Omit<ChannelOptions<A, R>, "owner" | "unowned"> {
|
|
13
|
+
readonly client: TTx & Transactional<TTx>;
|
|
14
|
+
readonly models: Partial<ChangeMap<TTx, A>>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export interface PrismaChanges<
|
|
18
|
-
readonly Client: Context.Reference<
|
|
17
|
+
export interface PrismaChanges<TTx, A, R> {
|
|
18
|
+
readonly Client: Context.Reference<TTx>;
|
|
19
19
|
readonly channel: Channel<A, R>;
|
|
20
20
|
readonly recordWrite: (write: Write) => Effect.Effect<void, never, R>;
|
|
21
|
-
readonly transaction: <
|
|
22
|
-
body: Effect.Effect<
|
|
21
|
+
readonly transaction: <TX, E, TR2>(
|
|
22
|
+
body: Effect.Effect<TX, E, TR2>,
|
|
23
23
|
options?: TransactionOptions,
|
|
24
|
-
) => Effect.Effect<
|
|
24
|
+
) => Effect.Effect<TX, E | TransactionExpired | PrismaError, R | TR2>;
|
|
25
25
|
readonly Unnamed: Context.Reference<UnnamedObserver>;
|
|
26
|
-
readonly use: <
|
|
26
|
+
readonly use: <TX>(query: (client: TTx) => PromiseLike<TX>) => Effect.Effect<TX, PrismaError, R>;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const ignoreUnnamed: UnnamedObserver = () => Effect.void;
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
Option.match(Exit.isFailure(exit) ? Cause.findErrorOption(exit.cause) : Option.none(), {
|
|
31
|
+
function expireOnClosed(Expiry: Context.Reference<Expire>, exit: Exit.Exit<unknown, PrismaError>): Effect.Effect<void> {
|
|
32
|
+
return Option.match(Exit.isFailure(exit) ? Cause.findErrorOption(exit.cause) : Option.none(), {
|
|
33
33
|
onNone: () => Effect.void,
|
|
34
34
|
onSome: ({ cause }) => (isTransactionClosed(cause) ? Effect.flatMap(Effect.service(Expiry), (expire) => expire(cause)) : Effect.void),
|
|
35
35
|
});
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
export const makePrismaChanges = <
|
|
38
|
+
export const makePrismaChanges = <TTx extends Transactional<TTx>, A, R = never>(
|
|
39
|
+
options: PrismaChangesOptions<TTx, A, R>,
|
|
40
|
+
): PrismaChanges<TTx, A, R> => {
|
|
38
41
|
const { client, models: typed, ...channelOptions } = options;
|
|
39
42
|
const models: LooseMap<A> = typed;
|
|
40
43
|
const prefix = `@shivaedev/effect-changes-prisma/${options.name}/${crypto.randomUUID()}`;
|
|
41
44
|
const channel = makeChannel<A, R>({ ...channelOptions, owner: Effect.succeed(client) });
|
|
42
|
-
const Client = Context.Reference<
|
|
45
|
+
const Client = Context.Reference<TTx>(`${prefix}/Client`, { defaultValue: () => client });
|
|
43
46
|
const Unnamed = Context.Reference<UnnamedObserver>(`${prefix}/Unnamed`, { defaultValue: () => ignoreUnnamed });
|
|
44
47
|
const Expiry = makeExpiry(`${prefix}/Expiry`);
|
|
45
48
|
const delegates = delegatesOf(models);
|
|
@@ -54,7 +57,7 @@ export const makePrismaChanges = <Tx extends Transactional<Tx>, A, R = never>(op
|
|
|
54
57
|
}
|
|
55
58
|
});
|
|
56
59
|
|
|
57
|
-
const use = Effect.fn("PrismaChanges.use")(function* <
|
|
60
|
+
const use = Effect.fn("PrismaChanges.use")(function* <TX>(query: (client: TTx) => PromiseLike<TX>) {
|
|
58
61
|
const current = yield* Client;
|
|
59
62
|
const writes: Write[] = [];
|
|
60
63
|
const recording = recordingClient(current, delegates, (write) => writes.push(write));
|
|
@@ -64,11 +67,11 @@ export const makePrismaChanges = <Tx extends Transactional<Tx>, A, R = never>(op
|
|
|
64
67
|
return yield* exit;
|
|
65
68
|
}, Effect.uninterruptible);
|
|
66
69
|
|
|
67
|
-
const transaction = <
|
|
70
|
+
const transaction = <TX, E, TR2>(body: Effect.Effect<TX, E, TR2>, transactionOptions?: TransactionOptions) =>
|
|
68
71
|
Effect.flatMap(Effect.service(Client), (current) => {
|
|
69
72
|
const savepoint = isTransactionClient(current);
|
|
70
73
|
const run = runTransaction({
|
|
71
|
-
body: (tx:
|
|
74
|
+
body: (tx: TTx) => Effect.provideService(body, Client, tx),
|
|
72
75
|
client: current,
|
|
73
76
|
deadline: savepoint ? undefined : (transactionOptions?.timeout ?? configuredTimeout(current)),
|
|
74
77
|
Expiry,
|
package/src/coverage.ts
CHANGED
|
@@ -14,11 +14,13 @@ export interface Coverage<A> {
|
|
|
14
14
|
readonly written: Iterable<string>;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
[...observations].flatMap((observation) => (observation._tag === "Recorded" ? observation.changes : []));
|
|
17
|
+
function recordedIn<A>(observations: Iterable<Observation<A>>): readonly A[] {
|
|
18
|
+
return [...observations].flatMap((observation) => (observation._tag === "Recorded" ? observation.changes : []));
|
|
19
|
+
}
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
write.reason === "narrowed" ? `${write.model}.${write.operation}.${write.field}` : `${write.model}.${write.operation}`;
|
|
21
|
+
function identify(write: UnnamedWrite): string {
|
|
22
|
+
return write.reason === "narrowed" ? `${write.model}.${write.operation}.${write.field}` : `${write.model}.${write.operation}`;
|
|
23
|
+
}
|
|
22
24
|
|
|
23
25
|
export const checkCoverage = <A>(coverage: Coverage<A>): readonly CoverageViolation[] => {
|
|
24
26
|
const recorded = recordedIn(coverage.observations);
|
package/src/expiry.ts
CHANGED
|
@@ -22,11 +22,11 @@ export const configuredTimeout = (client: object): number | undefined =>
|
|
|
22
22
|
|
|
23
23
|
const wallClock = Clock.Clock.defaultValue();
|
|
24
24
|
|
|
25
|
-
export const expiring = <
|
|
26
|
-
body: Effect.Effect<
|
|
25
|
+
export const expiring = <TX, E, R>(
|
|
26
|
+
body: Effect.Effect<TX, E, R>,
|
|
27
27
|
timeout: number | undefined,
|
|
28
28
|
Expiry: Context.Reference<Expire>,
|
|
29
|
-
): Effect.Effect<
|
|
29
|
+
): Effect.Effect<TX, E | TransactionExpired, R> =>
|
|
30
30
|
Effect.gen(function* () {
|
|
31
31
|
const outer = yield* Expiry;
|
|
32
32
|
const expired = yield* Deferred.make<never, TransactionExpired>();
|