@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,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>;
@@ -204,16 +204,26 @@ export declare const RULE_REFERENCES: Set<string>;
204
204
  export type AuthorizationWhere = Record<string, unknown>;
205
205
  export interface AuthorizationFilterRule {
206
206
  operations: ReadonlySet<AuthOperation>;
207
+ /**
208
+ * Without a token the rule denies: the schema's
209
+ * `@authorizationDefaults(requireAuthentication:)`, and always true for
210
+ * a rule no anonymous request could pass.
211
+ */
207
212
  requireAuthentication: boolean;
208
- /** `requireAuthentication` was left to its default (true). */
213
+ /** The schema left `requireAuthentication` to its default (true). */
209
214
  requireAuthenticationDefaulted?: boolean;
210
215
  where: AuthorizationWhere;
211
216
  }
212
217
  export interface AuthorizationValidateRule {
213
218
  operations: ReadonlySet<AuthOperation>;
214
219
  when: ReadonlySet<"BEFORE" | "AFTER">;
220
+ /**
221
+ * Without a token the rule denies: the schema's
222
+ * `@authorizationDefaults(requireAuthentication:)`, and always true for
223
+ * a rule no anonymous request could pass.
224
+ */
215
225
  requireAuthentication: boolean;
216
- /** `requireAuthentication` was left to its default (true). */
226
+ /** The schema left `requireAuthentication` to its default (true). */
217
227
  requireAuthenticationDefaulted?: boolean;
218
228
  where: AuthorizationWhere;
219
229
  }
@@ -0,0 +1,255 @@
1
+ import { DocumentNode, GraphQLFieldResolver, GraphQLScalarType } from 'graphql';
2
+ import { LoraDriver, Statement } from './driver.js';
3
+ import { PopulatedByCallback } from './execute/mutate/env.js';
4
+ import { LoraTransaction } from './execute/transaction.js';
5
+ import { DocumentGuards } from './guards.js';
6
+ import { ModelOptions } from './model/build/limits.js';
7
+ import { ObservabilityOptions } from './observe.js';
8
+ export interface LoraGraphQLOptions extends ModelOptions, ObservabilityOptions {
9
+ /** Annotated SDL: the graph model and the API in one document. */
10
+ typeDefs: string | DocumentNode;
11
+ driver: LoraDriver;
12
+ /** Timeout for every statement, in milliseconds. Default 10 000; 0 disables. */
13
+ timeoutMs?: number;
14
+ /**
15
+ * Time budget for all root fields of one query, in milliseconds: past
16
+ * it, the operation's statements are aborted and its unfinished fields
17
+ * fail with TIMEOUT. Default twice `timeoutMs` (20 000); 0 disables.
18
+ * Subscriptions are not bounded by it; mutations keep `timeoutMs` per
19
+ * statement.
20
+ */
21
+ operationTimeoutMs?: number;
22
+ /**
23
+ * Statements one operation runs at once: aliased root fields queue for
24
+ * a slot instead of taking every libuv worker, so one request cannot
25
+ * starve the others. Default 2.
26
+ */
27
+ maxConcurrentStatements?: number;
28
+ /**
29
+ * Approximate bytes the compile cache may hold, and again the parsed
30
+ * document cache: entries are evicted oldest first past it, besides the
31
+ * entry caps. Requests with more than 16 KiB of variables a field uses
32
+ * (long `in:` lists, embedding vectors) are compiled but not cached.
33
+ * Default 64 MiB.
34
+ */
35
+ compileCacheBytes?: number;
36
+ /**
37
+ * Reject a root field whose estimated rows touched exceed this, before
38
+ * it runs. The estimate multiplies page sizes through nested lists,
39
+ * capped by relationship degrees from `analyze()` or `@cardinality`,
40
+ * and charges each filter the rows it examines: a label scan when no
41
+ * index answers it, the related nodes of every relationship it follows.
42
+ * Default 50 000; `Infinity` disables.
43
+ */
44
+ maxCost?: number;
45
+ /**
46
+ * The cost limit for one request, from its context (for example by
47
+ * user or plan). Undefined falls back to `maxCost`.
48
+ */
49
+ budget?: (context: unknown) => number | undefined;
50
+ /** Called with every root field's cost estimate, before it runs. */
51
+ onCost?: (event: CostEvent) => void;
52
+ /**
53
+ * The request's verified claims, from the GraphQL context. Default:
54
+ * `context.jwt`. The library never verifies tokens: do that in the
55
+ * server and put the claims in the context.
56
+ */
57
+ jwt?: (context: unknown) => Record<string, unknown> | undefined;
58
+ /**
59
+ * Most nodes one mutation may create, update or delete, nested ones
60
+ * included (and ten times as many relationships written). Default 1000: larger imports belong in a Cypher load, not a GraphQL
61
+ * request. Also the default `limit` of bulk updates and deletes.
62
+ */
63
+ maxBatch?: number;
64
+ /**
65
+ * Most items a list argument of a `@cypher` field takes, unless its
66
+ * `@size(max:)` says otherwise. More is BAD_USER_INPUT before the
67
+ * statement runs. Default 1000.
68
+ */
69
+ maxListArgument?: number;
70
+ /**
71
+ * Relationship levels one `where` may nest: quantifiers (`some`,
72
+ * `none`, `all`, `single`, `count`, `aggregate`), connection filters,
73
+ * `<field>Exists` and filters through a single relationship each count
74
+ * one. Deeper is BAD_USER_INPUT before anything runs: each level
75
+ * multiplies the work by the relationship's degree. Default 2.
76
+ */
77
+ maxFilterDepth?: number;
78
+ /**
79
+ * Items an `in` filter operand may hold. More is BAD_USER_INPUT before
80
+ * anything runs. Default 1000.
81
+ */
82
+ maxListFilter?: number;
83
+ /**
84
+ * Characters a string filter operand (`eq`, `contains`, an `in` item, …)
85
+ * may hold. More is BAD_USER_INPUT before anything runs. Default 10 000.
86
+ */
87
+ maxStringFilter?: number;
88
+ /**
89
+ * Changes a `changes()` consumer or subscriber may fall behind before it
90
+ * is ended with an error. Default 1000.
91
+ */
92
+ maxQueuedChanges?: number;
93
+ /**
94
+ * Live subscriptions one scope (see `subscriptionScope`) may hold; one
95
+ * more is LIMIT_EXCEEDED. Default 100.
96
+ */
97
+ maxSubscriptions?: number;
98
+ /**
99
+ * What `maxSubscriptions` counts per: by default the context object, so
100
+ * a server that reuses one context per connection (graphql-ws) limits
101
+ * each connection. Return the connection (or user) otherwise.
102
+ */
103
+ subscriptionScope?: (context: unknown) => object | undefined;
104
+ /**
105
+ * How deep relationship filters may nest in a subscription's `where`,
106
+ * which runs on every change. Deeper is LIMIT_EXCEEDED. Default 1.
107
+ */
108
+ maxSubscriptionFilterDepth?: number;
109
+ /**
110
+ * Per statement a subscription runs to check a change (visibility,
111
+ * `where`, related nodes). Default 2000, or `timeoutMs` when lower.
112
+ */
113
+ subscriptionTimeoutMs?: number;
114
+ /** Named callbacks for `@populatedBy(callback:)`. */
115
+ callbacks?: Record<string, PopulatedByCallback>;
116
+ /**
117
+ * Implementations of custom scalars declared with `@storedAs`, e.g. one
118
+ * that validates e-mail addresses. Without one a scalar passes through.
119
+ */
120
+ scalars?: Record<string, GraphQLScalarType>;
121
+ /**
122
+ * Feed subscriptions and `changes()` from the engine's committed change
123
+ * feed (lora-node `db.changes()`): every write to the database, from
124
+ * any path in the process that owns it, in commit order. `onWrite`
125
+ * still reports this instance's mutations, and `previousState` needs
126
+ * them. Default false.
127
+ */
128
+ changeFeed?: boolean;
129
+ /**
130
+ * Resolvers of `@customResolver` fields, by type and field name. The
131
+ * source holds the node's selected fields plus the field's `requires`.
132
+ */
133
+ resolvers?: Record<string, Record<string, GraphQLFieldResolver<Record<string, unknown>, unknown>>>;
134
+ /** Called with every statement before it runs; for logging and tests. */
135
+ onStatement?: (event: StatementEvent) => void;
136
+ /**
137
+ * Hide database error details from clients: they get
138
+ * `extensions.code` `DATABASE_ERROR` and an `id`, and `onError` gets the
139
+ * engine's message. Default: on when `NODE_ENV` is `production`.
140
+ */
141
+ maskErrors?: boolean;
142
+ /** Called with every database error, masked or not. */
143
+ onError?: (event: DatabaseErrorEvent) => void;
144
+ /**
145
+ * Limits on the documents `execute()`, `subscribe()` and `persist()`
146
+ * accept: depth,
147
+ * aliases, root fields, tokens, introspection. `false` turns them off.
148
+ * For other servers use `validationRules()` or `envelopPlugin()`.
149
+ */
150
+ guards?: DocumentGuards | false;
151
+ /**
152
+ * Make `execute()` and `subscribe()` refuse `source` and run only
153
+ * persisted operations by `id`. Default false.
154
+ */
155
+ persistedOnly?: boolean;
156
+ /**
157
+ * How `execute()` commits a mutation with several root fields.
158
+ * `"field"` (the default): each root field in its own transaction, so a
159
+ * later failure leaves the earlier ones committed. `"operation"`: every
160
+ * root field in one transaction, committed only when the operation
161
+ * reports no error, rolled back (with `data: null`) otherwise. A
162
+ * `transaction` in the context takes precedence. Envelop / Yoga servers
163
+ * on `getSchema()` get the same with `lora.envelopPlugin()`; other
164
+ * servers calling graphql-js directly put a `lora.begin()` transaction
165
+ * in the context (without one, a one-time warning says each root field
166
+ * committed on its own).
167
+ */
168
+ mutationTransaction?: "field" | "operation";
169
+ /**
170
+ * Add `extensions.timing` to `execute()` results: the request's total
171
+ * time, the time spent in LoraDB, and both per root field, in
172
+ * milliseconds. `true` for every request, or a function deciding per
173
+ * request from the GraphQL context (for example only for admins or in
174
+ * development). Default off: timings sent to clients can act as a
175
+ * timing side channel.
176
+ */
177
+ timing?: boolean | ((context: unknown) => boolean);
178
+ }
179
+ export interface CostEvent {
180
+ field: string;
181
+ /** Estimated rows this root field touches. */
182
+ cost: number;
183
+ /** Estimated rows of the operation so far, this field included. */
184
+ total: number;
185
+ /** The limit that applies: `budget(context)` or `maxCost`. */
186
+ limit: number;
187
+ context: unknown;
188
+ }
189
+ export interface DatabaseErrorEvent {
190
+ /** Correlation id, also in the client error's `extensions.id`. */
191
+ id: string;
192
+ /**
193
+ * The root field that failed, or `changeFeed` for a failure of the
194
+ * change feed (it reopens from where it stopped after a backoff).
195
+ */
196
+ field: string;
197
+ /** The engine's message, which may name labels, properties and Cypher. */
198
+ message: string;
199
+ /** The error as thrown by the driver. */
200
+ error: unknown;
201
+ }
202
+ export interface StatementEvent {
203
+ field: string;
204
+ statement: Statement;
205
+ }
206
+ /** Per-request options read from the GraphQL context, when present. */
207
+ export interface LoraGraphQLContext {
208
+ /** Verified claims; enables @authentication and @authorization. */
209
+ jwt?: Record<string, unknown>;
210
+ /** Cancels the request's statements when aborted. */
211
+ signal?: AbortSignal;
212
+ /**
213
+ * Run in this transaction (from `lora.begin()`) instead of one per
214
+ * field: the caller commits, together with its own Cypher.
215
+ */
216
+ transaction?: LoraTransaction;
217
+ }
218
+ export interface AssertSchemaOptions {
219
+ /** Create what is missing instead of only reporting it. */
220
+ create?: boolean;
221
+ }
222
+ export interface CheckOptions {
223
+ /**
224
+ * Flag statements whose largest engine row estimate (from graph
225
+ * statistics) exceeds this. Off by default: estimates ignore a LIMIT
226
+ * that stops an index-ordered scan early.
227
+ */
228
+ rowBudget?: number;
229
+ /**
230
+ * Operations to compile and plan-check (S2), with example variables and
231
+ * the GraphQL context to compile them under (e.g. `{ jwt }`, so rules
232
+ * compile as they do for a signed-in caller). Without one, an operation
233
+ * compiles as an anonymous request would.
234
+ */
235
+ operations?: Array<{
236
+ name?: string;
237
+ document: string | DocumentNode;
238
+ variables?: Record<string, unknown>;
239
+ context?: unknown;
240
+ }>;
241
+ }
242
+ export interface ExecuteArgs {
243
+ /** The document, or `id` of a persisted operation. */
244
+ source?: string;
245
+ id?: string;
246
+ variables?: Record<string, unknown>;
247
+ operationName?: string;
248
+ context?: unknown;
249
+ /**
250
+ * Attach the operation's read-set to the result as a non-enumerable
251
+ * `readSet` property (never serialized to the client), for a response
252
+ * cache to invalidate with `lora.affects(result.readSet, change)`.
253
+ */
254
+ readSet?: boolean;
255
+ }
@@ -0,0 +1,70 @@
1
+ import { ExecutionResult } from 'graphql';
2
+ import { CypherFinding } from './analyze/cypher-check.js';
3
+ import { SchemaRequirement } from './analyze/indexes.js';
4
+ import { PlanReport } from './analyze/plans.js';
5
+ import { ReadSet } from './compile/read/types.js';
6
+ import { ModelWarning } from './model/types.js';
7
+ /** `extensions.timing` of an `execute()` result (see the `timing` option). */
8
+ export interface ExecutionTiming {
9
+ /** The whole `execute()` call: parse, validation, execution. */
10
+ totalMs: number;
11
+ /** Time spent running statements in LoraDB. */
12
+ databaseMs: number;
13
+ /** Per root field, by response key (alias or name). */
14
+ fields: Record<string, {
15
+ totalMs: number;
16
+ databaseMs: number;
17
+ }>;
18
+ }
19
+ /** `execute()`'s result; `readSet` is there when `ExecuteArgs.readSet` asked. */
20
+ export type LoraExecutionResult = ExecutionResult & {
21
+ readonly readSet?: ReadSet;
22
+ };
23
+ export interface SchemaAssertion {
24
+ required: SchemaRequirement[];
25
+ missing: SchemaRequirement[];
26
+ created: SchemaRequirement[];
27
+ /**
28
+ * Full-text and vector indexes present under their name but defined
29
+ * differently (labels, properties, kind): search would keep using the
30
+ * old definition. Without `create`; with it they are re-created.
31
+ */
32
+ mismatched: SchemaRequirement[];
33
+ /** Indexes `create` dropped and created again with the model's definition. */
34
+ recreated: SchemaRequirement[];
35
+ }
36
+ export interface CheckReport {
37
+ /** True when nothing below is a failure. */
38
+ ok: boolean;
39
+ /** Model warnings, e.g. an unused @cypher argument. */
40
+ warnings: readonly ModelWarning[];
41
+ /** @cypher statements the engine rejects or that write from a query. */
42
+ cypher: CypherFinding[];
43
+ /** Constraints and indexes the database lacks. */
44
+ missing: SchemaRequirement[];
45
+ /** Indexes the database has that no part of the API needs. */
46
+ unused: Array<{
47
+ name: string;
48
+ type: string;
49
+ labels: string[];
50
+ properties: string[];
51
+ }>;
52
+ /** Schema lint: valid but costly or risky choices (not failures). */
53
+ lint: readonly ModelWarning[];
54
+ /**
55
+ * `@mutation` types with writes no rule guards (failures): declare them
56
+ * with `@authorization(public: [...])` when that is intended.
57
+ */
58
+ security: readonly ModelWarning[];
59
+ /** Plan findings per operation and root field. */
60
+ plans: Array<{
61
+ operation: string;
62
+ field: string;
63
+ reports: PlanReport[];
64
+ }>;
65
+ /** Operations that failed to compile. */
66
+ errors: Array<{
67
+ operation: string;
68
+ message: string;
69
+ }>;
70
+ }
@@ -0,0 +1,7 @@
1
+ import { GraphQLSchema } from 'graphql';
2
+ import { GraphModel } from '../model/types.js';
3
+ /**
4
+ * Every `@customResolver(requires:)` is a valid selection on its type and
5
+ * does not require custom fields (they are computed after the read).
6
+ */
7
+ export declare function checkCustomRequires(model: GraphModel, schema: GraphQLSchema): void;
@@ -0,0 +1,10 @@
1
+ import { GraphModel } from '../model/types.js';
2
+ import { DatabaseErrorEvent } from '../options.js';
3
+ export interface DatabaseErrorEnv {
4
+ model: GraphModel;
5
+ /** Hide database error details from clients (the `maskErrors` option). */
6
+ maskErrors: boolean;
7
+ onError: ((event: DatabaseErrorEvent) => void) | undefined;
8
+ }
9
+ /** The error to throw for `err`, raised while `field` ran. */
10
+ export declare function databaseError(env: DatabaseErrorEnv, field: string, err: unknown): unknown;
@@ -0,0 +1,35 @@
1
+ import { DocumentNode, ExecutionResult, GraphQLSchema, OperationDefinitionNode, ValidationRule } from 'graphql';
2
+ import { OperationManifest } from '../codegen.js';
3
+ import { DocumentGuards } from '../guards.js';
4
+ import { ExecuteArgs } from '../options.js';
5
+ export interface DocumentsOptions {
6
+ guards: DocumentGuards | false;
7
+ persistedOnly: boolean;
8
+ /** Approximate bytes the parsed document cache may hold. */
9
+ bytesMax: number;
10
+ /** The executable schema, built on first use. */
11
+ schema: () => GraphQLSchema;
12
+ /** The configured document guards as validation rules. */
13
+ rules: () => ValidationRule[];
14
+ }
15
+ export declare class Documents {
16
+ #private;
17
+ constructor(options: DocumentsOptions);
18
+ /**
19
+ * Register persisted operations by id. Every document is parsed and
20
+ * validated now, so a broken one fails at startup; at request time an
21
+ * id is looked up and executed without parsing or validating.
22
+ */
23
+ persist(operations: Record<string, string>): void;
24
+ /** Register a manifest's operations, without parsing or validating. */
25
+ load(manifest: OperationManifest): void;
26
+ /** A persisted operation's document, by id. */
27
+ persisted(id: string): DocumentNode | undefined;
28
+ /** The persisted id an operation node was registered under. */
29
+ persistedId(operation: OperationDefinitionNode): string | undefined;
30
+ /**
31
+ * The document `args` names: a persisted one by id, or `source` parsed
32
+ * and validated through the cache. An error result when there is none.
33
+ */
34
+ document(args: ExecuteArgs): DocumentNode | ExecutionResult;
35
+ }
@@ -0,0 +1,37 @@
1
+ import { GraphQLResolveInfo } from 'graphql';
2
+ import { OperationBudget } from '../execute/budget.js';
3
+ import { LoraGraphQLOptions } from '../options.js';
4
+ export interface OperationLimitsOptions {
5
+ operationTimeoutMs: number;
6
+ maxConcurrentStatements: number;
7
+ maxCost: number;
8
+ budget: LoraGraphQLOptions["budget"];
9
+ onCost: LoraGraphQLOptions["onCost"];
10
+ }
11
+ export declare class OperationLimits {
12
+ #private;
13
+ constructor(options: OperationLimitsOptions);
14
+ /** Mark `execution` as a root value `execute()` made. */
15
+ track(execution: object): void;
16
+ /** The estimated cost charged to an execution so far. */
17
+ spent(execution: object): number | undefined;
18
+ /**
19
+ * Charge `cost` to the operation: the limit holds per operation, so
20
+ * aliasing a root field many times does not multiply it. A
21
+ * subscription is charged per event.
22
+ */
23
+ charge(field: string, cost: number, context: unknown, info?: GraphQLResolveInfo): void;
24
+ /**
25
+ * The deadline and statement slots of the query `info` belongs to,
26
+ * started by its first root field. Subscriptions run indefinitely and
27
+ * are bounded per statement only.
28
+ */
29
+ operationBudget(context: unknown, info: GraphQLResolveInfo | undefined): OperationBudget | undefined;
30
+ /**
31
+ * A root field is done. When none is left in flight after the current
32
+ * turn (graphql-js starts a query's root fields together, and the next
33
+ * root field of a mutation in a microtask), the operation is over: a
34
+ * context reused for another request starts a fresh budget.
35
+ */
36
+ leaveOperation(context: object, info: GraphQLResolveInfo, budget: OperationBudget): void;
37
+ }
@@ -0,0 +1,33 @@
1
+ import { GraphQLError, DocumentNode, ExecutionResult, GraphQLResolveInfo, OperationDefinitionNode } from 'graphql';
2
+ import { RootKind } from '../compile/read/types.js';
3
+ import { SelectionContext } from '../compile/selection.js';
4
+ import { QueryResult, Statement } from '../driver.js';
5
+ import { LoraTransaction } from '../execute/transaction.js';
6
+ import { GraphModel, NodeType, SearchIndex } from '../model/types.js';
7
+ /** The read root field of a node type that `fieldName` names, if any. */
8
+ export declare function rootOf(model: GraphModel, fieldName: string): {
9
+ kind: RootKind;
10
+ node: NodeType;
11
+ } | undefined;
12
+ export declare function searchOf(model: GraphModel, fieldName: string): {
13
+ node: NodeType;
14
+ index: SearchIndex;
15
+ connection: boolean;
16
+ } | undefined;
17
+ /**
18
+ * A mutation with several root fields; a fragment at the root counts as
19
+ * several, since it may hold more than one.
20
+ */
21
+ export declare function multiRoot(operation: OperationDefinitionNode): boolean;
22
+ export declare function isDocument(value: DocumentNode | ExecutionResult): value is DocumentNode;
23
+ /**
24
+ * The type of the operation `operationName` selects; undefined when it
25
+ * selects none, which graphql then reports.
26
+ */
27
+ export declare function operationType(document: DocumentNode, operationName: string | null | undefined): "query" | "mutation" | "subscription" | undefined;
28
+ /** A variable graphql-js could not coerce: a request error with no code. */
29
+ export declare function isVariableError(e: GraphQLError): boolean;
30
+ export declare function findOperation(doc: DocumentNode, operationName: string | undefined): OperationDefinitionNode;
31
+ export declare function infoContext(info: GraphQLResolveInfo): SelectionContext;
32
+ /** Run statements one after the other in a caller-owned transaction. */
33
+ export declare function runInOrder(tx: LoraTransaction, statements: Statement[]): Promise<QueryResult[]>;
@@ -0,0 +1,13 @@
1
+ import { GraphQLResolveInfo } from 'graphql';
2
+ /** A request's timing entry for a root field, created on first use. */
3
+ export declare function timingEntry(timing: Map<string, {
4
+ totalMs: number;
5
+ databaseMs: number;
6
+ }>, key: string): {
7
+ totalMs: number;
8
+ databaseMs: number;
9
+ };
10
+ /** The response key of the root field `info` belongs to. */
11
+ export declare function rootKey(info: GraphQLResolveInfo | undefined): string | undefined;
12
+ /** Milliseconds, to a hundredth. */
13
+ export declare const ms: (value: number) => number;
@@ -0,0 +1,17 @@
1
+ import { GraphQLEnumType, GraphQLObjectType } from 'graphql';
2
+ import { GraphModel, ScalarField } from '../model/types.js';
3
+ import { BaseTypes } from './base.js';
4
+ /** Fields whose values can be aggregated: ordered scalars, not lists. */
5
+ export declare const aggregatable: (f: ScalarField) => boolean;
6
+ export declare const isNumeric: (f: ScalarField) => boolean;
7
+ /** The memoized `<Scalar>Aggregate` type of a field, shared by every aggregate. */
8
+ export declare function buildAggregateFieldType(base: BaseTypes): (f: ScalarField) => GraphQLObjectType<any, any>;
9
+ export type AggregateFieldType = ReturnType<typeof buildAggregateFieldType>;
10
+ export declare function buildAggregates(model: GraphModel, base: BaseTypes, aggregateFieldType: AggregateFieldType): {
11
+ aggregates: Map<string, GraphQLObjectType<any, any>>;
12
+ groups: Map<string, {
13
+ field: GraphQLEnumType;
14
+ group: GraphQLObjectType;
15
+ }>;
16
+ };
17
+ export type AggregateTypes = ReturnType<typeof buildAggregates>;
@@ -0,0 +1,17 @@
1
+ import { GraphQLEnumType, GraphQLInputObjectType, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLInputType, GraphQLOutputType, GraphQLScalarType } from 'graphql';
2
+ import { GraphModel, ScalarField, ScalarType } from '../model/types.js';
3
+ import { SchemaHooks } from './hooks.js';
4
+ export declare const nonNull: <T extends GraphQLOutputType | GraphQLInputType>(t: T) => GraphQLNonNull<T>;
5
+ export declare const listOf: <T extends GraphQLOutputType | GraphQLInputType>(t: T) => GraphQLList<T>;
6
+ export declare function buildBaseTypes(model: GraphModel, hooks: SchemaHooks): {
7
+ sortDirection: GraphQLEnumType;
8
+ pageInfo: GraphQLObjectType<any, any>;
9
+ countFilter: GraphQLInputObjectType;
10
+ enums: Map<string, GraphQLEnumType>;
11
+ nodeInterface: GraphQLInterfaceType | undefined;
12
+ customScalar: (name: string) => GraphQLScalarType | undefined;
13
+ scalarType: (f: ScalarField) => GraphQLScalarType | GraphQLEnumType | GraphQLObjectType;
14
+ baseType: (type: ScalarType, enumName: string | undefined) => GraphQLScalarType | GraphQLEnumType | GraphQLObjectType;
15
+ scalarOutput: (f: ScalarField) => GraphQLOutputType;
16
+ };
17
+ export type BaseTypes = ReturnType<typeof buildBaseTypes>;
@@ -1,43 +1,4 @@
1
- import { GraphQLSchema, GraphQLFieldResolver, GraphQLResolveInfo, GraphQLScalarType } from 'graphql';
2
- import { RootKind } from '../compile/read.js';
3
- import { AbstractType, CustomField, CypherField, GraphModel, NodeType, ScalarField, SearchIndex } from '../model/types.js';
4
- import { MutationResolver } from './mutations.js';
5
- /** One event of a generated subscription. */
6
- export interface ChangeEvent {
7
- operation: "CREATE" | "UPDATE" | "DELETE" | "CONNECT" | "DISCONNECT";
8
- key: unknown;
9
- /** When the write was committed, ISO-8601. */
10
- timestamp?: string | undefined;
11
- /** For CONNECT / DISCONNECT: the relationship and its other end. */
12
- relationship?: {
13
- field: string;
14
- type: string;
15
- relatedType: string;
16
- relatedKey: unknown;
17
- } | undefined;
18
- /** Stored properties before the write (`previousState: true`). */
19
- previous?: Record<string, unknown> | undefined;
20
- }
21
- export interface SchemaHooks {
22
- resolveAbstract: (abstract: AbstractType, info: GraphQLResolveInfo, context: unknown) => Promise<unknown>;
23
- subscribe: (node: NodeType, args: Record<string, unknown>, context: unknown) => AsyncIterable<ChangeEvent>;
24
- resolveChangedNode: (node: NodeType, event: ChangeEvent, info: GraphQLResolveInfo, context: unknown) => Promise<unknown>;
25
- /**
26
- * A `previousState` value as the subscriber may see it: throws when
27
- * field-level @authentication refuses it, applies masks by the claims.
28
- */
29
- previousValue: (node: NodeType, field: ScalarField, value: unknown, context: unknown) => unknown;
30
- /** Implementations of custom scalars, by name (the scalars option). */
31
- scalars?: Readonly<Record<string, GraphQLScalarType>> | undefined;
32
- /** The resolver of a `@customResolver` field (from the resolvers option). */
33
- customResolver: (node: NodeType, field: CustomField) => GraphQLFieldResolver<Record<string, unknown>, unknown>;
34
- resolveSearch: (node: NodeType, index: SearchIndex, info: GraphQLResolveInfo, context: unknown, connection: boolean) => Promise<unknown>;
35
- resolveRoot: RootResolver;
36
- resolveNode: NodeResolver;
37
- resolveCypher: CypherRootResolver;
38
- resolveMutation: MutationResolver;
39
- }
40
- export type CypherRootResolver = (field: CypherField, info: GraphQLResolveInfo, context: unknown) => Promise<unknown>;
41
- export type RootResolver = (kind: RootKind, node: NodeType, info: GraphQLResolveInfo, context: unknown) => Promise<unknown>;
42
- export type NodeResolver = (id: string, info: GraphQLResolveInfo, context: unknown) => Promise<unknown>;
1
+ import { GraphQLSchema } from 'graphql';
2
+ import { GraphModel } from '../model/types.js';
3
+ import { SchemaHooks } from './hooks.js';
43
4
  export declare function buildSchema(model: GraphModel, hooks: SchemaHooks): GraphQLSchema;