@query-graph/core 1.0.0-next.1 → 1.1.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/README.md +189 -91
- package/definition.d.ts +117 -39
- package/dsl.d.ts +789 -98
- package/index.js +50 -50
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -55,51 +55,65 @@ import {
|
|
|
55
55
|
source,
|
|
56
56
|
} from '@query-graph/core/dsl'
|
|
57
57
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
const users = source('users', {
|
|
59
|
+
id: 'int64',
|
|
60
|
+
email: 'string',
|
|
61
61
|
})
|
|
62
62
|
|
|
63
|
-
const
|
|
63
|
+
const profiles = source('profiles', {
|
|
64
64
|
id: 'int64',
|
|
65
|
-
|
|
65
|
+
userId: 'int64',
|
|
66
|
+
displayName: nullable('string'),
|
|
66
67
|
})
|
|
67
68
|
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
name: '
|
|
71
|
-
from:
|
|
72
|
-
to:
|
|
73
|
-
on: eq(
|
|
69
|
+
const userId = requiredParameter('userId', 'int64')
|
|
70
|
+
const profileRelation = relation({
|
|
71
|
+
name: 'profile',
|
|
72
|
+
from: users,
|
|
73
|
+
to: profiles,
|
|
74
|
+
on: eq(users.field('id'), profiles.field('userId')),
|
|
75
|
+
cardinality: 'one',
|
|
74
76
|
required: true,
|
|
77
|
+
selection: firstBy(asc(profiles.field('id'))),
|
|
75
78
|
})
|
|
76
79
|
|
|
77
|
-
const
|
|
78
|
-
name: '
|
|
79
|
-
sources: [
|
|
80
|
-
parameters: [
|
|
81
|
-
relations: [
|
|
80
|
+
const userProfileModule = defineGraphModule({
|
|
81
|
+
name: 'userProfile',
|
|
82
|
+
sources: [users, profiles],
|
|
83
|
+
parameters: [userId],
|
|
84
|
+
relations: [profileRelation],
|
|
82
85
|
constraints: [
|
|
83
86
|
constraint({
|
|
84
|
-
predicate: eq(
|
|
87
|
+
predicate: eq(users.field('id'), param(userId)),
|
|
85
88
|
}),
|
|
86
89
|
constraint({
|
|
87
|
-
predicate: exists(
|
|
90
|
+
predicate: exists(profiles, isNotNull(profiles.field('displayName'))),
|
|
88
91
|
}),
|
|
89
92
|
],
|
|
90
93
|
projection: [
|
|
91
94
|
project({
|
|
92
|
-
path: '
|
|
93
|
-
expression:
|
|
95
|
+
path: 'id',
|
|
96
|
+
expression: users.field('id'),
|
|
97
|
+
default: true,
|
|
98
|
+
}),
|
|
99
|
+
project({
|
|
100
|
+
path: 'profile.displayName',
|
|
101
|
+
expression: profiles.field('displayName'),
|
|
102
|
+
}),
|
|
103
|
+
],
|
|
104
|
+
orderings: [
|
|
105
|
+
ordering({
|
|
106
|
+
name: 'idAsc',
|
|
107
|
+
by: [asc(users.field('id'))],
|
|
94
108
|
default: true,
|
|
95
109
|
}),
|
|
96
110
|
],
|
|
97
111
|
})
|
|
98
112
|
|
|
99
113
|
const definition = defineGraph({
|
|
100
|
-
name: '
|
|
101
|
-
root:
|
|
102
|
-
modules: [
|
|
114
|
+
name: 'userProfile',
|
|
115
|
+
root: users,
|
|
116
|
+
modules: [userProfileModule],
|
|
103
117
|
})
|
|
104
118
|
|
|
105
119
|
const graph = registerDefinition(definition)
|
|
@@ -149,30 +163,30 @@ npm install @query-graph/core @query-graph/dsl-object
|
|
|
149
163
|
import { registerDefinition } from '@query-graph/core'
|
|
150
164
|
import { asc, defineGraph, eq, firstBy, project, relation, source } from '@query-graph/dsl-object'
|
|
151
165
|
|
|
152
|
-
const
|
|
153
|
-
const
|
|
166
|
+
const users = source('users', { id: 'int64' })
|
|
167
|
+
const profiles = source('profiles', {
|
|
154
168
|
id: 'int64',
|
|
155
|
-
|
|
156
|
-
|
|
169
|
+
userId: 'int64',
|
|
170
|
+
displayName: 'string',
|
|
157
171
|
})
|
|
158
172
|
|
|
159
173
|
const definition = defineGraph({
|
|
160
|
-
name: '
|
|
161
|
-
root:
|
|
162
|
-
sources: [
|
|
174
|
+
name: 'users',
|
|
175
|
+
root: users,
|
|
176
|
+
sources: [users, profiles],
|
|
163
177
|
relations: [
|
|
164
178
|
relation({
|
|
165
|
-
name: '
|
|
166
|
-
from:
|
|
167
|
-
to:
|
|
168
|
-
on: eq(
|
|
179
|
+
name: 'profile',
|
|
180
|
+
from: users,
|
|
181
|
+
to: profiles,
|
|
182
|
+
on: eq(users.field('id'), profiles.field('userId')),
|
|
169
183
|
cardinality: 'one',
|
|
170
|
-
selection: firstBy(asc(
|
|
184
|
+
selection: firstBy(asc(profiles.field('id'))),
|
|
171
185
|
}),
|
|
172
186
|
],
|
|
173
187
|
projection: [
|
|
174
|
-
project({ path: 'id', expression:
|
|
175
|
-
project({ path: '
|
|
188
|
+
project({ path: 'id', expression: users.field('id'), default: true }),
|
|
189
|
+
project({ path: 'profile.displayName', expression: profiles.field('displayName') }),
|
|
176
190
|
],
|
|
177
191
|
})
|
|
178
192
|
|
|
@@ -194,7 +208,7 @@ const graph = registerDefinition(definition)
|
|
|
194
208
|
|
|
195
209
|
```ts
|
|
196
210
|
constraint({
|
|
197
|
-
predicate: exists(
|
|
211
|
+
predicate: exists(memberships, eq(memberships.field('teamId'), param(teamId))),
|
|
198
212
|
})
|
|
199
213
|
```
|
|
200
214
|
|
|
@@ -213,7 +227,7 @@ Oracle и SQL Server compiler строят коррелированный `EXIST
|
|
|
213
227
|
|
|
214
228
|
```ts
|
|
215
229
|
constraint({
|
|
216
|
-
predicate: exists(
|
|
230
|
+
predicate: exists(permissions, permissionPredicate, { from: memberships }),
|
|
217
231
|
})
|
|
218
232
|
```
|
|
219
233
|
|
|
@@ -228,28 +242,38 @@ constraint({
|
|
|
228
242
|
`number | number[]`.
|
|
229
243
|
|
|
230
244
|
```ts
|
|
231
|
-
const
|
|
245
|
+
const users = source('users', {
|
|
246
|
+
id: 'int64',
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
const memberships = source('memberships', {
|
|
250
|
+
id: 'int64',
|
|
251
|
+
userId: 'int64',
|
|
252
|
+
teamId: 'int64',
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
const teamIds = requiredListParameter('teamIds', 'int64')
|
|
232
256
|
|
|
233
257
|
const definition = defineGraph({
|
|
234
|
-
name: '
|
|
235
|
-
root:
|
|
236
|
-
sources: [
|
|
237
|
-
parameters: [
|
|
258
|
+
name: 'usersByTeams',
|
|
259
|
+
root: users,
|
|
260
|
+
sources: [users, memberships],
|
|
261
|
+
parameters: [teamIds],
|
|
238
262
|
relations: [
|
|
239
263
|
relation({
|
|
240
|
-
name: '
|
|
241
|
-
from:
|
|
242
|
-
to:
|
|
243
|
-
on: eq(
|
|
264
|
+
name: 'memberships',
|
|
265
|
+
from: users,
|
|
266
|
+
to: memberships,
|
|
267
|
+
on: eq(users.field('id'), memberships.field('userId')),
|
|
244
268
|
cardinality: 'many',
|
|
245
269
|
}),
|
|
246
270
|
],
|
|
247
271
|
constraints: [
|
|
248
272
|
constraint({
|
|
249
|
-
predicate: exists(
|
|
273
|
+
predicate: exists(memberships, inParameter(memberships.field('teamId'), teamIds)),
|
|
250
274
|
}),
|
|
251
275
|
],
|
|
252
|
-
projection: [project({ path: 'id', expression:
|
|
276
|
+
projection: [project({ path: 'id', expression: users.field('id'), default: true })],
|
|
253
277
|
})
|
|
254
278
|
```
|
|
255
279
|
|
|
@@ -257,15 +281,15 @@ Operation передает обычный массив:
|
|
|
257
281
|
|
|
258
282
|
```ts
|
|
259
283
|
const statement = relationalGraph.compileSqlServer({
|
|
260
|
-
parameters: {
|
|
284
|
+
parameters: { teamIds: [12, 18, 24] },
|
|
261
285
|
})
|
|
262
286
|
```
|
|
263
287
|
|
|
264
288
|
Compiler разворачивает его в `IN (@p0, @p1, @p2)`. Каждый элемент получает
|
|
265
|
-
binding `{ parameter: '
|
|
289
|
+
binding `{ parameter: 'teamIds', index, scalarType: 'int64' }`, по которому
|
|
266
290
|
adapter исполнения берет значение из исходного массива. Rust проверяет каждый
|
|
267
291
|
элемент отдельно и возвращает путь ошибки наподобие
|
|
268
|
-
`parameters.
|
|
292
|
+
`parameters.teamIds[2]`.
|
|
269
293
|
|
|
270
294
|
Отсутствующий optional list отключает constraint с `when`. Переданный пустой
|
|
271
295
|
список остается присутствующим параметром и компилируется в ложный предикат
|
|
@@ -302,12 +326,12 @@ TypeScript выводит union имен из definition и подключенн
|
|
|
302
326
|
одной строки:
|
|
303
327
|
|
|
304
328
|
```ts
|
|
305
|
-
const
|
|
306
|
-
name: '
|
|
307
|
-
from:
|
|
308
|
-
to:
|
|
309
|
-
on: eq(
|
|
310
|
-
selection: firstBy(asc(
|
|
329
|
+
const profile = relation({
|
|
330
|
+
name: 'profile',
|
|
331
|
+
from: users,
|
|
332
|
+
to: profiles,
|
|
333
|
+
on: eq(users.field('id'), profiles.field('userId')),
|
|
334
|
+
selection: firstBy(asc(profiles.field('id'))),
|
|
311
335
|
})
|
|
312
336
|
```
|
|
313
337
|
|
|
@@ -327,46 +351,60 @@ SQL Server renderer использует `OUTER/CROSS APPLY` и `TOP (1)`, Oracl
|
|
|
327
351
|
SQL-конструкции `GROUP BY` и `HAVING`:
|
|
328
352
|
|
|
329
353
|
```ts
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
354
|
+
const teams = source('teams', {
|
|
355
|
+
id: 'int64',
|
|
356
|
+
workspaceId: 'int64',
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
const memberships = source('memberships', {
|
|
360
|
+
id: 'int64',
|
|
361
|
+
userId: 'int64',
|
|
362
|
+
teamId: 'int64',
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
const workspaceId = requiredParameter('workspaceId', 'int64')
|
|
366
|
+
const minimumMembers = requiredParameter('minimumMembers', 'int64')
|
|
367
|
+
|
|
368
|
+
const teamId = dimension({
|
|
369
|
+
path: 'teamId',
|
|
370
|
+
expression: teams.field('id'),
|
|
333
371
|
default: true,
|
|
334
372
|
})
|
|
335
373
|
|
|
336
|
-
const
|
|
337
|
-
path: '
|
|
338
|
-
expression: countDistinct(
|
|
374
|
+
const memberCount = measure({
|
|
375
|
+
path: 'memberCount',
|
|
376
|
+
expression: countDistinct(memberships.field('userId')),
|
|
339
377
|
default: true,
|
|
340
378
|
})
|
|
341
379
|
|
|
342
380
|
const definition = defineSummaryGraph({
|
|
343
|
-
name: '
|
|
344
|
-
root:
|
|
345
|
-
sources: [
|
|
346
|
-
parameters: [
|
|
381
|
+
name: 'teamSummary',
|
|
382
|
+
root: teams,
|
|
383
|
+
sources: [teams, memberships],
|
|
384
|
+
parameters: [workspaceId, minimumMembers],
|
|
347
385
|
relations: [
|
|
348
386
|
relation({
|
|
349
|
-
name: '
|
|
350
|
-
from:
|
|
351
|
-
to:
|
|
352
|
-
on: eq(
|
|
387
|
+
name: 'members',
|
|
388
|
+
from: teams,
|
|
389
|
+
to: memberships,
|
|
390
|
+
on: eq(teams.field('id'), memberships.field('teamId')),
|
|
353
391
|
cardinality: 'many',
|
|
354
392
|
}),
|
|
355
393
|
],
|
|
356
394
|
constraints: [
|
|
357
395
|
constraint({
|
|
358
|
-
predicate: eq(
|
|
396
|
+
predicate: eq(teams.field('workspaceId'), param(workspaceId)),
|
|
359
397
|
}),
|
|
360
398
|
constraint({
|
|
361
|
-
predicate: gte(
|
|
399
|
+
predicate: gte(memberCount, param(minimumMembers)),
|
|
362
400
|
}),
|
|
363
401
|
],
|
|
364
|
-
dimensions: [
|
|
365
|
-
measures: [
|
|
402
|
+
dimensions: [teamId],
|
|
403
|
+
measures: [memberCount],
|
|
366
404
|
orderings: [
|
|
367
405
|
ordering({
|
|
368
|
-
name: '
|
|
369
|
-
by: [desc(
|
|
406
|
+
name: 'memberCountDesc',
|
|
407
|
+
by: [desc(memberCount)],
|
|
370
408
|
default: true,
|
|
371
409
|
}),
|
|
372
410
|
],
|
|
@@ -443,10 +481,9 @@ TypeScript проверяет имена источников, полей и с
|
|
|
443
481
|
const relationalGraph = registerDefinition(definition).withRelationalMapping(mapping)
|
|
444
482
|
|
|
445
483
|
relationalGraph.compileSqlServer({
|
|
446
|
-
select: ['id', '
|
|
484
|
+
select: ['id', 'profile.displayName'],
|
|
447
485
|
parameters: {
|
|
448
|
-
|
|
449
|
-
personIds: [7, 11],
|
|
486
|
+
userId: 42,
|
|
450
487
|
},
|
|
451
488
|
})
|
|
452
489
|
```
|
|
@@ -459,6 +496,63 @@ JavaScript number и десятичная строка, а list-параметр
|
|
|
459
496
|
типа. Эти проверки существуют только в декларациях TypeScript; сериализация
|
|
460
497
|
definition, N-API вызов, runtime-валидация Rust и SQL compilation не меняются.
|
|
461
498
|
|
|
499
|
+
### Тип результата проекции
|
|
500
|
+
|
|
501
|
+
DSL сохраняет scalar type и nullability каждого projection expression в compile-time metadata.
|
|
502
|
+
`ResultOf` строит из этих сведений вложенный тип результата по projection paths:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import type { QueryOperation, ResultOf } from '@query-graph/core/dsl'
|
|
506
|
+
|
|
507
|
+
const operation = {
|
|
508
|
+
select: ['id', 'profile.displayName'],
|
|
509
|
+
parameters: { userId: 42 },
|
|
510
|
+
} as const satisfies QueryOperation<typeof definition>
|
|
511
|
+
|
|
512
|
+
type UserRow = ResultOf<typeof definition, typeof operation>
|
|
513
|
+
// {
|
|
514
|
+
// id: number | string
|
|
515
|
+
// profile: { displayName: string | null }
|
|
516
|
+
// }
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Если второй аргумент не передан, в результат входят только поля с `default: true`.
|
|
520
|
+
`ResultOf` также принимает тип, возвращенный `registerDefinition`, или mapped graph:
|
|
521
|
+
|
|
522
|
+
```ts
|
|
523
|
+
type DefaultUserRow = ResultOf<typeof graph>
|
|
524
|
+
// { id: number | string }
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
Nullability учитывает nullable-поле и всю цепочку optional relations до его source.
|
|
528
|
+
Required relation после optional relation не делает значение обязательным. Семантика
|
|
529
|
+
выражений тоже сохраняется: например, `coalesce(nullableField, 'fallback')` выводится
|
|
530
|
+
как non-null `string`.
|
|
531
|
+
|
|
532
|
+
Типы значений по умолчанию нейтральны к DB driver: `int64` и `decimal` представлены
|
|
533
|
+
как `number | string`, а `date`, `dateTime` и `binary` - как `string`. Адаптер
|
|
534
|
+
исполнения может передать третьим аргументом собственную полную scalar map:
|
|
535
|
+
|
|
536
|
+
```ts
|
|
537
|
+
import type { DefaultScalarOutputTypeMap, ResultOf } from '@query-graph/core/dsl'
|
|
538
|
+
|
|
539
|
+
type DriverScalars = Omit<DefaultScalarOutputTypeMap, 'int64' | 'dateTime'> & {
|
|
540
|
+
int64: bigint
|
|
541
|
+
dateTime: Date
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
type DriverUserRow = ResultOf<typeof definition, typeof operation, DriverScalars>
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Для точного учета явного `select` operation должна сохранять literal tuple через
|
|
548
|
+
`as const` или `satisfies`. Это только TypeScript API: wire definition, N-API и
|
|
549
|
+
Rust planner не получают дополнительного runtime state.
|
|
550
|
+
|
|
551
|
+
`ResultOf` описывает логическую форму одной строки, восстановленную из путей
|
|
552
|
+
проекции. Он не выполняет запрос и не превращает relation `many` в массив.
|
|
553
|
+
Группировка строк, дедупликация и гидратация коллекций остаются ответственностью
|
|
554
|
+
потребителя модуля.
|
|
555
|
+
|
|
462
556
|
## Диагностика
|
|
463
557
|
|
|
464
558
|
Ошибки N-API имеют имя `QueryGraphError` и сохраняют обычный `message` и stack.
|
|
@@ -494,18 +588,22 @@ Wire errors, semantic validation и SQL compilation имеют разные ве
|
|
|
494
588
|
```ts
|
|
495
589
|
const relationalGraph = graph.withRelationalMapping({
|
|
496
590
|
sources: {
|
|
497
|
-
|
|
591
|
+
users: {
|
|
498
592
|
table: {
|
|
499
593
|
schema: 'dbo',
|
|
500
|
-
name: '
|
|
594
|
+
name: 'users',
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
profiles: {
|
|
598
|
+
table: {
|
|
599
|
+
schema: 'dbo',
|
|
600
|
+
name: 'user_profiles',
|
|
501
601
|
},
|
|
502
602
|
columns: {
|
|
503
|
-
|
|
603
|
+
userId: 'user_id',
|
|
604
|
+
displayName: 'display_name',
|
|
504
605
|
},
|
|
505
606
|
},
|
|
506
|
-
value: {
|
|
507
|
-
table: 'ControllerObjectValue',
|
|
508
|
-
},
|
|
509
607
|
},
|
|
510
608
|
})
|
|
511
609
|
```
|
|
@@ -515,9 +613,9 @@ const relationalGraph = graph.withRelationalMapping({
|
|
|
515
613
|
|
|
516
614
|
```ts
|
|
517
615
|
const operation = {
|
|
518
|
-
select: ['
|
|
616
|
+
select: ['id', 'profile.displayName'],
|
|
519
617
|
parameters: {
|
|
520
|
-
|
|
618
|
+
userId: 42,
|
|
521
619
|
},
|
|
522
620
|
offset: 0,
|
|
523
621
|
limit: 25,
|
|
@@ -532,7 +630,7 @@ console.table(statement.relations)
|
|
|
532
630
|
```
|
|
533
631
|
|
|
534
632
|
`statement.bindings` связывает сгенерированные имена, например `p0`, с
|
|
535
|
-
логическими параметрами, например `
|
|
633
|
+
логическими параметрами, например `userId`, и содержит их scalar type.
|
|
536
634
|
Потребитель берет значения из `operation.parameters` и передает их
|
|
537
635
|
своему драйверу базы данных.
|
|
538
636
|
|
package/definition.d.ts
CHANGED
|
@@ -2,19 +2,27 @@ export * from './dsl.js'
|
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
4
|
ConstraintDefinition,
|
|
5
|
-
DimensionDefinition,
|
|
6
5
|
Expression,
|
|
7
6
|
ExpressionInput,
|
|
7
|
+
ExpressionNullability,
|
|
8
|
+
ExpressionScalarType,
|
|
8
9
|
FieldExpression,
|
|
10
|
+
FieldSpecIsNullable,
|
|
9
11
|
FieldSpecMap,
|
|
12
|
+
FieldSpecScalarType,
|
|
10
13
|
JoinProjectionPath,
|
|
11
|
-
MeasureDefinition,
|
|
12
14
|
ParameterRef,
|
|
13
|
-
ProjectionFieldDefinition,
|
|
14
15
|
RelationCardinality,
|
|
15
16
|
RelationRef,
|
|
16
17
|
RelationSelection,
|
|
18
|
+
ScalarType,
|
|
19
|
+
SourceFieldNullability,
|
|
20
|
+
SourceReferenceKey,
|
|
17
21
|
SourceRef,
|
|
22
|
+
TypedExpression,
|
|
23
|
+
TypedDimensionDefinition,
|
|
24
|
+
TypedMeasureDefinition,
|
|
25
|
+
TypedProjectionField,
|
|
18
26
|
} from './dsl.js'
|
|
19
27
|
|
|
20
28
|
export const GRAPH_DEFINITION_VERSION: 9
|
|
@@ -23,25 +31,41 @@ export function field<
|
|
|
23
31
|
const Key extends string,
|
|
24
32
|
const Fields extends FieldSpecMap,
|
|
25
33
|
const Name extends Extract<keyof Fields, string>,
|
|
26
|
-
>(
|
|
34
|
+
>(
|
|
35
|
+
source: SourceRef<Key, Fields>,
|
|
36
|
+
name: Name,
|
|
37
|
+
): TypedExpression<
|
|
38
|
+
FieldExpression<Key, Name>,
|
|
39
|
+
FieldSpecScalarType<Fields[Name]>,
|
|
40
|
+
SourceFieldNullability<Key, FieldSpecIsNullable<Fields[Name]>>
|
|
41
|
+
>
|
|
27
42
|
export function field<const Source extends string, const Name extends string>(
|
|
28
43
|
source: Source,
|
|
29
44
|
name: Name,
|
|
30
|
-
): FieldExpression<Source, Name
|
|
45
|
+
): TypedExpression<FieldExpression<Source, Name>, ScalarType, SourceFieldNullability<Source, boolean>>
|
|
31
46
|
|
|
32
|
-
export interface RelationOptions
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
export interface RelationOptions<
|
|
48
|
+
Required extends boolean = boolean,
|
|
49
|
+
Cardinality extends RelationCardinality = RelationCardinality,
|
|
50
|
+
> {
|
|
51
|
+
required?: Required
|
|
52
|
+
cardinality?: Cardinality
|
|
35
53
|
selection?: RelationSelection
|
|
36
54
|
}
|
|
37
55
|
|
|
38
|
-
export function relation<
|
|
56
|
+
export function relation<
|
|
57
|
+
const Name extends string,
|
|
58
|
+
const From extends string | SourceRef,
|
|
59
|
+
const To extends string | SourceRef,
|
|
60
|
+
const Required extends boolean = false,
|
|
61
|
+
const Cardinality extends RelationCardinality = 'one',
|
|
62
|
+
>(
|
|
39
63
|
name: Name,
|
|
40
|
-
from:
|
|
41
|
-
to:
|
|
64
|
+
from: From,
|
|
65
|
+
to: To,
|
|
42
66
|
on: Expression,
|
|
43
|
-
options?: RelationOptions,
|
|
44
|
-
): RelationRef<Name>
|
|
67
|
+
options?: RelationOptions<Required, Cardinality>,
|
|
68
|
+
): RelationRef<Name, SourceReferenceKey<From>, SourceReferenceKey<To>, Required, Cardinality>
|
|
45
69
|
|
|
46
70
|
export interface ConstraintOptions {
|
|
47
71
|
when?: string | ParameterRef
|
|
@@ -49,39 +73,93 @@ export interface ConstraintOptions {
|
|
|
49
73
|
|
|
50
74
|
export function constraint(predicate: Expression, options?: ConstraintOptions): ConstraintDefinition
|
|
51
75
|
|
|
52
|
-
export interface ProjectionOptions {
|
|
53
|
-
default?:
|
|
76
|
+
export interface ProjectionOptions<SelectedByDefault extends boolean = boolean> {
|
|
77
|
+
default?: SelectedByDefault
|
|
54
78
|
}
|
|
55
79
|
|
|
56
|
-
export function project<
|
|
80
|
+
export function project<
|
|
81
|
+
const Path extends string,
|
|
82
|
+
const Value extends ExpressionInput,
|
|
83
|
+
const SelectedByDefault extends boolean = false,
|
|
84
|
+
>(
|
|
57
85
|
path: Path,
|
|
58
|
-
expression:
|
|
59
|
-
options?: ProjectionOptions
|
|
60
|
-
):
|
|
61
|
-
|
|
86
|
+
expression: Value,
|
|
87
|
+
options?: ProjectionOptions<SelectedByDefault>,
|
|
88
|
+
): TypedProjectionField<
|
|
89
|
+
Path,
|
|
90
|
+
Extract<ExpressionScalarType<Value>, ScalarType>,
|
|
91
|
+
ExpressionNullability<Value>,
|
|
92
|
+
SelectedByDefault
|
|
93
|
+
>
|
|
94
|
+
export function project<
|
|
95
|
+
const Path extends readonly string[],
|
|
96
|
+
const Value extends ExpressionInput,
|
|
97
|
+
const SelectedByDefault extends boolean = false,
|
|
98
|
+
>(
|
|
62
99
|
path: Path,
|
|
63
|
-
expression:
|
|
64
|
-
options?: ProjectionOptions
|
|
65
|
-
):
|
|
100
|
+
expression: Value,
|
|
101
|
+
options?: ProjectionOptions<SelectedByDefault>,
|
|
102
|
+
): TypedProjectionField<
|
|
103
|
+
JoinProjectionPath<Path>,
|
|
104
|
+
Extract<ExpressionScalarType<Value>, ScalarType>,
|
|
105
|
+
ExpressionNullability<Value>,
|
|
106
|
+
SelectedByDefault
|
|
107
|
+
>
|
|
66
108
|
|
|
67
|
-
export function dimension<
|
|
109
|
+
export function dimension<
|
|
110
|
+
const Path extends string,
|
|
111
|
+
const Value extends ExpressionInput,
|
|
112
|
+
const SelectedByDefault extends boolean = false,
|
|
113
|
+
>(
|
|
68
114
|
path: Path,
|
|
69
|
-
expression:
|
|
70
|
-
options?: ProjectionOptions
|
|
71
|
-
):
|
|
72
|
-
|
|
115
|
+
expression: Value,
|
|
116
|
+
options?: ProjectionOptions<SelectedByDefault>,
|
|
117
|
+
): TypedDimensionDefinition<
|
|
118
|
+
Path,
|
|
119
|
+
Extract<ExpressionScalarType<Value>, ScalarType>,
|
|
120
|
+
ExpressionNullability<Value>,
|
|
121
|
+
SelectedByDefault
|
|
122
|
+
>
|
|
123
|
+
export function dimension<
|
|
124
|
+
const Path extends readonly string[],
|
|
125
|
+
const Value extends ExpressionInput,
|
|
126
|
+
const SelectedByDefault extends boolean = false,
|
|
127
|
+
>(
|
|
73
128
|
path: Path,
|
|
74
|
-
expression:
|
|
75
|
-
options?: ProjectionOptions
|
|
76
|
-
):
|
|
129
|
+
expression: Value,
|
|
130
|
+
options?: ProjectionOptions<SelectedByDefault>,
|
|
131
|
+
): TypedDimensionDefinition<
|
|
132
|
+
JoinProjectionPath<Path>,
|
|
133
|
+
Extract<ExpressionScalarType<Value>, ScalarType>,
|
|
134
|
+
ExpressionNullability<Value>,
|
|
135
|
+
SelectedByDefault
|
|
136
|
+
>
|
|
77
137
|
|
|
78
|
-
export function measure<
|
|
138
|
+
export function measure<
|
|
139
|
+
const Path extends string,
|
|
140
|
+
const Value extends ExpressionInput,
|
|
141
|
+
const SelectedByDefault extends boolean = false,
|
|
142
|
+
>(
|
|
79
143
|
path: Path,
|
|
80
|
-
expression:
|
|
81
|
-
options?: ProjectionOptions
|
|
82
|
-
):
|
|
83
|
-
|
|
144
|
+
expression: Value,
|
|
145
|
+
options?: ProjectionOptions<SelectedByDefault>,
|
|
146
|
+
): TypedMeasureDefinition<
|
|
147
|
+
Path,
|
|
148
|
+
Extract<ExpressionScalarType<Value>, ScalarType>,
|
|
149
|
+
ExpressionNullability<Value>,
|
|
150
|
+
SelectedByDefault
|
|
151
|
+
>
|
|
152
|
+
export function measure<
|
|
153
|
+
const Path extends readonly string[],
|
|
154
|
+
const Value extends ExpressionInput,
|
|
155
|
+
const SelectedByDefault extends boolean = false,
|
|
156
|
+
>(
|
|
84
157
|
path: Path,
|
|
85
|
-
expression:
|
|
86
|
-
options?: ProjectionOptions
|
|
87
|
-
):
|
|
158
|
+
expression: Value,
|
|
159
|
+
options?: ProjectionOptions<SelectedByDefault>,
|
|
160
|
+
): TypedMeasureDefinition<
|
|
161
|
+
JoinProjectionPath<Path>,
|
|
162
|
+
Extract<ExpressionScalarType<Value>, ScalarType>,
|
|
163
|
+
ExpressionNullability<Value>,
|
|
164
|
+
SelectedByDefault
|
|
165
|
+
>
|