@prisma-next/sql-builder 0.12.0-dev.17 → 0.12.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.
@@ -12,7 +12,7 @@ import {
12
12
  InsertAst,
13
13
  ParamRef,
14
14
  ProjectionItem,
15
- type TableSource,
15
+ 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';
@@ -153,7 +153,6 @@ export class InsertQueryImpl<
153
153
  extends BuilderBase<QC['capabilities']>
154
154
  implements InsertQuery<QC, AvailableScope, RowType>
155
155
  {
156
- readonly #tableSource: TableSource;
157
156
  readonly #tableName: string;
158
157
  readonly #table: StorageTable;
159
158
  readonly #scope: Scope;
@@ -163,7 +162,7 @@ export class InsertQueryImpl<
163
162
  readonly #annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
164
163
 
165
164
  constructor(
166
- tableSource: TableSource,
165
+ tableName: string,
167
166
  table: StorageTable,
168
167
  scope: Scope,
169
168
  rows: ReadonlyArray<Record<string, unknown>>,
@@ -173,8 +172,7 @@ export class InsertQueryImpl<
173
172
  annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> = new Map(),
174
173
  ) {
175
174
  super(ctx);
176
- this.#tableSource = tableSource;
177
- this.#tableName = tableSource.name;
175
+ this.#tableName = tableName;
178
176
  this.#table = table;
179
177
  this.#scope = scope;
180
178
  this.#rows = rows;
@@ -194,7 +192,7 @@ export class InsertQueryImpl<
194
192
  newRowFields[col] = field;
195
193
  }
196
194
  return new InsertQueryImpl(
197
- this.#tableSource,
195
+ this.#tableName,
198
196
  this.#table,
199
197
  this.#scope,
200
198
  this.#rows,
@@ -217,7 +215,7 @@ export class InsertQueryImpl<
217
215
  ...annotations: As & ValidAnnotations<'write', As>
218
216
  ): InsertQuery<QC, AvailableScope, RowType> {
219
217
  return new InsertQueryImpl(
220
- this.#tableSource,
218
+ this.#tableName,
221
219
  this.#table,
222
220
  this.#scope,
223
221
  this.#rows,
@@ -240,7 +238,7 @@ export class InsertQueryImpl<
240
238
  buildParamValues(rowValues, this.#table, this.#tableName, 'create', this.ctx),
241
239
  );
242
240
 
243
- let ast = InsertAst.into(this.#tableSource).withRows(paramRows);
241
+ let ast = InsertAst.into(TableSource.named(this.#tableName)).withRows(paramRows);
244
242
 
245
243
  if (this.#returningColumns.length > 0) {
246
244
  ast = ast.withReturning(
@@ -264,7 +262,6 @@ export class UpdateQueryImpl<
264
262
  extends BuilderBase<QC['capabilities']>
265
263
  implements UpdateQuery<QC, AvailableScope, RowType>
266
264
  {
267
- readonly #tableSource: TableSource;
268
265
  readonly #tableName: string;
269
266
  readonly #scope: Scope;
270
267
  readonly #setExpressions: Record<string, AstExpression>;
@@ -274,7 +271,7 @@ export class UpdateQueryImpl<
274
271
  readonly #annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
275
272
 
276
273
  constructor(
277
- tableSource: TableSource,
274
+ tableName: string,
278
275
  scope: Scope,
279
276
  setExpressions: Record<string, AstExpression>,
280
277
  ctx: BuilderContext,
@@ -284,8 +281,7 @@ export class UpdateQueryImpl<
284
281
  annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> = new Map(),
285
282
  ) {
286
283
  super(ctx);
287
- this.#tableSource = tableSource;
288
- this.#tableName = tableSource.name;
284
+ this.#tableName = tableName;
289
285
  this.#scope = scope;
290
286
  this.#setExpressions = setExpressions;
291
287
  this.#whereExprs = whereExprs;
@@ -299,7 +295,7 @@ export class UpdateQueryImpl<
299
295
  const fns = createFunctions(this.ctx.queryOperationTypes, this.ctx.rawCodecInferer);
300
296
  const result = (expr as ExpressionBuilder<Scope, QueryContext>)(fieldProxy, fns as never);
301
297
  return new UpdateQueryImpl(
302
- this.#tableSource,
298
+ this.#tableName,
303
299
  this.#scope,
304
300
  this.#setExpressions,
305
301
  this.ctx,
@@ -321,7 +317,7 @@ export class UpdateQueryImpl<
321
317
  newRowFields[col] = field;
322
318
  }
323
319
  return new UpdateQueryImpl(
324
- this.#tableSource,
320
+ this.#tableName,
325
321
  this.#scope,
326
322
  this.#setExpressions,
327
323
  this.ctx,
@@ -342,7 +338,7 @@ export class UpdateQueryImpl<
342
338
  ...annotations: As & ValidAnnotations<'write', As>
343
339
  ): UpdateQuery<QC, AvailableScope, RowType> {
344
340
  return new UpdateQueryImpl(
345
- this.#tableSource,
341
+ this.#tableName,
346
342
  this.#scope,
347
343
  this.#setExpressions,
348
344
  this.ctx,
@@ -357,7 +353,7 @@ export class UpdateQueryImpl<
357
353
  }
358
354
 
359
355
  build(): SqlQueryPlan<ResolveRow<RowType, QC['codecTypes'], QC['resolvedColumnOutputTypes']>> {
360
- let ast = UpdateAst.table(this.#tableSource)
356
+ let ast = UpdateAst.table(TableSource.named(this.#tableName))
361
357
  .withSet(this.#setExpressions)
362
358
  .withWhere(combineWhereExprs(this.#whereExprs));
363
359
 
@@ -383,7 +379,6 @@ export class DeleteQueryImpl<
383
379
  extends BuilderBase<QC['capabilities']>
384
380
  implements DeleteQuery<QC, AvailableScope, RowType>
385
381
  {
386
- readonly #tableSource: TableSource;
387
382
  readonly #tableName: string;
388
383
  readonly #scope: Scope;
389
384
  readonly #whereCallbacks: readonly WhereCallback[];
@@ -392,7 +387,7 @@ export class DeleteQueryImpl<
392
387
  readonly #annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>>;
393
388
 
394
389
  constructor(
395
- tableSource: TableSource,
390
+ tableName: string,
396
391
  scope: Scope,
397
392
  ctx: BuilderContext,
398
393
  whereCallbacks: readonly WhereCallback[] = [],
@@ -401,8 +396,7 @@ export class DeleteQueryImpl<
401
396
  annotations: ReadonlyMap<string, AnnotationValue<unknown, OperationKind>> = new Map(),
402
397
  ) {
403
398
  super(ctx);
404
- this.#tableSource = tableSource;
405
- this.#tableName = tableSource.name;
399
+ this.#tableName = tableName;
406
400
  this.#scope = scope;
407
401
  this.#whereCallbacks = whereCallbacks;
408
402
  this.#returningColumns = returningColumns;
@@ -412,7 +406,7 @@ export class DeleteQueryImpl<
412
406
 
413
407
  where(expr: ExpressionBuilder<AvailableScope, QC>): DeleteQuery<QC, AvailableScope, RowType> {
414
408
  return new DeleteQueryImpl(
415
- this.#tableSource,
409
+ this.#tableName,
416
410
  this.#scope,
417
411
  this.ctx,
418
412
  [...this.#whereCallbacks, expr as unknown as WhereCallback],
@@ -433,7 +427,7 @@ export class DeleteQueryImpl<
433
427
  newRowFields[col] = field;
434
428
  }
435
429
  return new DeleteQueryImpl(
436
- this.#tableSource,
430
+ this.#tableName,
437
431
  this.#scope,
438
432
  this.ctx,
439
433
  this.#whereCallbacks,
@@ -452,7 +446,7 @@ export class DeleteQueryImpl<
452
446
  ...annotations: As & ValidAnnotations<'write', As>
453
447
  ): DeleteQuery<QC, AvailableScope, RowType> {
454
448
  return new DeleteQueryImpl(
455
- this.#tableSource,
449
+ this.#tableName,
456
450
  this.#scope,
457
451
  this.ctx,
458
452
  this.#whereCallbacks,
@@ -472,7 +466,7 @@ export class DeleteQueryImpl<
472
466
  ),
473
467
  );
474
468
 
475
- let ast = DeleteAst.from(this.#tableSource).withWhere(whereExpr);
469
+ let ast = DeleteAst.from(TableSource.named(this.#tableName)).withWhere(whereExpr);
476
470
 
477
471
  if (this.#returningColumns.length > 0) {
478
472
  ast = ast.withReturning(
@@ -1,10 +1,9 @@
1
1
  import type { Contract } from '@prisma-next/contract/types';
2
- import type { SqlStorage } from '@prisma-next/sql-contract/types';
2
+ import type { SqlStorage, StorageTable } 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 { resolveTableForFlatName } from './resolve-table';
8
7
  import { TableProxyImpl } from './table-proxy-impl';
9
8
 
10
9
  export interface SqlOptions<C extends Contract<SqlStorage> & TableProxyContract> {
@@ -12,6 +11,21 @@ export interface SqlOptions<C extends Contract<SqlStorage> & TableProxyContract>
12
11
  readonly rawCodecInferer: RawCodecInferer;
13
12
  }
14
13
 
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
+
15
29
  export function sql<C extends Contract<SqlStorage> & TableProxyContract>(
16
30
  options: SqlOptions<C>,
17
31
  ): Db<C> {
@@ -28,9 +42,9 @@ export function sql<C extends Contract<SqlStorage> & TableProxyContract>(
28
42
 
29
43
  return new Proxy({} as Db<C>, {
30
44
  get(_target, prop: string) {
31
- const resolved = resolveTableForFlatName(context.contract.storage, prop);
32
- if (resolved) {
33
- return new TableProxyImpl(prop, resolved.table, prop, ctx, resolved.namespaceId);
45
+ const table = findTableAcrossNamespaces(context.contract.storage, prop);
46
+ if (table) {
47
+ return new TableProxyImpl(prop, table, prop, ctx);
34
48
  }
35
49
  return undefined;
36
50
  },
@@ -1,5 +1,5 @@
1
1
  import type { StorageTable } from '@prisma-next/sql-contract/types';
2
- import type { AnyFromSource, TableSource } from '@prisma-next/sql-relational-core/ast';
2
+ import { type AnyFromSource, TableSource } from '@prisma-next/sql-relational-core/ast';
3
3
  import type {
4
4
  AggregateFunctions,
5
5
  Expression,
@@ -43,7 +43,6 @@ 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';
47
46
 
48
47
  export class TableProxyImpl<
49
48
  C extends TableProxyContract,
@@ -62,23 +61,15 @@ export class TableProxyImpl<
62
61
 
63
62
  readonly #tableName: string;
64
63
  readonly #table: StorageTable;
65
- readonly #namespaceId: string;
66
64
  readonly #fromSource: TableSource;
67
65
  readonly #scope: Scope;
68
66
 
69
- constructor(
70
- tableName: string,
71
- table: StorageTable,
72
- alias: string,
73
- ctx: BuilderContext,
74
- namespaceId: string,
75
- ) {
67
+ constructor(tableName: string, table: StorageTable, alias: string, ctx: BuilderContext) {
76
68
  super(ctx);
77
69
  this.#tableName = tableName;
78
70
  this.#table = table;
79
- this.#namespaceId = namespaceId;
80
71
  this.#scope = tableToScope(alias, table, { storage: ctx.storage, tableName });
81
- this.#fromSource = tableSourceForProxy(tableName, alias, namespaceId);
72
+ this.#fromSource = TableSource.named(tableName, alias !== tableName ? alias : undefined);
82
73
  }
83
74
 
84
75
  lateralJoin = this._gate(
@@ -123,7 +114,7 @@ export class TableProxyImpl<
123
114
  as<NewAlias extends string>(
124
115
  newAlias: NewAlias,
125
116
  ): TableProxy<C, Name, NewAlias, RebindScope<AvailableScope, Alias, NewAlias>, QC> {
126
- return new TableProxyImpl(this.#tableName, this.#table, newAlias, this.ctx, this.#namespaceId);
117
+ return new TableProxyImpl(this.#tableName, this.#table, newAlias, this.ctx);
127
118
  }
128
119
 
129
120
  select<Columns extends (keyof AvailableScope['topLevel'] & string)[]>(
@@ -174,7 +165,7 @@ export class TableProxyImpl<
174
165
  }
175
166
 
176
167
  insert(rows: ReadonlyArray<Record<string, unknown>>): InsertQuery<QC, AvailableScope, EmptyRow> {
177
- return new InsertQueryImpl(this.#fromSource, this.#table, this.#scope, rows, this.ctx);
168
+ return new InsertQueryImpl(this.#tableName, this.#table, this.#scope, rows, this.ctx);
178
169
  }
179
170
 
180
171
  update(
@@ -199,7 +190,7 @@ export class TableProxyImpl<
199
190
  'update',
200
191
  this.ctx,
201
192
  );
202
- return new UpdateQueryImpl(this.#fromSource, this.#scope, setExpressions, this.ctx);
193
+ return new UpdateQueryImpl(this.#tableName, this.#scope, setExpressions, this.ctx);
203
194
  }
204
195
  const setExpressions = buildParamValues(
205
196
  setOrCallback,
@@ -208,11 +199,11 @@ export class TableProxyImpl<
208
199
  'update',
209
200
  this.ctx,
210
201
  );
211
- return new UpdateQueryImpl(this.#fromSource, this.#scope, setExpressions, this.ctx);
202
+ return new UpdateQueryImpl(this.#tableName, this.#scope, setExpressions, this.ctx);
212
203
  }
213
204
 
214
205
  delete(): DeleteQuery<QC, AvailableScope, EmptyRow> {
215
- return new DeleteQueryImpl(this.#fromSource, this.#scope, this.ctx);
206
+ return new DeleteQueryImpl(this.#tableName, this.#scope, this.ctx);
216
207
  }
217
208
 
218
209
  #toJoined(): JoinedTables<QC, AvailableScope> {
package/src/types/db.ts CHANGED
@@ -24,12 +24,12 @@ export type UnboundTables<C extends TableProxyContract> = {
24
24
  readonly [Name in TableNamesAcrossNamespaces<C>]: TableInAnyNamespace<C, Name>;
25
25
  };
26
26
 
27
- export type TableNamesAcrossNamespaces<C extends TableProxyContract> = {
27
+ type TableNamesAcrossNamespaces<C extends TableProxyContract> = {
28
28
  [NSId in keyof C['storage']['namespaces']]: keyof C['storage']['namespaces'][NSId]['tables'] &
29
29
  string;
30
30
  }[keyof C['storage']['namespaces']];
31
31
 
32
- export type TableInAnyNamespace<C extends TableProxyContract, Name extends string> = {
32
+ type TableInAnyNamespace<C extends TableProxyContract, Name extends string> = {
33
33
  [NSId in keyof C['storage']['namespaces']]: Name extends keyof C['storage']['namespaces'][NSId]['tables']
34
34
  ? C['storage']['namespaces'][NSId]['tables'][Name]
35
35
  : never;
@@ -1,4 +1,4 @@
1
- import type { Contract, ContractModelDefinitions } from '@prisma-next/contract/types';
1
+ import type { Contract, ContractModelsMap } 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 ContractModelDefinitions<C> & string]: ContractModelDefinitions<C>[M] extends {
25
+ [M in keyof ContractModelsMap<C> & string]: ContractModelsMap<C>[M] extends {
26
26
  readonly storage: { readonly table: TableName };
27
27
  }
28
28
  ? M
29
29
  : never;
30
- }[keyof ContractModelDefinitions<C> & string]
30
+ }[keyof ContractModelsMap<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 ContractModelDefinitions<C>
34
+ ? ModelName extends keyof ContractModelsMap<C>
35
35
  ? {
36
- [F in keyof ContractModelDefinitions<C>[ModelName]['storage']['fields'] &
37
- string]: ContractModelDefinitions<C>[ModelName]['storage']['fields'][F] extends {
36
+ [F in keyof ContractModelsMap<C>[ModelName]['storage']['fields'] &
37
+ string]: ContractModelsMap<C>[ModelName]['storage']['fields'][F] extends {
38
38
  readonly column: ColumnName;
39
39
  }
40
40
  ? F
41
41
  : never;
42
- }[keyof ContractModelDefinitions<C>[ModelName]['storage']['fields'] & string]
42
+ }[keyof ContractModelsMap<C>[ModelName]['storage']['fields'] & string]
43
43
  : never
44
44
  : never;
45
45
 
@@ -1,18 +0,0 @@
1
- import { resolveStorageTable } from '@prisma-next/sql-contract/resolve-storage-table';
2
- import type { SqlStorage, StorageTable } from '@prisma-next/sql-contract/types';
3
-
4
- export interface ResolvedTable {
5
- readonly namespaceId: string;
6
- readonly table: StorageTable;
7
- }
8
-
9
- export function resolveTableForFlatName(
10
- storage: SqlStorage,
11
- tableName: string,
12
- ): ResolvedTable | undefined {
13
- const resolved = resolveStorageTable(storage, tableName);
14
- if (resolved === undefined) {
15
- return undefined;
16
- }
17
- return resolved;
18
- }
@@ -1,9 +0,0 @@
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
- }