@prisma-next/sql-builder 0.12.0 → 0.13.0-dev.2
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/{db-DYq06sbo.d.mts → db-BdrQgIiw.d.mts} +14 -11
- package/dist/{db-DYq06sbo.d.mts.map → db-BdrQgIiw.d.mts.map} +1 -1
- package/dist/exports/types.d.mts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/runtime/index.d.mts +1 -1
- package/dist/runtime/index.d.mts.map +1 -1
- package/dist/runtime/index.mjs +70 -45
- package/dist/runtime/index.mjs.map +1 -1
- package/package.json +16 -16
- package/src/exports/types.ts +8 -1
- package/src/runtime/builder-base.ts +11 -3
- package/src/runtime/mutation-impl.ts +42 -22
- package/src/runtime/resolve-table.ts +13 -0
- package/src/runtime/sql.ts +26 -21
- package/src/runtime/table-proxy-impl.ts +31 -9
- package/src/runtime/table-source-for-proxy.ts +9 -0
- package/src/types/db.ts +21 -13
- package/src/types/table-proxy.ts +7 -7
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
InsertAst,
|
|
13
13
|
ParamRef,
|
|
14
14
|
ProjectionItem,
|
|
15
|
-
TableSource,
|
|
15
|
+
type TableSource,
|
|
16
16
|
UpdateAst,
|
|
17
17
|
} from '@prisma-next/sql-relational-core/ast';
|
|
18
18
|
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
@@ -68,6 +68,7 @@ export type UpdateSetCallback = (
|
|
|
68
68
|
|
|
69
69
|
export function buildParamValues(
|
|
70
70
|
values: Record<string, unknown>,
|
|
71
|
+
namespaceId: string,
|
|
71
72
|
table: StorageTable,
|
|
72
73
|
tableName: string,
|
|
73
74
|
op: MutationDefaultsOp,
|
|
@@ -76,12 +77,12 @@ export function buildParamValues(
|
|
|
76
77
|
const params: Record<string, ParamRef> = {};
|
|
77
78
|
for (const [col, value] of Object.entries(values)) {
|
|
78
79
|
const column = table.columns[col];
|
|
79
|
-
const codec = column ? codecRefFor(ctx, tableName, col) : undefined;
|
|
80
|
+
const codec = column ? codecRefFor(ctx, namespaceId, tableName, col) : undefined;
|
|
80
81
|
params[col] = ParamRef.of(value, codec ? { codec } : undefined);
|
|
81
82
|
}
|
|
82
83
|
for (const def of ctx.applyMutationDefaults({ op, table: tableName, values })) {
|
|
83
84
|
const column = table.columns[def.column];
|
|
84
|
-
const codec = column ? codecRefFor(ctx, tableName, def.column) : undefined;
|
|
85
|
+
const codec = column ? codecRefFor(ctx, namespaceId, tableName, def.column) : undefined;
|
|
85
86
|
params[def.column] = ParamRef.of(def.value, codec ? { codec } : undefined);
|
|
86
87
|
}
|
|
87
88
|
return params;
|
|
@@ -129,6 +130,7 @@ export function evaluateUpdateCallback(
|
|
|
129
130
|
|
|
130
131
|
export function buildSetExpressions(
|
|
131
132
|
exprs: Record<string, AstExpression>,
|
|
133
|
+
namespaceId: string,
|
|
132
134
|
table: StorageTable,
|
|
133
135
|
tableName: string,
|
|
134
136
|
op: MutationDefaultsOp,
|
|
@@ -138,7 +140,7 @@ export function buildSetExpressions(
|
|
|
138
140
|
for (const def of ctx.applyMutationDefaults({ op, table: tableName, values: exprs })) {
|
|
139
141
|
if (!(def.column in set)) {
|
|
140
142
|
const column = table.columns[def.column];
|
|
141
|
-
const codec = column ? codecRefFor(ctx, tableName, def.column) : undefined;
|
|
143
|
+
const codec = column ? codecRefFor(ctx, namespaceId, tableName, def.column) : undefined;
|
|
142
144
|
set[def.column] = ParamRef.of(def.value, ifDefined('codec', codec));
|
|
143
145
|
}
|
|
144
146
|
}
|
|
@@ -153,7 +155,9 @@ export class InsertQueryImpl<
|
|
|
153
155
|
extends BuilderBase<QC['capabilities']>
|
|
154
156
|
implements InsertQuery<QC, AvailableScope, RowType>
|
|
155
157
|
{
|
|
158
|
+
readonly #tableSource: TableSource;
|
|
156
159
|
readonly #tableName: string;
|
|
160
|
+
readonly #namespaceId: string;
|
|
157
161
|
readonly #table: StorageTable;
|
|
158
162
|
readonly #scope: Scope;
|
|
159
163
|
readonly #rows: ReadonlyArray<Record<string, unknown>>;
|
|
@@ -162,7 +166,8 @@ export class InsertQueryImpl<
|
|
|
162
166
|
readonly #annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
|
|
163
167
|
|
|
164
168
|
constructor(
|
|
165
|
-
|
|
169
|
+
tableSource: TableSource,
|
|
170
|
+
namespaceId: string,
|
|
166
171
|
table: StorageTable,
|
|
167
172
|
scope: Scope,
|
|
168
173
|
rows: ReadonlyArray<Record<string, unknown>>,
|
|
@@ -172,7 +177,9 @@ export class InsertQueryImpl<
|
|
|
172
177
|
annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> = new Map(),
|
|
173
178
|
) {
|
|
174
179
|
super(ctx);
|
|
175
|
-
this.#
|
|
180
|
+
this.#tableSource = tableSource;
|
|
181
|
+
this.#tableName = tableSource.name;
|
|
182
|
+
this.#namespaceId = namespaceId;
|
|
176
183
|
this.#table = table;
|
|
177
184
|
this.#scope = scope;
|
|
178
185
|
this.#rows = rows;
|
|
@@ -192,7 +199,8 @@ export class InsertQueryImpl<
|
|
|
192
199
|
newRowFields[col] = field;
|
|
193
200
|
}
|
|
194
201
|
return new InsertQueryImpl(
|
|
195
|
-
this.#
|
|
202
|
+
this.#tableSource,
|
|
203
|
+
this.#namespaceId,
|
|
196
204
|
this.#table,
|
|
197
205
|
this.#scope,
|
|
198
206
|
this.#rows,
|
|
@@ -215,7 +223,8 @@ export class InsertQueryImpl<
|
|
|
215
223
|
...annotations: As & ValidAnnotations<'write', As>
|
|
216
224
|
): InsertQuery<QC, AvailableScope, RowType> {
|
|
217
225
|
return new InsertQueryImpl(
|
|
218
|
-
this.#
|
|
226
|
+
this.#tableSource,
|
|
227
|
+
this.#namespaceId,
|
|
219
228
|
this.#table,
|
|
220
229
|
this.#scope,
|
|
221
230
|
this.#rows,
|
|
@@ -235,10 +244,17 @@ export class InsertQueryImpl<
|
|
|
235
244
|
}
|
|
236
245
|
|
|
237
246
|
const paramRows = this.#rows.map((rowValues) =>
|
|
238
|
-
buildParamValues(
|
|
247
|
+
buildParamValues(
|
|
248
|
+
rowValues,
|
|
249
|
+
this.#namespaceId,
|
|
250
|
+
this.#table,
|
|
251
|
+
this.#tableName,
|
|
252
|
+
'create',
|
|
253
|
+
this.ctx,
|
|
254
|
+
),
|
|
239
255
|
);
|
|
240
256
|
|
|
241
|
-
let ast = InsertAst.into(
|
|
257
|
+
let ast = InsertAst.into(this.#tableSource).withRows(paramRows);
|
|
242
258
|
|
|
243
259
|
if (this.#returningColumns.length > 0) {
|
|
244
260
|
ast = ast.withReturning(
|
|
@@ -262,6 +278,7 @@ export class UpdateQueryImpl<
|
|
|
262
278
|
extends BuilderBase<QC['capabilities']>
|
|
263
279
|
implements UpdateQuery<QC, AvailableScope, RowType>
|
|
264
280
|
{
|
|
281
|
+
readonly #tableSource: TableSource;
|
|
265
282
|
readonly #tableName: string;
|
|
266
283
|
readonly #scope: Scope;
|
|
267
284
|
readonly #setExpressions: Record<string, AstExpression>;
|
|
@@ -271,7 +288,7 @@ export class UpdateQueryImpl<
|
|
|
271
288
|
readonly #annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
|
|
272
289
|
|
|
273
290
|
constructor(
|
|
274
|
-
|
|
291
|
+
tableSource: TableSource,
|
|
275
292
|
scope: Scope,
|
|
276
293
|
setExpressions: Record<string, AstExpression>,
|
|
277
294
|
ctx: BuilderContext,
|
|
@@ -281,7 +298,8 @@ export class UpdateQueryImpl<
|
|
|
281
298
|
annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> = new Map(),
|
|
282
299
|
) {
|
|
283
300
|
super(ctx);
|
|
284
|
-
this.#
|
|
301
|
+
this.#tableSource = tableSource;
|
|
302
|
+
this.#tableName = tableSource.name;
|
|
285
303
|
this.#scope = scope;
|
|
286
304
|
this.#setExpressions = setExpressions;
|
|
287
305
|
this.#whereExprs = whereExprs;
|
|
@@ -295,7 +313,7 @@ export class UpdateQueryImpl<
|
|
|
295
313
|
const fns = createFunctions(this.ctx.queryOperationTypes, this.ctx.rawCodecInferer);
|
|
296
314
|
const result = (expr as ExpressionBuilder<Scope, QueryContext>)(fieldProxy, fns as never);
|
|
297
315
|
return new UpdateQueryImpl(
|
|
298
|
-
this.#
|
|
316
|
+
this.#tableSource,
|
|
299
317
|
this.#scope,
|
|
300
318
|
this.#setExpressions,
|
|
301
319
|
this.ctx,
|
|
@@ -317,7 +335,7 @@ export class UpdateQueryImpl<
|
|
|
317
335
|
newRowFields[col] = field;
|
|
318
336
|
}
|
|
319
337
|
return new UpdateQueryImpl(
|
|
320
|
-
this.#
|
|
338
|
+
this.#tableSource,
|
|
321
339
|
this.#scope,
|
|
322
340
|
this.#setExpressions,
|
|
323
341
|
this.ctx,
|
|
@@ -338,7 +356,7 @@ export class UpdateQueryImpl<
|
|
|
338
356
|
...annotations: As & ValidAnnotations<'write', As>
|
|
339
357
|
): UpdateQuery<QC, AvailableScope, RowType> {
|
|
340
358
|
return new UpdateQueryImpl(
|
|
341
|
-
this.#
|
|
359
|
+
this.#tableSource,
|
|
342
360
|
this.#scope,
|
|
343
361
|
this.#setExpressions,
|
|
344
362
|
this.ctx,
|
|
@@ -353,7 +371,7 @@ export class UpdateQueryImpl<
|
|
|
353
371
|
}
|
|
354
372
|
|
|
355
373
|
build(): SqlQueryPlan<ResolveRow<RowType, QC['codecTypes'], QC['resolvedColumnOutputTypes']>> {
|
|
356
|
-
let ast = UpdateAst.table(
|
|
374
|
+
let ast = UpdateAst.table(this.#tableSource)
|
|
357
375
|
.withSet(this.#setExpressions)
|
|
358
376
|
.withWhere(combineWhereExprs(this.#whereExprs));
|
|
359
377
|
|
|
@@ -379,6 +397,7 @@ export class DeleteQueryImpl<
|
|
|
379
397
|
extends BuilderBase<QC['capabilities']>
|
|
380
398
|
implements DeleteQuery<QC, AvailableScope, RowType>
|
|
381
399
|
{
|
|
400
|
+
readonly #tableSource: TableSource;
|
|
382
401
|
readonly #tableName: string;
|
|
383
402
|
readonly #scope: Scope;
|
|
384
403
|
readonly #whereCallbacks: readonly WhereCallback[];
|
|
@@ -387,7 +406,7 @@ export class DeleteQueryImpl<
|
|
|
387
406
|
readonly #annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
|
|
388
407
|
|
|
389
408
|
constructor(
|
|
390
|
-
|
|
409
|
+
tableSource: TableSource,
|
|
391
410
|
scope: Scope,
|
|
392
411
|
ctx: BuilderContext,
|
|
393
412
|
whereCallbacks: readonly WhereCallback[] = [],
|
|
@@ -396,7 +415,8 @@ export class DeleteQueryImpl<
|
|
|
396
415
|
annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> = new Map(),
|
|
397
416
|
) {
|
|
398
417
|
super(ctx);
|
|
399
|
-
this.#
|
|
418
|
+
this.#tableSource = tableSource;
|
|
419
|
+
this.#tableName = tableSource.name;
|
|
400
420
|
this.#scope = scope;
|
|
401
421
|
this.#whereCallbacks = whereCallbacks;
|
|
402
422
|
this.#returningColumns = returningColumns;
|
|
@@ -406,7 +426,7 @@ export class DeleteQueryImpl<
|
|
|
406
426
|
|
|
407
427
|
where(expr: ExpressionBuilder<AvailableScope, QC>): DeleteQuery<QC, AvailableScope, RowType> {
|
|
408
428
|
return new DeleteQueryImpl(
|
|
409
|
-
this.#
|
|
429
|
+
this.#tableSource,
|
|
410
430
|
this.#scope,
|
|
411
431
|
this.ctx,
|
|
412
432
|
[...this.#whereCallbacks, expr as unknown as WhereCallback],
|
|
@@ -427,7 +447,7 @@ export class DeleteQueryImpl<
|
|
|
427
447
|
newRowFields[col] = field;
|
|
428
448
|
}
|
|
429
449
|
return new DeleteQueryImpl(
|
|
430
|
-
this.#
|
|
450
|
+
this.#tableSource,
|
|
431
451
|
this.#scope,
|
|
432
452
|
this.ctx,
|
|
433
453
|
this.#whereCallbacks,
|
|
@@ -446,7 +466,7 @@ export class DeleteQueryImpl<
|
|
|
446
466
|
...annotations: As & ValidAnnotations<'write', As>
|
|
447
467
|
): DeleteQuery<QC, AvailableScope, RowType> {
|
|
448
468
|
return new DeleteQueryImpl(
|
|
449
|
-
this.#
|
|
469
|
+
this.#tableSource,
|
|
450
470
|
this.#scope,
|
|
451
471
|
this.ctx,
|
|
452
472
|
this.#whereCallbacks,
|
|
@@ -466,7 +486,7 @@ export class DeleteQueryImpl<
|
|
|
466
486
|
),
|
|
467
487
|
);
|
|
468
488
|
|
|
469
|
-
let ast = DeleteAst.from(
|
|
489
|
+
let ast = DeleteAst.from(this.#tableSource).withWhere(whereExpr);
|
|
470
490
|
|
|
471
491
|
if (this.#returningColumns.length > 0) {
|
|
472
492
|
ast = ast.withReturning(
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SqlStorage, StorageTable } from '@prisma-next/sql-contract/types';
|
|
2
|
+
|
|
3
|
+
export function resolveTableInNamespace(
|
|
4
|
+
storage: SqlStorage,
|
|
5
|
+
namespaceId: string,
|
|
6
|
+
tableName: string,
|
|
7
|
+
): StorageTable | undefined {
|
|
8
|
+
const namespace = storage.namespaces[namespaceId];
|
|
9
|
+
if (namespace === undefined || !Object.hasOwn(namespace.entries.table, tableName)) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
return namespace.entries.table[tableName];
|
|
13
|
+
}
|
package/src/runtime/sql.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
|
-
import type { SqlStorage
|
|
2
|
+
import type { SqlStorage } from '@prisma-next/sql-contract/types';
|
|
3
3
|
import type { RawCodecInferer } from '@prisma-next/sql-relational-core/expression';
|
|
4
4
|
import type { ExecutionContext } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
5
5
|
import type { Db, TableProxyContract } from '../types/db';
|
|
6
6
|
import type { BuilderContext } from './builder-base';
|
|
7
|
+
import { resolveTableInNamespace } from './resolve-table';
|
|
7
8
|
import { TableProxyImpl } from './table-proxy-impl';
|
|
8
9
|
|
|
9
10
|
export interface SqlOptions<C extends Contract<SqlStorage> & TableProxyContract> {
|
|
@@ -11,21 +12,6 @@ export interface SqlOptions<C extends Contract<SqlStorage> & TableProxyContract>
|
|
|
11
12
|
readonly rawCodecInferer: RawCodecInferer;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
// Find a table by name across every declared namespace. Mirrors the
|
|
15
|
-
// flat-DSL contract (db.<tableName>): the first namespace that declares
|
|
16
|
-
// `name` wins. Name collisions across namespaces are a type-level error
|
|
17
|
-
// at the DSL call site; landing the namespace-aware DSL is tracked
|
|
18
|
-
// separately.
|
|
19
|
-
function findTableAcrossNamespaces(storage: SqlStorage, name: string): StorageTable | undefined {
|
|
20
|
-
for (const ns of Object.values(storage.namespaces)) {
|
|
21
|
-
const tables = (ns as { tables?: Readonly<Record<string, StorageTable>> }).tables ?? {};
|
|
22
|
-
if (Object.hasOwn(tables, name)) {
|
|
23
|
-
return tables[name];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return undefined;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
15
|
export function sql<C extends Contract<SqlStorage> & TableProxyContract>(
|
|
30
16
|
options: SqlOptions<C>,
|
|
31
17
|
): Db<C> {
|
|
@@ -40,13 +26,32 @@ export function sql<C extends Contract<SqlStorage> & TableProxyContract>(
|
|
|
40
26
|
rawCodecInferer,
|
|
41
27
|
};
|
|
42
28
|
|
|
29
|
+
const { storage } = context.contract;
|
|
30
|
+
|
|
43
31
|
return new Proxy({} as Db<C>, {
|
|
44
|
-
get(_target, prop: string) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
32
|
+
get(_target, prop: string | symbol) {
|
|
33
|
+
if (typeof prop !== 'string') {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
if (!Object.hasOwn(storage.namespaces, prop)) {
|
|
37
|
+
return undefined;
|
|
48
38
|
}
|
|
49
|
-
|
|
39
|
+
const namespaceId = prop;
|
|
40
|
+
return new Proxy(
|
|
41
|
+
{},
|
|
42
|
+
{
|
|
43
|
+
get(_facetTarget, tableName: string | symbol) {
|
|
44
|
+
if (typeof tableName !== 'string') {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
const table = resolveTableInNamespace(storage, namespaceId, tableName);
|
|
48
|
+
if (table) {
|
|
49
|
+
return new TableProxyImpl(tableName, table, tableName, ctx, namespaceId);
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
);
|
|
50
55
|
},
|
|
51
56
|
});
|
|
52
57
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StorageTable } from '@prisma-next/sql-contract/types';
|
|
2
|
-
import {
|
|
2
|
+
import type { AnyFromSource, TableSource } from '@prisma-next/sql-relational-core/ast';
|
|
3
3
|
import type {
|
|
4
4
|
AggregateFunctions,
|
|
5
5
|
Expression,
|
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
type UpdateSetCallback,
|
|
44
44
|
} from './mutation-impl';
|
|
45
45
|
import { SelectQueryImpl } from './query-impl';
|
|
46
|
+
import { tableSourceForProxy } from './table-source-for-proxy';
|
|
46
47
|
|
|
47
48
|
export class TableProxyImpl<
|
|
48
49
|
C extends TableProxyContract,
|
|
@@ -61,15 +62,27 @@ export class TableProxyImpl<
|
|
|
61
62
|
|
|
62
63
|
readonly #tableName: string;
|
|
63
64
|
readonly #table: StorageTable;
|
|
65
|
+
readonly #namespaceId: string;
|
|
64
66
|
readonly #fromSource: TableSource;
|
|
65
67
|
readonly #scope: Scope;
|
|
66
68
|
|
|
67
|
-
constructor(
|
|
69
|
+
constructor(
|
|
70
|
+
tableName: string,
|
|
71
|
+
table: StorageTable,
|
|
72
|
+
alias: string,
|
|
73
|
+
ctx: BuilderContext,
|
|
74
|
+
namespaceId: string,
|
|
75
|
+
) {
|
|
68
76
|
super(ctx);
|
|
69
77
|
this.#tableName = tableName;
|
|
70
78
|
this.#table = table;
|
|
71
|
-
this.#
|
|
72
|
-
this.#
|
|
79
|
+
this.#namespaceId = namespaceId;
|
|
80
|
+
this.#scope = tableToScope(alias, table, {
|
|
81
|
+
storage: ctx.storage,
|
|
82
|
+
tableName,
|
|
83
|
+
namespaceId,
|
|
84
|
+
});
|
|
85
|
+
this.#fromSource = tableSourceForProxy(tableName, alias, namespaceId);
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
lateralJoin = this._gate(
|
|
@@ -114,7 +127,7 @@ export class TableProxyImpl<
|
|
|
114
127
|
as<NewAlias extends string>(
|
|
115
128
|
newAlias: NewAlias,
|
|
116
129
|
): TableProxy<C, Name, NewAlias, RebindScope<AvailableScope, Alias, NewAlias>, QC> {
|
|
117
|
-
return new TableProxyImpl(this.#tableName, this.#table, newAlias, this.ctx);
|
|
130
|
+
return new TableProxyImpl(this.#tableName, this.#table, newAlias, this.ctx, this.#namespaceId);
|
|
118
131
|
}
|
|
119
132
|
|
|
120
133
|
select<Columns extends (keyof AvailableScope['topLevel'] & string)[]>(
|
|
@@ -165,7 +178,14 @@ export class TableProxyImpl<
|
|
|
165
178
|
}
|
|
166
179
|
|
|
167
180
|
insert(rows: ReadonlyArray<Record<string, unknown>>): InsertQuery<QC, AvailableScope, EmptyRow> {
|
|
168
|
-
return new InsertQueryImpl(
|
|
181
|
+
return new InsertQueryImpl(
|
|
182
|
+
this.#fromSource,
|
|
183
|
+
this.#namespaceId,
|
|
184
|
+
this.#table,
|
|
185
|
+
this.#scope,
|
|
186
|
+
rows,
|
|
187
|
+
this.ctx,
|
|
188
|
+
);
|
|
169
189
|
}
|
|
170
190
|
|
|
171
191
|
update(
|
|
@@ -185,25 +205,27 @@ export class TableProxyImpl<
|
|
|
185
205
|
);
|
|
186
206
|
const setExpressions = buildSetExpressions(
|
|
187
207
|
callbackExprs,
|
|
208
|
+
this.#namespaceId,
|
|
188
209
|
this.#table,
|
|
189
210
|
this.#tableName,
|
|
190
211
|
'update',
|
|
191
212
|
this.ctx,
|
|
192
213
|
);
|
|
193
|
-
return new UpdateQueryImpl(this.#
|
|
214
|
+
return new UpdateQueryImpl(this.#fromSource, this.#scope, setExpressions, this.ctx);
|
|
194
215
|
}
|
|
195
216
|
const setExpressions = buildParamValues(
|
|
196
217
|
setOrCallback,
|
|
218
|
+
this.#namespaceId,
|
|
197
219
|
this.#table,
|
|
198
220
|
this.#tableName,
|
|
199
221
|
'update',
|
|
200
222
|
this.ctx,
|
|
201
223
|
);
|
|
202
|
-
return new UpdateQueryImpl(this.#
|
|
224
|
+
return new UpdateQueryImpl(this.#fromSource, this.#scope, setExpressions, this.ctx);
|
|
203
225
|
}
|
|
204
226
|
|
|
205
227
|
delete(): DeleteQuery<QC, AvailableScope, EmptyRow> {
|
|
206
|
-
return new DeleteQueryImpl(this.#
|
|
228
|
+
return new DeleteQueryImpl(this.#fromSource, this.#scope, this.ctx);
|
|
207
229
|
}
|
|
208
230
|
|
|
209
231
|
#toJoined(): JoinedTables<QC, AvailableScope> {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TableSource } from '@prisma-next/sql-relational-core/ast';
|
|
2
|
+
|
|
3
|
+
export function tableSourceForProxy(
|
|
4
|
+
tableName: string,
|
|
5
|
+
alias: string,
|
|
6
|
+
namespaceId: string,
|
|
7
|
+
): TableSource {
|
|
8
|
+
return TableSource.named(tableName, alias !== tableName ? alias : undefined, namespaceId);
|
|
9
|
+
}
|
package/src/types/db.ts
CHANGED
|
@@ -3,16 +3,13 @@ import type { TableProxy } from './table-proxy';
|
|
|
3
3
|
|
|
4
4
|
export type CapabilitiesBase = Record<string, Record<string, boolean>>;
|
|
5
5
|
|
|
6
|
-
// The sql-builder DSL is flat by table name across every declared
|
|
7
|
-
// namespace. Two namespaces declaring tables with the same name produce
|
|
8
|
-
// a union at the DSL surface (which collapses to a type error at the
|
|
9
|
-
// first call site); landing the namespace-aware DSL surface (db.<ns>.<table>)
|
|
10
|
-
// is tracked separately. Within scope here: the DSL accepts the
|
|
11
|
-
// namespaced storage shape directly and walks every namespace.
|
|
12
6
|
export type TableProxyContract = {
|
|
13
7
|
readonly storage: {
|
|
14
8
|
readonly namespaces: Readonly<
|
|
15
|
-
Record<
|
|
9
|
+
Record<
|
|
10
|
+
string,
|
|
11
|
+
{ readonly entries: { readonly table: Readonly<Record<string, StorageTable>> } }
|
|
12
|
+
>
|
|
16
13
|
>;
|
|
17
14
|
};
|
|
18
15
|
readonly capabilities: CapabilitiesBase;
|
|
@@ -24,17 +21,28 @@ export type UnboundTables<C extends TableProxyContract> = {
|
|
|
24
21
|
readonly [Name in TableNamesAcrossNamespaces<C>]: TableInAnyNamespace<C, Name>;
|
|
25
22
|
};
|
|
26
23
|
|
|
27
|
-
type TableNamesAcrossNamespaces<C extends TableProxyContract> = {
|
|
28
|
-
[NSId in keyof C['storage']['namespaces']]: keyof C['storage']['namespaces'][NSId]['
|
|
24
|
+
export type TableNamesAcrossNamespaces<C extends TableProxyContract> = {
|
|
25
|
+
[NSId in keyof C['storage']['namespaces']]: keyof C['storage']['namespaces'][NSId]['entries']['table'] &
|
|
29
26
|
string;
|
|
30
27
|
}[keyof C['storage']['namespaces']];
|
|
31
28
|
|
|
32
|
-
type TableInAnyNamespace<C extends TableProxyContract, Name extends string> = {
|
|
33
|
-
[NSId in keyof C['storage']['namespaces']]: Name extends keyof C['storage']['namespaces'][NSId]['
|
|
34
|
-
? C['storage']['namespaces'][NSId]['
|
|
29
|
+
export type TableInAnyNamespace<C extends TableProxyContract, Name extends string> = {
|
|
30
|
+
[NSId in keyof C['storage']['namespaces']]: Name extends keyof C['storage']['namespaces'][NSId]['entries']['table']
|
|
31
|
+
? C['storage']['namespaces'][NSId]['entries']['table'][Name]
|
|
35
32
|
: never;
|
|
36
33
|
}[keyof C['storage']['namespaces']];
|
|
37
34
|
|
|
35
|
+
// The tables of a single storage namespace, keyed by bare table name. Lets
|
|
36
|
+
// callers reach a table by its namespace coordinate (`db.<ns>.<table>`) when
|
|
37
|
+
// the same bare name is declared in more than one namespace.
|
|
38
|
+
export type Namespace<
|
|
39
|
+
C extends TableProxyContract,
|
|
40
|
+
NsId extends keyof C['storage']['namespaces'],
|
|
41
|
+
> = {
|
|
42
|
+
readonly [Name in keyof C['storage']['namespaces'][NsId]['entries']['table'] &
|
|
43
|
+
string]: TableProxy<C, Name>;
|
|
44
|
+
};
|
|
45
|
+
|
|
38
46
|
export type Db<C extends TableProxyContract> = {
|
|
39
|
-
[
|
|
47
|
+
readonly [Ns in keyof C['storage']['namespaces']]: Namespace<C, Ns>;
|
|
40
48
|
};
|
package/src/types/table-proxy.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Contract,
|
|
1
|
+
import type { Contract, ContractModelDefinitions } from '@prisma-next/contract/types';
|
|
2
2
|
import type {
|
|
3
3
|
ExtractCodecTypes,
|
|
4
4
|
ExtractFieldInputTypes,
|
|
@@ -22,24 +22,24 @@ import type { WithJoin, WithSelect } from './shared';
|
|
|
22
22
|
|
|
23
23
|
type FindModelForTable<C, TableName extends string> = C extends Contract
|
|
24
24
|
? {
|
|
25
|
-
[M in keyof
|
|
25
|
+
[M in keyof ContractModelDefinitions<C> & string]: ContractModelDefinitions<C>[M] extends {
|
|
26
26
|
readonly storage: { readonly table: TableName };
|
|
27
27
|
}
|
|
28
28
|
? M
|
|
29
29
|
: never;
|
|
30
|
-
}[keyof
|
|
30
|
+
}[keyof ContractModelDefinitions<C> & string]
|
|
31
31
|
: never;
|
|
32
32
|
|
|
33
33
|
type FindFieldForColumn<C, ModelName extends string, ColumnName extends string> = C extends Contract
|
|
34
|
-
? ModelName extends keyof
|
|
34
|
+
? ModelName extends keyof ContractModelDefinitions<C>
|
|
35
35
|
? {
|
|
36
|
-
[F in keyof
|
|
37
|
-
string]:
|
|
36
|
+
[F in keyof ContractModelDefinitions<C>[ModelName]['storage']['fields'] &
|
|
37
|
+
string]: ContractModelDefinitions<C>[ModelName]['storage']['fields'][F] extends {
|
|
38
38
|
readonly column: ColumnName;
|
|
39
39
|
}
|
|
40
40
|
? F
|
|
41
41
|
: never;
|
|
42
|
-
}[keyof
|
|
42
|
+
}[keyof ContractModelDefinitions<C>[ModelName]['storage']['fields'] & string]
|
|
43
43
|
: never
|
|
44
44
|
: never;
|
|
45
45
|
|