@query-graph/core 1.0.0 → 1.1.1

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/dsl.d.ts CHANGED
@@ -32,6 +32,44 @@ export type SemanticFunctionName = 'lower' | 'upper' | 'coalesce' | 'concat'
32
32
  export type AggregateFunctionName = 'count' | 'countDistinct' | 'sum' | 'average' | 'minimum' | 'maximum'
33
33
  export type ProjectionFieldRole = 'value' | 'dimension' | 'measure'
34
34
 
35
+ type BooleanOr<Value extends boolean> = true extends Value ? true : false
36
+
37
+ export interface SourceFieldNullability<Source extends string = string, FieldNullable extends boolean = boolean> {
38
+ kind: 'sourceField'
39
+ source: Source
40
+ fieldNullable: FieldNullable
41
+ }
42
+
43
+ export interface AnyNullability<Values = unknown> {
44
+ kind: 'any'
45
+ values: Values
46
+ }
47
+
48
+ export interface AllNullability<Values = unknown> {
49
+ kind: 'all'
50
+ values: Values
51
+ }
52
+
53
+ export type NullabilityExpression = boolean | SourceFieldNullability | AnyNullability | AllNullability
54
+
55
+ declare const expressionTypeMetadata: unique symbol
56
+
57
+ export interface ExpressionTypeMetadata<
58
+ Type extends ScalarType | null = ScalarType,
59
+ Nullability extends NullabilityExpression = NullabilityExpression,
60
+ > {
61
+ readonly [expressionTypeMetadata]: {
62
+ scalarType: Type
63
+ nullability: Nullability
64
+ }
65
+ }
66
+
67
+ export type TypedExpression<
68
+ Definition extends Expression = Expression,
69
+ Type extends ScalarType | null = ScalarType,
70
+ Nullability extends NullabilityExpression = NullabilityExpression,
71
+ > = Definition & ExpressionTypeMetadata<Type, Nullability>
72
+
35
73
  export interface FieldDefinition {
36
74
  name: string
37
75
  scalarType: ScalarType
@@ -149,12 +187,18 @@ export type Expression =
149
187
  | FunctionExpression
150
188
  | AggregateExpression
151
189
 
152
- export interface RelationDefinition {
153
- name: string
154
- from: string
155
- to: string
156
- cardinality?: RelationCardinality
157
- required?: boolean
190
+ export interface RelationDefinition<
191
+ Name extends string = string,
192
+ From extends string = string,
193
+ To extends string = string,
194
+ Required extends boolean = boolean,
195
+ Cardinality extends RelationCardinality = RelationCardinality,
196
+ > {
197
+ name: Name
198
+ from: From
199
+ to: To
200
+ cardinality?: Cardinality
201
+ required?: Required
158
202
  selection?: RelationSelection
159
203
  on: Expression
160
204
  }
@@ -177,34 +221,108 @@ export type JoinProjectionPath<Segments extends readonly string[]> = number exte
177
221
  : string
178
222
 
179
223
  declare const projectionPathType: unique symbol
224
+ declare const projectionScalarType: unique symbol
225
+ declare const projectionNullabilityType: unique symbol
226
+ declare const projectionDefaultType: unique symbol
180
227
  declare const summaryFieldType: unique symbol
228
+ declare const typedProjectionPathType: unique symbol
229
+ declare const typedProjectionScalarType: unique symbol
230
+ declare const typedProjectionNullabilityType: unique symbol
231
+ declare const typedProjectionDefaultType: unique symbol
232
+
233
+ export interface ProjectionTypeMetadata<
234
+ Path extends string = string,
235
+ Type extends ScalarType = ScalarType,
236
+ Nullability extends NullabilityExpression = NullabilityExpression,
237
+ SelectedByDefault extends boolean = boolean,
238
+ > {
239
+ readonly [typedProjectionPathType]: Path
240
+ readonly [typedProjectionScalarType]: Type
241
+ readonly [typedProjectionNullabilityType]: Nullability
242
+ readonly [typedProjectionDefaultType]: SelectedByDefault
243
+ }
181
244
 
182
- export interface ProjectionFieldDefinition<Path extends string = string> {
245
+ export type TypedProjectionField<
246
+ Path extends string = string,
247
+ Type extends ScalarType = ScalarType,
248
+ Nullability extends NullabilityExpression = NullabilityExpression,
249
+ SelectedByDefault extends boolean = boolean,
250
+ > = ProjectionFieldDefinition<Path, Type, Nullability, SelectedByDefault> &
251
+ ProjectionTypeMetadata<Path, Type, Nullability, SelectedByDefault>
252
+
253
+ export type TypedDimensionDefinition<
254
+ Path extends string = string,
255
+ Type extends ScalarType = ScalarType,
256
+ Nullability extends NullabilityExpression = NullabilityExpression,
257
+ SelectedByDefault extends boolean = boolean,
258
+ > = DimensionDefinition<Path, Type, Nullability, SelectedByDefault> &
259
+ ProjectionTypeMetadata<Path, Type, Nullability, SelectedByDefault>
260
+
261
+ export type TypedMeasureDefinition<
262
+ Path extends string = string,
263
+ Type extends ScalarType = ScalarType,
264
+ Nullability extends NullabilityExpression = NullabilityExpression,
265
+ SelectedByDefault extends boolean = boolean,
266
+ > = MeasureDefinition<Path, Type, Nullability, SelectedByDefault> &
267
+ ProjectionTypeMetadata<Path, Type, Nullability, SelectedByDefault>
268
+
269
+ export interface ProjectionFieldDefinition<
270
+ Path extends string = string,
271
+ Type extends ScalarType = ScalarType,
272
+ Nullability extends NullabilityExpression = NullabilityExpression,
273
+ SelectedByDefault extends boolean = boolean,
274
+ > {
183
275
  path: string[]
184
276
  readonly [projectionPathType]?: Path
277
+ readonly [projectionScalarType]?: Type
278
+ readonly [projectionNullabilityType]?: Nullability
279
+ readonly [projectionDefaultType]?: SelectedByDefault
185
280
  expression: Expression
186
281
  role?: ProjectionFieldRole
187
282
  selectedByDefault?: boolean
188
283
  }
189
284
 
190
- export interface DimensionDefinition<Path extends string = string> extends ProjectionFieldDefinition<Path> {
285
+ export interface DimensionDefinition<
286
+ Path extends string = string,
287
+ Type extends ScalarType = ScalarType,
288
+ Nullability extends NullabilityExpression = NullabilityExpression,
289
+ SelectedByDefault extends boolean = boolean,
290
+ > extends ProjectionFieldDefinition<Path, Type, Nullability, SelectedByDefault> {
191
291
  readonly [summaryFieldType]: 'dimension'
192
292
  role: 'dimension'
193
293
  }
194
294
 
195
- export interface MeasureDefinition<Path extends string = string> extends ProjectionFieldDefinition<Path> {
295
+ export interface MeasureDefinition<
296
+ Path extends string = string,
297
+ Type extends ScalarType = ScalarType,
298
+ Nullability extends NullabilityExpression = NullabilityExpression,
299
+ SelectedByDefault extends boolean = boolean,
300
+ > extends ProjectionFieldDefinition<Path, Type, Nullability, SelectedByDefault> {
196
301
  readonly [summaryFieldType]: 'measure'
197
302
  role: 'measure'
198
303
  }
199
304
 
200
- export type SummaryFieldDefinition<Path extends string = string> = DimensionDefinition<Path> | MeasureDefinition<Path>
201
-
202
- export interface ProjectionDefinition<Path extends string = string> {
203
- fields: ProjectionFieldDefinition<Path>[]
305
+ export type SummaryFieldDefinition<
306
+ Path extends string = string,
307
+ Type extends ScalarType = ScalarType,
308
+ Nullability extends NullabilityExpression = NullabilityExpression,
309
+ SelectedByDefault extends boolean = boolean,
310
+ > =
311
+ | DimensionDefinition<Path, Type, Nullability, SelectedByDefault>
312
+ | MeasureDefinition<Path, Type, Nullability, SelectedByDefault>
313
+
314
+ export interface ProjectionDefinition<
315
+ Path extends string = string,
316
+ Field extends ProjectionFieldDefinition = ProjectionFieldDefinition<Path>,
317
+ > {
318
+ fields: Field[]
204
319
  }
205
320
 
206
- export interface ProjectionDefinitionInput<Path extends string = string> {
207
- fields?: ProjectionFieldDefinition<Path>[]
321
+ export interface ProjectionDefinitionInput<
322
+ Path extends string = string,
323
+ Field extends ProjectionFieldDefinition = ProjectionFieldDefinition<Path>,
324
+ > {
325
+ fields?: Field[]
208
326
  }
209
327
 
210
328
  export interface OrderByDefinition {
@@ -242,11 +360,15 @@ export interface GraphDefinition<
242
360
  Parameter extends ParameterDefinition = ParameterDefinition,
243
361
  ProjectionPath extends string = string,
244
362
  OrderingName extends string = string,
363
+ ProjectionField extends ProjectionFieldDefinition = ProjectionFieldDefinition<ProjectionPath>,
364
+ Relation extends RelationDefinition = RelationDefinition,
365
+ Root extends string = string,
245
366
  > extends GraphDefinitionInput {
367
+ root: Root
246
368
  parameters: Parameter[]
247
- relations: RelationDefinition[]
369
+ relations: Relation[]
248
370
  constraints: ConstraintDefinition[]
249
- projection: ProjectionDefinition<ProjectionPath>
371
+ projection: ProjectionDefinition<ProjectionPath, ProjectionField>
250
372
  orderings: OrderingDefinition<OrderingName>[]
251
373
  }
252
374
 
@@ -278,24 +400,53 @@ export interface QueryOperationBase<SelectPath extends string = string, Ordering
278
400
  }
279
401
 
280
402
  export type DefinitionParameter<Definition extends GraphDefinitionInput> =
281
- Definition extends GraphDefinition<infer Parameter, infer _ProjectionPath, infer _OrderingName>
403
+ Definition extends GraphDefinition<
404
+ infer Parameter,
405
+ infer _ProjectionPath,
406
+ infer _OrderingName,
407
+ infer _ProjectionField,
408
+ infer _Relation,
409
+ infer _Root
410
+ >
282
411
  ? Parameter
283
412
  : NonNullable<Definition['parameters']>[number]
284
413
 
285
414
  export type DefinitionProjectionPath<Definition extends GraphDefinitionInput> =
286
- Definition extends GraphDefinition<infer _Parameter, infer ProjectionPath, infer _OrderingName>
415
+ Definition extends GraphDefinition<
416
+ infer _Parameter,
417
+ infer ProjectionPath,
418
+ infer _OrderingName,
419
+ infer _ProjectionField,
420
+ infer _Relation,
421
+ infer _Root
422
+ >
287
423
  ? ProjectionPath
288
424
  : Definition['projection'] extends ProjectionDefinitionInput<infer ProjectionPath>
289
425
  ? ProjectionPath
290
426
  : string
291
427
 
292
428
  export type DefinitionOrderingName<Definition extends GraphDefinitionInput> =
293
- Definition extends GraphDefinition<infer _Parameter, infer _ProjectionPath, infer OrderingName>
429
+ Definition extends GraphDefinition<
430
+ infer _Parameter,
431
+ infer _ProjectionPath,
432
+ infer OrderingName,
433
+ infer _ProjectionField,
434
+ infer _Relation,
435
+ infer _Root
436
+ >
294
437
  ? OrderingName
295
438
  : NonNullable<Definition['orderings']>[number] extends OrderingDefinition<infer OrderingName>
296
439
  ? OrderingName
297
440
  : never
298
441
 
442
+ export type DefinitionProjectionField<Definition extends GraphDefinitionInput> = NonNullable<
443
+ NonNullable<Definition['projection']>['fields']
444
+ >[number]
445
+
446
+ export type DefinitionRelation<Definition extends GraphDefinitionInput> = NonNullable<Definition['relations']>[number]
447
+
448
+ export type DefinitionRoot<Definition extends GraphDefinitionInput> = Definition['root']
449
+
299
450
  export type ParameterValue<Parameter extends ParameterDefinition> = Parameter extends { shape: 'list' }
300
451
  ? readonly ScalarParameterValue<Parameter['scalarType']>[]
301
452
  : ScalarParameterValue<Parameter['scalarType']>
@@ -332,7 +483,10 @@ export type QueryOperation<Definition extends GraphDefinitionInput = GraphDefini
332
483
  > &
333
484
  OperationParameterInput<Definition>
334
485
 
486
+ declare const graphDefinitionType: unique symbol
487
+
335
488
  export interface QueryGraph<Definition extends GraphDefinitionInput = GraphDefinitionInput> {
489
+ readonly [graphDefinitionType]?: Definition
336
490
  readonly name: string
337
491
  readonly root: string
338
492
  readonly sourceCount: number
@@ -346,6 +500,7 @@ export interface QueryGraph<Definition extends GraphDefinitionInput = GraphDefin
346
500
  }
347
501
 
348
502
  export interface RelationalQueryGraph<Definition extends GraphDefinitionInput = GraphDefinitionInput> {
503
+ readonly [graphDefinitionType]?: Definition
349
504
  readonly name: string
350
505
  compileSqlServer(
351
506
  operation: QueryOperation<Definition>,
@@ -357,6 +512,573 @@ export interface RelationalQueryGraph<Definition extends GraphDefinitionInput =
357
512
  ): import('./index.js').CompiledSqlStatement
358
513
  }
359
514
 
515
+ export type BatchCardinality = RelationCardinality
516
+
517
+ export interface BatchRelationWire {
518
+ name: string
519
+ from: string
520
+ to: string
521
+ parameter: string
522
+ cardinality: BatchCardinality
523
+ parameters?: Record<string, unknown>
524
+ ordering?: string
525
+ }
526
+
527
+ type ListDefinitionParameter<Definition extends GraphDefinitionInput> =
528
+ DefinitionParameter<Definition> extends infer Parameter extends ParameterDefinition
529
+ ? Parameter extends { shape: 'list' }
530
+ ? Parameter
531
+ : never
532
+ : never
533
+
534
+ type ListParameterReference<Definition extends GraphDefinitionInput> =
535
+ | ListDefinitionParameter<Definition>
536
+ | ListDefinitionParameter<Definition>['name']
537
+
538
+ type ParameterReferenceName<Reference> = Reference extends { name: infer Name extends string }
539
+ ? Name
540
+ : Reference extends string
541
+ ? Reference
542
+ : never
543
+
544
+ type ResolveListParameter<Definition extends GraphDefinitionInput, Reference> = Extract<
545
+ ListDefinitionParameter<Definition>,
546
+ { name: ParameterReferenceName<Reference> }
547
+ >
548
+
549
+ type BatchStaticParameterCandidate<
550
+ Parameter extends ParameterDefinition,
551
+ KeyName extends string,
552
+ > = Parameter extends ParameterDefinition ? (Parameter['name'] extends KeyName ? never : Parameter) : never
553
+
554
+ type BatchStaticParameter<
555
+ Definition extends GraphDefinitionInput,
556
+ KeyName extends string,
557
+ > = BatchStaticParameterCandidate<DefinitionParameter<Definition>, KeyName>
558
+
559
+ type BatchStaticParameters<Definition extends GraphDefinitionInput, KeyName extends string> = {
560
+ [Parameter in RequiredParameter<
561
+ BatchStaticParameter<Definition, KeyName>
562
+ > as Parameter['name']]-?: ParameterValue<Parameter>
563
+ } & {
564
+ [Parameter in OptionalParameter<
565
+ BatchStaticParameter<Definition, KeyName>
566
+ > as Parameter['name']]?: ParameterValue<Parameter>
567
+ }
568
+
569
+ type BatchStaticParameterInput<Definition extends GraphDefinitionInput, KeyName extends string> = [
570
+ BatchStaticParameter<Definition, KeyName>,
571
+ ] extends [never]
572
+ ? { parameters?: never }
573
+ : [RequiredParameter<BatchStaticParameter<Definition, KeyName>>] extends [never]
574
+ ? { parameters?: BatchStaticParameters<Definition, KeyName> }
575
+ : { parameters: BatchStaticParameters<Definition, KeyName> }
576
+
577
+ declare const batchQueryType: unique symbol
578
+
579
+ export interface BatchQuery<
580
+ Child extends RelationalQueryGraph = RelationalQueryGraph,
581
+ KeyPath extends string = string,
582
+ KeyParameter extends ParameterDefinition & { shape: 'list' } = ListParameterRef,
583
+ > {
584
+ readonly graph: Child
585
+ readonly key: {
586
+ readonly path: KeyPath
587
+ readonly parameter: KeyParameter['name']
588
+ }
589
+ readonly [batchQueryType]?: KeyParameter
590
+ }
591
+
592
+ export type BatchQueryConfiguration<
593
+ Child extends RelationalQueryGraph,
594
+ KeyPath extends DefinitionProjectionPath<DefinitionOf<Child>>,
595
+ ParameterReference extends ListParameterReference<DefinitionOf<Child>>,
596
+ > = {
597
+ graph: Child
598
+ key: {
599
+ path: KeyPath
600
+ parameter: ParameterReference
601
+ }
602
+ }
603
+
604
+ type CompatibleBatchQueryConfiguration<
605
+ Child extends RelationalQueryGraph,
606
+ KeyPath extends DefinitionProjectionPath<DefinitionOf<Child>>,
607
+ KeyParameter extends ParameterDefinition & { shape: 'list' },
608
+ > =
609
+ EqualScalarType<ProjectionScalarTypeAtPath<DefinitionOf<Child>, KeyPath>, KeyParameter['scalarType']> extends true
610
+ ? unknown
611
+ : never
612
+
613
+ export function batchQuery<
614
+ const Child extends RelationalQueryGraph,
615
+ const KeyPath extends DefinitionProjectionPath<DefinitionOf<Child>>,
616
+ const ParameterReference extends ListParameterReference<DefinitionOf<Child>>,
617
+ >(
618
+ configuration: BatchQueryConfiguration<Child, KeyPath, ParameterReference> &
619
+ CompatibleBatchQueryConfiguration<
620
+ Child,
621
+ KeyPath,
622
+ ResolveListParameter<DefinitionOf<Child>, NoInfer<ParameterReference>>
623
+ >,
624
+ ): BatchQuery<Child, KeyPath, ResolveListParameter<DefinitionOf<Child>, ParameterReference>>
625
+
626
+ type BatchQueryGraph<Query extends BatchQuery> =
627
+ Query extends BatchQuery<infer Child, infer _KeyPath, infer _KeyParameter> ? Child : never
628
+
629
+ type BatchQueryKeyPath<Query extends BatchQuery> =
630
+ Query extends BatchQuery<infer _Child, infer KeyPath, infer _KeyParameter> ? KeyPath : never
631
+
632
+ type BatchQueryKeyParameter<Query extends BatchQuery> =
633
+ Query extends BatchQuery<infer _Child, infer _KeyPath, infer KeyParameter> ? KeyParameter : never
634
+
635
+ declare const batchRelationType: unique symbol
636
+
637
+ export interface BatchRelation<
638
+ Name extends string = string,
639
+ Query extends BatchQuery = BatchQuery,
640
+ From extends string = string,
641
+ Cardinality extends BatchCardinality = BatchCardinality,
642
+ > {
643
+ readonly name: Name
644
+ readonly from: From
645
+ readonly query: Query
646
+ readonly cardinality: Cardinality
647
+ readonly parameters: BatchStaticParameters<
648
+ DefinitionOf<BatchQueryGraph<Query>>,
649
+ BatchQueryKeyParameter<Query>['name']
650
+ >
651
+ readonly ordering?: DefinitionOrderingName<DefinitionOf<BatchQueryGraph<Query>>>
652
+ readonly [batchRelationType]?: Query
653
+ }
654
+
655
+ export type BatchRelationConfiguration<
656
+ Name extends string,
657
+ Query extends BatchQuery,
658
+ From extends string,
659
+ Cardinality extends BatchCardinality,
660
+ > = {
661
+ name: Name
662
+ from: From
663
+ query: Query
664
+ cardinality: Cardinality
665
+ ordering?: DefinitionOrderingName<DefinitionOf<BatchQueryGraph<Query>>>
666
+ } & BatchStaticParameterInput<DefinitionOf<BatchQueryGraph<Query>>, BatchQueryKeyParameter<Query>['name']>
667
+
668
+ export function batchRelation<
669
+ const Name extends string,
670
+ const Query extends BatchQuery,
671
+ const From extends string,
672
+ const Cardinality extends BatchCardinality,
673
+ >(
674
+ configuration: BatchRelationConfiguration<Name, Query, From, Cardinality>,
675
+ ): BatchRelation<Name, Query, From, Cardinality>
676
+
677
+ type ProjectionScalarTypeAtPath<Definition extends GraphDefinitionInput, Path extends string> =
678
+ ProjectionFieldByPath<DefinitionProjectionField<Definition>, Path> extends infer Field
679
+ ? Field extends ProjectionTypeMetadata<infer _Path, infer Type, infer _Nullability, infer _SelectedByDefault>
680
+ ? Type
681
+ : Field extends ProjectionFieldDefinition<infer _Path, infer Type>
682
+ ? Type
683
+ : never
684
+ : never
685
+
686
+ type EqualScalarType<Left, Right> = [Left] extends [Right] ? ([Right] extends [Left] ? true : false) : false
687
+
688
+ type CompatibleBatchRelation<Root extends RelationalQueryGraph, Relation extends BatchRelation> =
689
+ Relation extends BatchRelation<infer Name, infer Query, infer From, infer _Cardinality>
690
+ ? From extends DefinitionProjectionPath<DefinitionOf<Root>>
691
+ ? Extract<DefinitionProjectionPath<DefinitionOf<Root>>, Name | `${Name}.${string}`> extends never
692
+ ? EqualScalarType<
693
+ ProjectionScalarTypeAtPath<DefinitionOf<Root>, From>,
694
+ ProjectionScalarTypeAtPath<DefinitionOf<BatchQueryGraph<Query>>, BatchQueryKeyPath<Query>>
695
+ > extends true
696
+ ? EqualScalarType<
697
+ ProjectionScalarTypeAtPath<DefinitionOf<BatchQueryGraph<Query>>, BatchQueryKeyPath<Query>>,
698
+ BatchQueryKeyParameter<Query>['scalarType']
699
+ > extends true
700
+ ? Relation
701
+ : never
702
+ : never
703
+ : never
704
+ : never
705
+ : never
706
+
707
+ type CompatibleBatchRelations<Root extends RelationalQueryGraph, Relations extends readonly BatchRelation[]> = {
708
+ readonly [Index in keyof Relations]: Relations[Index] extends BatchRelation
709
+ ? CompatibleBatchRelation<Root, Relations[Index]>
710
+ : never
711
+ }
712
+
713
+ type RelationName<Relations extends readonly BatchRelation[]> = Relations[number]['name']
714
+ type ChildPathsForRelation<Relation extends BatchRelation> = Relation extends BatchRelation
715
+ ? `${Relation['name']}.${DefinitionProjectionPath<DefinitionOf<BatchQueryGraph<Relation['query']>>>}`
716
+ : never
717
+ type ChildPaths<Relations extends readonly BatchRelation[]> = ChildPathsForRelation<Relations[number]>
718
+
719
+ export type ComposedSelection<Root extends RelationalQueryGraph, Relations extends readonly BatchRelation[]> =
720
+ | DefinitionProjectionPath<DefinitionOf<Root>>
721
+ | ChildPaths<Relations>
722
+
723
+ export interface BatchPlanMetadata<Relation extends BatchRelation = BatchRelation> {
724
+ name: Relation['name']
725
+ parentKey: Relation['from']
726
+ childKey: BatchQueryKeyPath<Relation['query']>
727
+ keyParameter: BatchQueryKeyParameter<Relation['query']>['name']
728
+ parameters: Readonly<Relation['parameters']>
729
+ cardinality: Relation['cardinality']
730
+ parentKeyInjected: boolean
731
+ childKeyInjected: boolean
732
+ }
733
+
734
+ type BatchRelationNamed<Relation extends BatchRelation, Name extends string> = Relation extends BatchRelation
735
+ ? Relation['name'] extends Name
736
+ ? Relation
737
+ : never
738
+ : never
739
+
740
+ type BatchRelationByName<Relations extends readonly BatchRelation[], Name extends string> = BatchRelationNamed<
741
+ Relations[number],
742
+ Name
743
+ >
744
+
745
+ type BatchKeyValue<Relation extends BatchRelation> = ScalarParameterValue<
746
+ BatchQueryKeyParameter<Relation['query']>['scalarType']
747
+ >
748
+
749
+ export interface CompiledQueryPlan<Relations extends readonly BatchRelation[] = readonly BatchRelation[]> {
750
+ readonly root: import('./index.js').CompiledSqlStatement
751
+ readonly batches: readonly BatchPlanMetadata<Relations[number]>[]
752
+ compileBatch<const Name extends RelationName<Relations>>(
753
+ name: Name,
754
+ keys: readonly BatchKeyValue<BatchRelationByName<Relations, Name>>[],
755
+ ): import('./index.js').CompiledSqlStatement
756
+ }
757
+
758
+ export type ComposedQueryOperation<
759
+ Root extends RelationalQueryGraph,
760
+ Relations extends readonly BatchRelation[],
761
+ > = QueryOperationBase<ComposedSelection<Root, Relations>, DefinitionOrderingName<DefinitionOf<Root>>> &
762
+ OperationParameterInput<DefinitionOf<Root>>
763
+
764
+ export interface ComposedQueryGraph<
765
+ Root extends RelationalQueryGraph = RelationalQueryGraph,
766
+ Relations extends readonly BatchRelation[] = readonly BatchRelation[],
767
+ > {
768
+ readonly name: string
769
+ compileOraclePlan(
770
+ operation: ComposedQueryOperation<Root, Relations>,
771
+ options?: OracleCompileOptions,
772
+ ): CompiledQueryPlan<Relations>
773
+ compileSqlServerPlan(
774
+ operation: ComposedQueryOperation<Root, Relations>,
775
+ options?: SqlServerCompileOptions,
776
+ ): CompiledQueryPlan<Relations>
777
+ }
778
+
779
+ export function composeGraph<
780
+ const Root extends RelationalQueryGraph,
781
+ const Relations extends readonly BatchRelation[],
782
+ >(configuration: {
783
+ root: Root
784
+ relations: Relations & CompatibleBatchRelations<Root, Relations>
785
+ }): ComposedQueryGraph<Root, Relations>
786
+
787
+ export interface ScalarOutputTypeMap {
788
+ boolean: unknown
789
+ int32: unknown
790
+ int64: unknown
791
+ float64: unknown
792
+ decimal: unknown
793
+ string: unknown
794
+ date: unknown
795
+ dateTime: unknown
796
+ binary: unknown
797
+ json: unknown
798
+ }
799
+
800
+ export interface DefaultScalarOutputTypeMap extends ScalarOutputTypeMap {
801
+ boolean: boolean
802
+ int32: number
803
+ int64: number | string
804
+ float64: number
805
+ decimal: number | string
806
+ string: string
807
+ date: string
808
+ dateTime: string
809
+ binary: string
810
+ json: JsonValue
811
+ }
812
+
813
+ export type DefinitionOf<Subject extends GraphDefinitionInput | QueryGraph | RelationalQueryGraph> =
814
+ Subject extends GraphDefinitionInput
815
+ ? Subject
816
+ : Subject extends QueryGraph<infer Definition>
817
+ ? Definition
818
+ : Subject extends RelationalQueryGraph<infer Definition>
819
+ ? Definition
820
+ : never
821
+
822
+ type IncomingRelation<Definition extends GraphDefinitionInput, Source extends string> =
823
+ DefinitionRelation<Definition> extends infer Candidate
824
+ ? Candidate extends RelationDefinition<infer _Name, infer _From, infer To, infer _Required, infer _Cardinality>
825
+ ? Source extends To
826
+ ? Candidate
827
+ : never
828
+ : never
829
+ : never
830
+
831
+ type RelationPathNullability<
832
+ Definition extends GraphDefinitionInput,
833
+ Relation,
834
+ Visited extends string,
835
+ Depth extends readonly unknown[],
836
+ > =
837
+ Relation extends RelationDefinition<infer _Name, infer From, infer _To, infer Required, infer _Cardinality>
838
+ ? BooleanOr<
839
+ | (Required extends true ? false : true)
840
+ | SourceOuterNullable<Definition, From, Visited, readonly [...Depth, unknown]>
841
+ >
842
+ : boolean
843
+
844
+ type SourceOuterNullable<
845
+ Definition extends GraphDefinitionInput,
846
+ Source extends string,
847
+ Visited extends string = never,
848
+ Depth extends readonly unknown[] = readonly [],
849
+ > = Depth['length'] extends 12
850
+ ? boolean
851
+ : string extends Source
852
+ ? boolean
853
+ : string extends DefinitionRoot<Definition>
854
+ ? boolean
855
+ : Source extends DefinitionRoot<Definition>
856
+ ? false
857
+ : Source extends Visited
858
+ ? boolean
859
+ : [IncomingRelation<Definition, Source>] extends [never]
860
+ ? boolean
861
+ : BooleanOr<
862
+ RelationPathNullability<Definition, IncomingRelation<Definition, Source>, Visited | Source, Depth>
863
+ >
864
+
865
+ type CombineAllNullability<Left extends boolean, Right extends boolean> = [Left] extends [false]
866
+ ? false
867
+ : [Right] extends [false]
868
+ ? false
869
+ : [Left] extends [true]
870
+ ? Right
871
+ : [Right] extends [true]
872
+ ? Left
873
+ : boolean
874
+
875
+ type EvaluateAnyNullability<
876
+ Definition extends GraphDefinitionInput,
877
+ Values,
878
+ Depth extends readonly unknown[],
879
+ > = Values extends readonly []
880
+ ? false
881
+ : Values extends readonly [
882
+ infer First extends NullabilityExpression,
883
+ ...infer Rest extends readonly NullabilityExpression[],
884
+ ]
885
+ ? BooleanOr<
886
+ | EvaluateNullability<Definition, First, readonly [...Depth, unknown]>
887
+ | EvaluateAnyNullability<Definition, Rest, readonly [...Depth, unknown]>
888
+ >
889
+ : Values extends readonly (infer Value extends NullabilityExpression)[]
890
+ ? BooleanOr<EvaluateNullability<Definition, Value, readonly [...Depth, unknown]>>
891
+ : boolean
892
+
893
+ type EvaluateAllNullability<
894
+ Definition extends GraphDefinitionInput,
895
+ Values,
896
+ Depth extends readonly unknown[],
897
+ > = Values extends readonly []
898
+ ? true
899
+ : Values extends readonly [
900
+ infer First extends NullabilityExpression,
901
+ ...infer Rest extends readonly NullabilityExpression[],
902
+ ]
903
+ ? CombineAllNullability<
904
+ EvaluateNullability<Definition, First, readonly [...Depth, unknown]>,
905
+ EvaluateAllNullability<Definition, Rest, readonly [...Depth, unknown]>
906
+ >
907
+ : boolean
908
+
909
+ type EvaluateNullability<
910
+ Definition extends GraphDefinitionInput,
911
+ Formula extends NullabilityExpression,
912
+ Depth extends readonly unknown[] = readonly [],
913
+ > = Depth['length'] extends 16
914
+ ? boolean
915
+ : NullabilityExpression extends Formula
916
+ ? boolean
917
+ : Formula extends boolean
918
+ ? Formula
919
+ : Formula extends SourceFieldNullability<infer Source, infer FieldNullable>
920
+ ? BooleanOr<FieldNullable | SourceOuterNullable<Definition, Source, never, Depth>>
921
+ : Formula extends AnyNullability<infer Values>
922
+ ? EvaluateAnyNullability<Definition, Values, Depth>
923
+ : Formula extends AllNullability<infer Values>
924
+ ? EvaluateAllNullability<Definition, Values, Depth>
925
+ : boolean
926
+
927
+ type ProjectionFieldPath<Field> =
928
+ Field extends ProjectionTypeMetadata<infer Path, infer _Type, infer _Nullability, infer _SelectedByDefault>
929
+ ? Path
930
+ : Field extends ProjectionFieldDefinition<infer Path>
931
+ ? Path
932
+ : never
933
+
934
+ type ProjectionFieldValue<Definition extends GraphDefinitionInput, Field, TypeMap extends ScalarOutputTypeMap> =
935
+ Field extends ProjectionTypeMetadata<infer _Path, infer Type, infer Nullability, infer _SelectedByDefault>
936
+ ? true extends EvaluateNullability<Definition, Nullability>
937
+ ? TypeMap[Type] | null
938
+ : TypeMap[Type]
939
+ : Field extends ProjectionFieldDefinition<infer _Path, infer Type, infer Nullability, infer _SelectedByDefault>
940
+ ? true extends EvaluateNullability<Definition, Nullability>
941
+ ? TypeMap[Type] | null
942
+ : TypeMap[Type]
943
+ : never
944
+
945
+ type ProjectionFieldByPath<Field, Path extends string> = Field extends ProjectionFieldDefinition
946
+ ? ProjectionFieldPath<Field> extends Path
947
+ ? Field
948
+ : never
949
+ : never
950
+
951
+ type ProjectionDefaultAtPath<Field, Path extends string> =
952
+ Field extends ProjectionTypeMetadata<infer FieldPath, infer _Type, infer _Nullability, infer SelectedByDefault>
953
+ ? FieldPath extends Path
954
+ ? SelectedByDefault
955
+ : never
956
+ : Field extends ProjectionFieldDefinition
957
+ ? ProjectionFieldPath<Field> extends Path
958
+ ? Field extends { selectedByDefault: true }
959
+ ? true
960
+ : false
961
+ : never
962
+ : never
963
+
964
+ type DefaultProjectionPath<Field, Path extends string = ProjectionFieldPath<Field>> = Path extends unknown
965
+ ? [ProjectionDefaultAtPath<Field, Path>] extends [never]
966
+ ? never
967
+ : ProjectionDefaultAtPath<Field, Path> extends true
968
+ ? Path
969
+ : never
970
+ : never
971
+
972
+ type DefaultProjectionField<Field> = ProjectionFieldByPath<Field, DefaultProjectionPath<Field>>
973
+
974
+ type SelectedProjectionField<Definition extends GraphDefinitionInput, Operation> = [Operation] extends [undefined]
975
+ ? DefaultProjectionField<DefinitionProjectionField<Definition>>
976
+ : Operation extends { select: readonly (infer Path extends string)[] }
977
+ ? ProjectionFieldByPath<DefinitionProjectionField<Definition>, Path>
978
+ : DefaultProjectionField<DefinitionProjectionField<Definition>>
979
+
980
+ type ProjectionEntry<
981
+ Definition extends GraphDefinitionInput,
982
+ Field,
983
+ TypeMap extends ScalarOutputTypeMap,
984
+ > = Field extends ProjectionFieldDefinition
985
+ ? {
986
+ path: ProjectionFieldPath<Field>
987
+ value: ProjectionFieldValue<Definition, Field, TypeMap>
988
+ }
989
+ : never
990
+
991
+ type ProjectionEntryHead<Entry> = Entry extends { path: infer Path extends string }
992
+ ? Path extends `${infer Head}.${string}`
993
+ ? Head
994
+ : Path
995
+ : never
996
+
997
+ type DirectProjectionEntryValue<Entry, Key extends string> = Entry extends {
998
+ path: infer Path extends string
999
+ value: infer Value
1000
+ }
1001
+ ? Path extends Key
1002
+ ? Value
1003
+ : never
1004
+ : never
1005
+
1006
+ type NestedProjectionEntry<Entry, Key extends string> = Entry extends {
1007
+ path: infer Path extends string
1008
+ value: infer Value
1009
+ }
1010
+ ? Path extends `${Key}.${infer Rest}`
1011
+ ? { path: Rest; value: Value }
1012
+ : never
1013
+ : never
1014
+
1015
+ type ProjectionValueAtKey<Entry, Key extends string> = [NestedProjectionEntry<Entry, Key>] extends [never]
1016
+ ? DirectProjectionEntryValue<Entry, Key>
1017
+ : [DirectProjectionEntryValue<Entry, Key>] extends [never]
1018
+ ? BuildProjectionResult<NestedProjectionEntry<Entry, Key>>
1019
+ : DirectProjectionEntryValue<Entry, Key> | BuildProjectionResult<NestedProjectionEntry<Entry, Key>>
1020
+
1021
+ type BuildProjectionResult<Entry> = [Entry] extends [never]
1022
+ ? Record<never, never>
1023
+ : {
1024
+ [Key in ProjectionEntryHead<Entry>]: ProjectionValueAtKey<Entry, Key>
1025
+ }
1026
+
1027
+ export type ResultOf<
1028
+ Subject extends GraphDefinitionInput | QueryGraph | RelationalQueryGraph | ComposedQueryGraph,
1029
+ Operation = undefined,
1030
+ TypeMap extends ScalarOutputTypeMap = DefaultScalarOutputTypeMap,
1031
+ > =
1032
+ Subject extends ComposedQueryGraph<infer Root, infer Relations>
1033
+ ? ComposedResult<Root, Relations, Operation, TypeMap>
1034
+ : DefinitionOf<
1035
+ Extract<Subject, GraphDefinitionInput | QueryGraph | RelationalQueryGraph>
1036
+ > extends infer Definition extends GraphDefinitionInput
1037
+ ? BuildProjectionResult<ProjectionEntry<Definition, SelectedProjectionField<Definition, Operation>, TypeMap>>
1038
+ : never
1039
+
1040
+ type SelectedPaths<Operation> = Operation extends { select: readonly (infer Path extends string)[] } ? Path : never
1041
+
1042
+ type RootOperation<Operation, Relations extends readonly BatchRelation[]> = Operation extends {
1043
+ select: readonly string[]
1044
+ }
1045
+ ? { select: readonly Exclude<SelectedPaths<Operation>, ChildPaths<Relations>>[] }
1046
+ : undefined
1047
+
1048
+ type SelectedChildPath<Operation, Name extends string> =
1049
+ Extract<SelectedPaths<Operation>, `${Name}.${string}`> extends `${Name}.${infer Path}` ? Path : never
1050
+
1051
+ type ChildOperation<Operation, Name extends string> = {
1052
+ select: readonly SelectedChildPath<Operation, Name>[]
1053
+ }
1054
+
1055
+ type SelectedRelationCandidate<Relation extends BatchRelation, Operation> = Relation extends BatchRelation
1056
+ ? Extract<SelectedPaths<Operation>, `${Relation['name']}.${string}`> extends never
1057
+ ? never
1058
+ : Relation
1059
+ : never
1060
+
1061
+ type SelectedRelation<Relations extends readonly BatchRelation[], Operation> = SelectedRelationCandidate<
1062
+ Relations[number],
1063
+ Operation
1064
+ >
1065
+
1066
+ type BatchResult<Relation extends BatchRelation, Operation, TypeMap extends ScalarOutputTypeMap> =
1067
+ ResultOf<BatchQueryGraph<Relation['query']>, ChildOperation<Operation, Relation['name']>, TypeMap> extends infer Child
1068
+ ? Relation['cardinality'] extends 'many'
1069
+ ? Child[]
1070
+ : Child | null
1071
+ : never
1072
+
1073
+ type ComposedResult<
1074
+ Root extends RelationalQueryGraph,
1075
+ Relations extends readonly BatchRelation[],
1076
+ Operation,
1077
+ TypeMap extends ScalarOutputTypeMap,
1078
+ > = ResultOf<Root, RootOperation<Operation, Relations>, TypeMap> & {
1079
+ [Relation in SelectedRelation<Relations, Operation> as Relation['name']]: BatchResult<Relation, Operation, TypeMap>
1080
+ }
1081
+
360
1082
  export type SqlServerVersion = '2008' | '2012' | '2016' | '2019' | '2022'
361
1083
  export type OracleVersion = '11g' | '12c' | '19c' | '21c' | '23ai'
362
1084
 
@@ -368,7 +1090,7 @@ export interface OracleCompileOptions {
368
1090
  version?: OracleVersion
369
1091
  }
370
1092
 
371
- export type QueryGraphErrorPhase = 'definition' | 'mapping' | 'operation' | 'sql'
1093
+ export type QueryGraphErrorPhase = 'definition' | 'mapping' | 'composition' | 'operation' | 'sql'
372
1094
 
373
1095
  export interface QueryGraphDiagnostic {
374
1096
  code: string
@@ -383,19 +1105,47 @@ export interface QueryGraphError extends Error {
383
1105
  readonly issues: readonly QueryGraphDiagnostic[]
384
1106
  }
385
1107
 
386
- export interface FieldSpecDefinition {
387
- scalarType: ScalarType
388
- nullable?: boolean
389
- selectable?: boolean
1108
+ export interface FieldSpecDefinition<
1109
+ Type extends ScalarType = ScalarType,
1110
+ Nullable extends boolean = boolean,
1111
+ Selectable extends boolean = boolean,
1112
+ > {
1113
+ scalarType: Type
1114
+ nullable?: Nullable
1115
+ selectable?: Selectable
390
1116
  }
391
1117
 
392
1118
  export type FieldSpec = ScalarType | FieldSpecDefinition
393
1119
  export type FieldSpecMap = Record<string, FieldSpec>
394
1120
 
1121
+ export type FieldSpecScalarType<Specification extends FieldSpec> = Specification extends ScalarType
1122
+ ? Specification
1123
+ : Specification extends FieldSpecDefinition<infer Type, infer _Nullable, infer _Selectable>
1124
+ ? Type
1125
+ : never
1126
+
1127
+ export type FieldSpecIsNullable<Specification extends FieldSpec> = Specification extends ScalarType
1128
+ ? false
1129
+ : Specification extends FieldSpecDefinition<infer _Type, infer Nullable, infer _Selectable>
1130
+ ? Nullable
1131
+ : boolean
1132
+
1133
+ export type FieldSpecIsSelectable<Specification extends FieldSpec> = Specification extends ScalarType
1134
+ ? true
1135
+ : Specification extends FieldSpecDefinition<infer _Type, infer _Nullable, infer Selectable>
1136
+ ? Selectable
1137
+ : boolean
1138
+
395
1139
  export interface SourceRef<Key extends string = string, Fields extends FieldSpecMap = FieldSpecMap>
396
1140
  extends SourceDefinition {
397
1141
  key: Key
398
- field<Name extends Extract<keyof Fields, string>>(name: Name): FieldExpression<Key, Name>
1142
+ field<Name extends Extract<keyof Fields, string>>(
1143
+ name: Name,
1144
+ ): TypedExpression<
1145
+ FieldExpression<Key, Name>,
1146
+ FieldSpecScalarType<Fields[Name]>,
1147
+ SourceFieldNullability<Key, FieldSpecIsNullable<Fields[Name]>>
1148
+ >
399
1149
  }
400
1150
 
401
1151
  export interface ScalarParameterRef<
@@ -426,21 +1176,95 @@ export type ParameterRef<
426
1176
  Required extends boolean = boolean,
427
1177
  > = ScalarParameterRef<Name, Type, Required> | ListParameterRef<Name, Type, Required>
428
1178
 
429
- export interface RelationRef<Name extends string = string> extends RelationDefinition {
430
- name: Name
431
- }
1179
+ export type RelationRef<
1180
+ Name extends string = string,
1181
+ From extends string = string,
1182
+ To extends string = string,
1183
+ Required extends boolean = boolean,
1184
+ Cardinality extends RelationCardinality = RelationCardinality,
1185
+ > = RelationDefinition<Name, From, To, Required, Cardinality>
432
1186
 
433
1187
  export type LiteralInput = null | boolean | string | number
434
1188
  export type ExpressionInput = Expression | LiteralInput | SummaryFieldDefinition
435
1189
 
1190
+ type NumberLiteralScalarType<Value extends number> = number extends Value
1191
+ ? 'int64' | 'decimal'
1192
+ : `${Value}` extends `${bigint}`
1193
+ ? 'int64'
1194
+ : 'decimal'
1195
+
1196
+ type InputScalarType<Input extends ExpressionInput> =
1197
+ Input extends ExpressionTypeMetadata<infer Type, infer _Nullability>
1198
+ ? Type
1199
+ : Input extends ProjectionFieldDefinition<infer _Path, infer Type, infer _Nullability, infer _SelectedByDefault>
1200
+ ? Type
1201
+ : Input extends null
1202
+ ? null
1203
+ : Input extends boolean
1204
+ ? 'boolean'
1205
+ : Input extends string
1206
+ ? 'string'
1207
+ : Input extends number
1208
+ ? NumberLiteralScalarType<Input>
1209
+ : ScalarType
1210
+
1211
+ type InputNullability<Input extends ExpressionInput> =
1212
+ Input extends ExpressionTypeMetadata<infer _Type, infer Nullability>
1213
+ ? Nullability
1214
+ : Input extends ProjectionFieldDefinition<infer _Path, infer _Type, infer Nullability, infer _SelectedByDefault>
1215
+ ? Nullability
1216
+ : Input extends null
1217
+ ? true
1218
+ : Input extends Expression
1219
+ ? boolean
1220
+ : false
1221
+
1222
+ export type ExpressionScalarType<Input extends ExpressionInput> = InputScalarType<Input>
1223
+ export type ExpressionNullability<Input extends ExpressionInput> = InputNullability<Input>
1224
+
1225
+ type PromoteScalarType<Type extends ScalarType | null> = 'float64' extends Type
1226
+ ? 'float64'
1227
+ : 'decimal' extends Type
1228
+ ? 'decimal'
1229
+ : 'int64' extends Type
1230
+ ? 'int64'
1231
+ : 'int32' extends Type
1232
+ ? 'int32'
1233
+ : 'dateTime' extends Type
1234
+ ? 'dateTime'
1235
+ : Exclude<Type, null>
1236
+
1237
+ type AverageScalarType<Type extends ScalarType | null> = Type extends 'float64'
1238
+ ? 'float64'
1239
+ : Type extends 'int32' | 'int64' | 'decimal'
1240
+ ? 'decimal'
1241
+ : Exclude<Type, null>
1242
+
1243
+ type InputNullabilities<Inputs extends readonly ExpressionInput[]> = {
1244
+ [Index in keyof Inputs]: InputNullability<Inputs[Index]>
1245
+ }
1246
+
1247
+ type AnyInputNullability<Inputs extends readonly ExpressionInput[]> = AnyNullability<InputNullabilities<Inputs>>
1248
+ type AllInputNullability<Inputs extends readonly ExpressionInput[]> = AllNullability<InputNullabilities<Inputs>>
1249
+
436
1250
  export interface FieldTypeOptions {
437
1251
  nullable?: boolean
438
1252
  selectable?: boolean
439
1253
  }
440
1254
 
441
- export function fieldType(scalarType: ScalarType, options?: FieldTypeOptions): FieldSpecDefinition
442
- export function nullable(specification: FieldSpec): FieldSpecDefinition
443
- export function hidden(specification: FieldSpec): FieldSpecDefinition
1255
+ type OptionNullable<Options extends FieldTypeOptions> = Options extends { nullable: true } ? true : false
1256
+ type OptionSelectable<Options extends FieldTypeOptions> = Options extends { selectable: false } ? false : true
1257
+
1258
+ export function fieldType<const Type extends ScalarType, const Options extends FieldTypeOptions = Record<never, never>>(
1259
+ scalarType: Type,
1260
+ options?: Options,
1261
+ ): FieldSpecDefinition<Type, OptionNullable<Options>, OptionSelectable<Options>>
1262
+ export function nullable<const Specification extends FieldSpec>(
1263
+ specification: Specification,
1264
+ ): FieldSpecDefinition<FieldSpecScalarType<Specification>, true, FieldSpecIsSelectable<Specification>>
1265
+ export function hidden<const Specification extends FieldSpec>(
1266
+ specification: Specification,
1267
+ ): FieldSpecDefinition<FieldSpecScalarType<Specification>, FieldSpecIsNullable<Specification>, false>
444
1268
 
445
1269
  export function source<const Key extends string, const Fields extends FieldSpecMap>(
446
1270
  key: Key,
@@ -465,33 +1289,75 @@ export function optionalListParameter<const Name extends string, const Type exte
465
1289
  ): ListParameterRef<Name, Type, false>
466
1290
  export function param<const Name extends string, const Type extends ScalarType>(
467
1291
  parameter: ScalarParameterRef<Name, Type>,
468
- ): ParameterExpression<Name>
469
-
470
- export function literal(value: LiteralInput): LiteralExpression
471
- export function integer(value: number): LiteralExpression
472
- export function decimal(value: string | number): LiteralExpression
473
-
474
- export function eq(left: ExpressionInput, right: ExpressionInput): BinaryExpression
475
- export function neq(left: ExpressionInput, right: ExpressionInput): BinaryExpression
476
- export function lt(left: ExpressionInput, right: ExpressionInput): BinaryExpression
477
- export function lte(left: ExpressionInput, right: ExpressionInput): BinaryExpression
478
- export function gt(left: ExpressionInput, right: ExpressionInput): BinaryExpression
479
- export function gte(left: ExpressionInput, right: ExpressionInput): BinaryExpression
480
- export function like(expression: ExpressionInput, pattern: ExpressionInput): LikeExpression
481
- export function inList(expression: ExpressionInput, values: readonly ExpressionInput[]): InExpression
482
- export function and(...expressions: readonly ExpressionInput[]): ExpressionGroup
483
- export function inParameter<const Name extends string, const Type extends ScalarType>(
484
- expression: ExpressionInput,
1292
+ ): TypedExpression<ParameterExpression<Name>, Type, false>
1293
+
1294
+ export function literal<const Value extends LiteralInput>(
1295
+ value: Value,
1296
+ ): TypedExpression<LiteralExpression, InputScalarType<Value>, InputNullability<Value>>
1297
+ export function integer(value: number): TypedExpression<LiteralExpression, 'int64', false>
1298
+ export function decimal(value: string | number): TypedExpression<LiteralExpression, 'decimal', false>
1299
+
1300
+ type EqualityNullability<Left extends ExpressionInput, Right extends ExpressionInput> = null extends
1301
+ | InputScalarType<Left>
1302
+ | InputScalarType<Right>
1303
+ ? false
1304
+ : AnyInputNullability<readonly [Left, Right]>
1305
+
1306
+ export function eq<const Left extends ExpressionInput, const Right extends ExpressionInput>(
1307
+ left: Left,
1308
+ right: Right,
1309
+ ): TypedExpression<BinaryExpression, 'boolean', EqualityNullability<Left, Right>>
1310
+ export function neq<const Left extends ExpressionInput, const Right extends ExpressionInput>(
1311
+ left: Left,
1312
+ right: Right,
1313
+ ): TypedExpression<BinaryExpression, 'boolean', EqualityNullability<Left, Right>>
1314
+ export function lt<const Left extends ExpressionInput, const Right extends ExpressionInput>(
1315
+ left: Left,
1316
+ right: Right,
1317
+ ): TypedExpression<BinaryExpression, 'boolean', AnyInputNullability<readonly [Left, Right]>>
1318
+ export function lte<const Left extends ExpressionInput, const Right extends ExpressionInput>(
1319
+ left: Left,
1320
+ right: Right,
1321
+ ): TypedExpression<BinaryExpression, 'boolean', AnyInputNullability<readonly [Left, Right]>>
1322
+ export function gt<const Left extends ExpressionInput, const Right extends ExpressionInput>(
1323
+ left: Left,
1324
+ right: Right,
1325
+ ): TypedExpression<BinaryExpression, 'boolean', AnyInputNullability<readonly [Left, Right]>>
1326
+ export function gte<const Left extends ExpressionInput, const Right extends ExpressionInput>(
1327
+ left: Left,
1328
+ right: Right,
1329
+ ): TypedExpression<BinaryExpression, 'boolean', AnyInputNullability<readonly [Left, Right]>>
1330
+ export function like<const Value extends ExpressionInput, const Pattern extends ExpressionInput>(
1331
+ expression: Value,
1332
+ pattern: Pattern,
1333
+ ): TypedExpression<LikeExpression, 'boolean', AnyInputNullability<readonly [Value, Pattern]>>
1334
+ export function inList<const Value extends ExpressionInput, const Values extends readonly ExpressionInput[]>(
1335
+ expression: Value,
1336
+ values: Values,
1337
+ ): TypedExpression<InExpression, 'boolean', AnyInputNullability<readonly [Value, ...Values]>>
1338
+ export function and<const Expressions extends readonly ExpressionInput[]>(
1339
+ ...expressions: Expressions
1340
+ ): TypedExpression<ExpressionGroup, 'boolean', AnyInputNullability<Expressions>>
1341
+ export function inParameter<
1342
+ const Value extends ExpressionInput,
1343
+ const Name extends string,
1344
+ const Type extends ScalarType,
1345
+ >(
1346
+ expression: Value,
485
1347
  parameter: ListParameterRef<Name, Type>,
486
- ): InParameterExpression<Name>
487
- export function or(...expressions: readonly ExpressionInput[]): ExpressionGroup
488
- export function not(expression: ExpressionInput): UnaryExpression
489
- export function isNull(expression: ExpressionInput): UnaryExpression
490
- export function isNotNull(expression: ExpressionInput): UnaryExpression
1348
+ ): TypedExpression<InParameterExpression<Name>, 'boolean', InputNullability<Value>>
1349
+ export function or<const Expressions extends readonly ExpressionInput[]>(
1350
+ ...expressions: Expressions
1351
+ ): TypedExpression<ExpressionGroup, 'boolean', AnyInputNullability<Expressions>>
1352
+ export function not<const Value extends ExpressionInput>(
1353
+ expression: Value,
1354
+ ): TypedExpression<UnaryExpression, 'boolean', InputNullability<Value>>
1355
+ export function isNull(expression: ExpressionInput): TypedExpression<UnaryExpression, 'boolean', false>
1356
+ export function isNotNull(expression: ExpressionInput): TypedExpression<UnaryExpression, 'boolean', false>
491
1357
  export function exists<const Source extends string>(
492
1358
  source: Source | SourceRef<Source>,
493
1359
  predicate?: ExpressionInput,
494
- ): ExistsExpression<Source, never>
1360
+ ): TypedExpression<ExistsExpression<Source, never>, 'boolean', false>
495
1361
  export interface ExistsConfiguration<From extends string = string> {
496
1362
  from: From | SourceRef<From>
497
1363
  }
@@ -499,35 +1365,75 @@ export function exists<const Source extends string, const From extends string>(
499
1365
  source: Source | SourceRef<Source>,
500
1366
  predicate: ExpressionInput | undefined,
501
1367
  configuration: ExistsConfiguration<From>,
502
- ): ExistsExpression<Source, From>
503
-
504
- export function lower(expression: ExpressionInput): FunctionExpression
505
- export function upper(expression: ExpressionInput): FunctionExpression
506
- export function coalesce(
507
- first: ExpressionInput,
508
- second: ExpressionInput,
509
- ...rest: readonly ExpressionInput[]
510
- ): FunctionExpression
511
- export function concat(first: ExpressionInput, ...rest: readonly ExpressionInput[]): FunctionExpression
512
-
513
- export function count(expression?: ExpressionInput): AggregateExpression
514
- export function countDistinct(expression: ExpressionInput): AggregateExpression
515
- export function sum(expression: ExpressionInput): AggregateExpression
516
- export function average(expression: ExpressionInput): AggregateExpression
517
- export function minimum(expression: ExpressionInput): AggregateExpression
518
- export function maximum(expression: ExpressionInput): AggregateExpression
519
-
520
- export interface RelationConfiguration<Name extends string = string> {
1368
+ ): TypedExpression<ExistsExpression<Source, From>, 'boolean', false>
1369
+
1370
+ export function lower<const Value extends ExpressionInput>(
1371
+ expression: Value,
1372
+ ): TypedExpression<FunctionExpression, 'string', InputNullability<Value>>
1373
+ export function upper<const Value extends ExpressionInput>(
1374
+ expression: Value,
1375
+ ): TypedExpression<FunctionExpression, 'string', InputNullability<Value>>
1376
+ export function coalesce<
1377
+ const First extends ExpressionInput,
1378
+ const Second extends ExpressionInput,
1379
+ const Rest extends readonly ExpressionInput[],
1380
+ >(
1381
+ first: First,
1382
+ second: Second,
1383
+ ...rest: Rest
1384
+ ): TypedExpression<
1385
+ FunctionExpression,
1386
+ PromoteScalarType<InputScalarType<First | Second | Rest[number]>>,
1387
+ AllInputNullability<readonly [First, Second, ...Rest]>
1388
+ >
1389
+ export function concat<const First extends ExpressionInput, const Rest extends readonly ExpressionInput[]>(
1390
+ first: First,
1391
+ ...rest: Rest
1392
+ ): TypedExpression<FunctionExpression, 'string', AllInputNullability<readonly [First, ...Rest]>>
1393
+
1394
+ export function count(expression?: ExpressionInput): TypedExpression<AggregateExpression, 'int64', false>
1395
+ export function countDistinct(expression: ExpressionInput): TypedExpression<AggregateExpression, 'int64', false>
1396
+ export function sum<const Value extends ExpressionInput>(
1397
+ expression: Value,
1398
+ ): TypedExpression<AggregateExpression, Exclude<InputScalarType<Value>, null>, true>
1399
+ export function average<const Value extends ExpressionInput>(
1400
+ expression: Value,
1401
+ ): TypedExpression<AggregateExpression, AverageScalarType<InputScalarType<Value>>, true>
1402
+ export function minimum<const Value extends ExpressionInput>(
1403
+ expression: Value,
1404
+ ): TypedExpression<AggregateExpression, Exclude<InputScalarType<Value>, null>, true>
1405
+ export function maximum<const Value extends ExpressionInput>(
1406
+ expression: Value,
1407
+ ): TypedExpression<AggregateExpression, Exclude<InputScalarType<Value>, null>, true>
1408
+
1409
+ export type SourceReferenceKey<Reference extends string | SourceRef> =
1410
+ Reference extends SourceRef<infer Key, infer _Fields> ? Key : Reference extends string ? Reference : string
1411
+
1412
+ export interface RelationConfiguration<
1413
+ Name extends string = string,
1414
+ From extends string | SourceRef = string | SourceRef,
1415
+ To extends string | SourceRef = string | SourceRef,
1416
+ Required extends boolean = boolean,
1417
+ Cardinality extends RelationCardinality = RelationCardinality,
1418
+ > {
521
1419
  name: Name
522
- from: string | SourceRef
523
- to: string | SourceRef
1420
+ from: From
1421
+ to: To
524
1422
  on: Expression
525
- required?: boolean
526
- cardinality?: RelationCardinality
1423
+ required?: Required
1424
+ cardinality?: Cardinality
527
1425
  selection?: RelationSelection
528
1426
  }
529
1427
 
530
- export function relation<const Name extends string>(configuration: RelationConfiguration<Name>): RelationRef<Name>
1428
+ export function relation<
1429
+ const Name extends string,
1430
+ const From extends string | SourceRef,
1431
+ const To extends string | SourceRef,
1432
+ const Required extends boolean = false,
1433
+ const Cardinality extends RelationCardinality = 'one',
1434
+ >(
1435
+ configuration: RelationConfiguration<Name, From, To, Required, Cardinality>,
1436
+ ): RelationRef<Name, SourceReferenceKey<From>, SourceReferenceKey<To>, Required, Cardinality>
531
1437
 
532
1438
  export interface ConstraintConfiguration {
533
1439
  predicate: Expression
@@ -536,10 +1442,14 @@ export interface ConstraintConfiguration {
536
1442
 
537
1443
  export function constraint(configuration: ConstraintConfiguration): ConstraintDefinition
538
1444
 
539
- export interface ProjectionConfiguration<Path extends string | readonly string[] = string | readonly string[]> {
1445
+ export interface ProjectionConfiguration<
1446
+ Path extends string | readonly string[] = string | readonly string[],
1447
+ Value extends ExpressionInput = ExpressionInput,
1448
+ SelectedByDefault extends boolean = boolean,
1449
+ > {
540
1450
  path: Path
541
- expression: ExpressionInput
542
- default?: boolean
1451
+ expression: Value
1452
+ default?: SelectedByDefault
543
1453
  }
544
1454
 
545
1455
  type ConfigurationPath<Path extends string | readonly string[]> = Path extends string
@@ -548,17 +1458,44 @@ type ConfigurationPath<Path extends string | readonly string[]> = Path extends s
548
1458
  ? JoinProjectionPath<Path>
549
1459
  : never
550
1460
 
551
- export function project<const Path extends string | readonly string[]>(
552
- configuration: ProjectionConfiguration<Path>,
553
- ): ProjectionFieldDefinition<ConfigurationPath<Path>>
1461
+ export function project<
1462
+ const Path extends string | readonly string[],
1463
+ const Value extends ExpressionInput,
1464
+ const SelectedByDefault extends boolean = false,
1465
+ >(
1466
+ configuration: ProjectionConfiguration<Path, Value, SelectedByDefault>,
1467
+ ): TypedProjectionField<
1468
+ ConfigurationPath<Path>,
1469
+ Extract<InputScalarType<Value>, ScalarType>,
1470
+ InputNullability<Value>,
1471
+ SelectedByDefault
1472
+ >
554
1473
 
555
- export function dimension<const Path extends string | readonly string[]>(
556
- configuration: ProjectionConfiguration<Path>,
557
- ): DimensionDefinition<ConfigurationPath<Path>>
1474
+ export function dimension<
1475
+ const Path extends string | readonly string[],
1476
+ const Value extends ExpressionInput,
1477
+ const SelectedByDefault extends boolean = false,
1478
+ >(
1479
+ configuration: ProjectionConfiguration<Path, Value, SelectedByDefault>,
1480
+ ): TypedDimensionDefinition<
1481
+ ConfigurationPath<Path>,
1482
+ Extract<InputScalarType<Value>, ScalarType>,
1483
+ InputNullability<Value>,
1484
+ SelectedByDefault
1485
+ >
558
1486
 
559
- export function measure<const Path extends string | readonly string[]>(
560
- configuration: ProjectionConfiguration<Path>,
561
- ): MeasureDefinition<ConfigurationPath<Path>>
1487
+ export function measure<
1488
+ const Path extends string | readonly string[],
1489
+ const Value extends ExpressionInput,
1490
+ const SelectedByDefault extends boolean = false,
1491
+ >(
1492
+ configuration: ProjectionConfiguration<Path, Value, SelectedByDefault>,
1493
+ ): TypedMeasureDefinition<
1494
+ ConfigurationPath<Path>,
1495
+ Extract<InputScalarType<Value>, ScalarType>,
1496
+ InputNullability<Value>,
1497
+ SelectedByDefault
1498
+ >
562
1499
 
563
1500
  export interface OrderByOptions {
564
1501
  nulls?: NullsOrder
@@ -597,13 +1534,59 @@ type ConfigurationElement<Configuration, Key extends PropertyKey> = Key extends
597
1534
  : never
598
1535
 
599
1536
  type ModuleParameter<Module> =
600
- Module extends GraphModule<infer Parameter, infer _ProjectionPath, infer _OrderingName> ? Parameter : never
1537
+ Module extends GraphModule<
1538
+ infer Parameter,
1539
+ infer _ProjectionPath,
1540
+ infer _OrderingName,
1541
+ infer _ProjectionField,
1542
+ infer _Relation
1543
+ >
1544
+ ? Parameter
1545
+ : never
601
1546
 
602
1547
  type ModuleProjectionPath<Module> =
603
- Module extends GraphModule<infer _Parameter, infer ProjectionPath, infer _OrderingName> ? ProjectionPath : never
1548
+ Module extends GraphModule<
1549
+ infer _Parameter,
1550
+ infer ProjectionPath,
1551
+ infer _OrderingName,
1552
+ infer _ProjectionField,
1553
+ infer _Relation
1554
+ >
1555
+ ? ProjectionPath
1556
+ : never
604
1557
 
605
1558
  type ModuleOrderingName<Module> =
606
- Module extends GraphModule<infer _Parameter, infer _ProjectionPath, infer OrderingName> ? OrderingName : never
1559
+ Module extends GraphModule<
1560
+ infer _Parameter,
1561
+ infer _ProjectionPath,
1562
+ infer OrderingName,
1563
+ infer _ProjectionField,
1564
+ infer _Relation
1565
+ >
1566
+ ? OrderingName
1567
+ : never
1568
+
1569
+ type ModuleProjectionField<Module> =
1570
+ Module extends GraphModule<
1571
+ infer _Parameter,
1572
+ infer _ProjectionPath,
1573
+ infer _OrderingName,
1574
+ infer ProjectionField,
1575
+ infer _Relation
1576
+ >
1577
+ ? ProjectionField
1578
+ : never
1579
+
1580
+ type ModuleRelation<Module> =
1581
+ Module extends GraphModule<
1582
+ infer _Parameter,
1583
+ infer _ProjectionPath,
1584
+ infer _OrderingName,
1585
+ infer _ProjectionField,
1586
+ infer Relation
1587
+ >
1588
+ ? Relation
1589
+ : never
607
1590
 
608
1591
  type ProjectionPathOf<Field> = Field extends ProjectionFieldDefinition<infer Path> ? Path : never
609
1592
 
@@ -619,21 +1602,39 @@ type ConfigurationProjectionPath<Configuration> =
619
1602
  | ProjectionPathOf<ConfigurationElement<Configuration, 'measures'>>
620
1603
  | ModuleProjectionPath<ConfigurationElement<Configuration, 'modules'>>
621
1604
 
1605
+ type ConfigurationProjectionField<Configuration> =
1606
+ | Extract<ConfigurationElement<Configuration, 'projection'>, ProjectionFieldDefinition>
1607
+ | Extract<ConfigurationElement<Configuration, 'dimensions'>, ProjectionFieldDefinition>
1608
+ | Extract<ConfigurationElement<Configuration, 'measures'>, ProjectionFieldDefinition>
1609
+ | ModuleProjectionField<ConfigurationElement<Configuration, 'modules'>>
1610
+
622
1611
  type ConfigurationOrderingName<Configuration> =
623
1612
  | OrderingNameOf<ConfigurationElement<Configuration, 'orderings'>>
624
1613
  | ModuleOrderingName<ConfigurationElement<Configuration, 'modules'>>
625
1614
 
1615
+ type ConfigurationRelation<Configuration> =
1616
+ | Extract<ConfigurationElement<Configuration, 'relations'>, RelationDefinition>
1617
+ | ModuleRelation<ConfigurationElement<Configuration, 'modules'>>
1618
+
1619
+ type ConfigurationRoot<Configuration> = Configuration extends {
1620
+ root: infer Root extends string | SourceRef
1621
+ }
1622
+ ? SourceReferenceKey<Root>
1623
+ : string
1624
+
626
1625
  export interface GraphModule<
627
1626
  Parameter extends ParameterDefinition = ParameterDefinition,
628
1627
  ProjectionPath extends string = string,
629
1628
  OrderingName extends string = string,
1629
+ ProjectionField extends ProjectionFieldDefinition = ProjectionFieldDefinition<ProjectionPath>,
1630
+ Relation extends RelationDefinition = RelationDefinition,
630
1631
  > {
631
1632
  readonly name: string
632
1633
  readonly sources: readonly SourceRef[]
633
1634
  readonly parameters: readonly Parameter[]
634
- readonly relations: readonly RelationDefinition[]
1635
+ readonly relations: readonly Relation[]
635
1636
  readonly constraints: readonly ConstraintDefinition[]
636
- readonly projection: readonly ProjectionFieldDefinition<ProjectionPath>[]
1637
+ readonly projection: readonly ProjectionField[]
637
1638
  readonly orderings: readonly OrderingDefinition<OrderingName>[]
638
1639
  }
639
1640
 
@@ -642,7 +1643,9 @@ export function defineGraphModule<const Configuration extends GraphModuleConfigu
642
1643
  ): GraphModule<
643
1644
  ConfigurationParameter<Configuration>,
644
1645
  ConfigurationProjectionPath<Configuration>,
645
- ConfigurationOrderingName<Configuration>
1646
+ ConfigurationOrderingName<Configuration>,
1647
+ ConfigurationProjectionField<Configuration>,
1648
+ ConfigurationRelation<Configuration>
646
1649
  >
647
1650
 
648
1651
  export interface GraphConfiguration {
@@ -662,7 +1665,10 @@ export function defineGraph<const Configuration extends GraphConfiguration>(
662
1665
  ): GraphDefinition<
663
1666
  ConfigurationParameter<Configuration>,
664
1667
  ConfigurationProjectionPath<Configuration>,
665
- ConfigurationOrderingName<Configuration>
1668
+ ConfigurationOrderingName<Configuration>,
1669
+ ConfigurationProjectionField<Configuration>,
1670
+ ConfigurationRelation<Configuration>,
1671
+ ConfigurationRoot<Configuration>
666
1672
  >
667
1673
 
668
1674
  export interface SummaryGraphConfiguration {
@@ -683,5 +1689,8 @@ export function defineSummaryGraph<const Configuration extends SummaryGraphConfi
683
1689
  ): GraphDefinition<
684
1690
  ConfigurationParameter<Configuration>,
685
1691
  ConfigurationProjectionPath<Configuration>,
686
- ConfigurationOrderingName<Configuration>
1692
+ ConfigurationOrderingName<Configuration>,
1693
+ ConfigurationProjectionField<Configuration>,
1694
+ ConfigurationRelation<Configuration>,
1695
+ ConfigurationRoot<Configuration>
687
1696
  >