@loradb/lora-graphql 0.17.0 → 0.19.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/dist/driver.d.ts CHANGED
@@ -27,10 +27,15 @@ export interface RunOptions {
27
27
  signal?: AbortSignal | undefined;
28
28
  /**
29
29
  * A read the library vouches for: generated, or a @cypher statement
30
- * checked read-only at startup. The driver may stream it outside a
30
+ * checked read-only at startup. The driver may run it outside a
31
31
  * read-only transaction.
32
32
  */
33
33
  verified?: boolean;
34
+ /**
35
+ * A verified read of at most one row, by an exact @key seek, projecting
36
+ * only stored properties. Cheap enough to run synchronously.
37
+ */
38
+ bounded?: boolean;
34
39
  }
35
40
  /** An open interactive transaction: statements see earlier writes. */
36
41
  export interface DriverTransaction {
@@ -82,20 +87,24 @@ export interface LoraDatabaseLike {
82
87
  timeoutMs?: number;
83
88
  signal?: AbortSignal;
84
89
  }): Promise<QueryResult[]>;
85
- explain?(query: string, params?: never): Promise<QueryPlan>;
86
- changes?(options?: {
87
- fromLsn?: number;
90
+ execute?(query: string, params?: never, options?: {
91
+ timeoutMs?: number;
88
92
  signal?: AbortSignal;
89
- }): AsyncIterable<DriverChangeBatch> & {
90
- ready: Promise<void>;
91
- };
93
+ }): Promise<QueryResult>;
92
94
  stream?(query: string, params?: never, options?: {
93
95
  timeoutMs?: number;
94
96
  signal?: AbortSignal;
95
97
  }): {
96
- columns(): string[];
98
+ columns(): string[] | Promise<string[]>;
97
99
  toArray(): Promise<Array<Record<string, unknown>>>;
98
100
  };
101
+ explain?(query: string, params?: never): Promise<QueryPlan>;
102
+ changes?(options?: {
103
+ fromLsn?: number;
104
+ signal?: AbortSignal;
105
+ }): AsyncIterable<DriverChangeBatch> & {
106
+ ready: Promise<void>;
107
+ };
99
108
  begin?(mode?: "read_write" | "read_only"): Promise<{
100
109
  execute(query: string, params?: never, options?: {
101
110
  timeoutMs?: number;
package/dist/errors.d.ts CHANGED
@@ -15,6 +15,6 @@ export declare class ModelError extends Error {
15
15
  constructor(problems: ModelProblem[]);
16
16
  }
17
17
  export declare function formatProblem(p: ModelProblem): string;
18
- export type LoraGraphQLErrorCode = "BAD_USER_INPUT" | "INVALID_CURSOR" | "LIMIT_EXCEEDED" | "COST_EXCEEDED" | "UNAUTHENTICATED" | "FORBIDDEN" | "NOT_FOUND" | "CONSTRAINT_VIOLATION" | "DATABASE_ERROR" | "PERSISTED_QUERY_ONLY";
18
+ export type LoraGraphQLErrorCode = "BAD_USER_INPUT" | "INVALID_CURSOR" | "LIMIT_EXCEEDED" | "COST_EXCEEDED" | "UNAUTHENTICATED" | "FORBIDDEN" | "NOT_FOUND" | "CONSTRAINT_VIOLATION" | "DATABASE_ERROR" | "PERSISTED_QUERY_ONLY" | "WRONG_OPERATION_TYPE";
19
19
  /** A request-time error with a stable `extensions.code`. */
20
20
  export declare function requestError(code: LoraGraphQLErrorCode, message: string, cause?: unknown, extensions?: Record<string, unknown>): GraphQLError;
@@ -3,7 +3,7 @@ import { GraphModel } from '../model/types.js';
3
3
  import { WriteChange } from './changes.js';
4
4
  export declare class EngineFeed {
5
5
  #private;
6
- constructor(driver: LoraDriver, model: GraphModel, emit: (change: WriteChange) => void);
6
+ constructor(driver: LoraDriver, model: GraphModel, emit: (change: WriteChange) => void, onError?: (err: unknown) => void);
7
7
  /** Subscribe; resolves once every later commit will be delivered. */
8
8
  start(): Promise<void>;
9
9
  stop(): void;
package/dist/guards.d.ts CHANGED
@@ -1,7 +1,18 @@
1
1
  import { ParseOptions, ValidationRule } from 'graphql';
2
2
  export interface DocumentGuards {
3
- /** Deepest field nesting, fragments followed. Default 12. */
3
+ /**
4
+ * Deepest field nesting, fragments followed. Default 12. An
5
+ * introspection field (`__schema`, `__type`) counts as one level here:
6
+ * its subtree follows the type-reference chain, not the graph, and is
7
+ * bounded by `maxIntrospectionDepth`.
8
+ */
4
9
  maxDepth?: number;
10
+ /**
11
+ * Deepest nesting under `__schema` or `__type`, the field included.
12
+ * Default 20: the standard introspection query (every option on) needs
13
+ * 15, and a runaway `ofType { ofType … }` chain is still refused.
14
+ */
15
+ maxIntrospectionDepth?: number;
5
16
  /** Aliased fields in one document. Default 30. */
6
17
  maxAliases?: number;
7
18
  /** Root fields in one operation. Default 20. */
@@ -16,6 +27,7 @@ export interface DocumentGuards {
16
27
  }
17
28
  export declare const DEFAULT_GUARDS: {
18
29
  readonly maxDepth: 12;
30
+ readonly maxIntrospectionDepth: 20;
19
31
  readonly maxAliases: 30;
20
32
  readonly maxRootFields: 20;
21
33
  readonly maxTokens: 5000;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { D as e, L as r, a as o, M as l, b as i, c as d, d as n, e as t, f, g as m, i as p, l as c, p as h, r as D, s as b, h as u, t as v, v as L } from "./driver-BmnRtkpd.js";
2
- import { d as x } from "./diff-8nsBSSNP.js";
1
+ import { D as e, L as r, a as o, M as l, b as i, c as d, d as n, e as t, f, g as m, i as p, l as c, p as h, r as D, s as b, h as u, t as v, v as L } from "./driver-CuXOoYWT.js";
2
+ import { d as x } from "./diff-BH4Na9pC.js";
3
3
  export {
4
4
  e as DEFAULT_GUARDS,
5
5
  r as LoraGraphQL,
@@ -81,14 +81,15 @@ export interface LoraGraphQLOptions extends ModelOptions, ObservabilityOptions {
81
81
  /** Called with every database error, masked or not. */
82
82
  onError?: (event: DatabaseErrorEvent) => void;
83
83
  /**
84
- * Limits on the documents `execute()` and `persist()` accept: depth,
84
+ * Limits on the documents `execute()`, `subscribe()` and `persist()`
85
+ * accept: depth,
85
86
  * aliases, root fields, tokens, introspection. `false` turns them off.
86
87
  * For other servers use `validationRules()` or `envelopPlugin()`.
87
88
  */
88
89
  guards?: DocumentGuards | false;
89
90
  /**
90
- * Make `execute()` refuse `source` and run only persisted operations
91
- * by `id`. Default false.
91
+ * Make `execute()` and `subscribe()` refuse `source` and run only
92
+ * persisted operations by `id`. Default false.
92
93
  */
93
94
  persistedOnly?: boolean;
94
95
  }
@@ -105,7 +106,10 @@ export interface CostEvent {
105
106
  export interface DatabaseErrorEvent {
106
107
  /** Correlation id, also in the client error's `extensions.id`. */
107
108
  id: string;
108
- /** The root field that failed. */
109
+ /**
110
+ * The root field that failed, or `changeFeed` for a failure of the
111
+ * change feed (it reopens from where it stopped after a backoff).
112
+ */
109
113
  field: string;
110
114
  /** The engine's message, which may name labels, properties and Cypher. */
111
115
  message: string;
@@ -270,15 +274,30 @@ export declare class LoraGraphQL {
270
274
  */
271
275
  loadManifest(manifest: OperationManifest): void;
272
276
  /**
273
- * Execute an operation against the schema. Parsed and validated
274
- * documents are cached by source text; persisted ones by id.
277
+ * Execute a query or mutation against the schema. Parsed and validated
278
+ * documents are cached by source text; persisted ones by id. A
279
+ * subscription runs with {@link LoraGraphQL.subscribe}; given one, this
280
+ * returns a `WRONG_OPERATION_TYPE` error.
275
281
  */
276
282
  execute(args: ExecuteArgs): Promise<ExecutionResult>;
283
+ /**
284
+ * Run a subscription: an async iterable of results, one per event, or a
285
+ * single result with the errors when it cannot start (an unknown id, a
286
+ * validation error, a denied subscribe). Takes the same arguments as
287
+ * {@link LoraGraphQL.execute}, a persisted id included, with the same
288
+ * document cache and guards; a query or mutation gets a
289
+ * `WRONG_OPERATION_TYPE` error. End it with `return()` on the iterator
290
+ * or with an `AbortSignal` passed as `context.signal`: either ends it at
291
+ * once, without waiting for another event, and drops its listener. The
292
+ * cost limit applies to each event on its own.
293
+ */
294
+ subscribe(args: ExecuteArgs): Promise<AsyncIterableIterator<ExecutionResult> | ExecutionResult>;
277
295
  /** Called after every committed mutation with its exact write-set. */
278
296
  onWrite(listener: (change: WriteChange) => void): () => void;
279
297
  /**
280
298
  * Committed writes as an async iterator, e.g. for a subscription
281
- * resolver. Only writes made through this instance are seen.
299
+ * resolver. Only writes made through this instance are seen. `return()`
300
+ * or aborting `signal` (already aborted included) ends it at once.
282
301
  */
283
302
  changes(options?: {
284
303
  signal?: AbortSignal;
package/dist/testing.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { graphql as h } from "graphql";
2
- import { L as w, l as u } from "./driver-BmnRtkpd.js";
2
+ import { L as w, l as u } from "./driver-CuXOoYWT.js";
3
3
  async function L(l) {
4
4
  let s;
5
5
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loradb/lora-graphql",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "Schema-first GraphQL for LoraDB: one annotated SDL becomes an executable, index-aware GraphQL API that compiles every operation to a single Cypher statement.",
5
5
  "license": "BUSL-1.1",
6
6
  "packageManager": "yarn@4.5.1",
@@ -61,10 +61,11 @@
61
61
  "lint:fix": "eslint src test bench --fix",
62
62
  "format": "prettier --write src test",
63
63
  "format:check": "prettier --check src test",
64
- "bench": "vitest bench --run"
64
+ "bench": "vitest bench --run",
65
+ "bench:load": "node bench/load/main.mjs"
65
66
  },
66
67
  "peerDependencies": {
67
- "@loradb/lora-node": "^0.17.0",
68
+ "@loradb/lora-node": "^0.19.0",
68
69
  "graphql": "^16.8.0 || ^17.0.0"
69
70
  },
70
71
  "devDependencies": {