@query-graph/core 1.1.3 → 1.1.5

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.js CHANGED
@@ -1,765 +1,59 @@
1
1
  'use strict'
2
2
 
3
- const GRAPH_DEFINITION_VERSION = 10
4
- const SCALAR_TYPES = new Set([
5
- 'boolean',
6
- 'int32',
7
- 'int64',
8
- 'float64',
9
- 'decimal',
10
- 'string',
11
- 'date',
12
- 'dateTime',
13
- 'binary',
14
- 'json',
15
- ])
16
- const GRAPH_MODULE_BRAND = Symbol('GraphModule')
17
- const SUMMARY_FIELD_BRAND = Symbol('SummaryField')
18
-
19
- const RELATION_CONFIGURATION_KEYS = new Set(['name', 'from', 'to', 'on', 'required', 'cardinality', 'selection'])
20
- const CONSTRAINT_CONFIGURATION_KEYS = new Set(['predicate', 'when'])
21
- const PROJECTION_CONFIGURATION_KEYS = new Set(['path', 'expression', 'default'])
22
- const PROJECTION_OBJECT_CONFIGURATION_KEYS = new Set(['path', 'presence'])
23
- const EXISTS_CONFIGURATION_KEYS = new Set(['from'])
24
- const ORDERING_CONFIGURATION_KEYS = new Set(['name', 'by', 'default'])
25
-
26
- function configurationOf(factory, value, allowedKeys) {
27
- if (value === null || typeof value !== 'object' || Array.isArray(value)) {
28
- throw new TypeError(`${factory} expects a configuration object`)
29
- }
30
-
31
- const unknownKeys = Reflect.ownKeys(value).filter((key) => typeof key !== 'string' || !allowedKeys.has(key))
32
- if (unknownKeys.length > 0) {
33
- const label = unknownKeys.length === 1 ? 'field' : 'fields'
34
- const keys = unknownKeys.map((key) => JSON.stringify(String(key))).join(', ')
35
- throw new TypeError(`${factory} received unknown configuration ${label} ${keys}`)
36
- }
37
-
38
- return value
39
- }
40
-
41
- function fieldType(scalarType, options = {}) {
42
- assertScalarType(scalarType)
43
-
44
- const definition = { scalarType }
45
- if (options.nullable === true) {
46
- definition.nullable = true
47
- }
48
- if (options.selectable === false) {
49
- definition.selectable = false
50
- }
51
- return definition
52
- }
53
-
54
- function nullable(specification) {
55
- return {
56
- ...normalizeFieldSpec(specification),
57
- nullable: true,
58
- }
59
- }
60
-
61
- function hidden(specification) {
62
- return {
63
- ...normalizeFieldSpec(specification),
64
- selectable: false,
65
- }
66
- }
67
-
68
- function source(key, fieldSpecifications) {
69
- const fields = Object.entries(fieldSpecifications).map(([name, specification]) => ({
70
- name,
71
- ...normalizeFieldSpec(specification),
72
- }))
73
- const sourceReference = { key, fields }
74
-
75
- Object.defineProperty(sourceReference, 'field', {
76
- enumerable: false,
77
- value(name) {
78
- return field(sourceReference, name)
79
- },
80
- })
81
-
82
- return sourceReference
83
- }
84
-
85
- function field(sourceReference, name) {
86
- const sourceKey = referenceName(sourceReference, 'source')
87
-
88
- if (typeof sourceReference !== 'string' && !sourceReference.fields.some((candidate) => candidate.name === name)) {
89
- throw new TypeError(`Source ${sourceKey} does not define field ${name}`)
90
- }
91
-
92
- return {
93
- kind: 'field',
94
- source: sourceKey,
95
- field: name,
96
- }
97
- }
98
-
99
- function requiredParameter(name, scalarType) {
100
- return parameterDefinition(name, scalarType, true)
101
- }
102
-
103
- function optionalParameter(name, scalarType) {
104
- return parameterDefinition(name, scalarType, false)
105
- }
106
-
107
- function requiredListParameter(name, scalarType) {
108
- return parameterDefinition(name, scalarType, true, 'list')
109
- }
110
-
111
- function optionalListParameter(name, scalarType) {
112
- return parameterDefinition(name, scalarType, false, 'list')
113
- }
114
-
115
- function param(parameterReference) {
116
- if (typeof parameterReference !== 'string' && parameterReference?.shape === 'list') {
117
- throw new TypeError(`List parameter ${parameterReference.name} cannot be used as a scalar expression`)
118
- }
119
-
120
- return {
121
- kind: 'parameter',
122
- name: referenceName(parameterReference, 'parameter'),
123
- }
124
- }
125
-
126
- function literal(value) {
127
- if (value === null) {
128
- return literalExpression({ kind: 'null' })
129
- }
130
- if (typeof value === 'boolean') {
131
- return literalExpression({ kind: 'boolean', value })
132
- }
133
- if (typeof value === 'string') {
134
- return literalExpression({ kind: 'string', value })
135
- }
136
- if (typeof value === 'number') {
137
- return Number.isInteger(value) ? integer(value) : decimal(value)
138
- }
139
-
140
- throw new TypeError('Literal must be null, boolean, string, or number')
141
- }
142
-
143
- function integer(value) {
144
- if (!Number.isSafeInteger(value)) {
145
- throw new TypeError('Integer literal must be a safe JavaScript integer')
146
- }
147
- return literalExpression({ kind: 'integer', value })
148
- }
149
-
150
- function decimal(value) {
151
- const text = String(value)
152
- if (!/^-?(?:\d+(?:\.\d*)?|\.\d+)$/.test(text)) {
153
- throw new TypeError(`Invalid decimal literal ${text}`)
154
- }
155
- return literalExpression({ kind: 'decimal', value: text })
156
- }
157
-
158
- function eq(left, right) {
159
- return binaryExpression('eq', left, right)
160
- }
161
-
162
- function neq(left, right) {
163
- return binaryExpression('notEq', left, right)
164
- }
165
-
166
- function lt(left, right) {
167
- return binaryExpression('lessThan', left, right)
168
- }
169
-
170
- function lte(left, right) {
171
- return binaryExpression('lessThanOrEqual', left, right)
172
- }
173
-
174
- function gt(left, right) {
175
- return binaryExpression('greaterThan', left, right)
176
- }
177
-
178
- function gte(left, right) {
179
- return binaryExpression('greaterThanOrEqual', left, right)
180
- }
181
-
182
- function like(expression, pattern) {
183
- return {
184
- kind: 'like',
185
- expression: asExpression(expression),
186
- pattern: asExpression(pattern),
187
- }
188
- }
189
-
190
- function inList(expression, values) {
191
- return {
192
- kind: 'in',
193
- expression: asExpression(expression),
194
- values: values.map(asExpression),
195
- }
196
- }
197
-
198
- function inParameter(expression, parameterReference) {
199
- if (typeof parameterReference !== 'string' && parameterReference?.shape !== 'list') {
200
- throw new TypeError(`Parameter ${parameterReference?.name ?? '<unknown>'} is not a list parameter`)
201
- }
202
-
203
- return {
204
- kind: 'inParameter',
205
- expression: asExpression(expression),
206
- parameter: referenceName(parameterReference, 'parameter'),
207
- }
208
- }
209
- function and(...expressions) {
210
- return {
211
- kind: 'and',
212
- expressions: expressions.map(asExpression),
213
- }
214
- }
215
-
216
- function or(...expressions) {
217
- return {
218
- kind: 'or',
219
- expressions: expressions.map(asExpression),
220
- }
221
- }
222
-
223
- function not(expression) {
224
- return unaryExpression('not', expression)
225
- }
226
-
227
- function isNull(expression) {
228
- return unaryExpression('isNull', expression)
229
- }
230
-
231
- function isNotNull(expression) {
232
- return unaryExpression('isNotNull', expression)
233
- }
234
-
235
- function exists(sourceReference, predicate, options) {
236
- const expression = {
237
- kind: 'exists',
238
- source: referenceName(sourceReference, 'source'),
239
- }
240
-
241
- if (options !== undefined) {
242
- const configuration = configurationOf('exists', options, EXISTS_CONFIGURATION_KEYS)
243
- if (configuration.from === undefined) {
244
- throw new TypeError('exists requires configuration field "from"')
245
- }
246
- expression.from = referenceName(configuration.from, 'source')
247
- }
248
-
249
- if (predicate !== undefined) {
250
- expression.predicate = asExpression(predicate)
251
- }
252
-
253
- return expression
254
- }
255
-
256
- function call(name, ...arguments_) {
257
- return {
258
- kind: 'function',
259
- name,
260
- arguments: arguments_.map(asExpression),
261
- }
262
- }
263
-
264
- function lower(expression) {
265
- return call('lower', expression)
266
- }
267
-
268
- function upper(expression) {
269
- return call('upper', expression)
270
- }
271
-
272
- function coalesce(first, second, ...rest) {
273
- return call('coalesce', first, second, ...rest)
274
- }
275
-
276
- function concat(first, ...rest) {
277
- return call('concat', first, ...rest)
278
- }
279
-
280
- function aggregate(functionName, expression) {
281
- const definition = {
282
- kind: 'aggregate',
283
- function: functionName,
284
- }
285
- if (expression !== undefined) {
286
- definition.expression = asExpression(expression)
287
- }
288
- return definition
289
- }
290
-
291
- function count(expression) {
292
- return aggregate('count', expression)
293
- }
294
-
295
- function countDistinct(expression) {
296
- return aggregate('countDistinct', expression)
297
- }
298
-
299
- function sum(expression) {
300
- return aggregate('sum', expression)
301
- }
302
-
303
- function average(expression) {
304
- return aggregate('average', expression)
305
- }
306
-
307
- function minimum(expression) {
308
- return aggregate('minimum', expression)
309
- }
310
-
311
- function maximum(expression) {
312
- return aggregate('maximum', expression)
313
- }
314
-
315
- function relation(value) {
316
- const configuration = configurationOf('relation', value, RELATION_CONFIGURATION_KEYS)
317
- const definition = {
318
- name: configuration.name,
319
- from: referenceName(configuration.from, 'source'),
320
- to: referenceName(configuration.to, 'source'),
321
- on: asExpression(configuration.on),
322
- }
323
- if (configuration.required === true) {
324
- definition.required = true
325
- }
326
- if (configuration.cardinality === 'many') {
327
- definition.cardinality = 'many'
328
- }
329
- if (configuration.selection !== undefined) {
330
- definition.selection = configuration.selection
331
- }
332
- return definition
333
- }
334
-
335
- function constraint(value) {
336
- const configuration = configurationOf('constraint', value, CONSTRAINT_CONFIGURATION_KEYS)
337
- const definition = {
338
- predicate: asExpression(configuration.predicate),
339
- }
340
- if (configuration.when !== undefined) {
341
- definition.when = {
342
- kind: 'parameterPresent',
343
- parameter: referenceName(configuration.when, 'parameter'),
344
- }
345
- }
346
- return definition
347
- }
348
-
349
- function project(value) {
350
- const configuration = configurationOf('project', value, PROJECTION_CONFIGURATION_KEYS)
351
- const definition = {
352
- path: typeof configuration.path === 'string' ? configuration.path.split('.') : [...configuration.path],
353
- expression: asExpression(configuration.expression),
354
- }
355
- if (configuration.default === true) {
356
- definition.selectedByDefault = true
357
- }
358
- return definition
359
- }
360
-
361
- function projectObject(value) {
362
- const configuration = configurationOf('projectObject', value, PROJECTION_OBJECT_CONFIGURATION_KEYS)
363
- return {
364
- path: typeof configuration.path === 'string' ? configuration.path.split('.') : [...configuration.path],
365
- presence: asExpression(configuration.presence),
366
- }
367
- }
368
-
369
- function dimension(value) {
370
- return summaryField('dimension', configurationOf('dimension', value, PROJECTION_CONFIGURATION_KEYS))
371
- }
372
-
373
- function measure(value) {
374
- return summaryField('measure', configurationOf('measure', value, PROJECTION_CONFIGURATION_KEYS))
375
- }
376
-
377
- function summaryField(role, configuration) {
378
- const definition = {
379
- ...project(configuration),
380
- role,
381
- }
382
- Object.defineProperty(definition, SUMMARY_FIELD_BRAND, {
383
- value: true,
384
- })
385
-
386
- return definition
387
- }
388
-
389
- function asc(expression, options = {}) {
390
- return orderBy('asc', expression, options)
391
- }
392
-
393
- function desc(expression, options = {}) {
394
- return orderBy('desc', expression, options)
395
- }
396
-
397
- function ordering(value) {
398
- const configuration = configurationOf('ordering', value, ORDERING_CONFIGURATION_KEYS)
399
- if (typeof configuration.name !== 'string' || configuration.name.trim() === '') {
400
- throw new TypeError('ordering name must be a non-empty string')
401
- }
402
- if (!Array.isArray(configuration.by) || configuration.by.length === 0) {
403
- throw new TypeError('ordering by must contain at least one order expression')
404
- }
405
- if (configuration.default !== undefined && typeof configuration.default !== 'boolean') {
406
- throw new TypeError('ordering default must be a boolean')
407
- }
408
-
409
- const definition = {
410
- name: configuration.name,
411
- orderBy: [...configuration.by],
412
- }
413
- if (configuration.default === true) {
414
- definition.default = true
415
- }
416
-
417
- return definition
418
- }
419
-
420
- function firstBy(firstOrder, ...rest) {
421
- if (firstOrder === undefined) {
422
- throw new TypeError('firstBy requires at least one order expression')
423
- }
424
-
425
- return {
426
- kind: 'firstBy',
427
- orderBy: [firstOrder, ...rest],
428
- }
429
- }
430
-
431
- function defineGraphModule(configuration) {
432
- const content = composeDefinitionContent(configuration)
433
-
434
- const module = {
435
- name: configuration.name,
436
- sources: content.sources,
437
- parameters: content.parameters,
438
- relations: content.relations,
439
- constraints: content.constraints,
440
- projection: content.projection,
441
- objects: content.objects,
442
- orderings: content.orderings,
443
- }
444
- Object.defineProperty(module, GRAPH_MODULE_BRAND, { value: true })
445
-
446
- return deepFreeze(module)
447
- }
448
-
449
- function defineGraph(configuration) {
450
- return buildGraphDefinition(configuration, 'record')
451
- }
452
-
453
- function defineSummaryGraph(configuration) {
454
- if (configuration.projection !== undefined) {
455
- throw new TypeError('Summary graph uses dimensions and measures instead of projection')
456
- }
457
-
458
- return buildGraphDefinition(
459
- {
460
- ...configuration,
461
- projection: [...(configuration.dimensions ?? []), ...(configuration.measures ?? [])],
462
- },
463
- 'summary',
464
- )
465
- }
466
-
467
- function buildGraphDefinition(configuration, mode) {
468
- const content = composeDefinitionContent(configuration)
469
- validateProjectionMode(content.projection, content.objects, mode)
470
-
471
- return deepFreeze({
472
- schemaVersion: GRAPH_DEFINITION_VERSION,
473
- name: configuration.name,
474
- root: referenceName(configuration.root, 'source'),
475
- sources: content.sources.map(copySource),
476
- parameters: content.parameters,
477
- relations: content.relations,
478
- constraints: content.constraints,
479
- projection: {
480
- fields: content.projection,
481
- objects: content.objects,
482
- },
483
- orderings: content.orderings,
484
- })
485
- }
486
-
487
- function validateProjectionMode(projection, objects, mode) {
488
- if (mode === 'summary') {
489
- if (objects.length > 0) {
490
- throw new TypeError('Summary graph cannot define projection objects')
491
- }
492
- if (projection.length === 0) {
493
- throw new TypeError('Summary graph must define at least one dimension or measure')
494
- }
495
- const invalid = projection.find((field) => field.role !== 'dimension' && field.role !== 'measure')
496
- if (invalid !== undefined) {
497
- throw new TypeError(
498
- `Summary graph projection field ${JSON.stringify(invalid.path.join('.'))} has no summary role`,
499
- )
500
- }
501
- return
502
- }
503
-
504
- const summaryField = projection.find((field) => field.role === 'dimension' || field.role === 'measure')
505
- if (summaryField !== undefined) {
506
- throw new TypeError(
507
- `Record graph projection field ${JSON.stringify(summaryField.path.join('.'))} has a summary role`,
508
- )
509
- }
510
- }
511
-
512
- function composeDefinitionContent(configuration) {
513
- const content = {
514
- sources: [],
515
- parameters: [],
516
- relations: [],
517
- constraints: [],
518
- projection: [],
519
- objects: [],
520
- orderings: [],
521
- }
522
- const indexes = {
523
- sources: new Map(),
524
- parameters: new Map(),
525
- relations: new Map(),
526
- constraints: new Set(),
527
- projection: new Map(),
528
- objects: new Map(),
529
- orderings: new Map(),
530
- }
531
-
532
- for (const [index, module] of (configuration.modules ?? []).entries()) {
533
- if (module?.[GRAPH_MODULE_BRAND] !== true) {
534
- throw new TypeError(`Graph module at index ${index} was not created by defineGraphModule`)
535
- }
536
-
537
- addDefinitionPart(content, indexes, module, `graph module ${JSON.stringify(module.name)}`)
538
- }
539
-
540
- addDefinitionPart(content, indexes, configuration, `definition ${JSON.stringify(configuration.name)}`)
541
- return content
542
- }
543
-
544
- function addDefinitionPart(content, indexes, part, owner) {
545
- addNamedDefinitions(content.sources, indexes.sources, part.sources, 'source', owner, (source) => source.key)
546
- addNamedDefinitions(
547
- content.parameters,
548
- indexes.parameters,
549
- part.parameters,
550
- 'parameter',
551
- owner,
552
- (parameter) => parameter.name,
553
- )
554
- addNamedDefinitions(
555
- content.relations,
556
- indexes.relations,
557
- part.relations,
558
- 'relation',
559
- owner,
560
- (relation) => relation.name,
561
- )
562
- addIdentityDefinitions(content.constraints, indexes.constraints, part.constraints)
563
- addNamedDefinitions(content.projection, indexes.projection, part.projection, 'projection', owner, (projection) =>
564
- projection.path.join('.'),
565
- )
566
- addNamedDefinitions(content.objects, indexes.objects, part.objects, 'projection object', owner, (object) =>
567
- object.path.join('.'),
568
- )
569
-
570
- addNamedDefinitions(
571
- content.orderings,
572
- indexes.orderings,
573
- part.orderings,
574
- 'ordering',
575
- owner,
576
- (orderingDefinition) => orderingDefinition.name,
577
- )
578
- }
579
-
580
- function addNamedDefinitions(target, index, definitions, type, owner, getKey) {
581
- for (const definition of definitions ?? []) {
582
- const key = getKey(definition)
583
- const existing = index.get(key)
584
-
585
- if (existing === undefined) {
586
- index.set(key, { definition, owner })
587
- target.push(definition)
588
- continue
589
- }
590
-
591
- if (existing.definition !== definition) {
592
- throw new TypeError(`Conflicting ${type} ${JSON.stringify(key)} from ${existing.owner} and ${owner}`)
593
- }
594
- }
595
- }
596
-
597
- function addIdentityDefinitions(target, index, definitions) {
598
- for (const definition of definitions ?? []) {
599
- if (!index.has(definition)) {
600
- index.add(definition)
601
- target.push(definition)
602
- }
603
- }
604
- }
605
-
606
- function normalizeFieldSpec(specification) {
607
- if (typeof specification === 'string') {
608
- return fieldType(specification)
609
- }
610
- if (specification && typeof specification === 'object') {
611
- return fieldType(specification.scalarType, specification)
612
- }
613
- throw new TypeError('Field specification must contain a scalar type')
614
- }
615
-
616
- function parameterDefinition(name, scalarType, required, shape = 'scalar') {
617
- assertScalarType(scalarType)
618
- const definition = { name, scalarType }
619
- if (required) {
620
- definition.required = true
621
- }
622
- if (shape === 'list') {
623
- definition.shape = 'list'
624
- }
625
- return definition
626
- }
627
-
628
- function literalExpression(value) {
629
- return {
630
- kind: 'literal',
631
- value,
632
- }
633
- }
634
-
635
- function binaryExpression(kind, left, right) {
636
- return {
637
- kind,
638
- left: asExpression(left),
639
- right: asExpression(right),
640
- }
641
- }
642
-
643
- function unaryExpression(kind, expression) {
644
- return {
645
- kind,
646
- expression: asExpression(expression),
647
- }
648
- }
649
-
650
- function asExpression(value) {
651
- if (value?.[SUMMARY_FIELD_BRAND] === true) {
652
- return value.expression
653
- }
654
- if (value && typeof value === 'object' && typeof value.kind === 'string') {
655
- return value
656
- }
657
- return literal(value)
658
- }
659
-
660
- function orderBy(direction, expression, options) {
661
- const definition = {
662
- expression: asExpression(expression),
663
- direction,
664
- }
665
- if (options.nulls !== undefined) {
666
- definition.nulls = options.nulls
667
- }
668
- return definition
669
- }
670
-
671
- function referenceName(reference, type) {
672
- if (typeof reference === 'string') {
673
- return reference
674
- }
675
- if (type === 'source') {
676
- if (reference && typeof reference.key === 'string') {
677
- return reference.key
678
- }
679
- throw new TypeError('Invalid source reference')
680
- }
681
- if (reference && typeof reference.name === 'string') {
682
- return reference.name
683
- }
684
- throw new TypeError(`Invalid ${type} reference`)
685
- }
686
-
687
- function copySource(sourceReference) {
688
- return {
689
- key: sourceReference.key,
690
- fields: sourceReference.fields.map((fieldDefinition) => ({ ...fieldDefinition })),
691
- }
692
- }
693
-
694
- function deepFreeze(value, seen = new WeakSet()) {
695
- if (value === null || typeof value !== 'object' || seen.has(value)) {
696
- return value
697
- }
698
-
699
- seen.add(value)
700
- for (const property of Reflect.ownKeys(value)) {
701
- deepFreeze(value[property], seen)
702
- }
703
-
704
- return Object.freeze(value)
705
- }
706
-
707
- function assertScalarType(scalarType) {
708
- if (!SCALAR_TYPES.has(scalarType)) {
709
- throw new TypeError(`Unknown scalar type ${scalarType}`)
710
- }
711
- }
712
-
713
- exports.fieldType = fieldType
714
- exports.nullable = nullable
715
- exports.hidden = hidden
716
- exports.source = source
717
- exports.requiredParameter = requiredParameter
718
- exports.optionalParameter = optionalParameter
719
- exports.param = param
720
- exports.literal = literal
721
- exports.integer = integer
722
- exports.decimal = decimal
723
- exports.requiredListParameter = requiredListParameter
724
- exports.optionalListParameter = optionalListParameter
725
- exports.eq = eq
726
- exports.neq = neq
727
- exports.lt = lt
728
- exports.lte = lte
729
- exports.gt = gt
730
- exports.gte = gte
731
- exports.like = like
732
- exports.inList = inList
733
- exports.and = and
734
- exports.or = or
735
- exports.not = not
736
- exports.isNull = isNull
737
- exports.isNotNull = isNotNull
738
- exports.inParameter = inParameter
739
- exports.exists = exists
740
- exports.lower = lower
741
- exports.upper = upper
742
- exports.coalesce = coalesce
743
- exports.concat = concat
744
- exports.count = count
745
- exports.countDistinct = countDistinct
746
- exports.sum = sum
747
- exports.average = average
748
- exports.minimum = minimum
749
- exports.maximum = maximum
750
- exports.relation = relation
751
- exports.constraint = constraint
752
- exports.ordering = ordering
753
- exports.project = project
754
- exports.projectObject = projectObject
755
- exports.dimension = dimension
756
- exports.measure = measure
757
- exports.asc = asc
758
- exports.desc = desc
759
- exports.defineGraphModule = defineGraphModule
760
- exports.defineGraph = defineGraph
761
- exports.defineSummaryGraph = defineSummaryGraph
762
- exports.firstBy = firstBy
763
- exports.batchQuery = require('./composition.js').batchQuery
764
- exports.batchRelation = require('./composition.js').batchRelation
765
- exports.composeGraph = require('./composition.js').composeGraph
3
+ const primitives = require('./lib/authoring/primitives.js')
4
+ const definitions = require('./lib/authoring/definition.js')
5
+ const composition = require('./lib/composition.js')
6
+
7
+ exports.fieldType = primitives.fieldType
8
+ exports.nullable = primitives.nullable
9
+ exports.hidden = primitives.hidden
10
+ exports.source = primitives.source
11
+ exports.requiredParameter = primitives.requiredParameter
12
+ exports.optionalParameter = primitives.optionalParameter
13
+ exports.param = primitives.param
14
+ exports.literal = primitives.literal
15
+ exports.integer = primitives.integer
16
+ exports.decimal = primitives.decimal
17
+ exports.requiredListParameter = primitives.requiredListParameter
18
+ exports.optionalListParameter = primitives.optionalListParameter
19
+ exports.eq = primitives.eq
20
+ exports.neq = primitives.neq
21
+ exports.lt = primitives.lt
22
+ exports.lte = primitives.lte
23
+ exports.gt = primitives.gt
24
+ exports.gte = primitives.gte
25
+ exports.like = primitives.like
26
+ exports.inList = primitives.inList
27
+ exports.and = primitives.and
28
+ exports.or = primitives.or
29
+ exports.not = primitives.not
30
+ exports.isNull = primitives.isNull
31
+ exports.isNotNull = primitives.isNotNull
32
+ exports.inParameter = primitives.inParameter
33
+ exports.exists = primitives.exists
34
+ exports.lower = primitives.lower
35
+ exports.upper = primitives.upper
36
+ exports.coalesce = primitives.coalesce
37
+ exports.concat = primitives.concat
38
+ exports.count = primitives.count
39
+ exports.countDistinct = primitives.countDistinct
40
+ exports.sum = primitives.sum
41
+ exports.average = primitives.average
42
+ exports.minimum = primitives.minimum
43
+ exports.maximum = primitives.maximum
44
+ exports.relation = definitions.relation
45
+ exports.constraint = definitions.constraint
46
+ exports.ordering = definitions.ordering
47
+ exports.project = definitions.project
48
+ exports.projectObject = definitions.projectObject
49
+ exports.dimension = definitions.dimension
50
+ exports.measure = definitions.measure
51
+ exports.asc = definitions.asc
52
+ exports.desc = definitions.desc
53
+ exports.defineGraphModule = definitions.defineGraphModule
54
+ exports.defineGraph = definitions.defineGraph
55
+ exports.defineSummaryGraph = definitions.defineSummaryGraph
56
+ exports.firstBy = definitions.firstBy
57
+ exports.batchQuery = composition.batchQuery
58
+ exports.batchRelation = composition.batchRelation
59
+ exports.composeGraph = composition.composeGraph