@loradb/lora-graphql 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -10
- package/dist/analyze/access-lint.d.ts +7 -0
- package/dist/analyze/access.d.ts +2 -30
- package/dist/analyze/assert-schema.d.ts +19 -0
- package/dist/analyze/diff.d.ts +1 -1
- package/dist/analyze/plans.d.ts +1 -1
- package/dist/analyze/principals.d.ts +25 -0
- package/dist/analyze/verdicts.d.ts +45 -0
- package/dist/cli.js +2 -2
- package/dist/cli.js.map +1 -1
- package/dist/compile/cache.d.ts +1 -1
- package/dist/compile/read/abstract.d.ts +19 -0
- package/dist/compile/read/aggregates.d.ts +34 -0
- package/dist/compile/read/by-keys.d.ts +10 -0
- package/dist/compile/read/common.d.ts +30 -0
- package/dist/compile/read/connection.d.ts +26 -0
- package/dist/compile/read/cypher-field.d.ts +21 -0
- package/dist/compile/read/match.d.ts +11 -0
- package/dist/compile/read/project.d.ts +15 -0
- package/dist/compile/read/root.d.ts +5 -0
- package/dist/compile/read/search.d.ts +16 -0
- package/dist/compile/read/sort.d.ts +42 -0
- package/dist/compile/read/types.d.ts +61 -0
- package/dist/{diff-B9iDdELF.js → diff-aDivqYqr.js} +2 -2
- package/dist/diff-aDivqYqr.js.map +1 -0
- package/dist/{driver-C5dSoSD8.js → driver-DSnytFsU.js} +11092 -10674
- package/dist/driver-DSnytFsU.js.map +1 -0
- package/dist/execute/cypher-mutation.d.ts +1 -1
- package/dist/execute/mutate/adjust.d.ts +5 -0
- package/dist/execute/mutate/checks.d.ts +21 -0
- package/dist/execute/mutate/delete.d.ts +7 -0
- package/dist/execute/mutate/env.d.ts +73 -0
- package/dist/execute/mutate/errors.d.ts +7 -0
- package/dist/execute/mutate/fragments.d.ts +37 -0
- package/dist/execute/mutate/plan.d.ts +95 -0
- package/dist/execute/mutate/runner.d.ts +129 -0
- package/dist/execute/mutate/unique-together.d.ts +18 -0
- package/dist/execute/mutate.d.ts +2 -79
- package/dist/index.d.ts +10 -6
- package/dist/index.js +2 -2
- package/dist/lora-graphql.d.ts +12 -326
- package/dist/model/build/authorization.d.ts +31 -0
- package/dist/model/build/cypher-field.d.ts +11 -0
- package/dist/model/build/directive-args.d.ts +16 -0
- package/dist/model/build/limits.d.ts +18 -0
- package/dist/model/build/relationship-field.d.ts +11 -0
- package/dist/model/build/rule-checks.d.ts +23 -0
- package/dist/model/build/rule-references.d.ts +28 -0
- package/dist/model/build/scalar-field.d.ts +7 -0
- package/dist/model/build/search.d.ts +4 -0
- package/dist/model/build/shapes.d.ts +18 -0
- package/dist/model/build/unique-together.d.ts +5 -0
- package/dist/model/build.d.ts +3 -20
- package/dist/model/directives.d.ts +1 -1
- package/dist/model/types.d.ts +12 -2
- package/dist/options.d.ts +255 -0
- package/dist/results.d.ts +70 -0
- package/dist/runtime/custom-requires.d.ts +7 -0
- package/dist/runtime/database-error.d.ts +10 -0
- package/dist/runtime/documents.d.ts +35 -0
- package/dist/runtime/limits.d.ts +37 -0
- package/dist/runtime/request.d.ts +33 -0
- package/dist/runtime/timing.d.ts +13 -0
- package/dist/schema/aggregates.d.ts +17 -0
- package/dist/schema/base.d.ts +17 -0
- package/dist/schema/build.d.ts +3 -42
- package/dist/schema/filters.d.ts +10 -0
- package/dist/schema/hooks.d.ts +42 -0
- package/dist/schema/objects.d.ts +36 -0
- package/dist/schema/query.d.ts +8 -0
- package/dist/schema/resolvers.d.ts +13 -0
- package/dist/schema/sorts.d.ts +5 -0
- package/dist/schema/subscriptions.d.ts +7 -0
- package/dist/subscriptions/change-hub.d.ts +50 -0
- package/dist/subscriptions/compiles.d.ts +23 -0
- package/dist/subscriptions/events.d.ts +9 -0
- package/dist/subscriptions/filter-cost.d.ts +15 -0
- package/dist/subscriptions/subscriptions.d.ts +73 -0
- package/dist/testing.d.ts +4 -1
- package/dist/testing.js +34 -29
- package/dist/testing.js.map +1 -1
- package/package.json +2 -2
- package/dist/compile/read.d.ts +0 -102
- package/dist/diff-B9iDdELF.js.map +0 -1
- package/dist/driver-C5dSoSD8.js.map +0 -1
package/dist/lora-graphql.d.ts
CHANGED
|
@@ -1,331 +1,17 @@
|
|
|
1
|
-
import { ExecutionArgs, DocumentNode, ExecutionResult, GraphQLSchema,
|
|
2
|
-
import { CypherFinding } from './analyze/cypher-check.js';
|
|
1
|
+
import { ExecutionArgs, DocumentNode, ExecutionResult, GraphQLSchema, ValidationRule } from 'graphql';
|
|
3
2
|
import { SchemaRequirement } from './analyze/indexes.js';
|
|
4
3
|
import { PlanReport } from './analyze/plans.js';
|
|
5
|
-
import {
|
|
4
|
+
import { OperationAccess } from './analyze/access.js';
|
|
5
|
+
import { AccessEntry } from './analyze/verdicts.js';
|
|
6
6
|
import { Statistics } from './analyze/statistics.js';
|
|
7
|
-
import { CompiledRead, ReadSet } from './compile/read.js';
|
|
8
|
-
import { LoraDriver, Statement } from './driver.js';
|
|
7
|
+
import { CompiledRead, ReadSet } from './compile/read/types.js';
|
|
9
8
|
import { WriteChange } from './execute/changes.js';
|
|
10
9
|
import { LoraTransaction } from './execute/transaction.js';
|
|
11
|
-
import { PopulatedByCallback } from './execute/mutate.js';
|
|
12
10
|
import { OperationManifest } from './codegen.js';
|
|
13
|
-
import { envelopPlugin
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
export interface LoraGraphQLOptions extends ModelOptions, ObservabilityOptions {
|
|
18
|
-
/** Annotated SDL: the graph model and the API in one document. */
|
|
19
|
-
typeDefs: string | DocumentNode;
|
|
20
|
-
driver: LoraDriver;
|
|
21
|
-
/** Timeout for every statement, in milliseconds. Default 10 000; 0 disables. */
|
|
22
|
-
timeoutMs?: number;
|
|
23
|
-
/**
|
|
24
|
-
* Time budget for all root fields of one query, in milliseconds: past
|
|
25
|
-
* it, the operation's statements are aborted and its unfinished fields
|
|
26
|
-
* fail with TIMEOUT. Default twice `timeoutMs` (20 000); 0 disables.
|
|
27
|
-
* Subscriptions are not bounded by it; mutations keep `timeoutMs` per
|
|
28
|
-
* statement.
|
|
29
|
-
*/
|
|
30
|
-
operationTimeoutMs?: number;
|
|
31
|
-
/**
|
|
32
|
-
* Statements one operation runs at once: aliased root fields queue for
|
|
33
|
-
* a slot instead of taking every libuv worker, so one request cannot
|
|
34
|
-
* starve the others. Default 2.
|
|
35
|
-
*/
|
|
36
|
-
maxConcurrentStatements?: number;
|
|
37
|
-
/**
|
|
38
|
-
* Approximate bytes the compile cache may hold, and again the parsed
|
|
39
|
-
* document cache: entries are evicted oldest first past it, besides the
|
|
40
|
-
* entry caps. Requests with more than 16 KiB of variables a field uses
|
|
41
|
-
* (long `in:` lists, embedding vectors) are compiled but not cached.
|
|
42
|
-
* Default 64 MiB.
|
|
43
|
-
*/
|
|
44
|
-
compileCacheBytes?: number;
|
|
45
|
-
/**
|
|
46
|
-
* Reject a root field whose estimated rows touched exceed this, before
|
|
47
|
-
* it runs. The estimate multiplies page sizes through nested lists,
|
|
48
|
-
* capped by relationship degrees from `analyze()` or `@cardinality`,
|
|
49
|
-
* and charges each filter the rows it examines: a label scan when no
|
|
50
|
-
* index answers it, the related nodes of every relationship it follows.
|
|
51
|
-
* Default 50 000; `Infinity` disables.
|
|
52
|
-
*/
|
|
53
|
-
maxCost?: number;
|
|
54
|
-
/**
|
|
55
|
-
* The cost limit for one request, from its context (for example by
|
|
56
|
-
* user or plan). Undefined falls back to `maxCost`.
|
|
57
|
-
*/
|
|
58
|
-
budget?: (context: unknown) => number | undefined;
|
|
59
|
-
/** Called with every root field's cost estimate, before it runs. */
|
|
60
|
-
onCost?: (event: CostEvent) => void;
|
|
61
|
-
/**
|
|
62
|
-
* The request's verified claims, from the GraphQL context. Default:
|
|
63
|
-
* `context.jwt`. The library never verifies tokens: do that in the
|
|
64
|
-
* server and put the claims in the context.
|
|
65
|
-
*/
|
|
66
|
-
jwt?: (context: unknown) => Record<string, unknown> | undefined;
|
|
67
|
-
/**
|
|
68
|
-
* Most nodes one mutation may create, update or delete, nested ones
|
|
69
|
-
* included (and ten times as many relationships written). Default 1000: larger imports belong in a Cypher load, not a GraphQL
|
|
70
|
-
* request. Also the default `limit` of bulk updates and deletes.
|
|
71
|
-
*/
|
|
72
|
-
maxBatch?: number;
|
|
73
|
-
/**
|
|
74
|
-
* Most items a list argument of a `@cypher` field takes, unless its
|
|
75
|
-
* `@size(max:)` says otherwise. More is BAD_USER_INPUT before the
|
|
76
|
-
* statement runs. Default 1000.
|
|
77
|
-
*/
|
|
78
|
-
maxListArgument?: number;
|
|
79
|
-
/**
|
|
80
|
-
* Relationship levels one `where` may nest: quantifiers (`some`,
|
|
81
|
-
* `none`, `all`, `single`, `count`, `aggregate`), connection filters,
|
|
82
|
-
* `<field>Exists` and filters through a single relationship each count
|
|
83
|
-
* one. Deeper is BAD_USER_INPUT before anything runs: each level
|
|
84
|
-
* multiplies the work by the relationship's degree. Default 2.
|
|
85
|
-
*/
|
|
86
|
-
maxFilterDepth?: number;
|
|
87
|
-
/**
|
|
88
|
-
* Items an `in` filter operand may hold. More is BAD_USER_INPUT before
|
|
89
|
-
* anything runs. Default 1000.
|
|
90
|
-
*/
|
|
91
|
-
maxListFilter?: number;
|
|
92
|
-
/**
|
|
93
|
-
* Characters a string filter operand (`eq`, `contains`, an `in` item, …)
|
|
94
|
-
* may hold. More is BAD_USER_INPUT before anything runs. Default 10 000.
|
|
95
|
-
*/
|
|
96
|
-
maxStringFilter?: number;
|
|
97
|
-
/**
|
|
98
|
-
* Changes a `changes()` consumer or subscriber may fall behind before it
|
|
99
|
-
* is ended with an error. Default 1000.
|
|
100
|
-
*/
|
|
101
|
-
maxQueuedChanges?: number;
|
|
102
|
-
/**
|
|
103
|
-
* Live subscriptions one scope (see `subscriptionScope`) may hold; one
|
|
104
|
-
* more is LIMIT_EXCEEDED. Default 100.
|
|
105
|
-
*/
|
|
106
|
-
maxSubscriptions?: number;
|
|
107
|
-
/**
|
|
108
|
-
* What `maxSubscriptions` counts per: by default the context object, so
|
|
109
|
-
* a server that reuses one context per connection (graphql-ws) limits
|
|
110
|
-
* each connection. Return the connection (or user) otherwise.
|
|
111
|
-
*/
|
|
112
|
-
subscriptionScope?: (context: unknown) => object | undefined;
|
|
113
|
-
/**
|
|
114
|
-
* How deep relationship filters may nest in a subscription's `where`,
|
|
115
|
-
* which runs on every change. Deeper is LIMIT_EXCEEDED. Default 1.
|
|
116
|
-
*/
|
|
117
|
-
maxSubscriptionFilterDepth?: number;
|
|
118
|
-
/**
|
|
119
|
-
* Per statement a subscription runs to check a change (visibility,
|
|
120
|
-
* `where`, related nodes). Default 2000, or `timeoutMs` when lower.
|
|
121
|
-
*/
|
|
122
|
-
subscriptionTimeoutMs?: number;
|
|
123
|
-
/** Named callbacks for `@populatedBy(callback:)`. */
|
|
124
|
-
callbacks?: Record<string, PopulatedByCallback>;
|
|
125
|
-
/**
|
|
126
|
-
* Implementations of custom scalars declared with `@storedAs`, e.g. one
|
|
127
|
-
* that validates e-mail addresses. Without one a scalar passes through.
|
|
128
|
-
*/
|
|
129
|
-
scalars?: Record<string, GraphQLScalarType>;
|
|
130
|
-
/**
|
|
131
|
-
* Feed subscriptions and `changes()` from the engine's committed change
|
|
132
|
-
* feed (lora-node `db.changes()`): every write to the database, from
|
|
133
|
-
* any path in the process that owns it, in commit order. `onWrite`
|
|
134
|
-
* still reports this instance's mutations, and `previousState` needs
|
|
135
|
-
* them. Default false.
|
|
136
|
-
*/
|
|
137
|
-
changeFeed?: boolean;
|
|
138
|
-
/**
|
|
139
|
-
* Resolvers of `@customResolver` fields, by type and field name. The
|
|
140
|
-
* source holds the node's selected fields plus the field's `requires`.
|
|
141
|
-
*/
|
|
142
|
-
resolvers?: Record<string, Record<string, GraphQLFieldResolver<Record<string, unknown>, unknown>>>;
|
|
143
|
-
/** Called with every statement before it runs; for logging and tests. */
|
|
144
|
-
onStatement?: (event: StatementEvent) => void;
|
|
145
|
-
/**
|
|
146
|
-
* Hide database error details from clients: they get
|
|
147
|
-
* `extensions.code` `DATABASE_ERROR` and an `id`, and `onError` gets the
|
|
148
|
-
* engine's message. Default: on when `NODE_ENV` is `production`.
|
|
149
|
-
*/
|
|
150
|
-
maskErrors?: boolean;
|
|
151
|
-
/** Called with every database error, masked or not. */
|
|
152
|
-
onError?: (event: DatabaseErrorEvent) => void;
|
|
153
|
-
/**
|
|
154
|
-
* Limits on the documents `execute()`, `subscribe()` and `persist()`
|
|
155
|
-
* accept: depth,
|
|
156
|
-
* aliases, root fields, tokens, introspection. `false` turns them off.
|
|
157
|
-
* For other servers use `validationRules()` or `envelopPlugin()`.
|
|
158
|
-
*/
|
|
159
|
-
guards?: DocumentGuards | false;
|
|
160
|
-
/**
|
|
161
|
-
* Make `execute()` and `subscribe()` refuse `source` and run only
|
|
162
|
-
* persisted operations by `id`. Default false.
|
|
163
|
-
*/
|
|
164
|
-
persistedOnly?: boolean;
|
|
165
|
-
/**
|
|
166
|
-
* How `execute()` commits a mutation with several root fields.
|
|
167
|
-
* `"field"` (the default): each root field in its own transaction, so a
|
|
168
|
-
* later failure leaves the earlier ones committed. `"operation"`: every
|
|
169
|
-
* root field in one transaction, committed only when the operation
|
|
170
|
-
* reports no error, rolled back (with `data: null`) otherwise. A
|
|
171
|
-
* `transaction` in the context takes precedence. Envelop / Yoga servers
|
|
172
|
-
* on `getSchema()` get the same with `lora.envelopPlugin()`; other
|
|
173
|
-
* servers calling graphql-js directly put a `lora.begin()` transaction
|
|
174
|
-
* in the context (without one, a one-time warning says each root field
|
|
175
|
-
* committed on its own).
|
|
176
|
-
*/
|
|
177
|
-
mutationTransaction?: "field" | "operation";
|
|
178
|
-
/**
|
|
179
|
-
* Add `extensions.timing` to `execute()` results: the request's total
|
|
180
|
-
* time, the time spent in LoraDB, and both per root field, in
|
|
181
|
-
* milliseconds. `true` for every request, or a function deciding per
|
|
182
|
-
* request from the GraphQL context (for example only for admins or in
|
|
183
|
-
* development). Default off: timings sent to clients can act as a
|
|
184
|
-
* timing side channel.
|
|
185
|
-
*/
|
|
186
|
-
timing?: boolean | ((context: unknown) => boolean);
|
|
187
|
-
}
|
|
188
|
-
/** `extensions.timing` of an `execute()` result (see the `timing` option). */
|
|
189
|
-
export interface ExecutionTiming {
|
|
190
|
-
/** The whole `execute()` call: parse, validation, execution. */
|
|
191
|
-
totalMs: number;
|
|
192
|
-
/** Time spent running statements in LoraDB. */
|
|
193
|
-
databaseMs: number;
|
|
194
|
-
/** Per root field, by response key (alias or name). */
|
|
195
|
-
fields: Record<string, {
|
|
196
|
-
totalMs: number;
|
|
197
|
-
databaseMs: number;
|
|
198
|
-
}>;
|
|
199
|
-
}
|
|
200
|
-
export interface CostEvent {
|
|
201
|
-
field: string;
|
|
202
|
-
/** Estimated rows this root field touches. */
|
|
203
|
-
cost: number;
|
|
204
|
-
/** Estimated rows of the operation so far, this field included. */
|
|
205
|
-
total: number;
|
|
206
|
-
/** The limit that applies: `budget(context)` or `maxCost`. */
|
|
207
|
-
limit: number;
|
|
208
|
-
context: unknown;
|
|
209
|
-
}
|
|
210
|
-
export interface DatabaseErrorEvent {
|
|
211
|
-
/** Correlation id, also in the client error's `extensions.id`. */
|
|
212
|
-
id: string;
|
|
213
|
-
/**
|
|
214
|
-
* The root field that failed, or `changeFeed` for a failure of the
|
|
215
|
-
* change feed (it reopens from where it stopped after a backoff).
|
|
216
|
-
*/
|
|
217
|
-
field: string;
|
|
218
|
-
/** The engine's message, which may name labels, properties and Cypher. */
|
|
219
|
-
message: string;
|
|
220
|
-
/** The error as thrown by the driver. */
|
|
221
|
-
error: unknown;
|
|
222
|
-
}
|
|
223
|
-
export interface StatementEvent {
|
|
224
|
-
field: string;
|
|
225
|
-
statement: Statement;
|
|
226
|
-
}
|
|
227
|
-
/** Per-request options read from the GraphQL context, when present. */
|
|
228
|
-
export interface LoraGraphQLContext {
|
|
229
|
-
/** Verified claims; enables @authentication and @authorization. */
|
|
230
|
-
jwt?: Record<string, unknown>;
|
|
231
|
-
/** Cancels the request's statements when aborted. */
|
|
232
|
-
signal?: AbortSignal;
|
|
233
|
-
/**
|
|
234
|
-
* Run in this transaction (from `lora.begin()`) instead of one per
|
|
235
|
-
* field: the caller commits, together with its own Cypher.
|
|
236
|
-
*/
|
|
237
|
-
transaction?: LoraTransaction;
|
|
238
|
-
}
|
|
239
|
-
export interface AssertSchemaOptions {
|
|
240
|
-
/** Create what is missing instead of only reporting it. */
|
|
241
|
-
create?: boolean;
|
|
242
|
-
}
|
|
243
|
-
export interface SchemaAssertion {
|
|
244
|
-
required: SchemaRequirement[];
|
|
245
|
-
missing: SchemaRequirement[];
|
|
246
|
-
created: SchemaRequirement[];
|
|
247
|
-
/**
|
|
248
|
-
* Full-text and vector indexes present under their name but defined
|
|
249
|
-
* differently (labels, properties, kind): search would keep using the
|
|
250
|
-
* old definition. Without `create`; with it they are re-created.
|
|
251
|
-
*/
|
|
252
|
-
mismatched: SchemaRequirement[];
|
|
253
|
-
/** Indexes `create` dropped and created again with the model's definition. */
|
|
254
|
-
recreated: SchemaRequirement[];
|
|
255
|
-
}
|
|
256
|
-
export interface CheckOptions {
|
|
257
|
-
/**
|
|
258
|
-
* Flag statements whose largest engine row estimate (from graph
|
|
259
|
-
* statistics) exceeds this. Off by default: estimates ignore a LIMIT
|
|
260
|
-
* that stops an index-ordered scan early.
|
|
261
|
-
*/
|
|
262
|
-
rowBudget?: number;
|
|
263
|
-
/**
|
|
264
|
-
* Operations to compile and plan-check (S2), with example variables and
|
|
265
|
-
* the GraphQL context to compile them under (e.g. `{ jwt }`, so rules
|
|
266
|
-
* compile as they do for a signed-in caller). Without one, an operation
|
|
267
|
-
* compiles as an anonymous request would.
|
|
268
|
-
*/
|
|
269
|
-
operations?: Array<{
|
|
270
|
-
name?: string;
|
|
271
|
-
document: string | DocumentNode;
|
|
272
|
-
variables?: Record<string, unknown>;
|
|
273
|
-
context?: unknown;
|
|
274
|
-
}>;
|
|
275
|
-
}
|
|
276
|
-
export interface CheckReport {
|
|
277
|
-
/** True when nothing below is a failure. */
|
|
278
|
-
ok: boolean;
|
|
279
|
-
/** Model warnings, e.g. an unused @cypher argument. */
|
|
280
|
-
warnings: readonly ModelWarning[];
|
|
281
|
-
/** @cypher statements the engine rejects or that write from a query. */
|
|
282
|
-
cypher: CypherFinding[];
|
|
283
|
-
/** Constraints and indexes the database lacks. */
|
|
284
|
-
missing: SchemaRequirement[];
|
|
285
|
-
/** Indexes the database has that no part of the API needs. */
|
|
286
|
-
unused: Array<{
|
|
287
|
-
name: string;
|
|
288
|
-
type: string;
|
|
289
|
-
labels: string[];
|
|
290
|
-
properties: string[];
|
|
291
|
-
}>;
|
|
292
|
-
/** Schema lint: valid but costly or risky choices (not failures). */
|
|
293
|
-
lint: readonly ModelWarning[];
|
|
294
|
-
/**
|
|
295
|
-
* `@mutation` types with writes no rule guards (failures): declare them
|
|
296
|
-
* with `@authorization(public: [...])` when that is intended.
|
|
297
|
-
*/
|
|
298
|
-
security: readonly ModelWarning[];
|
|
299
|
-
/** Plan findings per operation and root field. */
|
|
300
|
-
plans: Array<{
|
|
301
|
-
operation: string;
|
|
302
|
-
field: string;
|
|
303
|
-
reports: PlanReport[];
|
|
304
|
-
}>;
|
|
305
|
-
/** Operations that failed to compile. */
|
|
306
|
-
errors: Array<{
|
|
307
|
-
operation: string;
|
|
308
|
-
message: string;
|
|
309
|
-
}>;
|
|
310
|
-
}
|
|
311
|
-
export interface ExecuteArgs {
|
|
312
|
-
/** The document, or `id` of a persisted operation. */
|
|
313
|
-
source?: string;
|
|
314
|
-
id?: string;
|
|
315
|
-
variables?: Record<string, unknown>;
|
|
316
|
-
operationName?: string;
|
|
317
|
-
context?: unknown;
|
|
318
|
-
/**
|
|
319
|
-
* Attach the operation's read-set to the result as a non-enumerable
|
|
320
|
-
* `readSet` property (never serialized to the client), for a response
|
|
321
|
-
* cache to invalidate with `lora.affects(result.readSet, change)`.
|
|
322
|
-
*/
|
|
323
|
-
readSet?: boolean;
|
|
324
|
-
}
|
|
325
|
-
/** `execute()`'s result; `readSet` is there when `ExecuteArgs.readSet` asked. */
|
|
326
|
-
export type LoraExecutionResult = ExecutionResult & {
|
|
327
|
-
readonly readSet?: ReadSet;
|
|
328
|
-
};
|
|
11
|
+
import { envelopPlugin } from './guards.js';
|
|
12
|
+
import { GraphModel } from './model/types.js';
|
|
13
|
+
import { AssertSchemaOptions, CheckOptions, ExecuteArgs, LoraGraphQLOptions } from './options.js';
|
|
14
|
+
import { CheckReport, LoraExecutionResult, SchemaAssertion } from './results.js';
|
|
329
15
|
export declare class LoraGraphQL {
|
|
330
16
|
#private;
|
|
331
17
|
readonly model: GraphModel;
|
|
@@ -374,10 +60,6 @@ export declare class LoraGraphQL {
|
|
|
374
60
|
/** Use statistics gathered earlier, e.g. by the CLI. */
|
|
375
61
|
useStatistics(stats: Statistics): void;
|
|
376
62
|
get statistics(): Statistics | undefined;
|
|
377
|
-
/**
|
|
378
|
-
* The CI gate: @cypher statements plan, the database has what the API
|
|
379
|
-
* needs, and each operation's statements seek where they should.
|
|
380
|
-
*/
|
|
381
63
|
/**
|
|
382
64
|
* Who may do what: for every type and guarded field, each operation as
|
|
383
65
|
* each kind of caller (anonymous, authenticated, and each role the rules
|
|
@@ -393,6 +75,10 @@ export declare class LoraGraphQL {
|
|
|
393
75
|
* several operations.
|
|
394
76
|
*/
|
|
395
77
|
operationAccess(document: string | DocumentNode, operationName?: string): OperationAccess;
|
|
78
|
+
/**
|
|
79
|
+
* The CI gate: @cypher statements plan, the database has what the API
|
|
80
|
+
* needs, and each operation's statements seek where they should.
|
|
81
|
+
*/
|
|
396
82
|
check(options?: CheckOptions): Promise<CheckReport>;
|
|
397
83
|
/**
|
|
398
84
|
* Compile a query without running it: one entry per root field, with its
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AuthOperation, Authorization, RelationshipField } from '../types.js';
|
|
2
|
+
export declare function authOps(args: Record<string, unknown> | undefined): Set<AuthOperation> | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Field-level rules on a relationship or @cypher field: READ validate rules
|
|
5
|
+
* only, checked for each row that reads (or filters on) the field.
|
|
6
|
+
*/
|
|
7
|
+
export declare function readOnlyRules(args: Record<string, unknown> | undefined, at: (message: string) => void, relationship?: boolean): Authorization | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* `@authorization` on a Query or Mutation @cypher field: validate rules
|
|
10
|
+
* guarding the call, tested before the statement runs. There is no node,
|
|
11
|
+
* so they test claims (`jwt`) and the caller's node (`viewer`); their
|
|
12
|
+
* `operations` and `when` do not matter.
|
|
13
|
+
*/
|
|
14
|
+
export declare function rootFieldRules(args: Record<string, unknown> | undefined, at: (message: string) => void): Authorization | undefined;
|
|
15
|
+
export declare function readAuthorization(args: Record<string, unknown> | undefined): Authorization | undefined;
|
|
16
|
+
export declare const PROPERTY_OPS: Set<AuthOperation>;
|
|
17
|
+
/** Keys of a rule that are not claim tests: `node`, `viewer`, … */
|
|
18
|
+
/**
|
|
19
|
+
* Whether a request without a token could pass the rule: some branch
|
|
20
|
+
* reads no claim. A claim read without a token denies its branch (and
|
|
21
|
+
* the whole rule under NOT), so those branches never pass.
|
|
22
|
+
*/
|
|
23
|
+
export declare function passableWithoutClaims(where: unknown): boolean;
|
|
24
|
+
export declare function claimsOnlyViolations(where: unknown, path?: string): string[];
|
|
25
|
+
/** The relationship operations a field's rules cover. */
|
|
26
|
+
export declare function relationshipRuleOperations(f: RelationshipField): Set<AuthOperation>;
|
|
27
|
+
/** A rule over a relationship's source, target and edge. */
|
|
28
|
+
export declare const isRelationshipRule: (rule: {
|
|
29
|
+
operations: ReadonlySet<AuthOperation>;
|
|
30
|
+
}) => boolean;
|
|
31
|
+
export declare const isRecord: (x: unknown) => x is Record<string, unknown>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GraphQLDirective, GraphQLField, GraphQLSchema } from 'graphql';
|
|
2
|
+
import { ModelProblem } from '../../errors.js';
|
|
3
|
+
import { CypherField, ModelWarning } from '../types.js';
|
|
4
|
+
export declare function buildCypherField(owner: string, f: GraphQLField<unknown, unknown>, d: (n: string) => GraphQLDirective, problems: ModelProblem[], warnings: ModelWarning[], ctx: {
|
|
5
|
+
nodeNames: Set<string>;
|
|
6
|
+
plainNames: Set<string>;
|
|
7
|
+
schema: GraphQLSchema;
|
|
8
|
+
root: "Query" | "Mutation" | undefined;
|
|
9
|
+
/** Whether the @jwt type has a @viewer claim (enables `$viewer`). */
|
|
10
|
+
viewer: boolean;
|
|
11
|
+
}): CypherField | undefined;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ConstDirectiveNode, GraphQLDirective } from 'graphql';
|
|
2
|
+
export declare function directive(def: GraphQLDirective, node: {
|
|
3
|
+
astNode?: unknown;
|
|
4
|
+
extensionASTNodes?: unknown;
|
|
5
|
+
}, at: (message: string) => void): Record<string, unknown> | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Every use of the directive `name` on `node`: its definition's, then each
|
|
8
|
+
* extension's, with where it was written (for messages).
|
|
9
|
+
*/
|
|
10
|
+
export declare function directiveNodes(name: string, node: {
|
|
11
|
+
astNode?: unknown;
|
|
12
|
+
extensionASTNodes?: unknown;
|
|
13
|
+
}): Array<{
|
|
14
|
+
node: ConstDirectiveNode;
|
|
15
|
+
place: string;
|
|
16
|
+
}>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ModelProblem } from '../../errors.js';
|
|
2
|
+
import { PageLimit } from '../types.js';
|
|
3
|
+
export interface ModelOptions {
|
|
4
|
+
/** Page size used when a list or connection gets no `limit` / `first`. */
|
|
5
|
+
defaultLimit?: number;
|
|
6
|
+
/** Hard cap on any page size; `@limit(max:)` may only lower it. */
|
|
7
|
+
maxLimit?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Sign cursors with HMAC-SHA-256 under this secret, and reject cursors
|
|
10
|
+
* whose signature does not match. Without it cursors are only tagged
|
|
11
|
+
* with their sort. Changing the secret invalidates every cursor.
|
|
12
|
+
*/
|
|
13
|
+
cursorSecret?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const DEFAULT_LIMIT = 25;
|
|
16
|
+
export declare const MAX_LIMIT = 100;
|
|
17
|
+
export declare function resolveGlobalLimit(options: ModelOptions): PageLimit;
|
|
18
|
+
export declare function resolveLimit(args: Record<string, unknown> | undefined, global: PageLimit, type: string, field: string | undefined, problems: ModelProblem[]): PageLimit;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GraphQLDirective, GraphQLField, GraphQLObjectType } from 'graphql';
|
|
2
|
+
import { ModelProblem } from '../../errors.js';
|
|
3
|
+
import { DeclaredRelationship, NodeType, PageLimit, RelationshipField } from '../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* An interface field under `@declareRelationship`: every implementation
|
|
6
|
+
* must declare a relationship field of that name with the same target and
|
|
7
|
+
* shape (the relationship type and direction may differ). Returns the
|
|
8
|
+
* problem when one does not.
|
|
9
|
+
*/
|
|
10
|
+
export declare function declareRelationship(iface: string, f: GraphQLField<unknown, unknown>, members: readonly string[], nodes: ReadonlyMap<string, NodeType>): DeclaredRelationship | string;
|
|
11
|
+
export declare function buildRelationshipField(t: GraphQLObjectType, f: GraphQLField<unknown, unknown>, d: (n: string) => GraphQLDirective, problems: ModelProblem[], propsNames: Set<string>, globalLimit: PageLimit): RelationshipField | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ModelProblem } from '../../errors.js';
|
|
2
|
+
import { AbstractType, NodeType, RelationshipPropertiesType } from '../types.js';
|
|
3
|
+
/** Check an `@authorization` where against the model, at startup. */
|
|
4
|
+
export declare function checkAuthorizationWhere(nodes: ReadonlyMap<string, NodeType>, props: ReadonlyMap<string, RelationshipPropertiesType>, node: NodeType, where: unknown, problems: ModelProblem[], jwtShape?: ReadonlyMap<string, string>, viewerNode?: NodeType): void;
|
|
5
|
+
/**
|
|
6
|
+
* Check a rule's where. Without `node` (a relationship property's rules)
|
|
7
|
+
* only claims may be tested: a @relationshipProperties type can sit under
|
|
8
|
+
* several relationship fields, from either end, so `node` would be
|
|
9
|
+
* ambiguous.
|
|
10
|
+
*/
|
|
11
|
+
/** The ends a relationship field's rule tests, for its checks. */
|
|
12
|
+
export interface RuleEnds {
|
|
13
|
+
source: NodeType;
|
|
14
|
+
target: NodeType;
|
|
15
|
+
edge: RelationshipPropertiesType | undefined;
|
|
16
|
+
}
|
|
17
|
+
export declare function checkRuleWhere(nodes: ReadonlyMap<string, NodeType>, props: ReadonlyMap<string, RelationshipPropertiesType>, node: NodeType | undefined, type: string, field: string | undefined, where: unknown, problems: ModelProblem[], jwtShape?: ReadonlyMap<string, string>, viewerNode?: NodeType, ends?: RuleEnds, nodeless?: string): void;
|
|
18
|
+
export declare function checkNodeWhere(nodes: ReadonlyMap<string, NodeType>, props: ReadonlyMap<string, RelationshipPropertiesType>, node: NodeType, where: unknown, path: string, at: (message: string) => void): void;
|
|
19
|
+
/**
|
|
20
|
+
* Interfaces and unions of a model being built, by its node map: the rule
|
|
21
|
+
* checks below receive the node map only.
|
|
22
|
+
*/
|
|
23
|
+
export declare const abstractsOf: WeakMap<ReadonlyMap<string, NodeType>, ReadonlyMap<string, AbstractType>>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { NodeType, RelationshipPropertiesType } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Claim names referenced anywhere in a value: as "$jwt.name…" strings and
|
|
4
|
+
* as ${jwt.name…} placeholders.
|
|
5
|
+
*/
|
|
6
|
+
export declare function claimRefs(value: unknown): string[];
|
|
7
|
+
/**
|
|
8
|
+
* Malformed claim and context references in a rule's strings: a whole
|
|
9
|
+
* string "$jwt.path" names a path and nothing else; any `${` starts a
|
|
10
|
+
* `${jwt.path}` or `${context.path}` placeholder.
|
|
11
|
+
*/
|
|
12
|
+
/** `${viewer.field}` placeholders need @viewer, a scalar field, a string operand. */
|
|
13
|
+
export declare function viewerRefProblems(value: unknown, viewerNode: NodeType | undefined, inList?: boolean): string[];
|
|
14
|
+
/** What a rule's `${node.…}`, `${source.…}`, `${target.…}`, `${edge.…}` may read. */
|
|
15
|
+
export interface RuleReferences {
|
|
16
|
+
node?: NodeType;
|
|
17
|
+
source?: NodeType;
|
|
18
|
+
target?: NodeType;
|
|
19
|
+
edge?: RelationshipPropertiesType | undefined;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `${node.path}`-style placeholders: the source must be available where
|
|
23
|
+
* the string stands (`node` in a type's rules, `source` / `target` /
|
|
24
|
+
* `edge` in a relationship field's), the path must reach a scalar through
|
|
25
|
+
* single relationships to node types, and it stands for one value.
|
|
26
|
+
*/
|
|
27
|
+
export declare function ruleReferenceProblems(value: unknown, refs: RuleReferences, nodes: ReadonlyMap<string, NodeType>, inList?: boolean): string[];
|
|
28
|
+
export declare function ruleStringProblems(value: unknown): string[];
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GraphQLDirective, GraphQLField, GraphQLObjectType } from 'graphql';
|
|
2
|
+
import { ModelProblem } from '../../errors.js';
|
|
3
|
+
import { ScalarField, ScalarType } from '../types.js';
|
|
4
|
+
export declare function buildScalarField(t: GraphQLObjectType, f: GraphQLField<unknown, unknown>, d: (n: string) => GraphQLDirective, problems: ModelProblem[], opts: {
|
|
5
|
+
allowKey: boolean;
|
|
6
|
+
}): ScalarField | undefined;
|
|
7
|
+
export declare function defaultMatches(type: ScalarType, list: boolean, value: unknown): boolean;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ModelProblem } from '../../errors.js';
|
|
2
|
+
import { SearchIndex, ScalarField } from '../types.js';
|
|
3
|
+
export declare const vectorQueryNames: WeakMap<ScalarField, string>;
|
|
4
|
+
export declare function readSearch(typeName: string, label: string, defaultName: string, plural: string | undefined, scalars: ScalarField[], fulltext: Record<string, unknown> | undefined, problems: ModelProblem[]): SearchIndex[];
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { GraphQLNamedType, GraphQLInputType, GraphQLOutputType, GraphQLSchema } from 'graphql';
|
|
2
|
+
import { TypeShape, ScalarType } from '../types.js';
|
|
3
|
+
export declare const BUILTIN_SCALARS: Record<string, ScalarType>;
|
|
4
|
+
export declare function unwrap(type: GraphQLOutputType): {
|
|
5
|
+
required: boolean;
|
|
6
|
+
list: boolean;
|
|
7
|
+
itemRequired: boolean;
|
|
8
|
+
depth: number;
|
|
9
|
+
};
|
|
10
|
+
export declare function isScalarLike(name: string, schema: GraphQLSchema): boolean;
|
|
11
|
+
/** A custom scalar's storage type, from its `@storedAs(type:)`. */
|
|
12
|
+
export declare function storageOf(t: GraphQLNamedType): ScalarType | undefined;
|
|
13
|
+
export declare function lowerFirst(s: string): string;
|
|
14
|
+
export declare function defaultPlural(typeName: string): string;
|
|
15
|
+
export declare function shapeOf(shape: ReturnType<typeof unwrap>): Omit<TypeShape, "named">;
|
|
16
|
+
export declare function unwrapInput(type: GraphQLInputType): Omit<TypeShape, "named">;
|
|
17
|
+
export declare function upperFirst(s: string): string;
|
|
18
|
+
export declare function snakeCase(s: string): string;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { GraphQLDirective, GraphQLObjectType } from 'graphql';
|
|
2
|
+
import { ModelProblem } from '../../errors.js';
|
|
3
|
+
import { NodeType, RelationshipPropertiesType, UniqueTogether } from '../types.js';
|
|
4
|
+
/** Every `@uniqueTogether` of a node type (repeatable), checked. */
|
|
5
|
+
export declare function readUniqueTogether(t: GraphQLObjectType, node: NodeType, nodes: ReadonlyMap<string, NodeType>, props: ReadonlyMap<string, RelationshipPropertiesType>, d: (name: string) => GraphQLDirective, problems: ModelProblem[]): UniqueTogether[];
|
package/dist/model/build.d.ts
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
import { DocumentNode
|
|
2
|
-
import { GraphModel
|
|
3
|
-
|
|
4
|
-
/** Page size used when a list or connection gets no `limit` / `first`. */
|
|
5
|
-
defaultLimit?: number;
|
|
6
|
-
/** Hard cap on any page size; `@limit(max:)` may only lower it. */
|
|
7
|
-
maxLimit?: number;
|
|
8
|
-
/**
|
|
9
|
-
* Sign cursors with HMAC-SHA-256 under this secret, and reject cursors
|
|
10
|
-
* whose signature does not match. Without it cursors are only tagged
|
|
11
|
-
* with their sort. Changing the secret invalidates every cursor.
|
|
12
|
-
*/
|
|
13
|
-
cursorSecret?: string;
|
|
14
|
-
}
|
|
15
|
-
export declare const DEFAULT_LIMIT = 25;
|
|
16
|
-
export declare const MAX_LIMIT = 100;
|
|
1
|
+
import { DocumentNode } from 'graphql';
|
|
2
|
+
import { GraphModel } from './types.js';
|
|
3
|
+
import { ModelOptions } from './build/limits.js';
|
|
17
4
|
/**
|
|
18
5
|
* Parse and validate annotated type definitions into a `GraphModel`.
|
|
19
6
|
* Throws a `ModelError` listing every problem found.
|
|
20
7
|
*/
|
|
21
8
|
export declare function buildModel(typeDefs: string | DocumentNode, options?: ModelOptions): GraphModel;
|
|
22
|
-
/** A custom scalar's storage type, from its `@storedAs(type:)`. */
|
|
23
|
-
export declare function storageOf(t: GraphQLNamedType): ScalarType | undefined;
|
|
24
|
-
export declare function lowerFirst(s: string): string;
|
|
25
|
-
export declare function defaultPlural(typeName: string): string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const directiveTypeDefs = "\n \"A node label set. Defaults to the type name.\"\n directive @node(labels: [String!], plural: String) on OBJECT\n\n \"Natural key: required, unique and immutable; the tie-breaker of every sort and the anchor of cursors, global ids, updates and deletes. With generate: true, creates fill it with a UUID when the input leaves it out.\"\n directive @key(\n generate: Boolean = false\n \"VIEWER: a created key must start with the caller's @viewer claim and the separator (lou:tomorrowland).\"\n scope: KeyScope\n separator: String = \":\"\n ) on FIELD_DEFINITION\n\n enum KeyScope {\n VIEWER\n }\n\n \"On an interface field: every implementation declares this relationship (with @relationship, possibly of different types or directions), so clients can select it on the interface.\"\n directive @declareRelationship on FIELD_DEFINITION\n\n \"Offer this field as a grouping key of <plural>Grouped (needs @query(aggregate: true)).\"\n directive @groupBy on FIELD_DEFINITION\n\n \"A field computed in JavaScript by the resolver passed in the resolvers option. requires is a selection on this type (for example name capacity) fetched in the same statement, so the resolver reads it from its source.\"\n directive @customResolver(requires: String) on FIELD_DEFINITION\n\n \"On a custom scalar: how its values are stored. Filters, sorts and indexes follow the storage type; the scalar is passed through unless the scalars option supplies an implementation.\"\n directive @storedAs(type: StorageType!) on SCALAR\n\n enum StorageType {\n STRING\n INT\n FLOAT\n BOOLEAN\n DATETIME\n DATE\n }\n\n \"A uniqueness constraint.\"\n directive @unique on FIELD_DEFINITION\n\n \"No two nodes of this type (among those matching where) share the values of fields: scalar fields, single relationships (by the target's @key) and at most one list relationship (by the set of target keys). Enforced by every generated mutation, for every caller.\"\n directive @uniqueTogether(\n fields: [String!]!\n where: NodeWhere\n ) repeatable on OBJECT\n\n \"An explicit index. Usually unnecessary: inferred from @filterable and @sortable.\"\n directive @index(kind: IndexKind!) on FIELD_DEFINITION\n\n \"An edge. The target type is the field's type.\"\n directive @relationship(\n type: String!\n direction: RelationshipDirection!\n properties: String\n \"UNDIRECTED reads follow the relationship both ways; writes use direction.\"\n queryDirection: QueryDirection = DIRECTED\n \"What deleting this node does to nodes reached through the field.\"\n onDelete: OnDelete = DETACH\n \"Which nested writes mutation inputs offer for the field.\"\n nestedOperations: [NestedOperation!] = [\n CREATE\n CONNECT\n DISCONNECT\n UPDATE\n DELETE\n ]\n \"false: no aggregate on the field's connection and no aggregate filter.\"\n aggregate: Boolean = true\n ) on FIELD_DEFINITION\n\n \"UPDATE changes a connected node and its relationship properties in place; UPDATE_EDGE only the properties.\"\n enum NestedOperation {\n CREATE\n CONNECT\n DISCONNECT\n UPDATE\n UPDATE_EDGE\n DELETE\n }\n\n enum QueryDirection {\n DIRECTED\n UNDIRECTED\n }\n\n \"DETACH removes the relationships; CASCADE deletes the related nodes too; RESTRICT refuses while any exist.\"\n enum OnDelete {\n DETACH\n CASCADE\n RESTRICT\n }\n\n \"Which mutations may set the field. @readonly is onCreate: false, onUpdate: false.\"\n directive @settable(\n onCreate: Boolean = true\n onUpdate: Boolean = true\n ) on FIELD_DEFINITION\n\n \"Whether the field can be read (onRead: false makes it write-only) or aggregated.\"\n directive @selectable(\n onRead: Boolean = true\n onAggregate: Boolean = true\n ) on FIELD_DEFINITION\n\n \"Set by a callback passed to LoraGraphQL({ callbacks }) on these operations. Client-settable only with an explicit @settable(onCreate: true) or (onUpdate: true) and a field-level @authorization(validate:) rule for that operation.\"\n directive @populatedBy(\n callback: String!\n operations: [TimestampOperation!]! = [CREATE, UPDATE]\n ) on FIELD_DEFINITION\n\n \"The shape of the request's claims. Rules may only test declared claims.\"\n directive @jwt on OBJECT\n\n \"Where a declared claim lives in the token, e.g. app_metadata.roles.\"\n directive @jwtClaim(path: String!) on FIELD_DEFINITION\n\n \"The claim that identifies the caller: the node of `type` whose `field` (a @key or @unique field) equals it. Enables isViewer and viewer in rules.\"\n directive @viewer(type: String!, field: String!) on FIELD_DEFINITION\n\n \"Properties carried by a relationship type.\"\n directive @relationshipProperties on OBJECT\n\n \"API name differs from the stored property.\"\n directive @alias(property: String!) on FIELD_DEFINITION\n\n \"Stored, never exposed.\"\n directive @private on FIELD_DEFINITION\n\n \"Declared upper bound on a relationship's fan-out, used by cost estimates.\"\n directive @cardinality(max: Int!) on FIELD_DEFINITION\n\n \"The most items a list argument of a @cypher field takes; more is BAD_USER_INPUT before the statement runs. Without it, maxListArgument applies.\"\n directive @size(max: Int!) on ARGUMENT_DEFINITION\n\n \"Bounds of an Int or Float argument of a @cypher field (each item, for a list); a value outside them is BAD_USER_INPUT before the statement runs.\"\n directive @range(min: Float, max: Float) on ARGUMENT_DEFINITION\n\n \"Generated read operations for a node type. Reads are on by default.\"\n directive @query(\n read: Boolean = true\n aggregate: Boolean = false\n ) on OBJECT | INTERFACE | UNION\n\n \"The plural of an interface or union, for its root field.\"\n directive @plural(value: String!) on INTERFACE | UNION\n\n \"Filter operators for a field. Without arguments: EQ and IN. On a relationship field: enables relationship filters.\"\n directive @filterable(byValue: [FilterOperator!]) on FIELD_DEFINITION\n\n \"Sort and keyset-paginate on this field.\"\n directive @sortable on FIELD_DEFINITION\n\n \"Page size bounds for lists of this type.\"\n directive @limit(\n default: Int\n max: Int\n ) on OBJECT | INTERFACE | UNION | FIELD_DEFINITION\n\n \"Expose an opaque global id derived from this @key field.\"\n directive @relayId on FIELD_DEFINITION\n\n \"Full-text search over String fields: a FULLTEXT index and a search root field per entry.\"\n directive @fulltext(indexes: [FulltextIndex!]!) on OBJECT\n\n \"A vector embedding ([Float!]): a VECTOR index and a similarity root field.\"\n directive @vector(\n dimensions: Int!\n similarity: VectorSimilarity = COSINE\n queryName: String\n ) on FIELD_DEFINITION\n\n input FulltextIndex {\n \"Index name. Default: <label>_search for the first, required after.\"\n name: String\n fields: [String!]!\n analyzer: FulltextAnalyzer = STANDARD\n \"Root field name. Default: search<Plural>, or search<Plural>By<Name>.\"\n queryName: String\n }\n\n enum FulltextAnalyzer {\n STANDARD\n SIMPLE\n }\n\n enum VectorSimilarity {\n COSINE\n EUCLIDEAN\n }\n\n \"Generated subscriptions to changes made through the library. None without this directive.\"\n directive @subscription(\n operations: [MutationOperation!]! = [CREATE, UPDATE, DELETE]\n \"Also send CONNECT and DISCONNECT events for the type's relationships.\"\n relationships: Boolean = false\n \"Send the stored values before an update or delete (one extra read per write).\"\n previousState: Boolean = false\n ) on OBJECT\n\n \"Generated mutations for a node type. None without this directive.\"\n directive @mutation(\n operations: [MutationOperation!]! = [CREATE, UPDATE, DELETE]\n ) on OBJECT\n\n \"Value stored on create when the input leaves the field out.\"\n directive @default(value: DefaultValue!) on FIELD_DEFINITION\n\n \"Set to the current time by the listed operations. Client-settable only with an explicit @settable(onCreate: true) or (onUpdate: true) and a field-level @authorization(validate:) rule for that operation.\"\n directive @timestamp(\n operations: [TimestampOperation!]! = [CREATE, UPDATE]\n ) on FIELD_DEFINITION\n\n \"Readable but never client-settable.\"\n directive @readonly on FIELD_DEFINITION\n\n \"A field backed by a Cypher statement. `this` is the parent node; arguments are $parameters, $jwt holds the request's claims, and $viewer the caller's @viewer node key.\"\n directive @cypher(statement: String!, columnName: String) on FIELD_DEFINITION\n\n \"Require an authenticated request (a jwt in the context) for these operations.\"\n directive @authentication(\n operations: [AuthOperation!]! = [\n READ\n CREATE\n UPDATE\n DELETE\n CREATE_RELATIONSHIP\n DELETE_RELATIONSHIP\n SUBSCRIBE\n ]\n \"Claims the request must also satisfy, such as a role in roles.\"\n jwt: AuthorizationWhere\n ) on OBJECT | FIELD_DEFINITION\n\n \"Row-level rules over the node and the request's claims, compiled into the statements.\"\n directive @authorization(\n filter: [AuthorizationFilterRule!]\n validate: [AuthorizationValidateRule!]\n \"On a type: false keeps the schema's bypass (see @authorizationDefaults) from skipping this type's rules; true lets it skip them, as without the argument, and tells check() that was meant.\"\n bypass: Boolean\n \"On a @mutation type: operations deliberately open to every caller, so check() does not report them as unguarded.\"\n public: [AuthOperation!]\n \"On a scalar field: a row failing unless reads the field as value (null when left out) instead of failing the request.\"\n mask: [AuthorizationMask!]\n ) on OBJECT | FIELD_DEFINITION\n\n \"Named rules over claims, usable in any rule as { rule: name }, on `extend schema`.\"\n directive @authorizationRules(\n rules: [AuthorizationRuleDefinition!]!\n ) on SCHEMA\n\n input AuthorizationRuleDefinition {\n name: String!\n where: AuthorizationWhere!\n }\n\n \"A named rule of this type, usable in its rules as { rule: name } and through a relationship to it as { rel: { rule: name } }.\"\n directive @authorizationRule(\n name: String!\n where: AuthorizationWhere!\n ) repeatable on OBJECT\n\n \"Schema-wide authorization settings, on `extend schema`.\"\n directive @authorizationDefaults(\n \"A claims-only test (jwt, AND, OR, NOT): a request passing it skips every filter and validate rule (not @authentication).\"\n bypass: AuthorizationWhere\n \"The write rule of every @mutation type that declares no CREATE, UPDATE or DELETE rule of its own.\"\n mutations: AuthorizationWhere\n ) on SCHEMA\n\n input AuthorizationMask {\n unless: AuthorizationWhere!\n value: DefaultValue\n }\n\n input AuthorizationFilterRule {\n operations: [AuthOperation!]! = [READ, UPDATE, DELETE]\n \"Default true: without a token the rule denies.\"\n requireAuthentication: Boolean\n where: AuthorizationWhere!\n }\n\n input AuthorizationValidateRule {\n operations: [AuthOperation!]! = [READ, CREATE, UPDATE, DELETE]\n when: [AuthorizationWhen!]! = [BEFORE, AFTER]\n \"Default true: without a token the rule denies.\"\n requireAuthentication: Boolean\n where: AuthorizationWhere!\n }\n\n enum MutationOperation {\n CREATE\n UPDATE\n DELETE\n }\n\n enum TimestampOperation {\n CREATE\n UPDATE\n }\n\n enum AuthOperation {\n READ\n CREATE\n UPDATE\n DELETE\n CREATE_RELATIONSHIP\n DELETE_RELATIONSHIP\n SUBSCRIBE\n \"On a relationship field: creating one of its relationships (connect, nested create).\"\n CONNECT\n \"On a relationship field: removing one of its relationships (disconnect).\"\n DISCONNECT\n \"On a relationship field: setting properties on an existing relationship (edge update, re-connect).\"\n UPDATE_EDGE\n \"On a relationship field: reading, filtering, sorting or aggregating its properties.\"\n READ_EDGE\n }\n\n enum AuthorizationWhen {\n BEFORE\n AFTER\n }\n\n \"Any literal.\"\n scalar DefaultValue\n\n \"{ node: <Type>Where-shaped filter, jwt: claim filter, AND, OR, NOT }. String values starting with $jwt. are replaced by claims.\"\n scalar AuthorizationWhere\n\n \"A <Type>Where-shaped filter over the type the directive is on.\"\n scalar NodeWhere\n\n enum IndexKind {\n RANGE\n TEXT\n POINT\n }\n\n enum RelationshipDirection {\n IN\n OUT\n }\n\n enum FilterOperator {\n EQ\n IN\n LT\n LTE\n GT\n GTE\n CONTAINS\n STARTS_WITH\n ENDS_WITH\n WITHIN_BBOX\n DISTANCE\n INCLUDES\n IS_NULL\n CASE_INSENSITIVE\n }\n\n scalar BigInt\n scalar Date\n scalar Time\n scalar LocalTime\n scalar DateTime\n scalar LocalDateTime\n scalar Duration\n\n type Point {\n longitude: Float!\n latitude: Float!\n height: Float\n srid: Int!\n crs: String!\n }\n\n type CartesianPoint {\n x: Float!\n y: Float!\n z: Float\n srid: Int!\n crs: String!\n }\n";
|
|
1
|
+
export declare const directiveTypeDefs = "\n \"A node label set. Defaults to the type name.\"\n directive @node(labels: [String!], plural: String) on OBJECT\n\n \"Natural key: required, unique and immutable; the tie-breaker of every sort and the anchor of cursors, global ids, updates and deletes. With generate: true, creates fill it with a UUID when the input leaves it out.\"\n directive @key(\n generate: Boolean = false\n \"VIEWER: a created key must start with the caller's @viewer claim and the separator (lou:tomorrowland).\"\n scope: KeyScope\n separator: String = \":\"\n ) on FIELD_DEFINITION\n\n enum KeyScope {\n VIEWER\n }\n\n \"On an interface field: every implementation declares this relationship (with @relationship, possibly of different types or directions), so clients can select it on the interface.\"\n directive @declareRelationship on FIELD_DEFINITION\n\n \"Offer this field as a grouping key of <plural>Grouped (needs @query(aggregate: true)).\"\n directive @groupBy on FIELD_DEFINITION\n\n \"A field computed in JavaScript by the resolver passed in the resolvers option. requires is a selection on this type (for example name capacity) fetched in the same statement, so the resolver reads it from its source.\"\n directive @customResolver(requires: String) on FIELD_DEFINITION\n\n \"On a custom scalar: how its values are stored. Filters, sorts and indexes follow the storage type; the scalar is passed through unless the scalars option supplies an implementation.\"\n directive @storedAs(type: StorageType!) on SCALAR\n\n enum StorageType {\n STRING\n INT\n FLOAT\n BOOLEAN\n DATETIME\n DATE\n }\n\n \"A uniqueness constraint.\"\n directive @unique on FIELD_DEFINITION\n\n \"No two nodes of this type (among those matching where) share the values of fields: scalar fields, single relationships (by the target's @key) and at most one list relationship (by the set of target keys). Enforced by every generated mutation, for every caller.\"\n directive @uniqueTogether(\n fields: [String!]!\n where: NodeWhere\n ) repeatable on OBJECT\n\n \"An explicit index. Usually unnecessary: inferred from @filterable and @sortable.\"\n directive @index(kind: IndexKind!) on FIELD_DEFINITION\n\n \"An edge. The target type is the field's type.\"\n directive @relationship(\n type: String!\n direction: RelationshipDirection!\n properties: String\n \"UNDIRECTED reads follow the relationship both ways; writes use direction.\"\n queryDirection: QueryDirection = DIRECTED\n \"What deleting this node does to nodes reached through the field.\"\n onDelete: OnDelete = DETACH\n \"Which nested writes mutation inputs offer for the field.\"\n nestedOperations: [NestedOperation!] = [\n CREATE\n CONNECT\n DISCONNECT\n UPDATE\n DELETE\n ]\n \"false: no aggregate on the field's connection and no aggregate filter.\"\n aggregate: Boolean = true\n ) on FIELD_DEFINITION\n\n \"UPDATE changes a connected node and its relationship properties in place; UPDATE_EDGE only the properties.\"\n enum NestedOperation {\n CREATE\n CONNECT\n DISCONNECT\n UPDATE\n UPDATE_EDGE\n DELETE\n }\n\n enum QueryDirection {\n DIRECTED\n UNDIRECTED\n }\n\n \"DETACH removes the relationships; CASCADE deletes the related nodes too; RESTRICT refuses while any exist.\"\n enum OnDelete {\n DETACH\n CASCADE\n RESTRICT\n }\n\n \"Which mutations may set the field. @readonly is onCreate: false, onUpdate: false.\"\n directive @settable(\n onCreate: Boolean = true\n onUpdate: Boolean = true\n ) on FIELD_DEFINITION\n\n \"Whether the field can be read (onRead: false makes it write-only) or aggregated.\"\n directive @selectable(\n onRead: Boolean = true\n onAggregate: Boolean = true\n ) on FIELD_DEFINITION\n\n \"Set by a callback passed to LoraGraphQL({ callbacks }) on these operations. Client-settable only with an explicit @settable(onCreate: true) or (onUpdate: true) and a field-level @authorization(validate:) rule for that operation.\"\n directive @populatedBy(\n callback: String!\n operations: [TimestampOperation!]! = [CREATE, UPDATE]\n ) on FIELD_DEFINITION\n\n \"The shape of the request's claims. Rules may only test declared claims.\"\n directive @jwt on OBJECT\n\n \"Where a declared claim lives in the token, e.g. app_metadata.roles.\"\n directive @jwtClaim(path: String!) on FIELD_DEFINITION\n\n \"The claim that identifies the caller: the node of `type` whose `field` (a @key or @unique field) equals it. Enables isViewer and viewer in rules.\"\n directive @viewer(type: String!, field: String!) on FIELD_DEFINITION\n\n \"Properties carried by a relationship type.\"\n directive @relationshipProperties on OBJECT\n\n \"API name differs from the stored property.\"\n directive @alias(property: String!) on FIELD_DEFINITION\n\n \"Stored, never exposed.\"\n directive @private on FIELD_DEFINITION\n\n \"Declared upper bound on a relationship's fan-out, used by cost estimates.\"\n directive @cardinality(max: Int!) on FIELD_DEFINITION\n\n \"The most items a list argument of a @cypher field takes; more is BAD_USER_INPUT before the statement runs. Without it, maxListArgument applies.\"\n directive @size(max: Int!) on ARGUMENT_DEFINITION\n\n \"Bounds of an Int or Float argument of a @cypher field (each item, for a list); a value outside them is BAD_USER_INPUT before the statement runs.\"\n directive @range(min: Float, max: Float) on ARGUMENT_DEFINITION\n\n \"Generated read operations for a node type. Reads are on by default.\"\n directive @query(\n read: Boolean = true\n aggregate: Boolean = false\n ) on OBJECT | INTERFACE | UNION\n\n \"The plural of an interface or union, for its root field.\"\n directive @plural(value: String!) on INTERFACE | UNION\n\n \"Filter operators for a field. Without arguments: EQ and IN. On a relationship field: enables relationship filters.\"\n directive @filterable(byValue: [FilterOperator!]) on FIELD_DEFINITION\n\n \"Sort and keyset-paginate on this field.\"\n directive @sortable on FIELD_DEFINITION\n\n \"Page size bounds for lists of this type.\"\n directive @limit(\n default: Int\n max: Int\n ) on OBJECT | INTERFACE | UNION | FIELD_DEFINITION\n\n \"Expose an opaque global id derived from this @key field.\"\n directive @relayId on FIELD_DEFINITION\n\n \"Full-text search over String fields: a FULLTEXT index and a search root field per entry.\"\n directive @fulltext(indexes: [FulltextIndex!]!) on OBJECT\n\n \"A vector embedding ([Float!]): a VECTOR index and a similarity root field.\"\n directive @vector(\n dimensions: Int!\n similarity: VectorSimilarity = COSINE\n queryName: String\n ) on FIELD_DEFINITION\n\n input FulltextIndex {\n \"Index name. Default: <label>_search for the first, required after.\"\n name: String\n fields: [String!]!\n analyzer: FulltextAnalyzer = STANDARD\n \"Root field name. Default: search<Plural>, or search<Plural>By<Name>.\"\n queryName: String\n }\n\n enum FulltextAnalyzer {\n STANDARD\n SIMPLE\n }\n\n enum VectorSimilarity {\n COSINE\n EUCLIDEAN\n }\n\n \"Generated subscriptions to changes made through the library. None without this directive.\"\n directive @subscription(\n operations: [MutationOperation!]! = [CREATE, UPDATE, DELETE]\n \"Also send CONNECT and DISCONNECT events for the type's relationships.\"\n relationships: Boolean = false\n \"Send the stored values before an update or delete (one extra read per write).\"\n previousState: Boolean = false\n ) on OBJECT\n\n \"Generated mutations for a node type. None without this directive.\"\n directive @mutation(\n operations: [MutationOperation!]! = [CREATE, UPDATE, DELETE]\n ) on OBJECT\n\n \"Value stored on create when the input leaves the field out.\"\n directive @default(value: DefaultValue!) on FIELD_DEFINITION\n\n \"Set to the current time by the listed operations. Client-settable only with an explicit @settable(onCreate: true) or (onUpdate: true) and a field-level @authorization(validate:) rule for that operation.\"\n directive @timestamp(\n operations: [TimestampOperation!]! = [CREATE, UPDATE]\n ) on FIELD_DEFINITION\n\n \"Readable but never client-settable.\"\n directive @readonly on FIELD_DEFINITION\n\n \"A field backed by a Cypher statement. `this` is the parent node; arguments are $parameters, $jwt holds the request's claims, and $viewer the caller's @viewer node key.\"\n directive @cypher(statement: String!, columnName: String) on FIELD_DEFINITION\n\n \"Require an authenticated request (a jwt in the context) for these operations.\"\n directive @authentication(\n operations: [AuthOperation!]! = [\n READ\n CREATE\n UPDATE\n DELETE\n CREATE_RELATIONSHIP\n DELETE_RELATIONSHIP\n SUBSCRIBE\n ]\n \"Claims the request must also satisfy, such as a role in roles.\"\n jwt: AuthorizationWhere\n ) on OBJECT | FIELD_DEFINITION\n\n \"Row-level rules over the node and the request's claims, compiled into the statements.\"\n directive @authorization(\n filter: [AuthorizationFilterRule!]\n validate: [AuthorizationValidateRule!]\n \"On a type: false keeps the schema's bypass (see @authorizationDefaults) from skipping this type's rules; true lets it skip them, as without the argument, and tells check() that was meant.\"\n bypass: Boolean\n \"On a @mutation type: operations deliberately open to every caller, so check() does not report them as unguarded.\"\n public: [AuthOperation!]\n \"On a scalar field: a row failing unless reads the field as value (null when left out) instead of failing the request.\"\n mask: [AuthorizationMask!]\n ) on OBJECT | FIELD_DEFINITION\n\n \"Named rules over claims, usable in any rule as { rule: name }, on `extend schema`.\"\n directive @authorizationRules(\n rules: [AuthorizationRuleDefinition!]!\n ) on SCHEMA\n\n input AuthorizationRuleDefinition {\n name: String!\n where: AuthorizationWhere!\n }\n\n \"A named rule of this type, usable in its rules as { rule: name } and through a relationship to it as { rel: { rule: name } }.\"\n directive @authorizationRule(\n name: String!\n where: AuthorizationWhere!\n ) repeatable on OBJECT\n\n \"Schema-wide authorization settings, on `extend schema`.\"\n directive @authorizationDefaults(\n \"A claims-only test (jwt, AND, OR, NOT): a request passing it skips every filter and validate rule (not @authentication).\"\n bypass: AuthorizationWhere\n \"The write rule of every @mutation type that declares no CREATE, UPDATE or DELETE rule of its own.\"\n mutations: AuthorizationWhere\n \"Default true: without a token every rule denies. false: a rule with a branch that reads no claims decides that branch for anonymous requests too; a rule that needs claims still asks for a token.\"\n requireAuthentication: Boolean\n ) on SCHEMA\n\n input AuthorizationMask {\n unless: AuthorizationWhere!\n value: DefaultValue\n }\n\n input AuthorizationFilterRule {\n operations: [AuthOperation!]! = [READ, UPDATE, DELETE]\n where: AuthorizationWhere!\n }\n\n input AuthorizationValidateRule {\n operations: [AuthOperation!]! = [READ, CREATE, UPDATE, DELETE]\n when: [AuthorizationWhen!]! = [BEFORE, AFTER]\n where: AuthorizationWhere!\n }\n\n enum MutationOperation {\n CREATE\n UPDATE\n DELETE\n }\n\n enum TimestampOperation {\n CREATE\n UPDATE\n }\n\n enum AuthOperation {\n READ\n CREATE\n UPDATE\n DELETE\n CREATE_RELATIONSHIP\n DELETE_RELATIONSHIP\n SUBSCRIBE\n \"On a relationship field: creating one of its relationships (connect, nested create).\"\n CONNECT\n \"On a relationship field: removing one of its relationships (disconnect).\"\n DISCONNECT\n \"On a relationship field: setting properties on an existing relationship (edge update, re-connect).\"\n UPDATE_EDGE\n \"On a relationship field: reading, filtering, sorting or aggregating its properties.\"\n READ_EDGE\n }\n\n enum AuthorizationWhen {\n BEFORE\n AFTER\n }\n\n \"Any literal.\"\n scalar DefaultValue\n\n \"{ node: <Type>Where-shaped filter, jwt: claim filter, AND, OR, NOT }. String values starting with $jwt. are replaced by claims.\"\n scalar AuthorizationWhere\n\n \"A <Type>Where-shaped filter over the type the directive is on.\"\n scalar NodeWhere\n\n enum IndexKind {\n RANGE\n TEXT\n POINT\n }\n\n enum RelationshipDirection {\n IN\n OUT\n }\n\n enum FilterOperator {\n EQ\n IN\n LT\n LTE\n GT\n GTE\n CONTAINS\n STARTS_WITH\n ENDS_WITH\n WITHIN_BBOX\n DISTANCE\n INCLUDES\n IS_NULL\n CASE_INSENSITIVE\n }\n\n scalar BigInt\n scalar Date\n scalar Time\n scalar LocalTime\n scalar DateTime\n scalar LocalDateTime\n scalar Duration\n\n type Point {\n longitude: Float!\n latitude: Float!\n height: Float\n srid: Int!\n crs: String!\n }\n\n type CartesianPoint {\n x: Float!\n y: Float!\n z: Float\n srid: Int!\n crs: String!\n }\n";
|
|
2
2
|
/** Names defined by the prelude; never treated as user types. */
|
|
3
3
|
export declare const PRELUDE_TYPES: Set<string>;
|