@shivaedev/effect-prisma 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +198 -155
  3. package/dist/database.d.ts +7 -7
  4. package/dist/database.d.ts.map +1 -1
  5. package/dist/database.js +12 -8
  6. package/dist/database.js.map +1 -1
  7. package/dist/databaseTypes.d.ts +33 -0
  8. package/dist/databaseTypes.d.ts.map +1 -0
  9. package/dist/{internal/database-types.js → databaseTypes.js} +1 -1
  10. package/dist/databaseTypes.js.map +1 -0
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/internal/adapters/transaction-settlement.d.ts.map +1 -1
  13. package/dist/internal/adapters/transaction-settlement.js +9 -7
  14. package/dist/internal/adapters/transaction-settlement.js.map +1 -1
  15. package/dist/internal/client-lifecycle.d.ts.map +1 -1
  16. package/dist/internal/contract-normalization.d.ts.map +1 -1
  17. package/dist/internal/database-facade.d.ts +12 -12
  18. package/dist/internal/database-facade.d.ts.map +1 -1
  19. package/dist/internal/database-facade.js.map +1 -1
  20. package/dist/internal/database-factory.d.ts +2 -2
  21. package/dist/internal/database-factory.d.ts.map +1 -1
  22. package/dist/internal/database-factory.js +3 -3
  23. package/dist/internal/database-factory.js.map +1 -1
  24. package/dist/internal/dynamic.d.ts.map +1 -1
  25. package/dist/internal/dynamic.js +3 -1
  26. package/dist/internal/dynamic.js.map +1 -1
  27. package/dist/internal/executor.d.ts +6 -6
  28. package/dist/internal/executor.d.ts.map +1 -1
  29. package/dist/internal/promise.d.ts.map +1 -1
  30. package/dist/internal/query-execution.d.ts.map +1 -1
  31. package/dist/internal/recipe.d.ts.map +1 -1
  32. package/dist/internal/recipe.js +10 -10
  33. package/dist/internal/recipe.js.map +1 -1
  34. package/dist/internal/relation-plan.d.ts.map +1 -1
  35. package/dist/internal/relation-result.d.ts.map +1 -1
  36. package/dist/internal/relation-result.js +6 -2
  37. package/dist/internal/relation-result.js.map +1 -1
  38. package/dist/internal/relation-runtime.d.ts +1 -1
  39. package/dist/internal/relation-runtime.d.ts.map +1 -1
  40. package/dist/internal/relation-runtime.js +11 -6
  41. package/dist/internal/relation-runtime.js.map +1 -1
  42. package/dist/internal/relation-stream.d.ts +1 -1
  43. package/dist/internal/relation-stream.d.ts.map +1 -1
  44. package/dist/internal/relation-stream.js +9 -7
  45. package/dist/internal/relation-stream.js.map +1 -1
  46. package/dist/internal/sqlite-datetime.d.ts.map +1 -1
  47. package/dist/internal/sqlite-datetime.js +11 -9
  48. package/dist/internal/sqlite-datetime.js.map +1 -1
  49. package/dist/internal/sqlite-pragmas.d.ts.map +1 -1
  50. package/dist/internal/testing.d.ts +5 -5
  51. package/dist/internal/testing.d.ts.map +1 -1
  52. package/dist/internal/testing.js.map +1 -1
  53. package/dist/internal/transaction.d.ts +6 -6
  54. package/dist/internal/transaction.d.ts.map +1 -1
  55. package/dist/internal/transaction.js +5 -3
  56. package/dist/internal/transaction.js.map +1 -1
  57. package/dist/relation/include.d.ts +20 -20
  58. package/dist/relation/include.d.ts.map +1 -1
  59. package/dist/relation.d.ts +23 -23
  60. package/dist/relation.d.ts.map +1 -1
  61. package/dist/sqlite.d.ts +1 -1
  62. package/dist/sqlite.d.ts.map +1 -1
  63. package/dist/sqlite.js +8 -6
  64. package/dist/sqlite.js.map +1 -1
  65. package/dist/testing/transaction.d.ts +1 -1
  66. package/dist/testing/transaction.d.ts.map +1 -1
  67. package/dist/testing/transaction.js.map +1 -1
  68. package/dist/testing/types.d.ts +2 -3
  69. package/dist/testing/types.d.ts.map +1 -1
  70. package/dist/testing/vitest.d.ts +2 -1
  71. package/dist/testing/vitest.d.ts.map +1 -1
  72. package/dist/testing/vitest.js +1 -1
  73. package/dist/testing/vitest.js.map +1 -1
  74. package/docs/north-star.md +47 -0
  75. package/docs/roadmap.md +32 -0
  76. package/package.json +33 -40
  77. package/src/database.ts +30 -30
  78. package/src/databaseTypes.ts +65 -0
  79. package/src/internal/adapters/transaction-settlement.ts +9 -8
  80. package/src/internal/database-facade.ts +28 -28
  81. package/src/internal/database-factory.ts +15 -15
  82. package/src/internal/dynamic.ts +3 -1
  83. package/src/internal/executor.ts +6 -6
  84. package/src/internal/recipe.ts +10 -10
  85. package/src/internal/relation-result.ts +6 -3
  86. package/src/internal/relation-runtime.ts +25 -20
  87. package/src/internal/relation-stream.ts +5 -4
  88. package/src/internal/sqlite-datetime.ts +11 -9
  89. package/src/internal/testing.ts +8 -8
  90. package/src/internal/transaction.ts +16 -15
  91. package/src/relation/include.ts +48 -48
  92. package/src/relation.ts +38 -38
  93. package/src/sqlite.ts +9 -7
  94. package/src/testing/transaction.ts +1 -1
  95. package/src/testing/types.ts +2 -3
  96. package/src/testing/vitest.ts +4 -2
  97. package/dist/index.d.ts +0 -5
  98. package/dist/index.d.ts.map +0 -1
  99. package/dist/index.js +0 -4
  100. package/dist/index.js.map +0 -1
  101. package/dist/internal/database-types.d.ts +0 -33
  102. package/dist/internal/database-types.d.ts.map +0 -1
  103. package/dist/internal/database-types.js.map +0 -1
  104. package/dist/testing.d.ts +0 -4
  105. package/dist/testing.d.ts.map +0 -1
  106. package/dist/testing.js +0 -3
  107. package/dist/testing.js.map +0 -1
  108. package/src/index.ts +0 -17
  109. package/src/internal/database-types.ts +0 -65
  110. package/src/testing.ts +0 -10
@@ -3,10 +3,13 @@ import type { PrismaError } from "#error.ts";
3
3
  import { hasMethod, invokeMethod, isPromiseLike } from "./dynamic.ts";
4
4
  import { fromPrismaPromise } from "./promise.ts";
5
5
 
6
- const settle = (value: unknown, map: (result: unknown) => unknown): Effect.Effect<unknown, PrismaError> =>
7
- isPromiseLike(value) ? fromPrismaPromise(() => value).pipe(Effect.map(map)) : Effect.succeed(map(value));
6
+ function settle(value: unknown, map: (result: unknown) => unknown): Effect.Effect<unknown, PrismaError> {
7
+ return isPromiseLike(value) ? fromPrismaPromise(() => value).pipe(Effect.map(map)) : Effect.succeed(map(value));
8
+ }
8
9
 
9
- const countOf = (result: unknown): unknown => (typeof result === "object" && result !== null ? Reflect.get(result, "count") : undefined);
10
+ function countOf(result: unknown): unknown {
11
+ return typeof result === "object" && result !== null ? Reflect.get(result, "count") : undefined;
12
+ }
10
13
 
11
14
  export const evaluateResult = (value: unknown, terminal: PropertyKey | undefined): Effect.Effect<unknown, PrismaError> => {
12
15
  if (terminal === "count" && hasMethod(value, "aggregate")) {
@@ -1,6 +1,7 @@
1
1
  import { Effect, Effectable, type Stream } from "effect";
2
2
  import type { PrismaError } from "#error.ts";
3
3
  import type { Relation } from "#relation.ts";
4
+ import { hasMethod } from "./dynamic.ts";
4
5
  import type { AnyPostgresContract, DatabaseExecutor } from "./executor.ts";
5
6
  import { executeQuery } from "./query-execution.ts";
6
7
  import { appendOperation, type RelationRecipe, replayRecipe, rootRecipe } from "./recipe.ts";
@@ -8,10 +9,10 @@ import { setRelationPlan } from "./relation-plan.ts";
8
9
  import { evaluateResult } from "./relation-result.ts";
9
10
  import { makeRelationStream } from "./relation-stream.ts";
10
11
 
11
- interface RelationRuntime<Models extends object, Contract extends AnyPostgresContract> {
12
- readonly executor: DatabaseExecutor<Models, Contract>;
12
+ interface RelationRuntime<TModels extends object, TContract extends AnyPostgresContract> {
13
+ readonly executor: DatabaseExecutor<TModels, TContract>;
13
14
  readonly recipe: RelationRecipe;
14
- readonly resolveExecutor: Effect.Effect<DatabaseExecutor<Models, Contract>, PrismaError>;
15
+ readonly resolveExecutor: Effect.Effect<DatabaseExecutor<TModels, TContract>, PrismaError>;
15
16
  readonly terminal?: PropertyKey;
16
17
  }
17
18
 
@@ -23,15 +24,15 @@ type AnyRelationRuntime = RelationRuntime<object, AnyPostgresContract>;
23
24
 
24
25
  const runtimes = new WeakMap<object, AnyRelationRuntime>();
25
26
 
26
- const runtimeOf = (self: object): AnyRelationRuntime => {
27
+ function runtimeOf(self: object): AnyRelationRuntime {
27
28
  const runtime = runtimes.get(self);
28
29
  if (runtime === undefined) {
29
30
  throw new TypeError("Relation runtime is unavailable");
30
31
  }
31
32
  return runtime;
32
- };
33
+ }
33
34
 
34
- const relationEffect = (self: object): Effect.Effect<unknown, PrismaError> => {
35
+ function relationEffect(self: object): Effect.Effect<unknown, PrismaError> {
35
36
  const runtime = runtimeOf(self);
36
37
  return Effect.flatMap(runtime.resolveExecutor, (executor) =>
37
38
  executeQuery(
@@ -50,11 +51,11 @@ const relationEffect = (self: object): Effect.Effect<unknown, PrismaError> => {
50
51
  kind: "client",
51
52
  }),
52
53
  );
53
- };
54
+ }
54
55
 
55
56
  const RelationPrototype = {
56
57
  ...Effectable.Prototype<RelationValue>({
57
- evaluate() {
58
+ evaluate(this: RelationValue) {
58
59
  return relationEffect(this);
59
60
  },
60
61
  label: "EffectPrismaRelation",
@@ -65,7 +66,7 @@ const RelationPrototype = {
65
66
  },
66
67
  };
67
68
 
68
- const makeRelationProxy = (runtime: AnyRelationRuntime): object => {
69
+ function makeRelationProxy(runtime: AnyRelationRuntime): object {
69
70
  const target: object = Object.create(RelationPrototype);
70
71
  const proxy = new Proxy(target, {
71
72
  get(self, property, receiver) {
@@ -89,6 +90,10 @@ const makeRelationProxy = (runtime: AnyRelationRuntime): object => {
89
90
  terminal: "count",
90
91
  });
91
92
  }
93
+ // Effect reads protocol keys such as its Exit identifier from every yielded value, so only the collection's own methods become Relation calls.
94
+ if (!hasMethod(Reflect.get(runtime.executor.models, runtime.recipe.model), property)) {
95
+ return undefined;
96
+ }
92
97
  return (...arguments_: readonly unknown[]) =>
93
98
  makeRelationProxy({
94
99
  ...runtime,
@@ -109,25 +114,25 @@ const makeRelationProxy = (runtime: AnyRelationRuntime): object => {
109
114
  setRelationPlan(value, plan);
110
115
  }
111
116
  return proxy;
112
- };
117
+ }
113
118
 
114
119
  // The proxy replays every Relation call onto the Prisma collection for `model`, so it has that collection's Relation surface.
115
- function asRelation<Collection, Model extends string>(proxy: object): Relation<Collection, undefined, Model>;
120
+ function asRelation<TCollection, TModel extends string>(proxy: object): Relation<TCollection, undefined, TModel>;
116
121
  function asRelation(proxy: object): unknown {
117
122
  return proxy;
118
123
  }
119
124
 
120
125
  export const makeModelRelation = <
121
- Collection,
122
- Models extends object,
123
- ExecutorContract extends AnyPostgresContract = AnyPostgresContract,
124
- Model extends string = string,
126
+ TCollection,
127
+ TModels extends object,
128
+ TExecutorContract extends AnyPostgresContract = AnyPostgresContract,
129
+ TModel extends string = string,
125
130
  >(
126
- executor: DatabaseExecutor<Models, ExecutorContract>,
127
- model: Model,
128
- resolveExecutor: Effect.Effect<DatabaseExecutor<Models, ExecutorContract>, PrismaError> = Effect.succeed(executor),
129
- ): Relation<Collection, undefined, Model> =>
130
- asRelation<Collection, Model>(
131
+ executor: DatabaseExecutor<TModels, TExecutorContract>,
132
+ model: TModel,
133
+ resolveExecutor: Effect.Effect<DatabaseExecutor<TModels, TExecutorContract>, PrismaError> = Effect.succeed(executor),
134
+ ): Relation<TCollection, undefined, TModel> =>
135
+ asRelation<TCollection, TModel>(
131
136
  makeRelationProxy({
132
137
  executor,
133
138
  recipe: rootRecipe(model),
@@ -6,17 +6,18 @@ import { fromPrismaPromise } from "./promise.ts";
6
6
  import { executeQuery } from "./query-execution.ts";
7
7
  import { type RelationRecipe, replayRecipe } from "./recipe.ts";
8
8
 
9
- const collectRows = (iterable: AsyncIterable<unknown>): Effect.Effect<unknown[], PrismaError> =>
10
- fromPrismaPromise(async () => {
9
+ function collectRows(iterable: AsyncIterable<unknown>): Effect.Effect<unknown[], PrismaError> {
10
+ return fromPrismaPromise(async () => {
11
11
  const rows: unknown[] = [];
12
12
  for await (const row of iterable) {
13
13
  rows.push(row);
14
14
  }
15
15
  return rows;
16
16
  });
17
+ }
17
18
 
18
- export const makeRelationStream = <Models extends object, Contract extends AnyPostgresContract>(
19
- resolveExecutor: Effect.Effect<DatabaseExecutor<Models, Contract>, PrismaError>,
19
+ export const makeRelationStream = <TModels extends object, TContract extends AnyPostgresContract>(
20
+ resolveExecutor: Effect.Effect<DatabaseExecutor<TModels, TContract>, PrismaError>,
20
21
  recipe: RelationRecipe,
21
22
  ): Stream.Stream<unknown, PrismaError> =>
22
23
  Stream.unwrap(
@@ -14,13 +14,15 @@ const zonelessDatetime = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}(?::\d{2})?(?:\.\d
14
14
  // with no zone, and `new Date` reads that form as local time. Values with a zone and date-only values already read as UTC.
15
15
  export const normalizeSqliteDatetime = (value: string): string => value.replace(zonelessDatetime, "$1T$2Z");
16
16
 
17
- const decodeAsUtc = (codec: ContractCodec): ContractCodec => ({
18
- decode: (wire: CodecWire, context) => codec.decode(typeof wire === "string" ? normalizeSqliteDatetime(wire) : wire, context),
19
- decodeJson: (json: CodecJson) => codec.decodeJson(typeof json === "string" ? normalizeSqliteDatetime(json) : json),
20
- encode: (value, context) => codec.encode(value, context),
21
- encodeJson: (value) => codec.encodeJson(value),
22
- id: sqliteDatetimeCodecId,
23
- });
17
+ function decodeAsUtc(codec: ContractCodec): ContractCodec {
18
+ return {
19
+ decode: (wire: CodecWire, context) => codec.decode(typeof wire === "string" ? normalizeSqliteDatetime(wire) : wire, context),
20
+ decodeJson: (json: CodecJson) => codec.decodeJson(typeof json === "string" ? normalizeSqliteDatetime(json) : json),
21
+ encode: (value, context) => codec.encode(value, context),
22
+ encodeJson: (value) => codec.encodeJson(value),
23
+ id: sqliteDatetimeCodecId,
24
+ };
25
+ }
24
26
 
25
27
  // The registry resolves codecs for rows and included relations alike, and Prisma Next rejects a second descriptor for a registered
26
28
  // codec id, so wrapping the registry is the one way to cover every read. It must run before the first query, which reads the
@@ -30,7 +32,7 @@ export const decodeSqliteDatetimesAsUtc = (context: ExecutionContext<AnySqlContr
30
32
  const descriptors = context.codecDescriptors;
31
33
  const utcCodecs = new WeakMap<ContractCodec, ContractCodec>();
32
34
 
33
- const wrap = (codec: ContractCodec): ContractCodec => {
35
+ function wrap(codec: ContractCodec): ContractCodec {
34
36
  const existing = utcCodecs.get(codec);
35
37
  if (existing !== undefined) {
36
38
  return existing;
@@ -38,7 +40,7 @@ export const decodeSqliteDatetimesAsUtc = (context: ExecutionContext<AnySqlContr
38
40
  const utc = decodeAsUtc(codec);
39
41
  utcCodecs.set(codec, utc);
40
42
  return utc;
41
- };
43
+ }
42
44
 
43
45
  const utcRegistry: CodecRegistry = {
44
46
  forCodecRef: (reference) => {
@@ -3,28 +3,28 @@ import type { PrismaError } from "#error.ts";
3
3
 
4
4
  export const DatabaseTestingTypeId: unique symbol = Symbol.for("@shivaedev/effect-prisma/DatabaseTesting");
5
5
 
6
- export interface DatabaseTesting<DatabaseId> {
6
+ export interface DatabaseTesting<TDatabaseId> {
7
7
  readonly withTestTransaction: <A, E, R>(
8
- program: Effect.Effect<A, E, R> & (DatabaseId extends R ? unknown : never),
9
- ) => Effect.Effect<A, E | PrismaError, DatabaseId | Exclude<R, DatabaseId>>;
8
+ program: Effect.Effect<A, E, R> & (TDatabaseId extends R ? unknown : never),
9
+ ) => Effect.Effect<A, E | PrismaError, TDatabaseId | Exclude<R, TDatabaseId>>;
10
10
  }
11
11
 
12
- export interface DatabaseWithTesting<DatabaseId> {
13
- readonly [DatabaseTestingTypeId]: DatabaseTesting<DatabaseId>;
12
+ export interface DatabaseWithTesting<TDatabaseId> {
13
+ readonly [DatabaseTestingTypeId]: DatabaseTesting<TDatabaseId>;
14
14
  }
15
15
 
16
16
  // makeSqlDatabase installs the testing hooks for the database's own service identifier.
17
- function testingFor<DatabaseId>(testing: object): DatabaseTesting<DatabaseId>;
17
+ function testingFor<TDatabaseId>(testing: object): DatabaseTesting<TDatabaseId>;
18
18
  function testingFor(testing: object): unknown {
19
19
  return testing;
20
20
  }
21
21
 
22
- export const getDatabaseTesting = <DatabaseId>(database: object): DatabaseTesting<DatabaseId> => {
22
+ export const getDatabaseTesting = <TDatabaseId>(database: object): DatabaseTesting<TDatabaseId> => {
23
23
  const testing: unknown = Reflect.get(database, DatabaseTestingTypeId);
24
24
 
25
25
  if (typeof testing !== "object" || testing === null || typeof Reflect.get(testing, "withTestTransaction") !== "function") {
26
26
  throw new TypeError("The database was not created by this copy of @shivaedev/effect-prisma");
27
27
  }
28
28
 
29
- return testingFor<DatabaseId>(testing);
29
+ return testingFor<TDatabaseId>(testing);
30
30
  };
@@ -5,26 +5,26 @@ import { type SettledConnection, type SettledTransaction, settleConnection } fro
5
5
  import type { AnySqlContract, DatabaseExecutor } from "./executor.ts";
6
6
  import { fromPrismaPromise } from "./promise.ts";
7
7
 
8
- export type TransactionOrm<Contract extends AnySqlContract> = ReturnType<typeof orm<Contract>>;
8
+ export type TransactionOrm<TContract extends AnySqlContract> = ReturnType<typeof orm<TContract>>;
9
9
 
10
10
  export const withTransactionSemaphore = <A, E, R>(
11
11
  semaphore: Semaphore.Semaphore | undefined,
12
12
  transaction: Effect.Effect<A, E, R>,
13
13
  ): Effect.Effect<A, E, R> => (semaphore === undefined ? transaction : semaphore.withPermit(transaction));
14
14
 
15
- export interface TransactionResource<Models extends object, Contract extends AnySqlContract> {
15
+ export interface TransactionResource<TModels extends object, TContract extends AnySqlContract> {
16
16
  readonly connection: SettledConnection;
17
- readonly executor: DatabaseExecutor<Models, Contract> & {
17
+ readonly executor: DatabaseExecutor<TModels, TContract> & {
18
18
  readonly querySemaphore: Semaphore.Semaphore;
19
19
  };
20
20
  readonly transaction: SettledTransaction;
21
21
  }
22
22
 
23
- export const acquireTransaction = <Models extends object, Contract extends AnySqlContract>(
24
- current: DatabaseExecutor<Models, Contract>,
25
- models: (orm: TransactionOrm<Contract>) => Models,
23
+ export const acquireTransaction = <TModels extends object, TContract extends AnySqlContract>(
24
+ current: DatabaseExecutor<TModels, TContract>,
25
+ models: (orm: TransactionOrm<TContract>) => TModels,
26
26
  mode: "test" | "transaction",
27
- ): Effect.Effect<TransactionResource<Models, Contract>, PrismaError> =>
27
+ ): Effect.Effect<TransactionResource<TModels, TContract>, PrismaError> =>
28
28
  fromPrismaPromise(async () => {
29
29
  const connection = await current.client.runtime().connection();
30
30
 
@@ -58,22 +58,22 @@ export const acquireTransaction = <Models extends object, Contract extends AnySq
58
58
  }
59
59
  });
60
60
 
61
- export const releaseTransaction = <Models extends object, Contract extends AnySqlContract, A, E>(
62
- resource: TransactionResource<Models, Contract>,
61
+ export const releaseTransaction = <TModels extends object, TContract extends AnySqlContract, A, E>(
62
+ resource: TransactionResource<TModels, TContract>,
63
63
  exit: Exit.Exit<A, E>,
64
64
  ): Effect.Effect<void, PrismaError> => settleTransaction(resource, exit, true);
65
65
 
66
- export const releaseTestTransaction = <Models extends object, Contract extends AnySqlContract, A, E>(
67
- resource: TransactionResource<Models, Contract>,
66
+ export const releaseTestTransaction = <TModels extends object, TContract extends AnySqlContract, A, E>(
67
+ resource: TransactionResource<TModels, TContract>,
68
68
  exit: Exit.Exit<A, E>,
69
69
  ): Effect.Effect<void, PrismaError> => settleTransaction(resource, exit, false);
70
70
 
71
- const settleTransaction = <Models extends object, Contract extends AnySqlContract, A, E>(
72
- resource: TransactionResource<Models, Contract>,
71
+ function settleTransaction<TModels extends object, TContract extends AnySqlContract, A, E>(
72
+ resource: TransactionResource<TModels, TContract>,
73
73
  exit: Exit.Exit<A, E>,
74
74
  commitOnSuccess: boolean,
75
- ): Effect.Effect<void, PrismaError> =>
76
- Effect.uninterruptible(
75
+ ): Effect.Effect<void, PrismaError> {
76
+ return Effect.uninterruptible(
77
77
  Effect.sync(() => {
78
78
  resource.executor.liveness.open = false;
79
79
  }).pipe(
@@ -82,3 +82,4 @@ const settleTransaction = <Models extends object, Contract extends AnySqlContrac
82
82
  ),
83
83
  ),
84
84
  );
85
+ }
@@ -2,18 +2,18 @@ import type { DefaultModelRow, Collection as PrismaCollection, RelationNames } f
2
2
  import type { Relation, RelationQuery } from "#relation.ts";
3
3
  import type { AnyPostgresContract, IncludedRelationValue, IsToManyRelation, RelatedModelNameOf } from "./include-metadata.ts";
4
4
 
5
- type Simplify<Value> = { [Key in keyof Value]: Value[Key] };
5
+ type Simplify<TValue> = { [TKey in keyof TValue]: TValue[TKey] };
6
6
 
7
- type QueryValue<Query> = Query extends RelationQuery<infer Value, infer _Contract, infer _Model, infer _DatabaseId> ? Value : never;
7
+ type QueryValue<TQuery> = TQuery extends RelationQuery<infer TValue, infer _Contract, infer _Model, infer _DatabaseId> ? TValue : never;
8
8
 
9
- type AcceptRelatedQuery<Query, Contract extends AnyPostgresContract, Model extends string, DatabaseId> = [Query] extends [
10
- RelationQuery<infer _Value, infer QueryContract, infer QueryModel, infer QueryDatabaseId>,
9
+ type AcceptRelatedQuery<TQuery, TContract extends AnyPostgresContract, TModel extends string, TDatabaseId> = [TQuery] extends [
10
+ RelationQuery<infer _Value, infer TQueryContract, infer TQueryModel, infer TQueryDatabaseId>,
11
11
  ]
12
- ? [QueryContract] extends [Contract]
13
- ? [Contract] extends [QueryContract]
14
- ? [QueryDatabaseId] extends [DatabaseId]
15
- ? [DatabaseId] extends [QueryDatabaseId]
16
- ? QueryModel extends Model
12
+ ? [TQueryContract] extends [TContract]
13
+ ? [TContract] extends [TQueryContract]
14
+ ? [TQueryDatabaseId] extends [TDatabaseId]
15
+ ? [TDatabaseId] extends [TQueryDatabaseId]
16
+ ? TQueryModel extends TModel
17
17
  ? unknown
18
18
  : never
19
19
  : never
@@ -22,63 +22,63 @@ type AcceptRelatedQuery<Query, Contract extends AnyPostgresContract, Model exten
22
22
  : never
23
23
  : never;
24
24
 
25
- type IncludedQueryValue<Query, Contract extends AnyPostgresContract, Model extends string, RelationName extends string> =
26
- QueryValue<Query> extends ReadonlyArray<infer Row> ? IncludedRelationValue<Contract, Model, RelationName, Row> : QueryValue<Query>;
25
+ type IncludedQueryValue<TQuery, TContract extends AnyPostgresContract, TModel extends string, TRelationName extends string> =
26
+ QueryValue<TQuery> extends ReadonlyArray<infer TRow> ? IncludedRelationValue<TContract, TModel, TRelationName, TRow> : QueryValue<TQuery>;
27
27
 
28
- type QueryShapeValue<Shape extends Readonly<Record<string, unknown>>> = {
29
- readonly [Key in keyof Shape]: QueryValue<Shape[Key]>;
28
+ type QueryShapeValue<TShape extends Readonly<Record<string, unknown>>> = {
29
+ readonly [TKey in keyof TShape]: QueryValue<TShape[TKey]>;
30
30
  };
31
31
 
32
32
  type AcceptRelatedQueryShape<
33
- Shape extends Readonly<Record<string, unknown>>,
34
- Contract extends AnyPostgresContract,
35
- Model extends string,
36
- DatabaseId,
33
+ TShape extends Readonly<Record<string, unknown>>,
34
+ TContract extends AnyPostgresContract,
35
+ TModel extends string,
36
+ TDatabaseId,
37
37
  > = {
38
- readonly [Key in keyof Shape]: Shape[Key] & AcceptRelatedQuery<Shape[Key], Contract, Model, DatabaseId>;
38
+ readonly [TKey in keyof TShape]: TShape[TKey] & AcceptRelatedQuery<TShape[TKey], TContract, TModel, TDatabaseId>;
39
39
  };
40
40
 
41
- type WithIncludedRelation<Collection, Contract extends AnyPostgresContract, Model extends string, RelationName extends string, Value> =
42
- Collection extends PrismaCollection<Contract, Model, infer Row, infer State>
43
- ? PrismaCollection<Contract, Model, Simplify<Row & { readonly [Key in RelationName]: Value }>, State>
41
+ type WithIncludedRelation<TCollection, TContract extends AnyPostgresContract, TModel extends string, TRelationName extends string, TValue> =
42
+ TCollection extends PrismaCollection<TContract, TModel, infer TRow, infer TState>
43
+ ? PrismaCollection<TContract, TModel, Simplify<TRow & { readonly [TKey in TRelationName]: TValue }>, TState>
44
44
  : never;
45
45
 
46
- interface IncludeOverloads<Collection, Contract extends AnyPostgresContract, Model extends string, DatabaseId> {
47
- <RelationName extends RelationNames<Contract, Model>>(
48
- relationName: RelationName,
46
+ interface IncludeOverloads<TCollection, TContract extends AnyPostgresContract, TModel extends string, TDatabaseId> {
47
+ <TRelationName extends RelationNames<TContract, TModel>>(
48
+ relationName: TRelationName,
49
49
  ): Relation<
50
50
  WithIncludedRelation<
51
- Collection,
52
- Contract,
53
- Model,
54
- RelationName,
55
- IncludedRelationValue<Contract, Model, RelationName, DefaultModelRow<Contract, RelatedModelNameOf<Contract, Model, RelationName>>>
51
+ TCollection,
52
+ TContract,
53
+ TModel,
54
+ TRelationName,
55
+ IncludedRelationValue<TContract, TModel, TRelationName, DefaultModelRow<TContract, RelatedModelNameOf<TContract, TModel, TRelationName>>>
56
56
  >,
57
- Contract,
58
- Model,
59
- DatabaseId
57
+ TContract,
58
+ TModel,
59
+ TDatabaseId
60
60
  >;
61
- <RelationName extends RelationNames<Contract, Model>, Query>(
62
- relationName: RelationName,
63
- query: Query & AcceptRelatedQuery<Query, Contract, RelatedModelNameOf<Contract, Model, RelationName>, DatabaseId>,
61
+ <TRelationName extends RelationNames<TContract, TModel>, TQuery>(
62
+ relationName: TRelationName,
63
+ query: TQuery & AcceptRelatedQuery<TQuery, TContract, RelatedModelNameOf<TContract, TModel, TRelationName>, TDatabaseId>,
64
64
  ): Relation<
65
- WithIncludedRelation<Collection, Contract, Model, RelationName, IncludedQueryValue<Query, Contract, Model, RelationName>>,
66
- Contract,
67
- Model,
68
- DatabaseId
65
+ WithIncludedRelation<TCollection, TContract, TModel, TRelationName, IncludedQueryValue<TQuery, TContract, TModel, TRelationName>>,
66
+ TContract,
67
+ TModel,
68
+ TDatabaseId
69
69
  >;
70
- <RelationName extends RelationNames<Contract, Model>, Shape extends Readonly<Record<string, unknown>>>(
71
- relationName: RelationName,
72
- shape: IsToManyRelation<Contract, Model, RelationName> extends true
73
- ? keyof Shape extends never
70
+ <TRelationName extends RelationNames<TContract, TModel>, TShape extends Readonly<Record<string, unknown>>>(
71
+ relationName: TRelationName,
72
+ shape: IsToManyRelation<TContract, TModel, TRelationName> extends true
73
+ ? keyof TShape extends never
74
74
  ? never
75
- : Shape & AcceptRelatedQueryShape<Shape, Contract, RelatedModelNameOf<Contract, Model, RelationName>, DatabaseId>
75
+ : TShape & AcceptRelatedQueryShape<TShape, TContract, RelatedModelNameOf<TContract, TModel, TRelationName>, TDatabaseId>
76
76
  : never,
77
- ): Relation<WithIncludedRelation<Collection, Contract, Model, RelationName, QueryShapeValue<Shape>>, Contract, Model, DatabaseId>;
77
+ ): Relation<WithIncludedRelation<TCollection, TContract, TModel, TRelationName, QueryShapeValue<TShape>>, TContract, TModel, TDatabaseId>;
78
78
  }
79
79
 
80
- export type IncludeMethod<Collection, Contract, Model extends string, DatabaseId> = Contract extends AnyPostgresContract
81
- ? Collection extends PrismaCollection<Contract, Model, infer _Row, infer _State>
82
- ? { include: IncludeOverloads<Collection, Contract, Model, DatabaseId> }
80
+ export type IncludeMethod<TCollection, TContract, TModel extends string, TDatabaseId> = TContract extends AnyPostgresContract
81
+ ? TCollection extends PrismaCollection<TContract, TModel, infer _Row, infer _State>
82
+ ? { include: IncludeOverloads<TCollection, TContract, TModel, TDatabaseId> }
83
83
  : Record<never, never>
84
84
  : Record<never, never>;
package/src/relation.ts CHANGED
@@ -4,40 +4,40 @@ import type { PrismaError } from "./error.ts";
4
4
 
5
5
  type AnyFunction = (...arguments_: readonly never[]) => unknown;
6
6
 
7
- export type CollectionResult<Collection> = Collection extends {
8
- all: () => infer Result;
7
+ export type CollectionResult<TCollection> = TCollection extends {
8
+ all: () => infer TResult;
9
9
  }
10
- ? Awaited<Result>
10
+ ? Awaited<TResult>
11
11
  : never;
12
12
 
13
- type NormalizeTerminal<Name, Result> = Name extends "first" ? import("effect").Option.Option<Exclude<Result, null>> : Result;
13
+ type NormalizeTerminal<TName, TResult> = TName extends "first" ? import("effect").Option.Option<Exclude<TResult, null>> : TResult;
14
14
 
15
- type WrapReturn<Name, Result, Contract, Model extends string, DatabaseId> =
16
- Result extends PromiseLike<infer Value>
17
- ? Effect.Effect<NormalizeTerminal<Name, Awaited<Value>>, PrismaError>
18
- : Result extends object
19
- ? Relation<Result, Contract, Model, DatabaseId>
15
+ type WrapReturn<TName, TResult, TContract, TModel extends string, TDatabaseId> =
16
+ TResult extends PromiseLike<infer TValue>
17
+ ? Effect.Effect<NormalizeTerminal<TName, Awaited<TValue>>, PrismaError>
18
+ : TResult extends object
19
+ ? Relation<TResult, TContract, TModel, TDatabaseId>
20
20
  : never;
21
21
 
22
- type WrapFunction<Name, Function_, Contract, Model extends string, DatabaseId> = Function_ extends {
23
- (...arguments_: infer Arguments1): infer Result1;
24
- (...arguments_: infer Arguments2): infer Result2;
25
- (...arguments_: infer Arguments3): infer Result3;
26
- (...arguments_: infer Arguments4): infer Result4;
27
- (...arguments_: infer Arguments5): infer Result5;
28
- (...arguments_: infer Arguments6): infer Result6;
22
+ type WrapFunction<TName, TFunction, TContract, TModel extends string, TDatabaseId> = TFunction extends {
23
+ (...arguments_: infer TArguments1): infer TResult1;
24
+ (...arguments_: infer TArguments2): infer TResult2;
25
+ (...arguments_: infer TArguments3): infer TResult3;
26
+ (...arguments_: infer TArguments4): infer TResult4;
27
+ (...arguments_: infer TArguments5): infer TResult5;
28
+ (...arguments_: infer TArguments6): infer TResult6;
29
29
  }
30
- ? ((...arguments_: Arguments1) => WrapReturn<Name, Result1, Contract, Model, DatabaseId>) &
31
- ((...arguments_: Arguments2) => WrapReturn<Name, Result2, Contract, Model, DatabaseId>) &
32
- ((...arguments_: Arguments3) => WrapReturn<Name, Result3, Contract, Model, DatabaseId>) &
33
- ((...arguments_: Arguments4) => WrapReturn<Name, Result4, Contract, Model, DatabaseId>) &
34
- ((...arguments_: Arguments5) => WrapReturn<Name, Result5, Contract, Model, DatabaseId>) &
35
- ((...arguments_: Arguments6) => WrapReturn<Name, Result6, Contract, Model, DatabaseId>)
30
+ ? ((...arguments_: TArguments1) => WrapReturn<TName, TResult1, TContract, TModel, TDatabaseId>) &
31
+ ((...arguments_: TArguments2) => WrapReturn<TName, TResult2, TContract, TModel, TDatabaseId>) &
32
+ ((...arguments_: TArguments3) => WrapReturn<TName, TResult3, TContract, TModel, TDatabaseId>) &
33
+ ((...arguments_: TArguments4) => WrapReturn<TName, TResult4, TContract, TModel, TDatabaseId>) &
34
+ ((...arguments_: TArguments5) => WrapReturn<TName, TResult5, TContract, TModel, TDatabaseId>) &
35
+ ((...arguments_: TArguments6) => WrapReturn<TName, TResult6, TContract, TModel, TDatabaseId>)
36
36
  : never;
37
37
 
38
- type FunctionKeys<Value> = {
39
- [Key in keyof Value]-?: Value[Key] extends AnyFunction ? Key : never;
40
- }[keyof Value];
38
+ type FunctionKeys<TValue> = {
39
+ [TKey in keyof TValue]-?: TValue[TKey] extends AnyFunction ? TKey : never;
40
+ }[keyof TValue];
41
41
 
42
42
  type ExplicitPrismaMethod =
43
43
  | "aggregate"
@@ -58,25 +58,25 @@ type ExplicitPrismaMethod =
58
58
  | "sum"
59
59
  | "variant";
60
60
 
61
- type RelationMethods<Collection, Contract, Model extends string, DatabaseId> = {
62
- readonly [Key in Exclude<FunctionKeys<Collection>, ExplicitPrismaMethod>]: WrapFunction<Key, Collection[Key], Contract, Model, DatabaseId>;
61
+ type RelationMethods<TCollection, TContract, TModel extends string, TDatabaseId> = {
62
+ readonly [TKey in Exclude<FunctionKeys<TCollection>, ExplicitPrismaMethod>]: WrapFunction<TKey, TCollection[TKey], TContract, TModel, TDatabaseId>;
63
63
  };
64
64
 
65
65
  declare const RelationQueryTypeId: unique symbol;
66
66
 
67
- export type RelationQuery<Value, Contract, Model extends string, DatabaseId> = Effect.Effect<Value, PrismaError> & {
67
+ export type RelationQuery<TValue, TContract, TModel extends string, TDatabaseId> = Effect.Effect<TValue, PrismaError> & {
68
68
  readonly [RelationQueryTypeId]: {
69
- readonly contract: Contract;
70
- readonly database: (database: DatabaseId) => DatabaseId;
71
- readonly model: Model;
69
+ readonly contract: TContract;
70
+ readonly database: (database: TDatabaseId) => TDatabaseId;
71
+ readonly model: TModel;
72
72
  };
73
73
  };
74
74
 
75
- export type Relation<Collection, Contract = undefined, Model extends string = string, DatabaseId = undefined> = RelationQuery<
76
- CollectionResult<Collection>,
77
- Contract,
78
- Model,
79
- DatabaseId
75
+ export type Relation<TCollection, TContract = undefined, TModel extends string = string, TDatabaseId = undefined> = RelationQuery<
76
+ CollectionResult<TCollection>,
77
+ TContract,
78
+ TModel,
79
+ TDatabaseId
80
80
  > &
81
- RelationMethods<Collection, Contract, Model, DatabaseId> &
82
- PrismaRelationMethods<Collection, Contract, Model, DatabaseId>;
81
+ RelationMethods<TCollection, TContract, TModel, TDatabaseId> &
82
+ PrismaRelationMethods<TCollection, TContract, TModel, TDatabaseId>;
package/src/sqlite.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import sqlite, { type SqliteClient, type SqliteOptionsBase } from "@prisma-next/sqlite/runtime";
2
2
  import { type Layer, Semaphore } from "effect";
3
+ import type { DatabaseIdentifier, DatabaseIdentifierLiteral, DatabaseServiceHolder, DefaultModels } from "#databaseTypes.ts";
3
4
  import { acquireConnectedClient, assertAvailableModelNames } from "#internal/client-lifecycle.ts";
4
5
  import { contractModels } from "#internal/database-facade.ts";
5
6
  import { makeSqlDatabase } from "#internal/database-factory.ts";
6
- import type { DatabaseIdentifier, DatabaseIdentifierLiteral, DatabaseServiceHolder, DefaultModels } from "#internal/database-types.ts";
7
7
  import type { AnySqlContract } from "#internal/executor.ts";
8
8
  import { fromPrismaPromise } from "#internal/promise.ts";
9
9
  import { decodeSqliteDatetimesAsUtc } from "#internal/sqlite-datetime.ts";
@@ -32,12 +32,14 @@ export interface SqliteDatabaseDefinition<Contract extends AnySqlContract, Ident
32
32
  readonly layer: (options: SqliteDatabaseLayerOptions) => Layer.Layer<DatabaseIdentifier<Contract, Identifier>, PrismaError>;
33
33
  }
34
34
 
35
- const clientOptions = ({ path, extensions, middleware, verifyMarker }: SqliteDatabaseLayerOptions) => ({
36
- path,
37
- ...(extensions === undefined ? {} : { extensions }),
38
- ...(middleware === undefined ? {} : { middleware }),
39
- ...(verifyMarker === undefined ? {} : { verifyMarker }),
40
- });
35
+ function clientOptions({ path, extensions, middleware, verifyMarker }: SqliteDatabaseLayerOptions) {
36
+ return {
37
+ path,
38
+ ...(extensions === undefined ? {} : { extensions }),
39
+ ...(middleware === undefined ? {} : { middleware }),
40
+ ...(verifyMarker === undefined ? {} : { verifyMarker }),
41
+ };
42
+ }
41
43
 
42
44
  export const makeSqliteDatabase =
43
45
  <const Contract extends AnySqlContract>() =>
@@ -1,7 +1,7 @@
1
1
  import type { Effect } from "effect";
2
+ import type { AnyDatabase } from "#databaseTypes.ts";
2
3
  import type { PrismaError } from "#error.ts";
3
4
  import { getDatabaseTesting } from "#internal/testing.ts";
4
- import type { AnyDatabase } from "./types.ts";
5
5
 
6
6
  type TestProgram<Database extends AnyDatabase, A, E, R> = Effect.Effect<A, E, R> & (Effect.Services<Database> extends R ? unknown : never);
7
7
 
@@ -1,9 +1,8 @@
1
1
  import type { TestContext, Vitest } from "@effect/vitest";
2
2
  import type { Effect, Layer } from "effect";
3
- import type { EffectClock, EffectTestOptions } from "@shivaedev/effect-test";
4
- import type { AnyDatabase, DatabaseServiceOf } from "#database.ts";
3
+ import type { EffectClock, EffectTestOptions } from "@shivaedev/effect-test/types.ts";
4
+ import type { AnyDatabase, DatabaseServiceOf } from "#databaseTypes.ts";
5
5
 
6
- export type { AnyDatabase } from "#database.ts";
7
6
  export type DatabaseService<Database extends AnyDatabase> = DatabaseServiceOf<Database>;
8
7
 
9
8
  export type DatabaseTest<Database extends AnyDatabase, Provided> = <A, Eff extends Effect.Effect<unknown, unknown, Provided>>(
@@ -1,8 +1,10 @@
1
1
  import { it as effectIt } from "@effect/vitest";
2
2
  import type { Effect, Layer } from "effect";
3
- import { type EffectClock, makeEffectIt } from "@shivaedev/effect-test";
3
+ import type { EffectClock } from "@shivaedev/effect-test/types.ts";
4
+ import { makeEffectIt } from "@shivaedev/effect-test/vitest.ts";
5
+ import type { AnyDatabase } from "#databaseTypes.ts";
4
6
  import { withTestTransaction } from "./transaction.ts";
5
- import type { AnyDatabase, DatabaseIt, MakeDatabaseItOptions } from "./types.ts";
7
+ import type { DatabaseIt, MakeDatabaseItOptions } from "./types.ts";
6
8
 
7
9
  export function makeDatabaseIt<Database extends AnyDatabase, Provided, LayerError>(
8
10
  options: MakeDatabaseItOptions<Database, Provided, LayerError> & {
package/dist/index.d.ts DELETED
@@ -1,5 +0,0 @@
1
- export { all, and, not, or } from "@prisma-next/sql-orm-client";
2
- export { type AnyDatabase, type DatabaseDefinition, type DatabaseLayerOptions, type DatabaseService, type DatabaseServiceOf, makeDatabase, } from "./database.ts";
3
- export { PrismaConnectionFailure, PrismaError, type PrismaErrorReason, PrismaQueryFailure, PrismaRuntimeFailure, } from "./error.ts";
4
- export type { Relation } from "./relation.ts";
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,YAAY,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,uBAAuB,EACvB,WAAW,EACX,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,oBAAoB,GACpB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}