@shivaedev/effect-changes-prisma 0.4.0 → 0.5.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/src/model.ts CHANGED
@@ -4,22 +4,22 @@ export interface TransactionOptions {
4
4
  readonly timeout?: number;
5
5
  }
6
6
 
7
- export interface Transactional<Tx> {
8
- $transaction: <X>(run: (tx: Tx) => Promise<X>, options?: TransactionOptions) => PromiseLike<X>;
7
+ export interface Transactional<TTx> {
8
+ $transaction: <TX>(run: (tx: TTx) => Promise<TX>, options?: TransactionOptions) => PromiseLike<TX>;
9
9
  }
10
10
 
11
- type PayloadOf<Delegate> = Delegate extends { readonly [key: symbol]: { readonly types: { readonly payload: infer Payload } } } ? Payload : never;
11
+ type PayloadOf<TDelegate> = TDelegate extends { readonly [key: symbol]: { readonly types: { readonly payload: infer TPayload } } } ? TPayload : never;
12
12
 
13
- type Delegates<Client> = Exclude<keyof Client & string, `$${string}`>;
13
+ type Delegates<TClient> = Exclude<keyof TClient & string, `$${string}`>;
14
14
 
15
- export type ModelName<Client> = {
16
- [Key in Delegates<Client>]: PayloadOf<Client[Key]> extends { readonly name: infer Name extends string } ? Name : never;
17
- }[Delegates<Client>];
15
+ export type ModelName<TClient> = {
16
+ [TKey in Delegates<TClient>]: PayloadOf<TClient[TKey]> extends { readonly name: infer TName extends string } ? TName : never;
17
+ }[Delegates<TClient>];
18
18
 
19
- export type ModelRow<Client, Model extends string> = Extract<
19
+ export type ModelRow<TClient, TModel extends string> = Extract<
20
20
  {
21
- [Key in Delegates<Client>]: PayloadOf<Client[Key]> extends { readonly name: Model; readonly scalars: infer Row } ? Row : never;
22
- }[Delegates<Client>],
21
+ [TKey in Delegates<TClient>]: PayloadOf<TClient[TKey]> extends { readonly name: TModel; readonly scalars: infer TRow } ? TRow : never;
22
+ }[Delegates<TClient>],
23
23
  object
24
24
  >;
25
25
 
@@ -27,10 +27,10 @@ export type RowOperation = "create" | "update" | "upsert" | "delete" | "createMa
27
27
 
28
28
  export type CountOperation = "createMany" | "updateMany" | "deleteMany";
29
29
 
30
- export type ModelChanges<Row, A> = (row: Row, operation: RowOperation) => Iterable<A>;
30
+ export type ModelChanges<TRow, A> = (row: TRow, operation: RowOperation) => Iterable<A>;
31
31
 
32
- export type ChangeMap<Client, A> = {
33
- readonly [Model in ModelName<Client>]: ModelChanges<ModelRow<Client, Model>, A> | null;
32
+ export type ChangeMap<TClient, A> = {
33
+ readonly [TModel in ModelName<TClient>]: ModelChanges<ModelRow<TClient, TModel>, A> | null;
34
34
  };
35
35
 
36
36
  export const rowOperations: ReadonlySet<string> = new Set<RowOperation>([
package/src/recording.ts CHANGED
@@ -10,10 +10,12 @@ export const delegatesOf = <A>(models: LooseMap<A>): ReadonlyMap<string, string>
10
10
  ),
11
11
  );
12
12
 
13
- const bound = (value: unknown, target: object): unknown => (typeof value === "function" ? value.bind(target) : value);
13
+ function bound(value: unknown, target: object): unknown {
14
+ return typeof value === "function" ? value.bind(target) : value;
15
+ }
14
16
 
15
- const recordingDelegate = (delegate: object, model: string, collect: (write: Write) => void): object =>
16
- new Proxy(delegate, {
17
+ function recordingDelegate(delegate: object, model: string, collect: (write: Write) => void): object {
18
+ return new Proxy(delegate, {
17
19
  get: (target, key) => {
18
20
  const value: unknown = Reflect.get(target, key);
19
21
  if (typeof key !== "string" || typeof value !== "function" || !isWriteOperation(key)) {
@@ -26,12 +28,13 @@ const recordingDelegate = (delegate: object, model: string, collect: (write: Wri
26
28
  });
27
29
  },
28
30
  });
31
+ }
29
32
 
30
- export const recordingClient = <Client extends object>(
31
- client: Client,
33
+ export const recordingClient = <TClient extends object>(
34
+ client: TClient,
32
35
  delegates: ReadonlyMap<string, string>,
33
36
  collect: (write: Write) => void,
34
- ): Client =>
37
+ ): TClient =>
35
38
  new Proxy(client, {
36
39
  get: (target, key) => {
37
40
  const value: unknown = Reflect.get(target, key);
@@ -4,25 +4,25 @@ import { PrismaError, TransactionExpired } from "./error.ts";
4
4
  import { type Expire, expiring, isTransactionClosed } from "./expiry.ts";
5
5
  import type { Transactional, TransactionOptions } from "./model.ts";
6
6
 
7
- interface Settled<X, E> {
7
+ interface Settled<TX, E> {
8
8
  readonly closed?: TransactionExpired;
9
9
  readonly committed: boolean;
10
- readonly exit: Exit.Exit<X, E | TransactionExpired | PrismaError>;
10
+ readonly exit: Exit.Exit<TX, E | TransactionExpired | PrismaError>;
11
11
  }
12
12
 
13
13
  class BodyFailed {}
14
14
 
15
- const commit = <Tx extends Transactional<Tx>, X, E, R>(
16
- client: Tx,
15
+ function commit<TTx extends Transactional<TTx>, TX, E, R>(
16
+ client: TTx,
17
17
  options: TransactionOptions | undefined,
18
18
  savepoint: boolean,
19
- body: (tx: Tx) => Effect.Effect<X, E, R>,
19
+ body: (tx: TTx) => Effect.Effect<TX, E, R>,
20
20
  context: Context.Context<R>,
21
21
  signal: AbortSignal,
22
- ): Promise<Settled<X, E>> => {
22
+ ): Promise<Settled<TX, E>> {
23
23
  let started = false;
24
- let failed: Exit.Exit<X, E> | undefined;
25
- const run = async (tx: Tx) => {
24
+ let failed: Exit.Exit<TX, E> | undefined;
25
+ async function run(tx: TTx) {
26
26
  started = true;
27
27
  const exit = await Effect.runPromiseExitWith(context)(body(tx), { signal });
28
28
  if (Exit.isSuccess(exit)) {
@@ -30,8 +30,8 @@ const commit = <Tx extends Transactional<Tx>, X, E, R>(
30
30
  }
31
31
  failed = exit;
32
32
  throw new BodyFailed();
33
- };
34
- const rejected = (cause: unknown): Settled<X, E> => {
33
+ }
34
+ function rejected(cause: unknown): Settled<TX, E> {
35
35
  if (failed !== undefined) {
36
36
  return { committed: false, exit: failed };
37
37
  }
@@ -40,36 +40,39 @@ const commit = <Tx extends Transactional<Tx>, X, E, R>(
40
40
  }
41
41
  const closed = new TransactionExpired({ cause, message: "The transaction was closed before it could finish" });
42
42
  return { closed, committed: false, exit: Exit.fail(closed) };
43
- };
43
+ }
44
44
  return Promise.resolve(client.$transaction(run, options)).then(
45
- (value): Settled<X, E> => ({ committed: true, exit: Exit.succeed(value) }),
45
+ (value): Settled<TX, E> => ({ committed: true, exit: Exit.succeed(value) }),
46
46
  rejected,
47
47
  );
48
- };
48
+ }
49
49
 
50
- export const runTransaction = <Tx extends Transactional<Tx>, X, E, R, RO>(options: {
51
- readonly client: Tx;
52
- readonly open: Effect.Effect<Frame, never, RO>;
53
- readonly body: (tx: Tx) => Effect.Effect<X, E, R>;
50
+ export const runTransaction = <TTx extends Transactional<TTx>, TX, E, R, TOpenRequirements>(options: {
51
+ readonly client: TTx;
52
+ readonly open: Effect.Effect<Frame, never, TOpenRequirements>;
53
+ readonly body: (tx: TTx) => Effect.Effect<TX, E, R>;
54
54
  readonly transaction: TransactionOptions | undefined;
55
55
  readonly savepoint: boolean;
56
56
  readonly deadline: number | undefined;
57
57
  readonly Expiry: Context.Reference<Expire>;
58
- }): Effect.Effect<X, E | TransactionExpired | PrismaError, R | RO> =>
58
+ }): Effect.Effect<TX, E | TransactionExpired | PrismaError, R | TOpenRequirements> =>
59
59
  Effect.uninterruptibleMask((restore) =>
60
60
  Effect.gen(function* () {
61
61
  const { client, savepoint, body, deadline, Expiry } = options;
62
62
  const frame = yield* options.open;
63
63
  const context = yield* Effect.context<R>();
64
64
  const abort = new AbortController();
65
- const guarded = (tx: Tx) => expiring(frame.provide(body(tx)), deadline, Expiry);
65
+ function guarded(tx: TTx) {
66
+ return expiring(frame.provide(body(tx)), deadline, Expiry);
67
+ }
66
68
  const outcome = commit(client, options.transaction, savepoint, guarded, context, abort.signal);
67
69
  const expire = yield* Expiry;
68
- const settle = (settled: Settled<X, E | TransactionExpired>) =>
69
- Effect.andThen(
70
+ function settle(settled: Settled<TX, E | TransactionExpired>) {
71
+ return Effect.andThen(
70
72
  settled.closed === undefined ? Effect.void : expire(settled.closed.cause),
71
73
  Effect.as(frame.settle(settled.committed ? "committed" : "rolledBack"), settled.exit),
72
74
  );
75
+ }
73
76
  const settled = yield* restore(Effect.promise(() => outcome)).pipe(
74
77
  Effect.onInterrupt(() =>
75
78
  Effect.andThen(
package/src/write.ts CHANGED
@@ -28,8 +28,8 @@ class MissingField {
28
28
  }
29
29
  }
30
30
 
31
- const guarded = (row: object): object =>
32
- new Proxy(row, {
31
+ function guarded(row: object): object {
32
+ return new Proxy(row, {
33
33
  get: (target, key, receiver) => {
34
34
  if (typeof key === "string" && !(key in target)) {
35
35
  throw new MissingField(key);
@@ -37,11 +37,15 @@ const guarded = (row: object): object =>
37
37
  return Reflect.get(target, key, receiver);
38
38
  },
39
39
  });
40
+ }
40
41
 
41
- const isRowOperation = (operation: string): operation is RowOperation => rowOperations.has(operation);
42
+ function isRowOperation(operation: string): operation is RowOperation {
43
+ return rowOperations.has(operation);
44
+ }
42
45
 
43
- const rowsOf = (result: unknown): readonly object[] =>
44
- (Array.isArray(result) ? result : [result]).filter((row): row is object => typeof row === "object" && row !== null);
46
+ function rowsOf(result: unknown): readonly object[] {
47
+ return (Array.isArray(result) ? result : [result]).filter((row): row is object => typeof row === "object" && row !== null);
48
+ }
45
49
 
46
50
  const nothing: Interpreted<never> = { changes: [], unnamed: undefined };
47
51