@leaven-graphql/plugins 0.1.0 → 0.2.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.
package/dist/builtin.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * @leaven-graphql/plugins - Built-in plugins
3
3
  *
4
- * Copyright 2026 Pegasus Heavy Industries LLC
4
+ * Copyright 2026 Joseph Quinn
5
5
  * Licensed under the Apache License, Version 2.0
6
6
  */
7
- import type { Plugin, PluginHooks, PluginMetadata } from './types';
7
+ import type { Plugin, PluginContext, PluginHooks, PluginMetadata } from './types';
8
8
  /**
9
9
  * Create a custom plugin
10
10
  */
@@ -15,12 +15,38 @@ export declare function createPlugin(metadata: PluginMetadata, hooks: PluginHook
15
15
  export declare function composePlugins(name: string, ...plugins: Plugin[]): Plugin;
16
16
  /**
17
17
  * Create a caching plugin
18
+ *
19
+ * Caches successful responses keyed by query, operation name, and variables.
20
+ * On a cache hit, `beforeExecute` returns the cached response, which
21
+ * `PluginManager.beforeExecute` surfaces to its caller so execution can be
22
+ * skipped entirely. Pipelines that ignore that return value still receive the
23
+ * cached response, because `afterExecute` substitutes it for the freshly
24
+ * executed result.
25
+ *
26
+ * A cache hit skips execution entirely, so resolvers — and any field-level
27
+ * authorization they perform — do not run. Caller identity must therefore be
28
+ * part of the cache key, and the plugin refuses to be constructed unless that
29
+ * choice is explicit: supply a `keyFn` that incorporates the identity, or set
30
+ * `allowSharedCache: true` to opt in to a cache shared by every caller (safe
31
+ * only for data that is identical for everyone, e.g. fully public content).
18
32
  */
19
33
  export declare function createCachingPlugin(options?: {
20
34
  /** Maximum cache size */
21
35
  maxSize?: number;
22
36
  /** Cache TTL in milliseconds */
23
37
  ttl?: number;
38
+ /**
39
+ * Derives the cache key for a request. Use this to incorporate user or
40
+ * tenant identity (e.g. from `context.context`) so cached responses are
41
+ * not shared across callers.
42
+ */
43
+ keyFn?: (context: PluginContext) => string;
44
+ /**
45
+ * Opt in to a cache keyed only by query, operation name, and variables —
46
+ * with NO caller identity, so any caller may be served any other caller's
47
+ * response. Required when no `keyFn` is supplied.
48
+ */
49
+ allowSharedCache?: boolean;
24
50
  }): Plugin;
25
51
  /**
26
52
  * Create a logging plugin
@@ -38,21 +64,66 @@ export declare function createLoggingPlugin(options?: {
38
64
  }): Plugin;
39
65
  /**
40
66
  * Create a tracing plugin
67
+ *
68
+ * Emits Apollo Tracing-shaped data (nanosecond offsets/durations) in
69
+ * `extensions.tracing`. Parsing, validation, and execution phases are each
70
+ * measured by their own hooks; a phase whose hooks did not run in the request
71
+ * pipeline is omitted from the output rather than reported as a false zero.
41
72
  */
42
73
  export declare function createTracingPlugin(): Plugin;
43
74
  /**
44
75
  * Create a depth limit plugin
76
+ *
77
+ * Accepts either the bare number form `createDepthLimitPlugin(10)` or the
78
+ * options-object form `createDepthLimitPlugin({ maxDepth: 10 })`. Only field
79
+ * selections add a level of depth, matching `calculateQueryDepth` in
80
+ * `@leaven-graphql/core`. Fragment spreads are resolved through their
81
+ * definitions and each fragment is measured once per document, so a document
82
+ * that spreads fragments repeatedly cannot fan out exponentially; recursive
83
+ * fragments are detected and terminated after one unrolling.
84
+ *
85
+ * Throws {@link DepthLimitError} (HTTP 400, `extensions.code: 'DEPTH_LIMIT'`)
86
+ * when a query exceeds the configured depth, or when analyzing the document
87
+ * would exceed the node budget (`extensions.reason:
88
+ * 'ANALYSIS_BUDGET_EXCEEDED'`).
45
89
  */
46
- export declare function createDepthLimitPlugin(maxDepth: number): Plugin;
90
+ export declare function createDepthLimitPlugin(maxDepth: number | {
91
+ maxDepth: number;
92
+ }): Plugin;
47
93
  /**
48
94
  * Create a complexity plugin
95
+ *
96
+ * A field scores `defaultComplexity` plus its children, and the whole subtree
97
+ * is multiplied by any `first`/`last`/`limit` page size — literal or variable.
98
+ * Fragment spreads are resolved through their definitions and each fragment is
99
+ * scored once per operation, so repeated spreads cannot fan out exponentially;
100
+ * recursive fragments are detected and terminated.
101
+ *
102
+ * Throws {@link ComplexityError} (HTTP 400,
103
+ * `extensions.code: 'COMPLEXITY_LIMIT'`) when a query exceeds the configured
104
+ * complexity, or when analyzing the document would exceed the node budget
105
+ * (`extensions.reason: 'ANALYSIS_BUDGET_EXCEEDED'`).
49
106
  */
50
107
  export declare function createComplexityPlugin(options: {
51
108
  /** Maximum allowed complexity */
52
109
  maxComplexity: number;
53
110
  /** Default field complexity */
54
111
  defaultComplexity?: number;
55
- /** Custom complexity calculator */
112
+ /**
113
+ * Page size assumed for a `first`/`last`/`limit` argument whose value cannot
114
+ * be determined from the document — a variable the request did not supply
115
+ * that also declares no default. Deliberately pessimistic: the value is
116
+ * client-controlled, so assuming a small page size would let an unbounded
117
+ * request score as a cheap one. Defaults to 100.
118
+ */
119
+ unknownMultiplier?: number;
120
+ /**
121
+ * Custom complexity calculator, invoked for each field node with the
122
+ * accumulated complexity of its children. Its return value is used as the
123
+ * field's TOTAL complexity (so incorporate `childComplexity` as desired).
124
+ * When omitted, a field scores `defaultComplexity` plus its children's
125
+ * complexity, all multiplied by any `first`/`last`/`limit` argument.
126
+ */
56
127
  calculator?: (node: unknown, childComplexity: number) => number;
57
128
  }): Plugin;
58
129
  //# sourceMappingURL=builtin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"builtin.d.ts","sourceRoot":"","sources":["../src/builtin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEnE;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,WAAW,GACjB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CA6EzE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,MAAM,CAsDT;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,gBAAgB;IAChB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5C,oBAAoB;IACpB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC5C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC5C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KAC9C,CAAC;CACH,GAAG,MAAM,CA6DT;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAsD5C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAuD/D;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,iCAAiC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mCAAmC;IACnC,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,OAAO,EACb,eAAe,EAAE,MAAM,KACpB,MAAM,CAAC;CACb,GAAG,MAAM,CA0ET"}
1
+ {"version":3,"file":"builtin.d.ts","sourceRoot":"","sources":["../src/builtin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAElF;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,WAAW,GACjB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CA0GzE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,MAAM,CAAC;IAC3C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,MAAM,CAgGT;AAOD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC5C,gBAAgB;IAChB,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IAC5C,oBAAoB;IACpB,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC7C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC5C,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;QAC5C,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;KAC9C,CAAC;CACH,GAAG,MAAM,CA6DT;AAaD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA+F5C;AAqID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtC,MAAM,CA4CR;AAsND;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,iCAAiC;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,OAAO,EACb,eAAe,EAAE,MAAM,KACpB,MAAM,CAAC;CACb,GAAG,MAAM,CAoDT"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @leaven-graphql/plugins - Plugin system for Leaven
3
3
  *
4
- * Copyright 2026 Pegasus Heavy Industries LLC
4
+ * Copyright 2026 Joseph Quinn
5
5
  * Licensed under the Apache License, Version 2.0
6
6
  */
7
7
  export { PluginManager, createPluginManager } from './manager';