@loradb/lora-graphql 0.23.0 → 0.24.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +68 -13
  2. package/dist/analyze/access-lint.d.ts +7 -0
  3. package/dist/analyze/access.d.ts +13 -33
  4. package/dist/analyze/assert-schema.d.ts +19 -0
  5. package/dist/analyze/diff.d.ts +1 -1
  6. package/dist/analyze/plans.d.ts +1 -1
  7. package/dist/analyze/principals.d.ts +25 -0
  8. package/dist/analyze/verdicts.d.ts +51 -0
  9. package/dist/cli.js +2 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/compile/cache.d.ts +1 -1
  12. package/dist/compile/read/abstract.d.ts +19 -0
  13. package/dist/compile/read/aggregates.d.ts +34 -0
  14. package/dist/compile/read/by-keys.d.ts +10 -0
  15. package/dist/compile/read/common.d.ts +30 -0
  16. package/dist/compile/read/connection.d.ts +26 -0
  17. package/dist/compile/read/cypher-field.d.ts +21 -0
  18. package/dist/compile/read/match.d.ts +11 -0
  19. package/dist/compile/read/project.d.ts +15 -0
  20. package/dist/compile/read/root.d.ts +5 -0
  21. package/dist/compile/read/search.d.ts +16 -0
  22. package/dist/compile/read/sort.d.ts +42 -0
  23. package/dist/compile/read/types.d.ts +61 -0
  24. package/dist/{diff-B9iDdELF.js → diff-K8-GSeKH.js} +2 -2
  25. package/dist/diff-K8-GSeKH.js.map +1 -0
  26. package/dist/{driver-C5dSoSD8.js → driver-CXKPLfkz.js} +10796 -10254
  27. package/dist/driver-CXKPLfkz.js.map +1 -0
  28. package/dist/execute/cypher-mutation.d.ts +1 -1
  29. package/dist/execute/mutate/adjust.d.ts +5 -0
  30. package/dist/execute/mutate/checks.d.ts +21 -0
  31. package/dist/execute/mutate/delete.d.ts +7 -0
  32. package/dist/execute/mutate/env.d.ts +73 -0
  33. package/dist/execute/mutate/errors.d.ts +7 -0
  34. package/dist/execute/mutate/fragments.d.ts +37 -0
  35. package/dist/execute/mutate/plan.d.ts +95 -0
  36. package/dist/execute/mutate/runner.d.ts +129 -0
  37. package/dist/execute/mutate/unique-together.d.ts +18 -0
  38. package/dist/execute/mutate.d.ts +2 -79
  39. package/dist/index.d.ts +10 -6
  40. package/dist/index.js +2 -2
  41. package/dist/lora-graphql.d.ts +18 -328
  42. package/dist/model/build/authorization.d.ts +31 -0
  43. package/dist/model/build/cypher-field.d.ts +11 -0
  44. package/dist/model/build/directive-args.d.ts +16 -0
  45. package/dist/model/build/limits.d.ts +18 -0
  46. package/dist/model/build/relationship-field.d.ts +11 -0
  47. package/dist/model/build/rule-checks.d.ts +23 -0
  48. package/dist/model/build/rule-references.d.ts +28 -0
  49. package/dist/model/build/scalar-field.d.ts +7 -0
  50. package/dist/model/build/search.d.ts +4 -0
  51. package/dist/model/build/shapes.d.ts +18 -0
  52. package/dist/model/build/unique-together.d.ts +5 -0
  53. package/dist/model/build.d.ts +3 -20
  54. package/dist/model/directives.d.ts +1 -1
  55. package/dist/model/types.d.ts +12 -2
  56. package/dist/options.d.ts +255 -0
  57. package/dist/results.d.ts +70 -0
  58. package/dist/runtime/custom-requires.d.ts +7 -0
  59. package/dist/runtime/database-error.d.ts +10 -0
  60. package/dist/runtime/documents.d.ts +35 -0
  61. package/dist/runtime/limits.d.ts +37 -0
  62. package/dist/runtime/request.d.ts +33 -0
  63. package/dist/runtime/timing.d.ts +13 -0
  64. package/dist/schema/aggregates.d.ts +17 -0
  65. package/dist/schema/base.d.ts +17 -0
  66. package/dist/schema/build.d.ts +3 -42
  67. package/dist/schema/filters.d.ts +10 -0
  68. package/dist/schema/hooks.d.ts +42 -0
  69. package/dist/schema/objects.d.ts +36 -0
  70. package/dist/schema/query.d.ts +8 -0
  71. package/dist/schema/resolvers.d.ts +13 -0
  72. package/dist/schema/sorts.d.ts +5 -0
  73. package/dist/schema/subscriptions.d.ts +7 -0
  74. package/dist/subscriptions/change-hub.d.ts +50 -0
  75. package/dist/subscriptions/compiles.d.ts +23 -0
  76. package/dist/subscriptions/events.d.ts +9 -0
  77. package/dist/subscriptions/filter-cost.d.ts +15 -0
  78. package/dist/subscriptions/subscriptions.d.ts +73 -0
  79. package/dist/testing.d.ts +4 -1
  80. package/dist/testing.js +34 -29
  81. package/dist/testing.js.map +1 -1
  82. package/package.json +2 -2
  83. package/dist/compile/read.d.ts +0 -102
  84. package/dist/diff-B9iDdELF.js.map +0 -1
  85. package/dist/driver-C5dSoSD8.js.map +0 -1
@@ -1,331 +1,17 @@
1
- import { ExecutionArgs, DocumentNode, ExecutionResult, GraphQLSchema, GraphQLFieldResolver, GraphQLScalarType, ValidationRule } from 'graphql';
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 { AccessEntry, OperationAccess } from './analyze/access.js';
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, DocumentGuards } from './guards.js';
14
- import { ModelOptions } from './model/build.js';
15
- import { ObservabilityOptions } from './observe.js';
16
- import { GraphModel, ModelWarning } from './model/types.js';
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
@@ -390,9 +72,17 @@ export declare class LoraGraphQL {
390
72
  * of caller, from the same rules as `accessMatrix()`, plus the most
391
73
  * restrictive verdict per caller. Takes a document (source or parsed)
392
74
  * or the id of a persisted operation; `operationName` picks one of
393
- * several operations.
75
+ * several operations. A mutation's inputs are read for the
76
+ * relationship writes they make (a nested connect, disconnect, create,
77
+ * update or delete), which count towards its root field's verdict.
78
+ * Pass `variables` for inputs the document takes as variables; a
79
+ * variable without a value is listed in the field's `unresolved`.
80
+ */
81
+ operationAccess(document: string | DocumentNode, operationName?: string, variables?: Readonly<Record<string, unknown>>): OperationAccess;
82
+ /**
83
+ * The CI gate: @cypher statements plan, the database has what the API
84
+ * needs, and each operation's statements seek where they should.
394
85
  */
395
- operationAccess(document: string | DocumentNode, operationName?: string): OperationAccess;
396
86
  check(options?: CheckOptions): Promise<CheckReport>;
397
87
  /**
398
88
  * 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[];
@@ -1,25 +1,8 @@
1
- import { DocumentNode, GraphQLNamedType } from 'graphql';
2
- import { GraphModel, ScalarType } 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;
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;