@query-graph/core 1.1.6 → 1.1.8
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/definition.d.ts +1 -1
- package/definition.js +5 -0
- package/docs/authoring.md +71 -1
- package/docs/diagnostics.md +25 -1
- package/docs/sql.md +124 -1
- package/docs/type-system.md +63 -1
- package/dsl.d.ts +12 -0
- package/dsl.js +5 -0
- package/lib/authoring/definition.js +1 -1
- package/lib/authoring/primitives.js +67 -3
- package/lib/authoring/symbols.js +1 -0
- package/native.d.ts +1 -0
- package/native.js +50 -50
- package/package.json +5 -5
- package/types/authoring.d.ts +83 -6
- package/types/composition.d.ts +3 -21
- package/types/model.d.ts +26 -2
- package/types/runtime.d.ts +14 -8
package/definition.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ import type {
|
|
|
30
30
|
} from './dsl.js'
|
|
31
31
|
|
|
32
32
|
/** @deprecated Import authoring primitives from `@query-graph/core/dsl`. */
|
|
33
|
-
export const GRAPH_DEFINITION_VERSION:
|
|
33
|
+
export const GRAPH_DEFINITION_VERSION: 12
|
|
34
34
|
|
|
35
35
|
/** @deprecated Use `source.field(name)` from `@query-graph/core/dsl`. */
|
|
36
36
|
export function field<
|
package/definition.js
CHANGED
|
@@ -76,6 +76,11 @@ exports.requiredListParameter = objectDsl.requiredListParameter
|
|
|
76
76
|
exports.requiredListParam = objectDsl.requiredListParam
|
|
77
77
|
exports.optionalListParameter = objectDsl.optionalListParameter
|
|
78
78
|
exports.optionalListParam = objectDsl.optionalListParam
|
|
79
|
+
exports.requiredGroupsParameter = objectDsl.requiredGroupsParameter
|
|
80
|
+
exports.requiredGroupsParam = objectDsl.requiredGroupsParam
|
|
81
|
+
exports.optionalGroupsParameter = objectDsl.optionalGroupsParameter
|
|
82
|
+
exports.optionalGroupsParam = objectDsl.optionalGroupsParam
|
|
83
|
+
exports.allGroups = objectDsl.allGroups
|
|
79
84
|
exports.eq = objectDsl.eq
|
|
80
85
|
exports.neq = objectDsl.neq
|
|
81
86
|
exports.lt = objectDsl.lt
|
package/docs/authoring.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Authoring DSL
|
|
2
2
|
|
|
3
3
|
Authoring API находится в <code>@query-graph/core/dsl</code>. Он создает
|
|
4
|
-
семантический definition версии
|
|
4
|
+
семантический definition версии 12, который не содержит таблиц, SQL aliases или
|
|
5
5
|
синтаксиса диалекта.
|
|
6
6
|
|
|
7
7
|
## Sources и поля
|
|
@@ -36,6 +36,76 @@ Scalar parameter передается в expression напрямую, list param
|
|
|
36
36
|
тех же factories. Optional parameter не активирует constraint с
|
|
37
37
|
<code>when</code>, пока значение отсутствует.
|
|
38
38
|
|
|
39
|
+
### Группированные параметры
|
|
40
|
+
|
|
41
|
+
Grouped list parameter описывает массив групп <code>{ key, values }</code>.
|
|
42
|
+
Каждая группа содержит один ключ и список значений:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { allGroups, and, constraint, eq, inParam, optionalGroupsParam, source } from '@query-graph/core/dsl'
|
|
46
|
+
|
|
47
|
+
const attributes = source('attributes', { name: 'string', valueId: 'int64' })
|
|
48
|
+
const filters = optionalGroupsParam('filters', { key: 'string', value: 'int64' })
|
|
49
|
+
const attributeFilter = constraint({
|
|
50
|
+
predicate: allGroups(filters, ({ key, values }) =>
|
|
51
|
+
and(eq(attributes.field('name'), key), inParam(attributes.field('valueId'), values)),
|
|
52
|
+
),
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Operation parameters:
|
|
56
|
+
const parameters = {
|
|
57
|
+
filters: [
|
|
58
|
+
{ key: 'color', values: [1, 2] },
|
|
59
|
+
{ key: 'size', values: [3] },
|
|
60
|
+
],
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Добавьте <code>filters</code> в <code>parameters</code> definition, а
|
|
65
|
+
<code>attributeFilter</code> в <code>constraints</code>. Если разные группы
|
|
66
|
+
должны совпасть с разными связанными строками, поместите <code>exists</code>
|
|
67
|
+
внутрь callback и объявите соответствующую relation.
|
|
68
|
+
|
|
69
|
+
<code>requiredGroupsParam</code> требует присутствия массива в operation.
|
|
70
|
+
Полные имена <code>optionalGroupsParameter</code> и
|
|
71
|
+
<code>requiredGroupsParameter</code> являются алиасами тех же factories.
|
|
72
|
+
Неизвестные поля конфигурации, scalar types и некорректные аргументы factories
|
|
73
|
+
отклоняются сразу при authoring.
|
|
74
|
+
|
|
75
|
+
Callback <code>allGroups</code> вызывается ровно один раз при построении AST,
|
|
76
|
+
а не для каждой runtime-группы. <code>key</code> является типизированным scalar
|
|
77
|
+
expression, <code>values</code> является отдельной scoped list reference только
|
|
78
|
+
для <code>inParam</code>/<code>inParameter</code>. Ни grouped parameter, ни
|
|
79
|
+
<code>values</code> нельзя передать в <code>param</code> или использовать как
|
|
80
|
+
обычное scalar expression. <code>values</code> также нельзя объявить root parameter.
|
|
81
|
+
|
|
82
|
+
Каждый binder получает UUID scope через <code>node:crypto.randomUUID()</code>,
|
|
83
|
+
независимо от загрузки отдельных экземпляров или копий DSL. Вложенный callback
|
|
84
|
+
может захватить <code>key</code> и <code>values</code> внешнего callback;
|
|
85
|
+
одноименные параметры не смешивают их scopes. Ссылки за пределами своего binder,
|
|
86
|
+
в том числе захваченные из соседнего callback, отклоняются Rust при регистрации.
|
|
87
|
+
Scope является внутренним идентификатором, его конкретное значение не гарантируется.
|
|
88
|
+
|
|
89
|
+
Семантика компиляции:
|
|
90
|
+
|
|
91
|
+
- отсутствующий optional parameter и пустой массив групп дают <code>true</code>;
|
|
92
|
+
- неактивное тело не требует optional scalar parameters или JOIN, используемых
|
|
93
|
+
только внутри него;
|
|
94
|
+
- predicates всех групп объединяются через <code>AND</code>;
|
|
95
|
+
- повторяющиеся ключи остаются независимыми группами, их values не объединяются;
|
|
96
|
+
- пустой <code>values</code> дает <code>false</code> в <code>inParam</code>;
|
|
97
|
+
- nullable predicate сохраняет обычную трехзначную SQL-семантику.
|
|
98
|
+
|
|
99
|
+
Rust разрешает <code>allGroups</code> только в constraint predicates, включая
|
|
100
|
+
вложенные boolean expressions и <code>exists</code>. Projection, ordering,
|
|
101
|
+
relation predicates и aggregate bodies не поддерживают binder.
|
|
102
|
+
|
|
103
|
+
Wire definition сохраняет тип элементов в <code>scalarType</code> и добавляет
|
|
104
|
+
<code>shape: 'groupedList'</code> и <code>keyType</code>. AST использует
|
|
105
|
+
<code>{ kind: 'allGroups', parameter, scope, predicate }</code>,
|
|
106
|
+
<code>{ kind: 'groupKey', scope }</code> и
|
|
107
|
+
<code>{ kind: 'inGroupValues', expression, scope }</code>.
|
|
108
|
+
|
|
39
109
|
## Expressions
|
|
40
110
|
|
|
41
111
|
DSL предоставляет сравнения, boolean groups, null tests, semantic functions,
|
package/docs/diagnostics.md
CHANGED
|
@@ -45,8 +45,32 @@ Rust выполняет semantic validation:
|
|
|
45
45
|
Такое разделение дает ранние ошибки опечаток, не дублируя planner rules в
|
|
46
46
|
JavaScript.
|
|
47
47
|
|
|
48
|
+
Циклические зависимости relation predicates через <code>exists</code> отклоняются
|
|
49
|
+
при регистрации definition: <code>invalidExistsContext</code> указывает на
|
|
50
|
+
<code>relations[i].on</code>, замыкающий цикл. Параметры, необходимые вложенным
|
|
51
|
+
<code>exists</code>, проверяются в фазе <code>operation</code>; отсутствующий
|
|
52
|
+
параметр получает <code>missingParameter</code> с location
|
|
53
|
+
<code>parameters.<name></code>.
|
|
54
|
+
|
|
55
|
+
Статические параметры batch relation проверяются при <code>composeGraph</code>:
|
|
56
|
+
ошибки относятся к фазе <code>composition</code>, в том числе для имен параметров
|
|
57
|
+
с квадратными скобками. Параметр batch key исключается из этой проверки по точному
|
|
58
|
+
имени; значения ключей проверяются позже, при <code>compileBatch</code>, в фазе
|
|
59
|
+
<code>operation</code>.
|
|
60
|
+
|
|
48
61
|
## Совместимость diagnostics
|
|
49
62
|
|
|
50
|
-
Wire schema
|
|
63
|
+
Wire schema версии 12 добавляет grouped-параметры и scoped-шаблоны `allGroups`.
|
|
64
|
+
Сохранённые raw definitions предыдущей версии требуют обновления; обычные
|
|
65
|
+
DSL-фабрики формируют актуальную версию автоматически. JS DSL и native binding
|
|
66
|
+
должны быть из одного выпуска пакета.
|
|
67
|
+
|
|
68
|
+
Невалидные данные группы получают `invalidParameterType` с точным путём,
|
|
69
|
+
например `parameters.characteristics[0].values[1]`. Ссылка вне своего шаблона
|
|
70
|
+
получает `unknownGroupScope`; повторное объявление активного scope получает
|
|
71
|
+
`shadowedGroupScope`. `allGroups` вне constraint predicate получает
|
|
72
|
+
`invalidAllGroupsContext`. Эти проверки выполняются и для raw wire definitions.
|
|
73
|
+
|
|
74
|
+
Для прежних ошибок сохраняются diagnostic
|
|
51
75
|
codes и locations. Message предназначен человеку и не должен использоваться как
|
|
52
76
|
machine-readable contract.
|
package/docs/sql.md
CHANGED
|
@@ -18,6 +18,53 @@ const graph = registerDefinition(definition).withRelationalMapping({
|
|
|
18
18
|
<code>withRelationalMappings</code>. Одинаковые mappings объединяются,
|
|
19
19
|
конфликтующие table/column names возвращают ошибку фазы mapping.
|
|
20
20
|
|
|
21
|
+
### Oracle Database Links
|
|
22
|
+
|
|
23
|
+
Для удалённой таблицы укажите <code>databaseLink</code> отдельно от имени:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
const graph = registerDefinition(definition).withRelationalMapping({
|
|
27
|
+
sources: {
|
|
28
|
+
users: {
|
|
29
|
+
table: { schema: 'APP', name: 'Users', databaseLink: 'REMOTE_GATE' },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Oracle скомпилирует адрес как <code>"APP"."Users"@REMOTE_GATE</code>.
|
|
36
|
+
Schema и name экранируются как идентификаторы, а ссылка добавляется вне кавычек.
|
|
37
|
+
Без schema получится <code>"Users"@REMOTE_GATE</code>; без databaseLink
|
|
38
|
+
сохраняется прежний локальный адрес. Строка <code>'Users@REMOTE_GATE'</code>
|
|
39
|
+
по-прежнему означает одно имя таблицы, а не удалённый адрес.
|
|
40
|
+
|
|
41
|
+
Поддерживается форма <code>LINK[.DOMAIN...][@CONNECTION]</code>, например
|
|
42
|
+
<code>REMOTE.EXAMPLE.COM@READER</code>. Имя должно содержать 1–128 ASCII-байт,
|
|
43
|
+
LINK и CONNECTION начинаются с латинской буквы; каждая непустая часть допускает
|
|
44
|
+
только буквы, цифры, `_`, `$` и `#`.
|
|
45
|
+
Не передавайте ведущий <code>@</code>, кавычки, пробелы или SQL-фрагменты.
|
|
46
|
+
Неверное имя отклоняется при подключении mapping с диагностикой
|
|
47
|
+
<code>invalidDatabaseLink</code> и путём
|
|
48
|
+
<code>sources.<source>.table.databaseLink</code>.
|
|
49
|
+
|
|
50
|
+
Регистр ссылки нечувствителен: компилятор выводит её в верхнем регистре,
|
|
51
|
+
а объединение mappings считает <code>remote_gate</code> и
|
|
52
|
+
<code>REMOTE_GATE</code> одной ссылкой. Локальная и удалённая таблицы, а также
|
|
53
|
+
таблицы через разные ссылки конфликтуют. Это не меняет сравнение schema/name.
|
|
54
|
+
Правила Oracle описаны в
|
|
55
|
+
[References to Objects in Remote Databases](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Syntax-for-Schema-Objects-and-Parts-in-SQL-Statements.html).
|
|
56
|
+
|
|
57
|
+
SQL Server отклоняет <code>databaseLink</code> с диагностикой
|
|
58
|
+
<code>unsupportedTableQualifier</code>, если операция обращается к этому source.
|
|
59
|
+
Неиспользуемые optional relations по-прежнему не входят в SQL.
|
|
60
|
+
Oracle по-прежнему не поддерживает qualifier <code>catalog</code>.
|
|
61
|
+
|
|
62
|
+
Ссылки работают в корневом source, JOIN, exists и firstBy через общий рендеринг
|
|
63
|
+
таблиц; bindings и projection metadata не меняются. Mapping выбирается при
|
|
64
|
+
инициализации приложения, не из пользовательских operation parameters.
|
|
65
|
+
Библиотека не создаёт DB link и не проверяет доступ к удалённой БД: это остаётся
|
|
66
|
+
ответственностью инфраструктуры потребителя.
|
|
67
|
+
|
|
21
68
|
## Диалекты
|
|
22
69
|
|
|
23
70
|
```ts
|
|
@@ -45,6 +92,29 @@ Semantic functions рендерятся с одинаковым поведени
|
|
|
45
92
|
SQL Server compiler принудительно переводит <code>divide</code> в дробную
|
|
46
93
|
арифметику, чтобы два integer operands не дали integer division.
|
|
47
94
|
|
|
95
|
+
В SQL Server 2012 и новее <code>concat</code> с одним аргументом компилируется
|
|
96
|
+
с дополнительной пустой строкой <code>''</code>. Списки длиннее 254 аргументов
|
|
97
|
+
разделяются на вложенные вызовы с сохранением порядка. Промежуточные группы
|
|
98
|
+
используют <code>nvarchar(max)</code>, чтобы избежать обрезания строк при
|
|
99
|
+
объединении. <code>NULL</code> обрабатывается как пустая строка согласно
|
|
100
|
+
[семантике CONCAT в SQL Server](https://learn.microsoft.com/en-us/sql/t-sql/functions/concat-transact-sql).
|
|
101
|
+
|
|
102
|
+
## Boolean expressions
|
|
103
|
+
|
|
104
|
+
Компилятор различает значения и условия. Boolean-поле в <code>WHERE</code>,
|
|
105
|
+
<code>ON</code> или логическом выражении превращается в сравнение с <code>1</code>.
|
|
106
|
+
Условие в <code>SELECT</code>, <code>GROUP BY</code> или аргументе функции
|
|
107
|
+
превращается в <code>CASE</code>: <code>TRUE</code> дает <code>1</code>,
|
|
108
|
+
<code>FALSE</code> — <code>0</code>, <code>UNKNOWN</code> — <code>NULL</code>.
|
|
109
|
+
Boolean metadata и TypeScript-типы сохраняются; преобразование значений драйвера
|
|
110
|
+
остается ответственностью executor.
|
|
111
|
+
|
|
112
|
+
В Oracle 23ai условия сохраняют нативный SQL-тип <code>BOOLEAN</code> в контексте
|
|
113
|
+
значения. В контексте условия скалярные значения оборачиваются в
|
|
114
|
+
<code>TO_BOOLEAN</code>, который принимает как числовое, так и boolean-представление.
|
|
115
|
+
Прямые проекции полей и существующие сравнения с boolean literals сохраняют
|
|
116
|
+
прежний SQL.
|
|
117
|
+
|
|
48
118
|
## Bindings
|
|
49
119
|
|
|
50
120
|
Compiler никогда не вставляет operation values в SQL. Каждый binding содержит:
|
|
@@ -52,11 +122,64 @@ Compiler никогда не вставляет operation values в SQL. Каж
|
|
|
52
122
|
- SQL placeholder name;
|
|
53
123
|
- имя parameter;
|
|
54
124
|
- scalar type;
|
|
55
|
-
- index элемента для list parameter
|
|
125
|
+
- index элемента для list parameter;
|
|
126
|
+
- path до вложенного значения для grouped parameter.
|
|
56
127
|
|
|
57
128
|
Повторное использование parameter переиспользует binding. Пустой list
|
|
58
129
|
компилируется в ложное условие без placeholders.
|
|
59
130
|
|
|
131
|
+
Для scalar отсутствуют и `index`, и `path`. Для обычного list сохраняется
|
|
132
|
+
`index`. Для grouped list используется только `path`, например:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
;[
|
|
136
|
+
{ name: 'p0', parameter: 'characteristics', scalarType: 'int64', path: [0, 'key'] },
|
|
137
|
+
{ name: 'p1', parameter: 'characteristics', scalarType: 'int64', path: [0, 'values', 1] },
|
|
138
|
+
]
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Executor извлекает значение из `operation.parameters[binding.parameter]`,
|
|
142
|
+
последовательно проходя по сегментам `path`. `index` и `path` взаимно исключаются;
|
|
143
|
+
отсутствующий сегмент должен приводить к ошибке, а не к подстановке `null`.
|
|
144
|
+
Тип binding соответствует конкретному ключу или элементу values, а не контейнеру.
|
|
145
|
+
Повторное обращение к тому же параметру и пути переиспользует placeholder.
|
|
146
|
+
Потребитель должен обновить resolver bindings до начала использования grouped-параметров.
|
|
147
|
+
|
|
148
|
+
`allGroups` разворачивает шаблон в условия, соединённые `AND`, только при
|
|
149
|
+
компиляции операции. Для отсутствующего optional-параметра и пустого списка
|
|
150
|
+
групп результат равен `TRUE`; зависимости тела шаблона не включаются в план.
|
|
151
|
+
Каждый `exists` остаётся коррелированным подзапросом по описанному пути relations,
|
|
152
|
+
включая `firstBy`. Definition не изменяется, но SQL зависит от количества групп
|
|
153
|
+
и значений. Это один SQL-запрос, а не отдельное выполнение на каждую группу.
|
|
154
|
+
|
|
155
|
+
На один statement допускается до 10 000 разворачиваний тела `allGroups`
|
|
156
|
+
суммарно по всем шаблонам, включая вложенные. Превышение возвращает
|
|
157
|
+
`groupExpansionLimitExceeded`: вложенность может увеличить SQL многократно,
|
|
158
|
+
даже когда все bindings переиспользуются. Лимит применяется отдельно к каждой
|
|
159
|
+
компиляции и не ограничивает каталог доступных групп в приложении.
|
|
160
|
+
|
|
161
|
+
Также ограничено суммарное число элементов параметров-массивов, развёрнутых
|
|
162
|
+
внутри этих шаблонов: до 100 000 на statement. Повторное использование
|
|
163
|
+
одинаковых placeholders считается повторно, поскольку увеличивает SQL.
|
|
164
|
+
Ограничение охватывает и `values` группы, и обычный list parameter внутри
|
|
165
|
+
`allGroups`; превышение даёт `groupValueExpansionLimitExceeded`.
|
|
166
|
+
|
|
167
|
+
SQL Server compiler отклоняет statement с более чем 2100 уникальными bindings
|
|
168
|
+
с диагностикой `tooManyParameters`. Считаются все scalar, list и grouped bindings
|
|
169
|
+
вместе; разбиение `IN` не уменьшает их количество. Для больших выборок нужна
|
|
170
|
+
другая стратегия передачи данных, которой текущий grouped DSL не подменяет
|
|
171
|
+
явную ошибку. Ограничение согласовано с
|
|
172
|
+
[бюджетом параметров SQL Server](https://learn.microsoft.com/sql/sql-server/maximum-capacity-specifications-for-sql-server).
|
|
173
|
+
|
|
174
|
+
В Oracle большие <code>inParam</code> (включая values группы) и <code>inList</code> разбиваются на
|
|
175
|
+
группы <code>IN</code>, объединённые <code>OR</code> в общих скобках внутри
|
|
176
|
+
одного SQL. Размер группы — до 1000 выражений в 11g–21c и до 65535 в 23ai
|
|
177
|
+
согласно [лимитам Oracle](https://python-oracledb.readthedocs.io/en/v2.5.1/user_guide/bind.html#binding-a-large-number-of-items-in-an-in-list).
|
|
178
|
+
<code>not</code> применяется ко всей группе и сохраняет SQL-семантику
|
|
179
|
+
<code>NULL</code>. Порядок элементов и индексы bindings сохраняются, включая
|
|
180
|
+
дубликаты. Пустой литеральный <code>inList</code> по-прежнему отклоняется при
|
|
181
|
+
валидации definition.
|
|
182
|
+
|
|
60
183
|
## Result metadata
|
|
61
184
|
|
|
62
185
|
SQL columns получают технические aliases <code>c0</code>,
|
package/docs/type-system.md
CHANGED
|
@@ -16,6 +16,10 @@ TypeScript помогает автору до регистрации, Rust ос
|
|
|
16
16
|
<code>int64</code> принимает number только в безопасном диапазоне JavaScript.
|
|
17
17
|
Decimal string проверяется как конечная десятичная запись.
|
|
18
18
|
|
|
19
|
+
<code>integer(value)</code> поддерживает весь диапазон от
|
|
20
|
+
<code>Number.MIN_SAFE_INTEGER</code> до <code>Number.MAX_SAFE_INTEGER</code>,
|
|
21
|
+
включая значения за пределами 32 бит.
|
|
22
|
+
|
|
19
23
|
## QueryOperation
|
|
20
24
|
|
|
21
25
|
Definition передает свои параметры, projection paths и ordering names в
|
|
@@ -34,6 +38,49 @@ const operation = {
|
|
|
34
38
|
Required parameters обязательны, optional параметры могут отсутствовать,
|
|
35
39
|
list parameters принимают readonly arrays.
|
|
36
40
|
|
|
41
|
+
Grouped list parameters выводятся как:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
readonly {
|
|
45
|
+
key: ScalarParameterValue<KeyType>
|
|
46
|
+
values: readonly ScalarParameterValue<ValueType>[]
|
|
47
|
+
}[]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Например, <code>requiredGroupsParam('filters', { key: 'string', value: 'int64' })</code>
|
|
51
|
+
требует <code>parameters.filters</code> типа
|
|
52
|
+
<code>readonly { key: string; values: readonly (number | string)[] }[]</code>.
|
|
53
|
+
Optional grouped parameter может отсутствовать, но не заменяться на <code>null</code>.
|
|
54
|
+
Оба массива принимают readonly tuples, в том числе из <code>as const</code>.
|
|
55
|
+
|
|
56
|
+
Контейнер групп, отдельная группа и контейнер <code>values</code> не могут быть
|
|
57
|
+
<code>null</code>. Ключ и элементы списка следуют обычному scalar contract:
|
|
58
|
+
<code>null</code> запрещен для всех типов, кроме <code>json</code>. JSON сохраняет
|
|
59
|
+
существующую семантику JSON values, включая <code>null</code> и вложенные структуры.
|
|
60
|
+
Rust проверяет наличие <code>key</code>/<code>values</code>, неизвестные поля
|
|
61
|
+
группы и scalar types, включая ограничения числовых значений.
|
|
62
|
+
|
|
63
|
+
Grouped parameters сохраняют эти типы при композиции GraphModule и могут быть
|
|
64
|
+
статическими параметрами дочернего <code>batchRelation</code>. Ключ
|
|
65
|
+
<code>batchQuery</code> по-прежнему требует обычный list parameter, не grouped list.
|
|
66
|
+
|
|
67
|
+
В callback <code>allGroups</code> ключ имеет scalar type <code>KeyType</code>,
|
|
68
|
+
а <code>GroupValuesRef<ValueType></code> принимается только как второй аргумент
|
|
69
|
+
<code>inParameter</code>/<code>inParam</code>. TypeScript исключает эту reference
|
|
70
|
+
из scalar expressions и root parameters; Rust проверяет lexical scope и
|
|
71
|
+
совместимость типов сравнения и membership.
|
|
72
|
+
|
|
73
|
+
Для grouped bindings <code>path</code> указывает на значение внутри operation
|
|
74
|
+
parameter: <code>[groupIndex, 'key']</code> или
|
|
75
|
+
<code>[groupIndex, 'values', valueIndex]</code>. Scalar bindings остаются без
|
|
76
|
+
<code>index</code>/<code>path</code>, обычные list bindings сохраняют
|
|
77
|
+
<code>index</code>. Поля <code>index</code> и <code>path</code> взаимоисключающие.
|
|
78
|
+
Это же правило действует для результатов <code>compileBatch</code>.
|
|
79
|
+
|
|
80
|
+
В Node API <code>offset</code> и <code>limit</code> принимают безопасные целые
|
|
81
|
+
JavaScript, включая значения больше <code>2 \*\* 32 - 1</code>.
|
|
82
|
+
<code>offset</code> должен быть неотрицательным, <code>limit</code> — положительным.
|
|
83
|
+
|
|
37
84
|
## Nullability
|
|
38
85
|
|
|
39
86
|
Nullability выражения складывается из:
|
|
@@ -46,6 +93,20 @@ Nullability выражения складывается из:
|
|
|
46
93
|
Required relation под optional ancestor остается nullable. Это свойство
|
|
47
94
|
вычисляется из topology один раз при регистрации.
|
|
48
95
|
|
|
96
|
+
В <code>fieldType</code> флаг <code>nullable</code> типа <code>boolean</code>
|
|
97
|
+
означает, что поле может быть NULL. Литеральные <code>true</code> и
|
|
98
|
+
<code>false</code> позволяют вывести точную nullability.
|
|
99
|
+
|
|
100
|
+
Сравнения <code>eq</code>/<code>neq</code> с гарантированным <code>null</code>
|
|
101
|
+
(включая <code>literal(null)</code>) дают non-null результат. Тип операнда
|
|
102
|
+
<code>string | null</code> сам по себе не гарантирует сравнение именно с NULL:
|
|
103
|
+
nullable поле при сравнении со строкой может дать NULL.
|
|
104
|
+
|
|
105
|
+
<code>allGroups</code> возвращает boolean с nullability predicate шаблона.
|
|
106
|
+
Пустой набор групп дает <code>true</code>, но при наличии групп nullable
|
|
107
|
+
сравнение внутри callback может дать SQL UNKNOWN. Если callback возвращает
|
|
108
|
+
<code>exists</code>, результат остается non-null boolean.
|
|
109
|
+
|
|
49
110
|
## ResultOf
|
|
50
111
|
|
|
51
112
|
```ts
|
|
@@ -77,7 +138,8 @@ compilation не меняются.
|
|
|
77
138
|
Rust проверяет:
|
|
78
139
|
|
|
79
140
|
- ссылки на sources, fields и parameters;
|
|
80
|
-
- scalar/list shape
|
|
141
|
+
- scalar/list/groupedList shape параметров и key type grouped parameters;
|
|
142
|
+
- lexical scopes ключей и списков групп, допустимость binder в constraint context;
|
|
81
143
|
- совместимость сравнений и функций;
|
|
82
144
|
- boolean тип predicates;
|
|
83
145
|
- orderable и groupable expressions;
|
package/dsl.d.ts
CHANGED
|
@@ -27,6 +27,9 @@ export type {
|
|
|
27
27
|
LikeExpression,
|
|
28
28
|
InExpression,
|
|
29
29
|
InParameterExpression,
|
|
30
|
+
GroupKeyExpression,
|
|
31
|
+
InGroupValuesExpression,
|
|
32
|
+
AllGroupsExpression,
|
|
30
33
|
ExpressionGroup,
|
|
31
34
|
UnaryExpression,
|
|
32
35
|
ExistsExpression,
|
|
@@ -94,6 +97,10 @@ export type {
|
|
|
94
97
|
SourceRef,
|
|
95
98
|
ScalarParameterRef,
|
|
96
99
|
ListParameterRef,
|
|
100
|
+
GroupedListParameterRef,
|
|
101
|
+
GroupedListParameterTypes,
|
|
102
|
+
GroupValuesRef,
|
|
103
|
+
GroupScope,
|
|
97
104
|
ParameterRef,
|
|
98
105
|
RelationRef,
|
|
99
106
|
LiteralInput,
|
|
@@ -127,6 +134,11 @@ export {
|
|
|
127
134
|
requiredListParam,
|
|
128
135
|
optionalListParameter,
|
|
129
136
|
optionalListParam,
|
|
137
|
+
requiredGroupsParameter,
|
|
138
|
+
requiredGroupsParam,
|
|
139
|
+
optionalGroupsParameter,
|
|
140
|
+
optionalGroupsParam,
|
|
141
|
+
allGroups,
|
|
130
142
|
param,
|
|
131
143
|
literal,
|
|
132
144
|
integer,
|
package/dsl.js
CHANGED
|
@@ -20,6 +20,11 @@ exports.requiredListParameter = primitives.requiredListParameter
|
|
|
20
20
|
exports.requiredListParam = primitives.requiredListParam
|
|
21
21
|
exports.optionalListParameter = primitives.optionalListParameter
|
|
22
22
|
exports.optionalListParam = primitives.optionalListParam
|
|
23
|
+
exports.requiredGroupsParameter = primitives.requiredGroupsParameter
|
|
24
|
+
exports.requiredGroupsParam = primitives.requiredGroupsParam
|
|
25
|
+
exports.optionalGroupsParameter = primitives.optionalGroupsParameter
|
|
26
|
+
exports.optionalGroupsParam = primitives.optionalGroupsParam
|
|
27
|
+
exports.allGroups = primitives.allGroups
|
|
23
28
|
exports.eq = primitives.eq
|
|
24
29
|
exports.neq = primitives.neq
|
|
25
30
|
exports.lt = primitives.lt
|
|
@@ -11,7 +11,7 @@ const {
|
|
|
11
11
|
const { asExpression, copySource, referenceName } = require('./primitives.js')
|
|
12
12
|
const { GRAPH_MODULE_BRAND, SUMMARY_FIELD_BRAND } = require('./symbols.js')
|
|
13
13
|
|
|
14
|
-
const GRAPH_DEFINITION_VERSION =
|
|
14
|
+
const GRAPH_DEFINITION_VERSION = 12
|
|
15
15
|
const RELATION_CONFIGURATION_KEYS = new Set(['name', 'from', 'to', 'on', 'required', 'cardinality', 'selection'])
|
|
16
16
|
const CONSTRAINT_CONFIGURATION_KEYS = new Set(['predicate', 'when'])
|
|
17
17
|
const PROJECTION_CONFIGURATION_KEYS = new Set(['path', 'expression', 'default'])
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { randomUUID } = require('node:crypto')
|
|
3
4
|
const { arrayOf, configurationOf, nonEmptyString, objectOf, optionalBoolean } = require('../configuration.js')
|
|
4
|
-
const { PARAMETER_REF_BRAND, SUMMARY_FIELD_BRAND } = require('./symbols.js')
|
|
5
|
+
const { GROUP_VALUES_REF_BRAND, PARAMETER_REF_BRAND, SUMMARY_FIELD_BRAND } = require('./symbols.js')
|
|
5
6
|
|
|
6
7
|
const SCALAR_TYPES = new Set([
|
|
7
8
|
'boolean',
|
|
@@ -18,6 +19,7 @@ const SCALAR_TYPES = new Set([
|
|
|
18
19
|
const FIELD_TYPE_OPTIONS_KEYS = new Set(['nullable', 'selectable'])
|
|
19
20
|
const FIELD_SPECIFICATION_KEYS = new Set(['scalarType', 'nullable', 'selectable'])
|
|
20
21
|
const EXISTS_CONFIGURATION_KEYS = new Set(['from'])
|
|
22
|
+
const GROUPED_LIST_CONFIGURATION_KEYS = new Set(['key', 'value'])
|
|
21
23
|
|
|
22
24
|
function fieldType(scalarType, options = {}) {
|
|
23
25
|
assertScalarType(scalarType)
|
|
@@ -100,10 +102,32 @@ function optionalListParameter(name, scalarType) {
|
|
|
100
102
|
return parameterDefinition(name, scalarType, false, 'list')
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
function requiredGroupsParameter(name, types) {
|
|
106
|
+
return groupedListParameterDefinition(name, types, true)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function optionalGroupsParameter(name, types) {
|
|
110
|
+
return groupedListParameterDefinition(name, types, false)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function groupedListParameterDefinition(name, types, required) {
|
|
114
|
+
const configuration = configurationOf('grouped list parameter', types, GROUPED_LIST_CONFIGURATION_KEYS)
|
|
115
|
+
assertScalarType(configuration.key)
|
|
116
|
+
const definition = parameterDefinition(name, configuration.value, required, 'groupedList')
|
|
117
|
+
definition.keyType = configuration.key
|
|
118
|
+
return definition
|
|
119
|
+
}
|
|
120
|
+
|
|
103
121
|
function param(parameterReference) {
|
|
104
122
|
if (typeof parameterReference !== 'string' && parameterReference?.shape === 'list') {
|
|
105
123
|
throw new TypeError(`List parameter ${parameterReference.name} cannot be used as a scalar expression`)
|
|
106
124
|
}
|
|
125
|
+
if (parameterReference?.shape === 'groupedList') {
|
|
126
|
+
throw new TypeError(`Grouped list parameter ${parameterReference.name} cannot be used as a scalar expression`)
|
|
127
|
+
}
|
|
128
|
+
if (parameterReference?.[GROUP_VALUES_REF_BRAND] === true) {
|
|
129
|
+
throw new TypeError('Group values cannot be used as a scalar expression')
|
|
130
|
+
}
|
|
107
131
|
|
|
108
132
|
return {
|
|
109
133
|
kind: 'parameter',
|
|
@@ -184,6 +208,13 @@ function inList(expression, values) {
|
|
|
184
208
|
}
|
|
185
209
|
|
|
186
210
|
function inParameter(expression, parameterReference) {
|
|
211
|
+
if (parameterReference?.[GROUP_VALUES_REF_BRAND] === true) {
|
|
212
|
+
return {
|
|
213
|
+
kind: 'inGroupValues',
|
|
214
|
+
expression: asExpression(expression),
|
|
215
|
+
scope: parameterReference.scope,
|
|
216
|
+
}
|
|
217
|
+
}
|
|
187
218
|
if (typeof parameterReference !== 'string' && parameterReference?.shape !== 'list') {
|
|
188
219
|
throw new TypeError(`Parameter ${parameterReference?.name ?? '<unknown>'} is not a list parameter`)
|
|
189
220
|
}
|
|
@@ -195,6 +226,31 @@ function inParameter(expression, parameterReference) {
|
|
|
195
226
|
}
|
|
196
227
|
}
|
|
197
228
|
|
|
229
|
+
function allGroups(parameterReference, predicate) {
|
|
230
|
+
if (parameterReference?.[PARAMETER_REF_BRAND] !== true || parameterReference.shape !== 'groupedList') {
|
|
231
|
+
throw new TypeError('allGroups requires a grouped list parameter')
|
|
232
|
+
}
|
|
233
|
+
const parameter = referenceName(parameterReference, 'parameter')
|
|
234
|
+
assertScalarType(parameterReference.keyType)
|
|
235
|
+
assertScalarType(parameterReference.scalarType)
|
|
236
|
+
if (typeof predicate !== 'function') {
|
|
237
|
+
throw new TypeError('allGroups predicate must be a function')
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const scope = randomUUID()
|
|
241
|
+
const key = Object.freeze({ kind: 'groupKey', scope })
|
|
242
|
+
const values = { scope }
|
|
243
|
+
Object.defineProperty(values, GROUP_VALUES_REF_BRAND, { value: true })
|
|
244
|
+
Object.freeze(values)
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
kind: 'allGroups',
|
|
248
|
+
parameter,
|
|
249
|
+
scope,
|
|
250
|
+
predicate: asExpression(predicate({ key, values })),
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
198
254
|
function and(...expressions) {
|
|
199
255
|
return {
|
|
200
256
|
kind: 'and',
|
|
@@ -334,8 +390,8 @@ function parameterDefinition(name, scalarType, required, shape = 'scalar') {
|
|
|
334
390
|
if (required) {
|
|
335
391
|
definition.required = true
|
|
336
392
|
}
|
|
337
|
-
if (shape
|
|
338
|
-
definition.shape =
|
|
393
|
+
if (shape !== 'scalar') {
|
|
394
|
+
definition.shape = shape
|
|
339
395
|
}
|
|
340
396
|
Object.defineProperty(definition, PARAMETER_REF_BRAND, { value: true })
|
|
341
397
|
return definition
|
|
@@ -364,6 +420,9 @@ function unaryExpression(kind, expression) {
|
|
|
364
420
|
}
|
|
365
421
|
|
|
366
422
|
function asExpression(value) {
|
|
423
|
+
if (value?.[GROUP_VALUES_REF_BRAND] === true) {
|
|
424
|
+
throw new TypeError('Group values cannot be used as a scalar expression')
|
|
425
|
+
}
|
|
367
426
|
if (value?.[SUMMARY_FIELD_BRAND] === true) {
|
|
368
427
|
return value.expression
|
|
369
428
|
}
|
|
@@ -406,6 +465,7 @@ function assertScalarType(scalarType) {
|
|
|
406
465
|
}
|
|
407
466
|
|
|
408
467
|
module.exports = {
|
|
468
|
+
allGroups,
|
|
409
469
|
and,
|
|
410
470
|
asExpression,
|
|
411
471
|
average,
|
|
@@ -439,6 +499,8 @@ module.exports = {
|
|
|
439
499
|
neq,
|
|
440
500
|
not,
|
|
441
501
|
nullable,
|
|
502
|
+
optionalGroupsParam: optionalGroupsParameter,
|
|
503
|
+
optionalGroupsParameter,
|
|
442
504
|
optionalListParam: optionalListParameter,
|
|
443
505
|
optionalListParameter,
|
|
444
506
|
optionalParam: optionalParameter,
|
|
@@ -446,6 +508,8 @@ module.exports = {
|
|
|
446
508
|
or,
|
|
447
509
|
param,
|
|
448
510
|
referenceName,
|
|
511
|
+
requiredGroupsParam: requiredGroupsParameter,
|
|
512
|
+
requiredGroupsParameter,
|
|
449
513
|
requiredListParam: requiredListParameter,
|
|
450
514
|
requiredListParameter,
|
|
451
515
|
requiredParam: requiredParameter,
|
package/lib/authoring/symbols.js
CHANGED
package/native.d.ts
CHANGED
package/native.js
CHANGED
|
@@ -81,12 +81,12 @@ function requireNative() {
|
|
|
81
81
|
const binding = require('@query-graph/core-android-arm64')
|
|
82
82
|
const bindingPackageVersion = require('@query-graph/core-android-arm64/package.json').version
|
|
83
83
|
if (
|
|
84
|
-
bindingPackageVersion !== '1.1.
|
|
84
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
85
85
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
86
86
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
87
87
|
) {
|
|
88
88
|
throw new Error(
|
|
89
|
-
`Native binding package version mismatch, expected 1.1.
|
|
89
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
90
90
|
)
|
|
91
91
|
}
|
|
92
92
|
return binding
|
|
@@ -103,12 +103,12 @@ function requireNative() {
|
|
|
103
103
|
const binding = require('@query-graph/core-android-arm-eabi')
|
|
104
104
|
const bindingPackageVersion = require('@query-graph/core-android-arm-eabi/package.json').version
|
|
105
105
|
if (
|
|
106
|
-
bindingPackageVersion !== '1.1.
|
|
106
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
107
107
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
108
108
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
109
109
|
) {
|
|
110
110
|
throw new Error(
|
|
111
|
-
`Native binding package version mismatch, expected 1.1.
|
|
111
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
112
112
|
)
|
|
113
113
|
}
|
|
114
114
|
return binding
|
|
@@ -129,12 +129,12 @@ function requireNative() {
|
|
|
129
129
|
const binding = require('@query-graph/core-win32-x64-msvc')
|
|
130
130
|
const bindingPackageVersion = require('@query-graph/core-win32-x64-msvc/package.json').version
|
|
131
131
|
if (
|
|
132
|
-
bindingPackageVersion !== '1.1.
|
|
132
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
133
133
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
134
134
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
135
135
|
) {
|
|
136
136
|
throw new Error(
|
|
137
|
-
`Native binding package version mismatch, expected 1.1.
|
|
137
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
138
138
|
)
|
|
139
139
|
}
|
|
140
140
|
return binding
|
|
@@ -151,12 +151,12 @@ function requireNative() {
|
|
|
151
151
|
const binding = require('@query-graph/core-win32-ia32-msvc')
|
|
152
152
|
const bindingPackageVersion = require('@query-graph/core-win32-ia32-msvc/package.json').version
|
|
153
153
|
if (
|
|
154
|
-
bindingPackageVersion !== '1.1.
|
|
154
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
155
155
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
156
156
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
157
157
|
) {
|
|
158
158
|
throw new Error(
|
|
159
|
-
`Native binding package version mismatch, expected 1.1.
|
|
159
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
160
160
|
)
|
|
161
161
|
}
|
|
162
162
|
return binding
|
|
@@ -173,12 +173,12 @@ function requireNative() {
|
|
|
173
173
|
const binding = require('@query-graph/core-win32-arm64-msvc')
|
|
174
174
|
const bindingPackageVersion = require('@query-graph/core-win32-arm64-msvc/package.json').version
|
|
175
175
|
if (
|
|
176
|
-
bindingPackageVersion !== '1.1.
|
|
176
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
177
177
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
178
178
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
179
179
|
) {
|
|
180
180
|
throw new Error(
|
|
181
|
-
`Native binding package version mismatch, expected 1.1.
|
|
181
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
182
182
|
)
|
|
183
183
|
}
|
|
184
184
|
return binding
|
|
@@ -198,12 +198,12 @@ function requireNative() {
|
|
|
198
198
|
const binding = require('@query-graph/core-darwin-universal')
|
|
199
199
|
const bindingPackageVersion = require('@query-graph/core-darwin-universal/package.json').version
|
|
200
200
|
if (
|
|
201
|
-
bindingPackageVersion !== '1.1.
|
|
201
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
202
202
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
203
203
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
204
204
|
) {
|
|
205
205
|
throw new Error(
|
|
206
|
-
`Native binding package version mismatch, expected 1.1.
|
|
206
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
207
207
|
)
|
|
208
208
|
}
|
|
209
209
|
return binding
|
|
@@ -220,12 +220,12 @@ function requireNative() {
|
|
|
220
220
|
const binding = require('@query-graph/core-darwin-x64')
|
|
221
221
|
const bindingPackageVersion = require('@query-graph/core-darwin-x64/package.json').version
|
|
222
222
|
if (
|
|
223
|
-
bindingPackageVersion !== '1.1.
|
|
223
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
224
224
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
225
225
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
226
226
|
) {
|
|
227
227
|
throw new Error(
|
|
228
|
-
`Native binding package version mismatch, expected 1.1.
|
|
228
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
229
229
|
)
|
|
230
230
|
}
|
|
231
231
|
return binding
|
|
@@ -242,12 +242,12 @@ function requireNative() {
|
|
|
242
242
|
const binding = require('@query-graph/core-darwin-arm64')
|
|
243
243
|
const bindingPackageVersion = require('@query-graph/core-darwin-arm64/package.json').version
|
|
244
244
|
if (
|
|
245
|
-
bindingPackageVersion !== '1.1.
|
|
245
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
246
246
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
247
247
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
248
248
|
) {
|
|
249
249
|
throw new Error(
|
|
250
|
-
`Native binding package version mismatch, expected 1.1.
|
|
250
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
251
251
|
)
|
|
252
252
|
}
|
|
253
253
|
return binding
|
|
@@ -268,12 +268,12 @@ function requireNative() {
|
|
|
268
268
|
const binding = require('@query-graph/core-freebsd-x64')
|
|
269
269
|
const bindingPackageVersion = require('@query-graph/core-freebsd-x64/package.json').version
|
|
270
270
|
if (
|
|
271
|
-
bindingPackageVersion !== '1.1.
|
|
271
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
272
272
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
273
273
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
274
274
|
) {
|
|
275
275
|
throw new Error(
|
|
276
|
-
`Native binding package version mismatch, expected 1.1.
|
|
276
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
277
277
|
)
|
|
278
278
|
}
|
|
279
279
|
return binding
|
|
@@ -290,12 +290,12 @@ function requireNative() {
|
|
|
290
290
|
const binding = require('@query-graph/core-freebsd-arm64')
|
|
291
291
|
const bindingPackageVersion = require('@query-graph/core-freebsd-arm64/package.json').version
|
|
292
292
|
if (
|
|
293
|
-
bindingPackageVersion !== '1.1.
|
|
293
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
294
294
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
295
295
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
296
296
|
) {
|
|
297
297
|
throw new Error(
|
|
298
|
-
`Native binding package version mismatch, expected 1.1.
|
|
298
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
299
299
|
)
|
|
300
300
|
}
|
|
301
301
|
return binding
|
|
@@ -317,12 +317,12 @@ function requireNative() {
|
|
|
317
317
|
const binding = require('@query-graph/core-linux-x64-musl')
|
|
318
318
|
const bindingPackageVersion = require('@query-graph/core-linux-x64-musl/package.json').version
|
|
319
319
|
if (
|
|
320
|
-
bindingPackageVersion !== '1.1.
|
|
320
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
321
321
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
322
322
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
323
323
|
) {
|
|
324
324
|
throw new Error(
|
|
325
|
-
`Native binding package version mismatch, expected 1.1.
|
|
325
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
326
326
|
)
|
|
327
327
|
}
|
|
328
328
|
return binding
|
|
@@ -339,12 +339,12 @@ function requireNative() {
|
|
|
339
339
|
const binding = require('@query-graph/core-linux-x64-gnu')
|
|
340
340
|
const bindingPackageVersion = require('@query-graph/core-linux-x64-gnu/package.json').version
|
|
341
341
|
if (
|
|
342
|
-
bindingPackageVersion !== '1.1.
|
|
342
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
343
343
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
344
344
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
345
345
|
) {
|
|
346
346
|
throw new Error(
|
|
347
|
-
`Native binding package version mismatch, expected 1.1.
|
|
347
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
348
348
|
)
|
|
349
349
|
}
|
|
350
350
|
return binding
|
|
@@ -363,12 +363,12 @@ function requireNative() {
|
|
|
363
363
|
const binding = require('@query-graph/core-linux-arm64-musl')
|
|
364
364
|
const bindingPackageVersion = require('@query-graph/core-linux-arm64-musl/package.json').version
|
|
365
365
|
if (
|
|
366
|
-
bindingPackageVersion !== '1.1.
|
|
366
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
367
367
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
368
368
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
369
369
|
) {
|
|
370
370
|
throw new Error(
|
|
371
|
-
`Native binding package version mismatch, expected 1.1.
|
|
371
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
372
372
|
)
|
|
373
373
|
}
|
|
374
374
|
return binding
|
|
@@ -385,12 +385,12 @@ function requireNative() {
|
|
|
385
385
|
const binding = require('@query-graph/core-linux-arm64-gnu')
|
|
386
386
|
const bindingPackageVersion = require('@query-graph/core-linux-arm64-gnu/package.json').version
|
|
387
387
|
if (
|
|
388
|
-
bindingPackageVersion !== '1.1.
|
|
388
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
389
389
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
390
390
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
391
391
|
) {
|
|
392
392
|
throw new Error(
|
|
393
|
-
`Native binding package version mismatch, expected 1.1.
|
|
393
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
394
394
|
)
|
|
395
395
|
}
|
|
396
396
|
return binding
|
|
@@ -409,12 +409,12 @@ function requireNative() {
|
|
|
409
409
|
const binding = require('@query-graph/core-linux-arm-musleabihf')
|
|
410
410
|
const bindingPackageVersion = require('@query-graph/core-linux-arm-musleabihf/package.json').version
|
|
411
411
|
if (
|
|
412
|
-
bindingPackageVersion !== '1.1.
|
|
412
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
413
413
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
414
414
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
415
415
|
) {
|
|
416
416
|
throw new Error(
|
|
417
|
-
`Native binding package version mismatch, expected 1.1.
|
|
417
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
418
418
|
)
|
|
419
419
|
}
|
|
420
420
|
return binding
|
|
@@ -431,12 +431,12 @@ function requireNative() {
|
|
|
431
431
|
const binding = require('@query-graph/core-linux-arm-gnueabihf')
|
|
432
432
|
const bindingPackageVersion = require('@query-graph/core-linux-arm-gnueabihf/package.json').version
|
|
433
433
|
if (
|
|
434
|
-
bindingPackageVersion !== '1.1.
|
|
434
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
435
435
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
436
436
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
437
437
|
) {
|
|
438
438
|
throw new Error(
|
|
439
|
-
`Native binding package version mismatch, expected 1.1.
|
|
439
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
440
440
|
)
|
|
441
441
|
}
|
|
442
442
|
return binding
|
|
@@ -455,12 +455,12 @@ function requireNative() {
|
|
|
455
455
|
const binding = require('@query-graph/core-linux-loong64-musl')
|
|
456
456
|
const bindingPackageVersion = require('@query-graph/core-linux-loong64-musl/package.json').version
|
|
457
457
|
if (
|
|
458
|
-
bindingPackageVersion !== '1.1.
|
|
458
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
459
459
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
460
460
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
461
461
|
) {
|
|
462
462
|
throw new Error(
|
|
463
|
-
`Native binding package version mismatch, expected 1.1.
|
|
463
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
464
464
|
)
|
|
465
465
|
}
|
|
466
466
|
return binding
|
|
@@ -477,12 +477,12 @@ function requireNative() {
|
|
|
477
477
|
const binding = require('@query-graph/core-linux-loong64-gnu')
|
|
478
478
|
const bindingPackageVersion = require('@query-graph/core-linux-loong64-gnu/package.json').version
|
|
479
479
|
if (
|
|
480
|
-
bindingPackageVersion !== '1.1.
|
|
480
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
481
481
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
482
482
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
483
483
|
) {
|
|
484
484
|
throw new Error(
|
|
485
|
-
`Native binding package version mismatch, expected 1.1.
|
|
485
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
486
486
|
)
|
|
487
487
|
}
|
|
488
488
|
return binding
|
|
@@ -501,12 +501,12 @@ function requireNative() {
|
|
|
501
501
|
const binding = require('@query-graph/core-linux-riscv64-musl')
|
|
502
502
|
const bindingPackageVersion = require('@query-graph/core-linux-riscv64-musl/package.json').version
|
|
503
503
|
if (
|
|
504
|
-
bindingPackageVersion !== '1.1.
|
|
504
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
505
505
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
506
506
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
507
507
|
) {
|
|
508
508
|
throw new Error(
|
|
509
|
-
`Native binding package version mismatch, expected 1.1.
|
|
509
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
510
510
|
)
|
|
511
511
|
}
|
|
512
512
|
return binding
|
|
@@ -523,12 +523,12 @@ function requireNative() {
|
|
|
523
523
|
const binding = require('@query-graph/core-linux-riscv64-gnu')
|
|
524
524
|
const bindingPackageVersion = require('@query-graph/core-linux-riscv64-gnu/package.json').version
|
|
525
525
|
if (
|
|
526
|
-
bindingPackageVersion !== '1.1.
|
|
526
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
527
527
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
528
528
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
529
529
|
) {
|
|
530
530
|
throw new Error(
|
|
531
|
-
`Native binding package version mismatch, expected 1.1.
|
|
531
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
532
532
|
)
|
|
533
533
|
}
|
|
534
534
|
return binding
|
|
@@ -546,12 +546,12 @@ function requireNative() {
|
|
|
546
546
|
const binding = require('@query-graph/core-linux-ppc64-gnu')
|
|
547
547
|
const bindingPackageVersion = require('@query-graph/core-linux-ppc64-gnu/package.json').version
|
|
548
548
|
if (
|
|
549
|
-
bindingPackageVersion !== '1.1.
|
|
549
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
550
550
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
551
551
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
552
552
|
) {
|
|
553
553
|
throw new Error(
|
|
554
|
-
`Native binding package version mismatch, expected 1.1.
|
|
554
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
555
555
|
)
|
|
556
556
|
}
|
|
557
557
|
return binding
|
|
@@ -568,12 +568,12 @@ function requireNative() {
|
|
|
568
568
|
const binding = require('@query-graph/core-linux-s390x-gnu')
|
|
569
569
|
const bindingPackageVersion = require('@query-graph/core-linux-s390x-gnu/package.json').version
|
|
570
570
|
if (
|
|
571
|
-
bindingPackageVersion !== '1.1.
|
|
571
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
572
572
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
573
573
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
574
574
|
) {
|
|
575
575
|
throw new Error(
|
|
576
|
-
`Native binding package version mismatch, expected 1.1.
|
|
576
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
577
577
|
)
|
|
578
578
|
}
|
|
579
579
|
return binding
|
|
@@ -594,12 +594,12 @@ function requireNative() {
|
|
|
594
594
|
const binding = require('@query-graph/core-openharmony-arm64')
|
|
595
595
|
const bindingPackageVersion = require('@query-graph/core-openharmony-arm64/package.json').version
|
|
596
596
|
if (
|
|
597
|
-
bindingPackageVersion !== '1.1.
|
|
597
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
598
598
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
599
599
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
600
600
|
) {
|
|
601
601
|
throw new Error(
|
|
602
|
-
`Native binding package version mismatch, expected 1.1.
|
|
602
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
603
603
|
)
|
|
604
604
|
}
|
|
605
605
|
return binding
|
|
@@ -616,12 +616,12 @@ function requireNative() {
|
|
|
616
616
|
const binding = require('@query-graph/core-openharmony-x64')
|
|
617
617
|
const bindingPackageVersion = require('@query-graph/core-openharmony-x64/package.json').version
|
|
618
618
|
if (
|
|
619
|
-
bindingPackageVersion !== '1.1.
|
|
619
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
620
620
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
621
621
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
622
622
|
) {
|
|
623
623
|
throw new Error(
|
|
624
|
-
`Native binding package version mismatch, expected 1.1.
|
|
624
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
625
625
|
)
|
|
626
626
|
}
|
|
627
627
|
return binding
|
|
@@ -638,12 +638,12 @@ function requireNative() {
|
|
|
638
638
|
const binding = require('@query-graph/core-openharmony-arm')
|
|
639
639
|
const bindingPackageVersion = require('@query-graph/core-openharmony-arm/package.json').version
|
|
640
640
|
if (
|
|
641
|
-
bindingPackageVersion !== '1.1.
|
|
641
|
+
bindingPackageVersion !== '1.1.8' &&
|
|
642
642
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK &&
|
|
643
643
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0'
|
|
644
644
|
) {
|
|
645
645
|
throw new Error(
|
|
646
|
-
`Native binding package version mismatch, expected 1.1.
|
|
646
|
+
`Native binding package version mismatch, expected 1.1.8 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`,
|
|
647
647
|
)
|
|
648
648
|
}
|
|
649
649
|
return binding
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@query-graph/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"description": "Native query graph planner and SQL compiler for Node.js",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"packages/*"
|
|
@@ -141,9 +141,9 @@
|
|
|
141
141
|
},
|
|
142
142
|
"packageManager": "yarn@4.13.0",
|
|
143
143
|
"optionalDependencies": {
|
|
144
|
-
"@query-graph/core-win32-x64-msvc": "1.1.
|
|
145
|
-
"@query-graph/core-darwin-x64": "1.1.
|
|
146
|
-
"@query-graph/core-linux-x64-gnu": "1.1.
|
|
147
|
-
"@query-graph/core-darwin-arm64": "1.1.
|
|
144
|
+
"@query-graph/core-win32-x64-msvc": "1.1.8",
|
|
145
|
+
"@query-graph/core-darwin-x64": "1.1.8",
|
|
146
|
+
"@query-graph/core-linux-x64-gnu": "1.1.8",
|
|
147
|
+
"@query-graph/core-darwin-arm64": "1.1.8"
|
|
148
148
|
}
|
|
149
149
|
}
|
package/types/authoring.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AggregateExpression,
|
|
3
|
+
AllGroupsExpression,
|
|
3
4
|
AllNullability,
|
|
4
5
|
AnyNullability,
|
|
5
6
|
BinaryExpression,
|
|
@@ -13,7 +14,9 @@ import type {
|
|
|
13
14
|
FirstBySelection,
|
|
14
15
|
FunctionExpression,
|
|
15
16
|
GraphDefinition,
|
|
17
|
+
GroupKeyExpression,
|
|
16
18
|
InExpression,
|
|
19
|
+
InGroupValuesExpression,
|
|
17
20
|
InParameterExpression,
|
|
18
21
|
JoinProjectionPath,
|
|
19
22
|
LikeExpression,
|
|
@@ -110,11 +113,45 @@ export interface ListParameterRef<
|
|
|
110
113
|
required?: Required
|
|
111
114
|
}
|
|
112
115
|
|
|
116
|
+
export interface GroupedListParameterRef<
|
|
117
|
+
Name extends string = string,
|
|
118
|
+
Key extends ScalarType = ScalarType,
|
|
119
|
+
Value extends ScalarType = ScalarType,
|
|
120
|
+
Required extends boolean = boolean,
|
|
121
|
+
> extends ParameterDefinition {
|
|
122
|
+
readonly [parameterRefBrand]: true
|
|
123
|
+
name: Name
|
|
124
|
+
scalarType: Value
|
|
125
|
+
shape: 'groupedList'
|
|
126
|
+
keyType: Key
|
|
127
|
+
required?: Required
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
declare const groupValuesRefBrand: unique symbol
|
|
131
|
+
|
|
132
|
+
export interface GroupValuesRef<Type extends ScalarType = ScalarType> {
|
|
133
|
+
readonly [groupValuesRefBrand]: Type
|
|
134
|
+
readonly scope: string
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface GroupedListParameterTypes<Key extends ScalarType = ScalarType, Value extends ScalarType = ScalarType> {
|
|
138
|
+
key: Key
|
|
139
|
+
value: Value
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface GroupScope<Key extends ScalarType = ScalarType, Value extends ScalarType = ScalarType> {
|
|
143
|
+
key: TypedExpression<GroupKeyExpression, Key, false>
|
|
144
|
+
values: GroupValuesRef<Value>
|
|
145
|
+
}
|
|
146
|
+
|
|
113
147
|
export type ParameterRef<
|
|
114
148
|
Name extends string = string,
|
|
115
149
|
Type extends ScalarType = ScalarType,
|
|
116
150
|
Required extends boolean = boolean,
|
|
117
|
-
> =
|
|
151
|
+
> =
|
|
152
|
+
| ScalarParameterRef<Name, Type, Required>
|
|
153
|
+
| ListParameterRef<Name, Type, Required>
|
|
154
|
+
| GroupedListParameterRef<Name, ScalarType, Type, Required>
|
|
118
155
|
|
|
119
156
|
export type RelationRef<
|
|
120
157
|
Name extends string = string,
|
|
@@ -198,7 +235,13 @@ export interface FieldTypeOptions {
|
|
|
198
235
|
selectable?: boolean
|
|
199
236
|
}
|
|
200
237
|
|
|
201
|
-
type OptionNullable<Options extends FieldTypeOptions> = Options extends
|
|
238
|
+
type OptionNullable<Options extends FieldTypeOptions> = Options extends unknown
|
|
239
|
+
? Options['nullable'] extends infer Nullable
|
|
240
|
+
? Nullable extends true
|
|
241
|
+
? true
|
|
242
|
+
: false
|
|
243
|
+
: never
|
|
244
|
+
: never
|
|
202
245
|
type OptionSelectable<Options extends FieldTypeOptions> = Options extends { selectable: false } ? false : true
|
|
203
246
|
|
|
204
247
|
export function fieldType<const Type extends ScalarType, const Options extends FieldTypeOptions = Record<never, never>>(
|
|
@@ -237,6 +280,27 @@ export function optionalListParameter<const Name extends string, const Type exte
|
|
|
237
280
|
scalarType: Type,
|
|
238
281
|
): ListParameterRef<Name, Type, false>
|
|
239
282
|
export const optionalListParam: typeof optionalListParameter
|
|
283
|
+
export function requiredGroupsParameter<
|
|
284
|
+
const Name extends string,
|
|
285
|
+
const Key extends ScalarType,
|
|
286
|
+
const Value extends ScalarType,
|
|
287
|
+
>(name: Name, types: GroupedListParameterTypes<Key, Value>): GroupedListParameterRef<Name, Key, Value, true>
|
|
288
|
+
export const requiredGroupsParam: typeof requiredGroupsParameter
|
|
289
|
+
export function optionalGroupsParameter<
|
|
290
|
+
const Name extends string,
|
|
291
|
+
const Key extends ScalarType,
|
|
292
|
+
const Value extends ScalarType,
|
|
293
|
+
>(name: Name, types: GroupedListParameterTypes<Key, Value>): GroupedListParameterRef<Name, Key, Value, false>
|
|
294
|
+
export const optionalGroupsParam: typeof optionalGroupsParameter
|
|
295
|
+
export function allGroups<
|
|
296
|
+
const Name extends string,
|
|
297
|
+
const Key extends ScalarType,
|
|
298
|
+
const Value extends ScalarType,
|
|
299
|
+
const Predicate extends ExpressionInput,
|
|
300
|
+
>(
|
|
301
|
+
parameter: GroupedListParameterRef<Name, Key, Value>,
|
|
302
|
+
predicate: (group: GroupScope<Key, Value>) => Predicate,
|
|
303
|
+
): TypedExpression<AllGroupsExpression<Name>, 'boolean', InputNullability<Predicate>>
|
|
240
304
|
/** @deprecated Pass a scalar parameter reference directly to an expression factory. */
|
|
241
305
|
export function param<const Name extends string, const Type extends ScalarType>(
|
|
242
306
|
parameter: ScalarParameterRef<Name, Type>,
|
|
@@ -248,11 +312,20 @@ export function literal<const Value extends LiteralInput>(
|
|
|
248
312
|
export function integer(value: number): TypedExpression<LiteralExpression, 'int64', false>
|
|
249
313
|
export function decimal(value: string | number): TypedExpression<LiteralExpression, 'decimal', false>
|
|
250
314
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
| InputScalarType<Right>
|
|
315
|
+
// A null literal becomes IS NULL / IS NOT NULL, so literals do not add equality nullability.
|
|
316
|
+
type EqualityOperandNullability<Input extends ExpressionInput> = Input extends LiteralExpression
|
|
254
317
|
? false
|
|
255
|
-
:
|
|
318
|
+
: InputNullability<Input>
|
|
319
|
+
|
|
320
|
+
type EqualityNullability<Left extends ExpressionInput, Right extends ExpressionInput> = Left extends unknown
|
|
321
|
+
? Right extends unknown
|
|
322
|
+
? [InputScalarType<Left>] extends [null]
|
|
323
|
+
? false
|
|
324
|
+
: [InputScalarType<Right>] extends [null]
|
|
325
|
+
? false
|
|
326
|
+
: AnyNullability<readonly [EqualityOperandNullability<Left>, EqualityOperandNullability<Right>]>
|
|
327
|
+
: never
|
|
328
|
+
: never
|
|
256
329
|
|
|
257
330
|
export function eq<const Left extends ExpressionInput, const Right extends ExpressionInput>(
|
|
258
331
|
left: Left,
|
|
@@ -297,6 +370,10 @@ export function inParameter<
|
|
|
297
370
|
expression: Value,
|
|
298
371
|
parameter: ListParameterRef<Name, Type>,
|
|
299
372
|
): TypedExpression<InParameterExpression<Name>, 'boolean', InputNullability<Value>>
|
|
373
|
+
export function inParameter<const Value extends ExpressionInput, const Type extends ScalarType>(
|
|
374
|
+
expression: Value,
|
|
375
|
+
values: GroupValuesRef<Type>,
|
|
376
|
+
): TypedExpression<InGroupValuesExpression, 'boolean', InputNullability<Value>>
|
|
300
377
|
export const inParam: typeof inParameter
|
|
301
378
|
export function or<const Expressions extends readonly ExpressionInput[]>(
|
|
302
379
|
...expressions: Expressions
|
package/types/composition.d.ts
CHANGED
|
@@ -12,35 +12,17 @@ import type {
|
|
|
12
12
|
DefinitionParameter,
|
|
13
13
|
DefinitionProjectionField,
|
|
14
14
|
DefinitionProjectionPath,
|
|
15
|
-
|
|
15
|
+
OperationParameterInput,
|
|
16
|
+
OptionalParameter,
|
|
16
17
|
OracleCompileOptions,
|
|
17
18
|
ParameterValue,
|
|
18
19
|
QueryOperationBase,
|
|
19
20
|
RelationalQueryGraph,
|
|
21
|
+
RequiredParameter,
|
|
20
22
|
SqlServerCompileOptions,
|
|
21
23
|
} from './runtime.js'
|
|
22
24
|
import type { ListParameterRef } from './authoring.js'
|
|
23
25
|
|
|
24
|
-
type RequiredParameter<Parameter extends ParameterDefinition> = Parameter extends unknown
|
|
25
|
-
? Parameter extends { required?: true }
|
|
26
|
-
? Parameter
|
|
27
|
-
: never
|
|
28
|
-
: never
|
|
29
|
-
|
|
30
|
-
type OptionalParameter<Parameter extends ParameterDefinition> = Parameter extends unknown
|
|
31
|
-
? Parameter extends { required?: true }
|
|
32
|
-
? never
|
|
33
|
-
: Parameter
|
|
34
|
-
: never
|
|
35
|
-
|
|
36
|
-
type OperationParameterInput<Definition extends GraphDefinitionInput> = [DefinitionParameter<Definition>] extends [
|
|
37
|
-
never,
|
|
38
|
-
]
|
|
39
|
-
? { parameters?: never }
|
|
40
|
-
: [RequiredParameter<DefinitionParameter<Definition>>] extends [never]
|
|
41
|
-
? { parameters?: OperationParameters<Definition> }
|
|
42
|
-
: { parameters: OperationParameters<Definition> }
|
|
43
|
-
|
|
44
26
|
type ProjectionFieldPath<Field> =
|
|
45
27
|
Field extends ProjectionTypeMetadata<infer Path, infer _Type, infer _Nullability, infer _SelectedByDefault>
|
|
46
28
|
? Path
|
package/types/model.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export type ScalarParameterValue<Type extends ScalarType> = Type extends 'boolea
|
|
|
24
24
|
? JsonValue
|
|
25
25
|
: never
|
|
26
26
|
|
|
27
|
-
export type ParameterShape = 'scalar' | 'list'
|
|
27
|
+
export type ParameterShape = 'scalar' | 'list' | 'groupedList'
|
|
28
28
|
export type RelationCardinality = 'one' | 'many'
|
|
29
29
|
export type OrderDirection = 'asc' | 'desc'
|
|
30
30
|
export type NullsOrder = 'first' | 'last'
|
|
@@ -86,6 +86,7 @@ export interface ParameterDefinition {
|
|
|
86
86
|
name: string
|
|
87
87
|
scalarType: ScalarType
|
|
88
88
|
shape?: ParameterShape
|
|
89
|
+
keyType?: ScalarType
|
|
89
90
|
required?: boolean
|
|
90
91
|
}
|
|
91
92
|
|
|
@@ -144,6 +145,24 @@ export interface InParameterExpression<Name extends string = string> {
|
|
|
144
145
|
parameter: Name
|
|
145
146
|
}
|
|
146
147
|
|
|
148
|
+
export interface GroupKeyExpression {
|
|
149
|
+
kind: 'groupKey'
|
|
150
|
+
scope: string
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface InGroupValuesExpression {
|
|
154
|
+
kind: 'inGroupValues'
|
|
155
|
+
expression: Expression
|
|
156
|
+
scope: string
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface AllGroupsExpression<Name extends string = string> {
|
|
160
|
+
kind: 'allGroups'
|
|
161
|
+
parameter: Name
|
|
162
|
+
scope: string
|
|
163
|
+
predicate: Expression
|
|
164
|
+
}
|
|
165
|
+
|
|
147
166
|
export interface ExpressionGroup {
|
|
148
167
|
kind: 'and' | 'or'
|
|
149
168
|
expressions: Expression[]
|
|
@@ -181,6 +200,9 @@ export type Expression =
|
|
|
181
200
|
| LikeExpression
|
|
182
201
|
| InExpression
|
|
183
202
|
| InParameterExpression
|
|
203
|
+
| GroupKeyExpression
|
|
204
|
+
| InGroupValuesExpression
|
|
205
|
+
| AllGroupsExpression
|
|
184
206
|
| ExpressionGroup
|
|
185
207
|
| UnaryExpression
|
|
186
208
|
| ExistsExpression
|
|
@@ -376,7 +398,7 @@ export interface FirstBySelection {
|
|
|
376
398
|
export type RelationSelection = FirstBySelection
|
|
377
399
|
|
|
378
400
|
export interface GraphDefinitionInput {
|
|
379
|
-
schemaVersion:
|
|
401
|
+
schemaVersion: 12
|
|
380
402
|
name: string
|
|
381
403
|
root: string
|
|
382
404
|
sources: SourceDefinition[]
|
|
@@ -413,6 +435,8 @@ export type TableName =
|
|
|
413
435
|
catalog?: string
|
|
414
436
|
schema?: string
|
|
415
437
|
name: string
|
|
438
|
+
/** Oracle database link name, without the leading @. Not supported by SQL Server. */
|
|
439
|
+
databaseLink?: string
|
|
416
440
|
}
|
|
417
441
|
|
|
418
442
|
export interface SourceMapping {
|
package/types/runtime.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
ProjectionDefinitionInput,
|
|
7
7
|
RelationalMapping,
|
|
8
8
|
ScalarParameterValue,
|
|
9
|
+
ScalarType,
|
|
9
10
|
} from './model.js'
|
|
10
11
|
|
|
11
12
|
export interface QueryOperationBase<SelectPath extends string = string, OrderingName extends string = string> {
|
|
@@ -66,17 +67,22 @@ export type DefinitionRelation<Definition extends GraphDefinitionInput> = NonNul
|
|
|
66
67
|
|
|
67
68
|
export type DefinitionRoot<Definition extends GraphDefinitionInput> = Definition['root']
|
|
68
69
|
|
|
69
|
-
export type ParameterValue<Parameter extends ParameterDefinition> = Parameter extends {
|
|
70
|
-
|
|
71
|
-
:
|
|
70
|
+
export type ParameterValue<Parameter extends ParameterDefinition> = Parameter extends {
|
|
71
|
+
shape: 'groupedList'
|
|
72
|
+
keyType: infer Key extends ScalarType
|
|
73
|
+
}
|
|
74
|
+
? readonly { key: ScalarParameterValue<Key>; values: readonly ScalarParameterValue<Parameter['scalarType']>[] }[]
|
|
75
|
+
: Parameter extends { shape: 'list' }
|
|
76
|
+
? readonly ScalarParameterValue<Parameter['scalarType']>[]
|
|
77
|
+
: ScalarParameterValue<Parameter['scalarType']>
|
|
72
78
|
|
|
73
|
-
type RequiredParameter<Parameter extends ParameterDefinition> = Parameter extends unknown
|
|
79
|
+
export type RequiredParameter<Parameter extends ParameterDefinition> = Parameter extends unknown
|
|
74
80
|
? Parameter extends { required?: true }
|
|
75
81
|
? Parameter
|
|
76
82
|
: never
|
|
77
83
|
: never
|
|
78
84
|
|
|
79
|
-
type OptionalParameter<Parameter extends ParameterDefinition> = Parameter extends unknown
|
|
85
|
+
export type OptionalParameter<Parameter extends ParameterDefinition> = Parameter extends unknown
|
|
80
86
|
? Parameter extends { required?: true }
|
|
81
87
|
? never
|
|
82
88
|
: Parameter
|
|
@@ -88,9 +94,9 @@ export type OperationParameters<Definition extends GraphDefinitionInput> = {
|
|
|
88
94
|
[Parameter in OptionalParameter<DefinitionParameter<Definition>> as Parameter['name']]?: ParameterValue<Parameter>
|
|
89
95
|
}
|
|
90
96
|
|
|
91
|
-
type OperationParameterInput<Definition extends GraphDefinitionInput> = [
|
|
92
|
-
|
|
93
|
-
]
|
|
97
|
+
export type OperationParameterInput<Definition extends GraphDefinitionInput> = [
|
|
98
|
+
DefinitionParameter<Definition>,
|
|
99
|
+
] extends [never]
|
|
94
100
|
? { parameters?: never }
|
|
95
101
|
: [RequiredParameter<DefinitionParameter<Definition>>] extends [never]
|
|
96
102
|
? { parameters?: OperationParameters<Definition> }
|