@prisma-next/compat-prisma 0.3.0-dev.3 → 0.3.0-dev.31
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/dist/exports/index.d.ts +2 -62
- package/dist/exports/index.d.ts.map +1 -0
- package/dist/prisma-client.d.ts +61 -0
- package/dist/prisma-client.d.ts.map +1 -0
- package/package.json +24 -24
- package/src/exports/index.ts +1 -0
- package/src/prisma-client.ts +457 -0
package/dist/exports/index.d.ts
CHANGED
|
@@ -1,62 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { Runtime, RuntimeContext } from '@prisma-next/sql-runtime';
|
|
4
|
-
|
|
5
|
-
interface PrismaClientOptions {
|
|
6
|
-
readonly contract: SqlContract<SqlStorage>;
|
|
7
|
-
readonly runtime?: Runtime;
|
|
8
|
-
readonly connectionString?: string;
|
|
9
|
-
}
|
|
10
|
-
interface FindUniqueArgs {
|
|
11
|
-
readonly where: Record<string, unknown>;
|
|
12
|
-
readonly select?: Record<string, boolean>;
|
|
13
|
-
}
|
|
14
|
-
interface FindManyArgs {
|
|
15
|
-
readonly where?: Record<string, unknown>;
|
|
16
|
-
readonly select?: Record<string, boolean>;
|
|
17
|
-
readonly orderBy?: Record<string, 'asc' | 'desc'>;
|
|
18
|
-
readonly take?: number;
|
|
19
|
-
readonly skip?: number;
|
|
20
|
-
}
|
|
21
|
-
type FindFirstArgs = FindManyArgs;
|
|
22
|
-
type TableFromSchema<Contract extends SqlContract<SqlStorage>> = ReturnType<typeof schema<Contract>>['tables'][string];
|
|
23
|
-
declare class ModelDelegate {
|
|
24
|
-
private readonly runtime;
|
|
25
|
-
private readonly context;
|
|
26
|
-
private readonly contract;
|
|
27
|
-
private readonly table;
|
|
28
|
-
private readonly tableName;
|
|
29
|
-
private readonly tableRef;
|
|
30
|
-
constructor(runtime: Runtime, context: RuntimeContext<SqlContract<SqlStorage>>, contract: SqlContract<SqlStorage>, table: TableFromSchema<SqlContract<SqlStorage>>, tableName: string);
|
|
31
|
-
findUnique(args: FindUniqueArgs): Promise<Record<string, unknown> | null>;
|
|
32
|
-
findFirst(args?: FindFirstArgs): Promise<Record<string, unknown> | null>;
|
|
33
|
-
findMany(args?: FindManyArgs): Promise<Record<string, unknown>[]>;
|
|
34
|
-
create(args: {
|
|
35
|
-
data: Record<string, unknown>;
|
|
36
|
-
}): Promise<Record<string, unknown>>;
|
|
37
|
-
update(_args: {
|
|
38
|
-
where: Record<string, unknown>;
|
|
39
|
-
data: Record<string, unknown>;
|
|
40
|
-
}): Promise<Record<string, unknown>>;
|
|
41
|
-
delete(_args: {
|
|
42
|
-
where: Record<string, unknown>;
|
|
43
|
-
}): Promise<Record<string, unknown>>;
|
|
44
|
-
private validateWhereArgs;
|
|
45
|
-
private unsupportedError;
|
|
46
|
-
}
|
|
47
|
-
declare class PrismaClientImpl {
|
|
48
|
-
readonly runtime: Runtime;
|
|
49
|
-
readonly context: RuntimeContext<SqlContract<SqlStorage>>;
|
|
50
|
-
readonly contract: SqlContract<SqlStorage>;
|
|
51
|
-
readonly schemaHandle: ReturnType<typeof schema>;
|
|
52
|
-
readonly models: Record<string, ModelDelegate>;
|
|
53
|
-
[key: string]: unknown;
|
|
54
|
-
constructor(options: PrismaClientOptions);
|
|
55
|
-
$disconnect(): Promise<void>;
|
|
56
|
-
}
|
|
57
|
-
declare class PrismaClient extends PrismaClientImpl {
|
|
58
|
-
readonly user: ModelDelegate;
|
|
59
|
-
constructor(options: PrismaClientOptions);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export { PrismaClient };
|
|
1
|
+
export { PrismaClient } from '../prisma-client';
|
|
2
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
2
|
+
import { schema } from '@prisma-next/sql-relational-core/schema';
|
|
3
|
+
import { type Runtime, type RuntimeContext } from '@prisma-next/sql-runtime';
|
|
4
|
+
interface PrismaClientOptions {
|
|
5
|
+
readonly contract: SqlContract<SqlStorage>;
|
|
6
|
+
readonly runtime?: Runtime;
|
|
7
|
+
readonly connectionString?: string;
|
|
8
|
+
}
|
|
9
|
+
interface FindUniqueArgs {
|
|
10
|
+
readonly where: Record<string, unknown>;
|
|
11
|
+
readonly select?: Record<string, boolean>;
|
|
12
|
+
}
|
|
13
|
+
interface FindManyArgs {
|
|
14
|
+
readonly where?: Record<string, unknown>;
|
|
15
|
+
readonly select?: Record<string, boolean>;
|
|
16
|
+
readonly orderBy?: Record<string, 'asc' | 'desc'>;
|
|
17
|
+
readonly take?: number;
|
|
18
|
+
readonly skip?: number;
|
|
19
|
+
}
|
|
20
|
+
type FindFirstArgs = FindManyArgs;
|
|
21
|
+
type TableFromSchema<Contract extends SqlContract<SqlStorage>> = ReturnType<typeof schema<Contract>>['tables'][string];
|
|
22
|
+
declare class ModelDelegate {
|
|
23
|
+
private readonly runtime;
|
|
24
|
+
private readonly context;
|
|
25
|
+
private readonly contract;
|
|
26
|
+
private readonly table;
|
|
27
|
+
private readonly tableName;
|
|
28
|
+
private readonly tableRef;
|
|
29
|
+
constructor(runtime: Runtime, context: RuntimeContext<SqlContract<SqlStorage>>, contract: SqlContract<SqlStorage>, table: TableFromSchema<SqlContract<SqlStorage>>, tableName: string);
|
|
30
|
+
findUnique(args: FindUniqueArgs): Promise<Record<string, unknown> | null>;
|
|
31
|
+
findFirst(args?: FindFirstArgs): Promise<Record<string, unknown> | null>;
|
|
32
|
+
findMany(args?: FindManyArgs): Promise<Record<string, unknown>[]>;
|
|
33
|
+
create(args: {
|
|
34
|
+
data: Record<string, unknown>;
|
|
35
|
+
}): Promise<Record<string, unknown>>;
|
|
36
|
+
update(_args: {
|
|
37
|
+
where: Record<string, unknown>;
|
|
38
|
+
data: Record<string, unknown>;
|
|
39
|
+
}): Promise<Record<string, unknown>>;
|
|
40
|
+
delete(_args: {
|
|
41
|
+
where: Record<string, unknown>;
|
|
42
|
+
}): Promise<Record<string, unknown>>;
|
|
43
|
+
private validateWhereArgs;
|
|
44
|
+
private unsupportedError;
|
|
45
|
+
}
|
|
46
|
+
declare class PrismaClientImpl {
|
|
47
|
+
readonly runtime: Runtime;
|
|
48
|
+
readonly context: RuntimeContext<SqlContract<SqlStorage>>;
|
|
49
|
+
readonly contract: SqlContract<SqlStorage>;
|
|
50
|
+
readonly schemaHandle: ReturnType<typeof schema>;
|
|
51
|
+
readonly models: Record<string, ModelDelegate>;
|
|
52
|
+
[key: string]: unknown;
|
|
53
|
+
constructor(options: PrismaClientOptions);
|
|
54
|
+
$disconnect(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
export declare class PrismaClient extends PrismaClientImpl {
|
|
57
|
+
readonly user: ModelDelegate;
|
|
58
|
+
constructor(options: PrismaClientOptions);
|
|
59
|
+
}
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=prisma-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prisma-client.d.ts","sourceRoot":"","sources":["../src/prisma-client.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/compat-prisma",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"files": [
|
|
7
|
-
"dist"
|
|
7
|
+
"dist",
|
|
8
|
+
"src"
|
|
8
9
|
],
|
|
9
10
|
"dependencies": {
|
|
10
|
-
"@prisma-next/adapter-postgres": "0.3.0-dev.
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/
|
|
13
|
-
"@prisma-next/sql-
|
|
14
|
-
"@prisma-next/sql-lane": "0.3.0-dev.
|
|
15
|
-
"@prisma-next/
|
|
16
|
-
"@prisma-next/sql-runtime": "0.3.0-dev.
|
|
17
|
-
"@prisma-next/target-postgres": "0.3.0-dev.
|
|
11
|
+
"@prisma-next/adapter-postgres": "0.3.0-dev.31",
|
|
12
|
+
"@prisma-next/driver-postgres": "0.3.0-dev.31",
|
|
13
|
+
"@prisma-next/sql-contract": "0.3.0-dev.31",
|
|
14
|
+
"@prisma-next/sql-relational-core": "0.3.0-dev.31",
|
|
15
|
+
"@prisma-next/sql-lane": "0.3.0-dev.31",
|
|
16
|
+
"@prisma-next/contract": "0.3.0-dev.31",
|
|
17
|
+
"@prisma-next/sql-runtime": "0.3.0-dev.31",
|
|
18
|
+
"@prisma-next/target-postgres": "0.3.0-dev.31"
|
|
18
19
|
},
|
|
19
20
|
"devDependencies": {
|
|
20
21
|
"@prisma/dev": "0.19.1",
|
|
21
|
-
"@types/pg": "
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"@prisma-next/
|
|
29
|
-
"@prisma-next/test-utils": "0.0.1"
|
|
22
|
+
"@types/pg": "8.16.0",
|
|
23
|
+
"pg": "8.16.3",
|
|
24
|
+
"tsup": "8.5.1",
|
|
25
|
+
"typescript": "5.9.3",
|
|
26
|
+
"vitest": "4.0.16",
|
|
27
|
+
"@prisma-next/sql-contract-ts": "0.3.0-dev.31",
|
|
28
|
+
"@prisma-next/test-utils": "0.0.1",
|
|
29
|
+
"@prisma-next/tsconfig": "0.0.0"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
32
32
|
".": {
|
|
@@ -35,13 +35,13 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"scripts": {
|
|
38
|
-
"build": "tsup --config tsup.config.ts",
|
|
38
|
+
"build": "tsup --config tsup.config.ts && tsc --project tsconfig.build.json",
|
|
39
39
|
"test": "vitest run",
|
|
40
40
|
"test:coverage": "vitest run --coverage",
|
|
41
41
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
42
|
-
"lint": "biome check . --
|
|
43
|
-
"lint:fix": "biome check --write .
|
|
44
|
-
"lint:fix:unsafe": "biome check --write --unsafe .
|
|
45
|
-
"clean": "
|
|
42
|
+
"lint": "biome check . --error-on-warnings",
|
|
43
|
+
"lint:fix": "biome check --write .",
|
|
44
|
+
"lint:fix:unsafe": "biome check --write --unsafe .",
|
|
45
|
+
"clean": "rm -rf dist dist-tsc dist-tsc-prod coverage .tmp-output"
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PrismaClient } from '../prisma-client';
|
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
import postgresAdapter from '@prisma-next/adapter-postgres/runtime';
|
|
2
|
+
import type { ExecutionPlan } from '@prisma-next/contract/types';
|
|
3
|
+
import postgresDriver from '@prisma-next/driver-postgres/runtime';
|
|
4
|
+
import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
5
|
+
import { sql } from '@prisma-next/sql-lane/sql';
|
|
6
|
+
import type { TableRef } from '@prisma-next/sql-relational-core/ast';
|
|
7
|
+
import { param } from '@prisma-next/sql-relational-core/param';
|
|
8
|
+
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
9
|
+
import { schema } from '@prisma-next/sql-relational-core/schema';
|
|
10
|
+
import type {
|
|
11
|
+
BinaryBuilder,
|
|
12
|
+
ColumnBuilder,
|
|
13
|
+
OrderBuilder,
|
|
14
|
+
} from '@prisma-next/sql-relational-core/types';
|
|
15
|
+
import {
|
|
16
|
+
createRuntime,
|
|
17
|
+
createRuntimeContext,
|
|
18
|
+
type Runtime,
|
|
19
|
+
type RuntimeContext,
|
|
20
|
+
} from '@prisma-next/sql-runtime';
|
|
21
|
+
import postgresTarget from '@prisma-next/target-postgres/runtime';
|
|
22
|
+
|
|
23
|
+
interface PrismaClientOptions {
|
|
24
|
+
readonly contract: SqlContract<SqlStorage>;
|
|
25
|
+
readonly runtime?: Runtime;
|
|
26
|
+
readonly connectionString?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface FindUniqueArgs {
|
|
30
|
+
readonly where: Record<string, unknown>;
|
|
31
|
+
readonly select?: Record<string, boolean>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface FindManyArgs {
|
|
35
|
+
readonly where?: Record<string, unknown>;
|
|
36
|
+
readonly select?: Record<string, boolean>;
|
|
37
|
+
readonly orderBy?: Record<string, 'asc' | 'desc'>;
|
|
38
|
+
readonly take?: number;
|
|
39
|
+
readonly skip?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
type FindFirstArgs = FindManyArgs;
|
|
43
|
+
|
|
44
|
+
type TableFromSchema<Contract extends SqlContract<SqlStorage>> = ReturnType<
|
|
45
|
+
typeof schema<Contract>
|
|
46
|
+
>['tables'][string];
|
|
47
|
+
|
|
48
|
+
function isColumnBuilder(value: unknown): value is ColumnBuilder {
|
|
49
|
+
return (
|
|
50
|
+
value !== null &&
|
|
51
|
+
value !== undefined &&
|
|
52
|
+
typeof value === 'object' &&
|
|
53
|
+
'kind' in value &&
|
|
54
|
+
value.kind === 'column'
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// NOTE: we can rely on the Prisma ORM's complex type definitions for the method return values, we only need to ensure the compatibility layer behaves correctly at runtime
|
|
59
|
+
class ModelDelegate {
|
|
60
|
+
private readonly tableName: string;
|
|
61
|
+
private readonly tableRef: TableRef;
|
|
62
|
+
|
|
63
|
+
constructor(
|
|
64
|
+
private readonly runtime: Runtime,
|
|
65
|
+
private readonly context: RuntimeContext<SqlContract<SqlStorage>>,
|
|
66
|
+
private readonly contract: SqlContract<SqlStorage>,
|
|
67
|
+
private readonly table: TableFromSchema<SqlContract<SqlStorage>>,
|
|
68
|
+
tableName: string,
|
|
69
|
+
) {
|
|
70
|
+
// Store table name explicitly (from schema key)
|
|
71
|
+
this.tableName = tableName;
|
|
72
|
+
// Create a clean TableRef that preserves the name property
|
|
73
|
+
// Object.assign in TableBuilderImpl may have overwritten name if there's a column named 'name'
|
|
74
|
+
// We preserve the original table for column access but create a clean ref for from() calls
|
|
75
|
+
this.tableRef = Object.freeze({
|
|
76
|
+
kind: 'table' as const,
|
|
77
|
+
name: tableName,
|
|
78
|
+
}) as TableRef;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async findUnique(args: FindUniqueArgs): Promise<Record<string, unknown> | null> {
|
|
82
|
+
const result = await this.findMany({
|
|
83
|
+
...args,
|
|
84
|
+
take: 1,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return result[0] ?? null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async findFirst(args: FindFirstArgs = {}): Promise<Record<string, unknown> | null> {
|
|
91
|
+
const result = await this.findMany({
|
|
92
|
+
...args,
|
|
93
|
+
take: 1,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
return result[0] ?? null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async findMany(args: FindManyArgs = {}): Promise<Record<string, unknown>[]> {
|
|
100
|
+
const tableName = this.tableName;
|
|
101
|
+
let query = sql({ context: this.context }).from(this.tableRef);
|
|
102
|
+
|
|
103
|
+
// Handle where clause (equality only for MVP)
|
|
104
|
+
if (args.where) {
|
|
105
|
+
this.validateWhereArgs(args.where);
|
|
106
|
+
const whereConditions: Array<{ column: ColumnBuilder; value: unknown }> = [];
|
|
107
|
+
|
|
108
|
+
for (const [field, value] of Object.entries(args.where)) {
|
|
109
|
+
// Check contract first to validate field exists
|
|
110
|
+
const tableDef = this.contract.storage.tables[this.tableName];
|
|
111
|
+
if (!tableDef || !tableDef.columns[field]) {
|
|
112
|
+
throw this.unsupportedError(`Unknown field '${field}' in where clause`);
|
|
113
|
+
}
|
|
114
|
+
// Access column via columns property to avoid conflicts with table properties
|
|
115
|
+
const columns = this.table.columns;
|
|
116
|
+
const column = columns[field];
|
|
117
|
+
if (!isColumnBuilder(column)) {
|
|
118
|
+
throw this.unsupportedError(`Invalid column '${field}' in where clause`);
|
|
119
|
+
}
|
|
120
|
+
whereConditions.push({ column, value });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (whereConditions.length === 1) {
|
|
124
|
+
const condition = whereConditions[0];
|
|
125
|
+
if (!condition) {
|
|
126
|
+
throw this.unsupportedError('Invalid where condition');
|
|
127
|
+
}
|
|
128
|
+
const column = condition.column as unknown as ColumnBuilder;
|
|
129
|
+
const paramPlaceholder = param(`${tableName}_${(column as { column: string }).column}`);
|
|
130
|
+
const binaryExpr = (column as { eq: (value: unknown) => BinaryBuilder }).eq(
|
|
131
|
+
paramPlaceholder,
|
|
132
|
+
);
|
|
133
|
+
query = query.where(binaryExpr);
|
|
134
|
+
} else if (whereConditions.length > 1) {
|
|
135
|
+
throw this.unsupportedError('Multiple where conditions (AND/OR) not supported in MVP');
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Handle select projection
|
|
140
|
+
const projection: Record<string, ColumnBuilder> = {};
|
|
141
|
+
if (args.select) {
|
|
142
|
+
for (const [field, include] of Object.entries(args.select)) {
|
|
143
|
+
if (include) {
|
|
144
|
+
// Check contract first, then access column
|
|
145
|
+
const tableDef = this.contract.storage.tables[this.tableName];
|
|
146
|
+
if (!tableDef || !tableDef.columns[field]) {
|
|
147
|
+
throw this.unsupportedError(`Unknown field '${field}' in select clause`);
|
|
148
|
+
}
|
|
149
|
+
const columns = this.table.columns;
|
|
150
|
+
const column = columns[field];
|
|
151
|
+
if (!isColumnBuilder(column)) {
|
|
152
|
+
throw this.unsupportedError(`Invalid column '${field}' in select clause`);
|
|
153
|
+
}
|
|
154
|
+
projection[field] = column;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
// Default: select all columns from contract definition
|
|
159
|
+
const tableDef = this.contract.storage.tables[tableName];
|
|
160
|
+
const tableColumns = this.table.columns;
|
|
161
|
+
if (tableDef && tableColumns) {
|
|
162
|
+
for (const columnName of Object.keys(tableDef.columns)) {
|
|
163
|
+
// Access column via columns property to avoid conflicts with table properties like 'name'
|
|
164
|
+
const column = tableColumns[columnName];
|
|
165
|
+
if (isColumnBuilder(column)) {
|
|
166
|
+
projection[columnName] = column;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Fallback: iterate table columns directly
|
|
172
|
+
if (Object.keys(projection).length === 0 && tableColumns) {
|
|
173
|
+
for (const key in tableColumns) {
|
|
174
|
+
const value = tableColumns[key];
|
|
175
|
+
if (isColumnBuilder(value)) {
|
|
176
|
+
projection[key] = value;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (Object.keys(projection).length === 0) {
|
|
182
|
+
throw this.unsupportedError('Select projection cannot be empty');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
query = query.select(projection);
|
|
187
|
+
|
|
188
|
+
// Handle orderBy
|
|
189
|
+
if (args.orderBy) {
|
|
190
|
+
const orderByEntries = Object.entries(args.orderBy);
|
|
191
|
+
if (orderByEntries.length > 1) {
|
|
192
|
+
throw this.unsupportedError('Multiple orderBy fields not supported in MVP');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const orderByEntry = orderByEntries[0];
|
|
196
|
+
if (!orderByEntry) {
|
|
197
|
+
throw this.unsupportedError('Invalid orderBy entry');
|
|
198
|
+
}
|
|
199
|
+
const [field, direction] = orderByEntry;
|
|
200
|
+
const tableDef = this.contract.storage.tables[this.tableName];
|
|
201
|
+
if (!tableDef || !tableDef.columns[field]) {
|
|
202
|
+
throw this.unsupportedError(`Unknown field '${field}' in orderBy clause`);
|
|
203
|
+
}
|
|
204
|
+
const columns = this.table.columns;
|
|
205
|
+
const columnValue = columns[field];
|
|
206
|
+
if (!isColumnBuilder(columnValue)) {
|
|
207
|
+
throw this.unsupportedError(`Invalid column '${field}' in orderBy clause`);
|
|
208
|
+
}
|
|
209
|
+
const column = columnValue as unknown as ColumnBuilder;
|
|
210
|
+
|
|
211
|
+
const orderExpr: OrderBuilder =
|
|
212
|
+
direction === 'asc'
|
|
213
|
+
? (column as { asc: () => OrderBuilder }).asc()
|
|
214
|
+
: (column as { desc: () => OrderBuilder }).desc();
|
|
215
|
+
query = query.orderBy(orderExpr);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Handle pagination
|
|
219
|
+
if (args.take !== undefined) {
|
|
220
|
+
query = query.limit(args.take);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (args.skip !== undefined) {
|
|
224
|
+
throw this.unsupportedError('skip/OFFSET not supported in MVP');
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Build plan with params
|
|
228
|
+
const paramsMap: Record<string, unknown> = {};
|
|
229
|
+
if (args.where) {
|
|
230
|
+
for (const [field, value] of Object.entries(args.where)) {
|
|
231
|
+
paramsMap[`${tableName}_${field}`] = value;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const plan = query.build({ params: paramsMap });
|
|
236
|
+
|
|
237
|
+
// Execute via runtime
|
|
238
|
+
const results: Record<string, unknown>[] = [];
|
|
239
|
+
for await (const row of this.runtime.execute<Record<string, unknown>>(
|
|
240
|
+
plan as ExecutionPlan<Record<string, unknown>> | SqlQueryPlan<Record<string, unknown>>,
|
|
241
|
+
)) {
|
|
242
|
+
results.push(row);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return results;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
async create(args: { data: Record<string, unknown> }): Promise<Record<string, unknown>> {
|
|
249
|
+
const tableName = this.tableName;
|
|
250
|
+
const tableDef = this.contract.storage.tables[tableName];
|
|
251
|
+
|
|
252
|
+
if (!tableDef) {
|
|
253
|
+
throw new Error(`Table ${tableName} not found in contract`);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Build INSERT statement using raw SQL (MVP: simple inserts only)
|
|
257
|
+
const columns: string[] = [];
|
|
258
|
+
const values: unknown[] = [];
|
|
259
|
+
const placeholders: string[] = [];
|
|
260
|
+
let paramIndex = 1;
|
|
261
|
+
|
|
262
|
+
for (const [field, value] of Object.entries(args.data)) {
|
|
263
|
+
const columnDef = tableDef.columns[field];
|
|
264
|
+
if (!columnDef) {
|
|
265
|
+
throw this.unsupportedError(`Unknown field '${field}' in create data`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Skip auto-generated fields (id with default, createdAt with default, etc.)
|
|
269
|
+
// For MVP, we'll include all provided fields
|
|
270
|
+
columns.push(`"${field}"`);
|
|
271
|
+
values.push(value);
|
|
272
|
+
placeholders.push(`$${paramIndex}`);
|
|
273
|
+
paramIndex++;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (columns.length === 0) {
|
|
277
|
+
throw this.unsupportedError('create() requires at least one field in data');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Use raw SQL for INSERT (MVP approach)
|
|
281
|
+
const sqlBuilder = sql({ context: this.context });
|
|
282
|
+
const insertPlan = sqlBuilder.raw(
|
|
283
|
+
`INSERT INTO "${tableName}" (${columns.join(', ')}) VALUES (${placeholders.join(', ')}) RETURNING *`,
|
|
284
|
+
{
|
|
285
|
+
params: values,
|
|
286
|
+
annotations: {
|
|
287
|
+
intent: 'write',
|
|
288
|
+
isMutation: true,
|
|
289
|
+
hasWhere: false,
|
|
290
|
+
hasLimit: false,
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
// Execute and return the created row
|
|
296
|
+
const results: Record<string, unknown>[] = [];
|
|
297
|
+
for await (const row of this.runtime.execute<Record<string, unknown>>(
|
|
298
|
+
insertPlan as ExecutionPlan<Record<string, unknown>> | SqlQueryPlan<Record<string, unknown>>,
|
|
299
|
+
)) {
|
|
300
|
+
results.push(row);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (results.length === 0) {
|
|
304
|
+
throw new Error('INSERT did not return a row');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const result = results[0];
|
|
308
|
+
if (!result) {
|
|
309
|
+
throw new Error('INSERT did not return a row');
|
|
310
|
+
}
|
|
311
|
+
return result;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
async update(_args: {
|
|
315
|
+
where: Record<string, unknown>;
|
|
316
|
+
data: Record<string, unknown>;
|
|
317
|
+
}): Promise<Record<string, unknown>> {
|
|
318
|
+
void _args;
|
|
319
|
+
throw this.unsupportedError('update() mutations are not supported in MVP compatibility layer');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async delete(_args: { where: Record<string, unknown> }): Promise<Record<string, unknown>> {
|
|
323
|
+
void _args;
|
|
324
|
+
throw this.unsupportedError('delete() mutations are not supported in MVP compatibility layer');
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
private validateWhereArgs(where: Record<string, unknown>): void {
|
|
328
|
+
// MVP: only simple equality is supported
|
|
329
|
+
for (const [field, value] of Object.entries(where)) {
|
|
330
|
+
if (value === null || value === undefined) {
|
|
331
|
+
throw this.unsupportedError('Null/undefined values in where clause not supported in MVP');
|
|
332
|
+
}
|
|
333
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
334
|
+
throw this.unsupportedError(
|
|
335
|
+
`Complex where predicates (e.g., {${field}: {gt: ...}}) not supported in MVP`,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
if (Array.isArray(value)) {
|
|
339
|
+
throw this.unsupportedError('IN/NOT IN predicates not supported in MVP');
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private unsupportedError(message: string): Error {
|
|
345
|
+
const error = new Error(message) as Error & {
|
|
346
|
+
code: string;
|
|
347
|
+
category: string;
|
|
348
|
+
severity: string;
|
|
349
|
+
};
|
|
350
|
+
error.code = 'CONFIG.INVALID';
|
|
351
|
+
error.category = 'CONFIG';
|
|
352
|
+
error.severity = 'error';
|
|
353
|
+
return error;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
class PrismaClientImpl {
|
|
358
|
+
readonly runtime: Runtime;
|
|
359
|
+
readonly context: RuntimeContext<SqlContract<SqlStorage>>;
|
|
360
|
+
readonly contract: SqlContract<SqlStorage>;
|
|
361
|
+
readonly schemaHandle: ReturnType<typeof schema>;
|
|
362
|
+
readonly models: Record<string, ModelDelegate> = {};
|
|
363
|
+
|
|
364
|
+
// Dynamic model access properties (populated at runtime)
|
|
365
|
+
[key: string]: unknown;
|
|
366
|
+
|
|
367
|
+
constructor(options: PrismaClientOptions) {
|
|
368
|
+
// Currently only SQL contracts are supported
|
|
369
|
+
this.contract = options.contract;
|
|
370
|
+
|
|
371
|
+
// Create context with contract and descriptor-first composition
|
|
372
|
+
this.context = createRuntimeContext({
|
|
373
|
+
contract: this.contract,
|
|
374
|
+
target: postgresTarget,
|
|
375
|
+
adapter: postgresAdapter,
|
|
376
|
+
extensionPacks: [],
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Initialize runtime if not provided
|
|
380
|
+
if (options.runtime) {
|
|
381
|
+
this.runtime = options.runtime;
|
|
382
|
+
} else {
|
|
383
|
+
const connectionString = options.connectionString ?? process.env['DATABASE_URL'];
|
|
384
|
+
|
|
385
|
+
if (!connectionString) {
|
|
386
|
+
throw new Error('DATABASE_URL environment variable or connectionString option is required');
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
const driver = postgresDriver.create({ connectionString });
|
|
390
|
+
|
|
391
|
+
this.runtime = createRuntime({
|
|
392
|
+
driver,
|
|
393
|
+
context: this.context,
|
|
394
|
+
verify: {
|
|
395
|
+
mode: 'onFirstUse',
|
|
396
|
+
requireMarker: false,
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Initialize schema handle
|
|
402
|
+
this.schemaHandle = schema(this.context);
|
|
403
|
+
|
|
404
|
+
// Build model delegates
|
|
405
|
+
for (const [tableName, table] of Object.entries(this.schemaHandle.tables)) {
|
|
406
|
+
// Convert table name to camelCase model name (e.g., "user" -> "user", "User" -> "user")
|
|
407
|
+
const modelName = tableName.charAt(0).toLowerCase() + tableName.slice(1);
|
|
408
|
+
// Pass tableName explicitly since Object.assign in TableBuilderImpl may interfere with name property
|
|
409
|
+
this.models[modelName] = new ModelDelegate(
|
|
410
|
+
this.runtime,
|
|
411
|
+
this.context,
|
|
412
|
+
this.contract,
|
|
413
|
+
table as TableFromSchema<SqlContract<SqlStorage>>,
|
|
414
|
+
tableName,
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
async $disconnect(): Promise<void> {
|
|
420
|
+
await this.runtime.close();
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Export PrismaClient as a Proxy-wrapped class for dynamic model access
|
|
425
|
+
export class PrismaClient extends PrismaClientImpl {
|
|
426
|
+
// Declare user model for TypeScript (MVP: assumes user table exists)
|
|
427
|
+
declare readonly user: ModelDelegate;
|
|
428
|
+
|
|
429
|
+
constructor(options: PrismaClientOptions) {
|
|
430
|
+
super(options);
|
|
431
|
+
const proxy = new Proxy(this, {
|
|
432
|
+
get(target, prop) {
|
|
433
|
+
if (prop in target && prop !== 'models') {
|
|
434
|
+
if (typeof prop === 'string' || typeof prop === 'number') {
|
|
435
|
+
return (target as Record<string | number, unknown>)[prop];
|
|
436
|
+
}
|
|
437
|
+
return undefined;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Check if it's a model name
|
|
441
|
+
if (typeof prop === 'string' && target.models[prop]) {
|
|
442
|
+
return target.models[prop];
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return undefined;
|
|
446
|
+
},
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// Copy model properties to instance for TypeScript type checking
|
|
450
|
+
for (const [modelName, delegate] of Object.entries(this.models)) {
|
|
451
|
+
(proxy as Record<string, unknown>)[modelName] = delegate;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// biome-ignore lint/correctness/noConstructorReturn: Proxy pattern requires returning the proxy
|
|
455
|
+
return proxy;
|
|
456
|
+
}
|
|
457
|
+
}
|