@shivaedev/effect-prisma 0.6.3 → 0.7.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 +26 -1
- package/dist/bin/normalize-contract.js +1 -0
- package/dist/bin/normalize-contract.js.map +1 -1
- package/dist/database.d.ts +4 -4
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +12 -12
- package/dist/database.js.map +1 -1
- package/dist/error.d.ts +5 -5
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +5 -6
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/internal/adapters/transaction-settlement.d.ts +10 -0
- package/dist/internal/adapters/transaction-settlement.d.ts.map +1 -0
- package/dist/internal/adapters/transaction-settlement.js +56 -0
- package/dist/internal/adapters/transaction-settlement.js.map +1 -0
- package/dist/internal/client-lifecycle.d.ts +2 -2
- package/dist/internal/client-lifecycle.d.ts.map +1 -1
- package/dist/internal/client-lifecycle.js.map +1 -1
- package/dist/internal/contract-normalization.d.ts +0 -4
- package/dist/internal/contract-normalization.d.ts.map +1 -1
- package/dist/internal/contract-normalization.js +5 -10
- package/dist/internal/contract-normalization.js.map +1 -1
- package/dist/internal/database-facade.d.ts +19 -0
- package/dist/internal/database-facade.d.ts.map +1 -0
- package/dist/internal/database-facade.js +79 -0
- package/dist/internal/database-facade.js.map +1 -0
- package/dist/internal/database-factory.d.ts +4 -48
- package/dist/internal/database-factory.d.ts.map +1 -1
- package/dist/internal/database-factory.js +11 -90
- package/dist/internal/database-factory.js.map +1 -1
- package/dist/internal/database-types.d.ts +33 -0
- package/dist/internal/database-types.d.ts.map +1 -0
- package/dist/internal/database-types.js +2 -0
- package/dist/internal/database-types.js.map +1 -0
- package/dist/internal/dynamic.d.ts +5 -0
- package/dist/internal/dynamic.d.ts.map +1 -0
- package/dist/internal/dynamic.js +12 -0
- package/dist/internal/dynamic.js.map +1 -0
- package/dist/internal/executor.d.ts +3 -7
- package/dist/internal/executor.d.ts.map +1 -1
- package/dist/internal/promise.d.ts +1 -1
- package/dist/internal/promise.d.ts.map +1 -1
- package/dist/internal/promise.js +2 -4
- package/dist/internal/promise.js.map +1 -1
- package/dist/internal/query-execution.d.ts +2 -2
- package/dist/internal/query-execution.d.ts.map +1 -1
- package/dist/internal/query-execution.js +2 -6
- package/dist/internal/query-execution.js.map +1 -1
- package/dist/internal/recipe.d.ts +3 -3
- package/dist/internal/recipe.d.ts.map +1 -1
- package/dist/internal/recipe.js +9 -20
- package/dist/internal/recipe.js.map +1 -1
- package/dist/internal/relation-plan.d.ts +1 -1
- package/dist/internal/relation-result.d.ts +4 -0
- package/dist/internal/relation-result.d.ts.map +1 -0
- package/dist/internal/relation-result.js +19 -0
- package/dist/internal/relation-result.js.map +1 -0
- package/dist/internal/relation-runtime.d.ts +3 -3
- package/dist/internal/relation-runtime.d.ts.map +1 -1
- package/dist/internal/relation-runtime.js +12 -37
- package/dist/internal/relation-runtime.js.map +1 -1
- package/dist/internal/relation-stream.d.ts +3 -3
- package/dist/internal/relation-stream.d.ts.map +1 -1
- package/dist/internal/relation-stream.js +20 -24
- package/dist/internal/relation-stream.js.map +1 -1
- package/dist/internal/sqlite-datetime.d.ts +1 -27
- package/dist/internal/sqlite-datetime.d.ts.map +1 -1
- package/dist/internal/sqlite-datetime.js +16 -35
- package/dist/internal/sqlite-datetime.js.map +1 -1
- package/dist/internal/sqlite-pragmas.d.ts +1 -13
- package/dist/internal/sqlite-pragmas.d.ts.map +1 -1
- package/dist/internal/sqlite-pragmas.js +2 -12
- package/dist/internal/sqlite-pragmas.js.map +1 -1
- package/dist/internal/testing.d.ts +1 -1
- package/dist/internal/testing.d.ts.map +1 -1
- package/dist/internal/testing.js +5 -2
- package/dist/internal/testing.js.map +1 -1
- package/dist/internal/transaction.d.ts +5 -5
- package/dist/internal/transaction.d.ts.map +1 -1
- package/dist/internal/transaction.js +5 -53
- package/dist/internal/transaction.js.map +1 -1
- package/dist/relation/include-metadata.d.ts +1 -1
- package/dist/relation/include-metadata.d.ts.map +1 -1
- package/dist/relation/include.d.ts +8 -5
- package/dist/relation/include.d.ts.map +1 -1
- package/dist/relation/prisma-methods.d.ts +17 -17
- package/dist/relation/prisma-methods.d.ts.map +1 -1
- package/dist/relation.d.ts +4 -4
- package/dist/relation.d.ts.map +1 -1
- package/dist/sqlite.d.ts +5 -10
- package/dist/sqlite.d.ts.map +1 -1
- package/dist/sqlite.js +14 -12
- package/dist/sqlite.js.map +1 -1
- package/dist/testing/transaction.d.ts +6 -7
- package/dist/testing/transaction.d.ts.map +1 -1
- package/dist/testing/transaction.js +2 -2
- package/dist/testing/transaction.js.map +1 -1
- package/dist/testing/types.d.ts +7 -7
- package/dist/testing/types.d.ts.map +1 -1
- package/dist/testing/vitest.d.ts +3 -3
- package/dist/testing/vitest.d.ts.map +1 -1
- package/dist/testing/vitest.js +2 -2
- package/dist/testing/vitest.js.map +1 -1
- package/dist/testing.d.ts +3 -3
- package/package.json +35 -37
- package/src/bin/normalize-contract.ts +2 -1
- package/src/database.ts +49 -67
- package/src/error.ts +13 -23
- package/src/index.ts +3 -3
- package/src/internal/adapters/transaction-settlement.ts +70 -0
- package/src/internal/client-lifecycle.ts +4 -11
- package/src/internal/contract-normalization.ts +6 -14
- package/src/internal/database-facade.ts +138 -0
- package/src/internal/database-factory.ts +34 -306
- package/src/internal/database-types.ts +65 -0
- package/src/internal/dynamic.ts +16 -0
- package/src/internal/executor.ts +4 -11
- package/src/internal/promise.ts +4 -12
- package/src/internal/query-execution.ts +4 -8
- package/src/internal/recipe.ts +24 -89
- package/src/internal/relation-plan.ts +1 -1
- package/src/internal/relation-result.ts +27 -0
- package/src/internal/relation-runtime.ts +45 -135
- package/src/internal/relation-stream.ts +24 -51
- package/src/internal/sqlite-datetime.ts +20 -54
- package/src/internal/sqlite-pragmas.ts +3 -16
- package/src/internal/testing.ts +13 -15
- package/src/internal/transaction.ts +16 -109
- package/src/relation/include-metadata.ts +11 -43
- package/src/relation/include.ts +46 -140
- package/src/relation/prisma-methods.ts +36 -122
- package/src/relation.ts +20 -48
- package/src/sqlite.ts +59 -85
- package/src/testing/transaction.ts +20 -33
- package/src/testing/types.ts +15 -34
- package/src/testing/vitest.ts +14 -28
- package/src/testing.ts +3 -3
|
@@ -2,11 +2,7 @@ import { DatabaseSync } from "node:sqlite";
|
|
|
2
2
|
|
|
3
3
|
export const MEMORY_PATH = ":memory:";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
* Prisma Next's SQLite driver opens a fresh `node:sqlite` connection for every
|
|
7
|
-
* `RuntimeConnection`, so an in-memory database would give each transaction its
|
|
8
|
-
* own empty database.
|
|
9
|
-
*/
|
|
5
|
+
// Prisma Next's SQLite driver opens a fresh `node:sqlite` connection per `RuntimeConnection`, so each transaction would get its own empty in-memory database.
|
|
10
6
|
export const assertFileBackedPath = (path: string): void => {
|
|
11
7
|
if (path === MEMORY_PATH || path.trim().length === 0) {
|
|
12
8
|
throw new TypeError(
|
|
@@ -15,17 +11,8 @@ export const assertFileBackedPath = (path: string): void => {
|
|
|
15
11
|
}
|
|
16
12
|
};
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* The driver already sets `foreign_keys` and `busy_timeout` on every connection
|
|
22
|
-
* it opens, but it has no hook for anything else, so durable pragmas such as
|
|
23
|
-
* `journal_mode` are applied once against the database file itself.
|
|
24
|
-
*/
|
|
25
|
-
export const applySqlitePragmas = (
|
|
26
|
-
path: string,
|
|
27
|
-
pragmas: ReadonlyArray<string>,
|
|
28
|
-
): void => {
|
|
14
|
+
// The driver has no hook for pragmas beyond `foreign_keys` and `busy_timeout`, so durable ones such as `journal_mode` go to the file once.
|
|
15
|
+
export const applySqlitePragmas = (path: string, pragmas: readonly string[]): void => {
|
|
29
16
|
if (pragmas.length === 0) {
|
|
30
17
|
return;
|
|
31
18
|
}
|
package/src/internal/testing.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { Effect } from "effect";
|
|
2
|
-
import type { PrismaError } from "../error.
|
|
2
|
+
import type { PrismaError } from "../error.ts";
|
|
3
3
|
|
|
4
|
-
export const DatabaseTestingTypeId: unique symbol = Symbol.for(
|
|
5
|
-
"@shivaedev/effect-prisma/DatabaseTesting",
|
|
6
|
-
);
|
|
4
|
+
export const DatabaseTestingTypeId: unique symbol = Symbol.for("@shivaedev/effect-prisma/DatabaseTesting");
|
|
7
5
|
|
|
8
6
|
export interface DatabaseTesting<DatabaseId> {
|
|
9
7
|
readonly withTestTransaction: <A, E, R>(
|
|
@@ -15,18 +13,18 @@ export interface DatabaseWithTesting<DatabaseId> {
|
|
|
15
13
|
readonly [DatabaseTestingTypeId]: DatabaseTesting<DatabaseId>;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
):
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
| undefined;
|
|
16
|
+
// makeSqlDatabase installs the testing hooks for the database's own service identifier.
|
|
17
|
+
function testingFor<DatabaseId>(testing: object): DatabaseTesting<DatabaseId>;
|
|
18
|
+
function testingFor(testing: object): unknown {
|
|
19
|
+
return testing;
|
|
20
|
+
}
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
export const getDatabaseTesting = <DatabaseId>(database: object): DatabaseTesting<DatabaseId> => {
|
|
23
|
+
const testing: unknown = Reflect.get(database, DatabaseTestingTypeId);
|
|
24
|
+
|
|
25
|
+
if (typeof testing !== "object" || testing === null || typeof Reflect.get(testing, "withTestTransaction") !== "function") {
|
|
26
|
+
throw new TypeError("The database was not created by this copy of @shivaedev/effect-prisma");
|
|
29
27
|
}
|
|
30
28
|
|
|
31
|
-
return testing;
|
|
29
|
+
return testingFor<DatabaseId>(testing);
|
|
32
30
|
};
|
|
@@ -1,45 +1,26 @@
|
|
|
1
1
|
import { orm } from "@prisma-next/sql-orm-client";
|
|
2
|
-
import type {
|
|
3
|
-
RuntimeConnection,
|
|
4
|
-
RuntimeTransaction,
|
|
5
|
-
} from "@prisma-next/sql-runtime";
|
|
6
2
|
import { Effect, Exit, Semaphore } from "effect";
|
|
7
|
-
import type { PrismaError } from "../error.
|
|
8
|
-
import type
|
|
9
|
-
import {
|
|
3
|
+
import type { PrismaError } from "../error.ts";
|
|
4
|
+
import { type SettledConnection, type SettledTransaction, settleConnection } from "./adapters/transaction-settlement.ts";
|
|
5
|
+
import type { AnySqlContract, DatabaseExecutor } from "./executor.ts";
|
|
6
|
+
import { fromPrismaPromise } from "./promise.ts";
|
|
10
7
|
|
|
11
|
-
export type TransactionOrm<Contract extends AnySqlContract> = ReturnType<
|
|
12
|
-
typeof orm<Contract>
|
|
13
|
-
>;
|
|
8
|
+
export type TransactionOrm<Contract extends AnySqlContract> = ReturnType<typeof orm<Contract>>;
|
|
14
9
|
|
|
15
10
|
export const withTransactionSemaphore = <A, E, R>(
|
|
16
11
|
semaphore: Semaphore.Semaphore | undefined,
|
|
17
12
|
transaction: Effect.Effect<A, E, R>,
|
|
18
|
-
): Effect.Effect<A, E, R> =>
|
|
19
|
-
semaphore === undefined ? transaction : semaphore.withPermit(transaction);
|
|
13
|
+
): Effect.Effect<A, E, R> => (semaphore === undefined ? transaction : semaphore.withPermit(transaction));
|
|
20
14
|
|
|
21
|
-
export interface TransactionResource<
|
|
22
|
-
|
|
23
|
-
Contract extends AnySqlContract,
|
|
24
|
-
> {
|
|
25
|
-
readonly connection: RuntimeConnection;
|
|
26
|
-
readonly transaction: RuntimeTransaction;
|
|
15
|
+
export interface TransactionResource<Models extends object, Contract extends AnySqlContract> {
|
|
16
|
+
readonly connection: SettledConnection;
|
|
27
17
|
readonly executor: DatabaseExecutor<Models, Contract> & {
|
|
28
18
|
readonly querySemaphore: Semaphore.Semaphore;
|
|
29
19
|
};
|
|
20
|
+
readonly transaction: SettledTransaction;
|
|
30
21
|
}
|
|
31
22
|
|
|
32
|
-
const
|
|
33
|
-
code: string,
|
|
34
|
-
cause: unknown,
|
|
35
|
-
details?: Readonly<Record<string, unknown>>,
|
|
36
|
-
): Error & { readonly code: string } =>
|
|
37
|
-
Object.assign(new Error(code, { cause }), { code, ...details });
|
|
38
|
-
|
|
39
|
-
export const acquireTransaction = <
|
|
40
|
-
Models extends object,
|
|
41
|
-
Contract extends AnySqlContract,
|
|
42
|
-
>(
|
|
23
|
+
export const acquireTransaction = <Models extends object, Contract extends AnySqlContract>(
|
|
43
24
|
current: DatabaseExecutor<Models, Contract>,
|
|
44
25
|
models: (orm: TransactionOrm<Contract>) => Models,
|
|
45
26
|
mode: "test" | "transaction",
|
|
@@ -50,13 +31,12 @@ export const acquireTransaction = <
|
|
|
50
31
|
try {
|
|
51
32
|
const transaction = await connection.transaction();
|
|
52
33
|
const transactionOrm = orm({
|
|
53
|
-
runtime: transaction,
|
|
54
34
|
context: current.client.context,
|
|
35
|
+
runtime: transaction,
|
|
55
36
|
});
|
|
56
37
|
|
|
57
38
|
return {
|
|
58
39
|
connection,
|
|
59
|
-
transaction,
|
|
60
40
|
executor: {
|
|
61
41
|
client: current.client,
|
|
62
42
|
identity: current.identity,
|
|
@@ -70,6 +50,7 @@ export const acquireTransaction = <
|
|
|
70
50
|
transactionIdentity: {},
|
|
71
51
|
transactionSemaphore: current.transactionSemaphore,
|
|
72
52
|
},
|
|
53
|
+
transaction,
|
|
73
54
|
};
|
|
74
55
|
} catch (error) {
|
|
75
56
|
await connection.destroy(error).catch(() => undefined);
|
|
@@ -77,32 +58,17 @@ export const acquireTransaction = <
|
|
|
77
58
|
}
|
|
78
59
|
});
|
|
79
60
|
|
|
80
|
-
export const releaseTransaction = <
|
|
81
|
-
Models extends object,
|
|
82
|
-
Contract extends AnySqlContract,
|
|
83
|
-
A,
|
|
84
|
-
E,
|
|
85
|
-
>(
|
|
61
|
+
export const releaseTransaction = <Models extends object, Contract extends AnySqlContract, A, E>(
|
|
86
62
|
resource: TransactionResource<Models, Contract>,
|
|
87
63
|
exit: Exit.Exit<A, E>,
|
|
88
64
|
): Effect.Effect<void, PrismaError> => settleTransaction(resource, exit, true);
|
|
89
65
|
|
|
90
|
-
export const releaseTestTransaction = <
|
|
91
|
-
Models extends object,
|
|
92
|
-
Contract extends AnySqlContract,
|
|
93
|
-
A,
|
|
94
|
-
E,
|
|
95
|
-
>(
|
|
66
|
+
export const releaseTestTransaction = <Models extends object, Contract extends AnySqlContract, A, E>(
|
|
96
67
|
resource: TransactionResource<Models, Contract>,
|
|
97
68
|
exit: Exit.Exit<A, E>,
|
|
98
69
|
): Effect.Effect<void, PrismaError> => settleTransaction(resource, exit, false);
|
|
99
70
|
|
|
100
|
-
const settleTransaction = <
|
|
101
|
-
Models extends object,
|
|
102
|
-
Contract extends AnySqlContract,
|
|
103
|
-
A,
|
|
104
|
-
E,
|
|
105
|
-
>(
|
|
71
|
+
const settleTransaction = <Models extends object, Contract extends AnySqlContract, A, E>(
|
|
106
72
|
resource: TransactionResource<Models, Contract>,
|
|
107
73
|
exit: Exit.Exit<A, E>,
|
|
108
74
|
commitOnSuccess: boolean,
|
|
@@ -112,66 +78,7 @@ const settleTransaction = <
|
|
|
112
78
|
resource.executor.liveness.open = false;
|
|
113
79
|
}).pipe(
|
|
114
80
|
Effect.andThen(
|
|
115
|
-
resource.executor.querySemaphore.withPermit(
|
|
116
|
-
fromPrismaPromise(async () => {
|
|
117
|
-
let disposed = false;
|
|
118
|
-
let failure: unknown;
|
|
119
|
-
|
|
120
|
-
const destroy = async (reason: unknown): Promise<void> => {
|
|
121
|
-
if (disposed) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
disposed = true;
|
|
125
|
-
await resource.connection.destroy(reason).catch(() => undefined);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
if (commitOnSuccess && Exit.isSuccess(exit)) {
|
|
129
|
-
try {
|
|
130
|
-
await resource.transaction.commit();
|
|
131
|
-
} catch (commitError) {
|
|
132
|
-
try {
|
|
133
|
-
await resource.transaction.rollback();
|
|
134
|
-
} catch {
|
|
135
|
-
await destroy(commitError);
|
|
136
|
-
}
|
|
137
|
-
failure = runtimeFailure(
|
|
138
|
-
"RUNTIME.TRANSACTION_COMMIT_FAILED",
|
|
139
|
-
commitError,
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
try {
|
|
144
|
-
await resource.transaction.rollback();
|
|
145
|
-
} catch (rollbackError) {
|
|
146
|
-
await destroy(rollbackError);
|
|
147
|
-
failure = runtimeFailure(
|
|
148
|
-
"RUNTIME.TRANSACTION_ROLLBACK_FAILED",
|
|
149
|
-
rollbackError,
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (!disposed) {
|
|
155
|
-
try {
|
|
156
|
-
await resource.connection.release();
|
|
157
|
-
} catch (releaseError) {
|
|
158
|
-
await destroy(releaseError);
|
|
159
|
-
if (failure !== undefined) {
|
|
160
|
-
throw runtimeFailure(
|
|
161
|
-
"RUNTIME.TRANSACTION_RELEASE_FAILED",
|
|
162
|
-
failure,
|
|
163
|
-
{ releaseError },
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
throw releaseError;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (failure !== undefined) {
|
|
171
|
-
throw failure;
|
|
172
|
-
}
|
|
173
|
-
}),
|
|
174
|
-
),
|
|
81
|
+
resource.executor.querySemaphore.withPermit(fromPrismaPromise(() => settleConnection(resource, commitOnSuccess && Exit.isSuccess(exit)))),
|
|
175
82
|
),
|
|
176
83
|
),
|
|
177
84
|
);
|
|
@@ -8,46 +8,26 @@ type RelationDefinition<
|
|
|
8
8
|
Contract extends AnyPostgresContract,
|
|
9
9
|
Model extends string,
|
|
10
10
|
RelationName extends string,
|
|
11
|
-
> = RelationName extends keyof RelationsOf<Contract, Model>
|
|
12
|
-
? RelationsOf<Contract, Model>[RelationName]
|
|
13
|
-
: never;
|
|
11
|
+
> = RelationName extends keyof RelationsOf<Contract, Model> ? RelationsOf<Contract, Model>[RelationName] : never;
|
|
14
12
|
|
|
15
|
-
type RelationCardinalityOf<
|
|
16
|
-
Contract extends AnyPostgresContract,
|
|
17
|
-
Model extends string,
|
|
18
|
-
RelationName extends string,
|
|
19
|
-
> =
|
|
13
|
+
type RelationCardinalityOf<Contract extends AnyPostgresContract, Model extends string, RelationName extends string> =
|
|
20
14
|
RelationDefinition<Contract, Model, RelationName> extends {
|
|
21
15
|
readonly cardinality: infer Cardinality extends string;
|
|
22
16
|
}
|
|
23
17
|
? Cardinality
|
|
24
18
|
: never;
|
|
25
19
|
|
|
26
|
-
export type IsToManyRelation<
|
|
27
|
-
Contract extends
|
|
28
|
-
Model extends string,
|
|
29
|
-
RelationName extends string,
|
|
30
|
-
> =
|
|
31
|
-
RelationCardinalityOf<Contract, Model, RelationName> extends "1:N" | "N:M"
|
|
32
|
-
? true
|
|
33
|
-
: false;
|
|
20
|
+
export type IsToManyRelation<Contract extends AnyPostgresContract, Model extends string, RelationName extends string> =
|
|
21
|
+
RelationCardinalityOf<Contract, Model, RelationName> extends "1:N" | "N:M" ? true : false;
|
|
34
22
|
|
|
35
|
-
export type RelatedModelNameOf<
|
|
36
|
-
Contract extends AnyPostgresContract,
|
|
37
|
-
Model extends string,
|
|
38
|
-
RelationName extends string,
|
|
39
|
-
> =
|
|
23
|
+
export type RelatedModelNameOf<Contract extends AnyPostgresContract, Model extends string, RelationName extends string> =
|
|
40
24
|
RelationDefinition<Contract, Model, RelationName> extends {
|
|
41
25
|
readonly to: { readonly model: infer Related extends string };
|
|
42
26
|
}
|
|
43
27
|
? Related
|
|
44
28
|
: never;
|
|
45
29
|
|
|
46
|
-
type RelationLocalFields<
|
|
47
|
-
Contract extends AnyPostgresContract,
|
|
48
|
-
Model extends string,
|
|
49
|
-
RelationName extends string,
|
|
50
|
-
> =
|
|
30
|
+
type RelationLocalFields<Contract extends AnyPostgresContract, Model extends string, RelationName extends string> =
|
|
51
31
|
RelationDefinition<Contract, Model, RelationName> extends {
|
|
52
32
|
readonly on: {
|
|
53
33
|
readonly localFields: infer Fields extends readonly string[];
|
|
@@ -56,8 +36,7 @@ type RelationLocalFields<
|
|
|
56
36
|
? Fields
|
|
57
37
|
: readonly [];
|
|
58
38
|
|
|
59
|
-
type DefaultNamespace<Contract extends AnyPostgresContract> =
|
|
60
|
-
Contract["domain"]["namespaces"][keyof Contract["domain"]["namespaces"]];
|
|
39
|
+
type DefaultNamespace<Contract extends AnyPostgresContract> = Contract["domain"]["namespaces"][keyof Contract["domain"]["namespaces"]];
|
|
61
40
|
|
|
62
41
|
type ModelFields<Contract extends AnyPostgresContract, Model extends string> =
|
|
63
42
|
DefaultNamespace<Contract> extends {
|
|
@@ -70,10 +49,7 @@ type ModelFields<Contract extends AnyPostgresContract, Model extends string> =
|
|
|
70
49
|
: never
|
|
71
50
|
: never;
|
|
72
51
|
|
|
73
|
-
type AnyNullableField<
|
|
74
|
-
Fields,
|
|
75
|
-
Names extends readonly string[],
|
|
76
|
-
> = Names extends readonly [
|
|
52
|
+
type AnyNullableField<Fields, Names extends readonly string[]> = Names extends readonly [
|
|
77
53
|
infer Head extends string,
|
|
78
54
|
...infer Tail extends readonly string[],
|
|
79
55
|
]
|
|
@@ -84,19 +60,11 @@ type AnyNullableField<
|
|
|
84
60
|
: true
|
|
85
61
|
: false;
|
|
86
62
|
|
|
87
|
-
export type IncludedRelationValue<
|
|
88
|
-
Contract extends AnyPostgresContract,
|
|
89
|
-
Model extends string,
|
|
90
|
-
RelationName extends string,
|
|
91
|
-
Value,
|
|
92
|
-
> =
|
|
63
|
+
export type IncludedRelationValue<Contract extends AnyPostgresContract, Model extends string, RelationName extends string, Value> =
|
|
93
64
|
RelationCardinalityOf<Contract, Model, RelationName> extends "1:N" | "N:M"
|
|
94
|
-
?
|
|
65
|
+
? Value[]
|
|
95
66
|
: RelationCardinalityOf<Contract, Model, RelationName> extends "N:1"
|
|
96
|
-
? AnyNullableField<
|
|
97
|
-
ModelFields<Contract, Model>,
|
|
98
|
-
RelationLocalFields<Contract, Model, RelationName>
|
|
99
|
-
> extends true
|
|
67
|
+
? AnyNullableField<ModelFields<Contract, Model>, RelationLocalFields<Contract, Model, RelationName>> extends true
|
|
100
68
|
? Value | null
|
|
101
69
|
: Value
|
|
102
70
|
: Value | null;
|
package/src/relation/include.ts
CHANGED
|
@@ -1,40 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
RelationNames,
|
|
5
|
-
} from "@prisma-next/sql-orm-client";
|
|
6
|
-
import type { Relation, RelationQuery } from "../relation.js";
|
|
7
|
-
import type {
|
|
8
|
-
AnyPostgresContract,
|
|
9
|
-
IncludedRelationValue,
|
|
10
|
-
IsToManyRelation,
|
|
11
|
-
RelatedModelNameOf,
|
|
12
|
-
} from "./include-metadata.js";
|
|
1
|
+
import type { DefaultModelRow, Collection as PrismaCollection, RelationNames } from "@prisma-next/sql-orm-client";
|
|
2
|
+
import type { Relation, RelationQuery } from "../relation.ts";
|
|
3
|
+
import type { AnyPostgresContract, IncludedRelationValue, IsToManyRelation, RelatedModelNameOf } from "./include-metadata.ts";
|
|
13
4
|
|
|
14
5
|
type Simplify<Value> = { [Key in keyof Value]: Value[Key] };
|
|
15
6
|
|
|
16
|
-
type QueryValue<Query> =
|
|
17
|
-
Query extends RelationQuery<
|
|
18
|
-
infer Value,
|
|
19
|
-
infer _Contract,
|
|
20
|
-
infer _Model,
|
|
21
|
-
infer _DatabaseId
|
|
22
|
-
>
|
|
23
|
-
? Value
|
|
24
|
-
: never;
|
|
7
|
+
type QueryValue<Query> = Query extends RelationQuery<infer Value, infer _Contract, infer _Model, infer _DatabaseId> ? Value : never;
|
|
25
8
|
|
|
26
|
-
type AcceptRelatedQuery<
|
|
27
|
-
|
|
28
|
-
Contract extends AnyPostgresContract,
|
|
29
|
-
Model extends string,
|
|
30
|
-
DatabaseId,
|
|
31
|
-
> = [Query] extends [
|
|
32
|
-
RelationQuery<
|
|
33
|
-
infer _Value,
|
|
34
|
-
infer QueryContract,
|
|
35
|
-
infer QueryModel,
|
|
36
|
-
infer QueryDatabaseId
|
|
37
|
-
>,
|
|
9
|
+
type AcceptRelatedQuery<Query, Contract extends AnyPostgresContract, Model extends string, DatabaseId> = [Query] extends [
|
|
10
|
+
RelationQuery<infer _Value, infer QueryContract, infer QueryModel, infer QueryDatabaseId>,
|
|
38
11
|
]
|
|
39
12
|
? [QueryContract] extends [Contract]
|
|
40
13
|
? [Contract] extends [QueryContract]
|
|
@@ -49,15 +22,8 @@ type AcceptRelatedQuery<
|
|
|
49
22
|
: never
|
|
50
23
|
: never;
|
|
51
24
|
|
|
52
|
-
type IncludedQueryValue<
|
|
53
|
-
Query,
|
|
54
|
-
Contract extends AnyPostgresContract,
|
|
55
|
-
Model extends string,
|
|
56
|
-
RelationName extends string,
|
|
57
|
-
> =
|
|
58
|
-
QueryValue<Query> extends ReadonlyArray<infer Row>
|
|
59
|
-
? IncludedRelationValue<Contract, Model, RelationName, Row>
|
|
60
|
-
: QueryValue<Query>;
|
|
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>;
|
|
61
27
|
|
|
62
28
|
type QueryShapeValue<Shape extends Readonly<Record<string, unknown>>> = {
|
|
63
29
|
readonly [Key in keyof Shape]: QueryValue<Shape[Key]>;
|
|
@@ -69,110 +35,50 @@ type AcceptRelatedQueryShape<
|
|
|
69
35
|
Model extends string,
|
|
70
36
|
DatabaseId,
|
|
71
37
|
> = {
|
|
72
|
-
readonly [Key in keyof Shape]: Shape[Key] &
|
|
73
|
-
AcceptRelatedQuery<Shape[Key], Contract, Model, DatabaseId>;
|
|
38
|
+
readonly [Key in keyof Shape]: Shape[Key] & AcceptRelatedQuery<Shape[Key], Contract, Model, DatabaseId>;
|
|
74
39
|
};
|
|
75
40
|
|
|
76
|
-
type WithIncludedRelation<
|
|
77
|
-
Collection,
|
|
78
|
-
Contract extends AnyPostgresContract,
|
|
79
|
-
Model extends string,
|
|
80
|
-
RelationName extends string,
|
|
81
|
-
Value,
|
|
82
|
-
> =
|
|
41
|
+
type WithIncludedRelation<Collection, Contract extends AnyPostgresContract, Model extends string, RelationName extends string, Value> =
|
|
83
42
|
Collection extends PrismaCollection<Contract, Model, infer Row, infer State>
|
|
84
|
-
? PrismaCollection<
|
|
85
|
-
Contract,
|
|
86
|
-
Model,
|
|
87
|
-
Simplify<Row & { readonly [Key in RelationName]: Value }>,
|
|
88
|
-
State
|
|
89
|
-
>
|
|
43
|
+
? PrismaCollection<Contract, Model, Simplify<Row & { readonly [Key in RelationName]: Value }>, State>
|
|
90
44
|
: never;
|
|
91
45
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
? Collection extends PrismaCollection<
|
|
46
|
+
interface IncludeOverloads<Collection, Contract extends AnyPostgresContract, Model extends string, DatabaseId> {
|
|
47
|
+
<RelationName extends RelationNames<Contract, Model>>(
|
|
48
|
+
relationName: RelationName,
|
|
49
|
+
): Relation<
|
|
50
|
+
WithIncludedRelation<
|
|
51
|
+
Collection,
|
|
99
52
|
Contract,
|
|
100
53
|
Model,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
AcceptRelatedQuery<
|
|
131
|
-
Query,
|
|
132
|
-
Contract,
|
|
133
|
-
RelatedModelNameOf<Contract, Model, RelationName>,
|
|
134
|
-
DatabaseId
|
|
135
|
-
>,
|
|
136
|
-
): Relation<
|
|
137
|
-
WithIncludedRelation<
|
|
138
|
-
Collection,
|
|
139
|
-
Contract,
|
|
140
|
-
Model,
|
|
141
|
-
RelationName,
|
|
142
|
-
IncludedQueryValue<Query, Contract, Model, RelationName>
|
|
143
|
-
>,
|
|
144
|
-
Contract,
|
|
145
|
-
Model,
|
|
146
|
-
DatabaseId
|
|
147
|
-
>;
|
|
148
|
-
include<
|
|
149
|
-
RelationName extends RelationNames<Contract, Model>,
|
|
150
|
-
Shape extends Readonly<Record<string, unknown>>,
|
|
151
|
-
>(
|
|
152
|
-
relationName: RelationName,
|
|
153
|
-
shape: IsToManyRelation<Contract, Model, RelationName> extends true
|
|
154
|
-
? keyof Shape extends never
|
|
155
|
-
? never
|
|
156
|
-
: Shape &
|
|
157
|
-
AcceptRelatedQueryShape<
|
|
158
|
-
Shape,
|
|
159
|
-
Contract,
|
|
160
|
-
RelatedModelNameOf<Contract, Model, RelationName>,
|
|
161
|
-
DatabaseId
|
|
162
|
-
>
|
|
163
|
-
: never,
|
|
164
|
-
): Relation<
|
|
165
|
-
WithIncludedRelation<
|
|
166
|
-
Collection,
|
|
167
|
-
Contract,
|
|
168
|
-
Model,
|
|
169
|
-
RelationName,
|
|
170
|
-
QueryShapeValue<Shape>
|
|
171
|
-
>,
|
|
172
|
-
Contract,
|
|
173
|
-
Model,
|
|
174
|
-
DatabaseId
|
|
175
|
-
>;
|
|
176
|
-
}
|
|
54
|
+
RelationName,
|
|
55
|
+
IncludedRelationValue<Contract, Model, RelationName, DefaultModelRow<Contract, RelatedModelNameOf<Contract, Model, RelationName>>>
|
|
56
|
+
>,
|
|
57
|
+
Contract,
|
|
58
|
+
Model,
|
|
59
|
+
DatabaseId
|
|
60
|
+
>;
|
|
61
|
+
<RelationName extends RelationNames<Contract, Model>, Query>(
|
|
62
|
+
relationName: RelationName,
|
|
63
|
+
query: Query & AcceptRelatedQuery<Query, Contract, RelatedModelNameOf<Contract, Model, RelationName>, DatabaseId>,
|
|
64
|
+
): Relation<
|
|
65
|
+
WithIncludedRelation<Collection, Contract, Model, RelationName, IncludedQueryValue<Query, Contract, Model, RelationName>>,
|
|
66
|
+
Contract,
|
|
67
|
+
Model,
|
|
68
|
+
DatabaseId
|
|
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
|
|
74
|
+
? never
|
|
75
|
+
: Shape & AcceptRelatedQueryShape<Shape, Contract, RelatedModelNameOf<Contract, Model, RelationName>, DatabaseId>
|
|
76
|
+
: never,
|
|
77
|
+
): Relation<WithIncludedRelation<Collection, Contract, Model, RelationName, QueryShapeValue<Shape>>, Contract, Model, DatabaseId>;
|
|
78
|
+
}
|
|
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> }
|
|
177
83
|
: Record<never, never>
|
|
178
84
|
: Record<never, never>;
|