@znight/core 0.1.3 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@znight/core",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Znight core runtime: compile-time DI container, lifecycle, plugins and marker decorators",
5
5
  "license": "MIT",
6
6
  "author": "Ugho STEPHAN",
package/src/errors.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * messaging, config, observability).
8
8
  * - From `ZNIGHT030`, each first-party package reserves a block of ten: `ZNIGHT030`–`039`
9
9
  * `@znight/openapi`, `ZNIGHT040`–`049` `@znight/schedule`, `ZNIGHT050`–`059` `@znight/websocket`
10
- * (reserved), `ZNIGHT060`–`069` `@znight/graphql` (reserved).
10
+ * (reserved), `ZNIGHT060`–`069` `@znight/graphql`.
11
11
  *
12
12
  * Within a range, codes are allocated in order without gaps. A package uses its block for its own
13
13
  * failure modes, with one catch-all code for invalid usage and options, and reuses a lower code
@@ -100,6 +100,34 @@ export const ErrorCode = {
100
100
  MissingLockStore: 'ZNIGHT043',
101
101
  /** A scheduled run was aborted (`ctx.signal.reason`, `JobAbortedError`); never thrown by the framework. */
102
102
  JobAborted: 'ZNIGHT044',
103
+
104
+ // ZNIGHT060–069: @znight/graphql (RFC 0005)
105
+ /** A TypeScript type cannot be mapped to a GraphQL type, or a resolver lacks the annotation it needs. */
106
+ InvalidGraphQLType: 'ZNIGHT060',
107
+ /** Two declarations or root fields share a GraphQL name, or a name is invalid or reserved. */
108
+ GraphQLNameConflict: 'ZNIGHT061',
109
+ /**
110
+ * Invalid resolver structure: `@ResolveField` without `@Parent()`, a subscription not returning an
111
+ * async iterable, no `@Query`, inherited handlers, resolvers in a compiled library.
112
+ */
113
+ InvalidResolver: 'ZNIGHT062',
114
+ /**
115
+ * Invalid input position: a type used as input and output, a getter, a union, a cycle of non-null
116
+ * input fields, a default value not matching its type.
117
+ */
118
+ InvalidGraphQLInput: 'ZNIGHT063',
119
+ /** The members of a GraphQL union cannot be told apart at runtime. */
120
+ UnresolvableAbstractType: 'ZNIGHT064',
121
+ /**
122
+ * Invalid loader: `@Loader()` on a type that is not `Loader<L>`, `L` not a `BatchLoad`; at runtime,
123
+ * a batch function returning another number of values than keys.
124
+ */
125
+ InvalidLoader: 'ZNIGHT065',
126
+ /**
127
+ * Invalid GraphQL setup at boot: malformed or version-skewed metadata, invalid schema, invalid
128
+ * `GraphQLPlugin` options, missing `HttpPlugin`, scalar name mismatch.
129
+ */
130
+ InvalidGraphQLSetup: 'ZNIGHT066',
103
131
  } as const
104
132
 
105
133
  export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode]
@@ -142,6 +170,13 @@ export const ERROR_DESCRIPTIONS: Readonly<Record<ErrorCode, string>> = {
142
170
  ZNIGHT042: 'Unknown job: no job has this name',
143
171
  ZNIGHT043: 'Missing lock store: a job requires a lock but SchedulePlugin has no store',
144
172
  ZNIGHT044: 'Job aborted: a scheduled run was aborted (timeout, lost lock, removal or shutdown)',
173
+ ZNIGHT060: 'Invalid GraphQL type: a TypeScript type cannot be mapped to a GraphQL type',
174
+ ZNIGHT061: 'GraphQL name conflict: two types or root fields share a name, or a name is invalid or reserved',
175
+ ZNIGHT062: 'Invalid resolver: the structure of a GraphQL resolver is invalid',
176
+ ZNIGHT063: 'Invalid GraphQL input: a type cannot be used in an input position',
177
+ ZNIGHT064: 'Unresolvable abstract type: the members of a GraphQL union cannot be told apart at runtime',
178
+ ZNIGHT065: 'Invalid loader: not a Loader of a BatchLoad provider, or a batch returning the wrong number of values',
179
+ ZNIGHT066: 'Invalid GraphQL setup: metadata, schema, GraphQLPlugin options or HttpPlugin missing',
145
180
  }
146
181
 
147
182
  export interface ZnightErrorOptions extends ErrorOptions {
package/src/hooks.ts CHANGED
@@ -27,6 +27,12 @@ export interface ZnightHooks {
27
27
  * drop, a wrapper that threw first): see `ScheduledRunEvent.outcome`.
28
28
  */
29
29
  'schedule:run': ScheduledRunEvent
30
+ /**
31
+ * One GraphQL operation handled by `@znight/graphql` (RFC 0005): a query or a mutation, or a whole
32
+ * subscription from its start to its end. Wrapped with `hooks.run` when wrappers exist, then
33
+ * emitted when listeners exist.
34
+ */
35
+ 'graphql:operation': GraphQLOperationEvent
30
36
  }
31
37
 
32
38
  /**
@@ -162,6 +168,59 @@ export interface ScheduledRunEvent {
162
168
  aborted?: ScheduledRunAbortReason
163
169
  }
164
170
 
171
+ /** Type of a GraphQL operation (`GraphQLOperationEvent.operationType`). */
172
+ export type GraphQLOperationType = 'query' | 'mutation' | 'subscription'
173
+
174
+ /**
175
+ * How a GraphQL operation reached the server (`GraphQLOperationEvent.transport`): GraphQL over HTTP,
176
+ * GraphQL over Server-Sent Events, or a direct call (`execute()` / `subscribe()` of the plugin).
177
+ */
178
+ export type GraphQLOperationTransport = 'http' | 'sse' | 'direct'
179
+
180
+ /**
181
+ * Outcome of a GraphQL operation (`GraphQLOperationEvent.outcome`):
182
+ *
183
+ * - `'success'`: executed, no error;
184
+ * - `'partial'`: executed, with data and field errors;
185
+ * - `'error'`: executed, without data (a non-null root field failed, or the execution threw);
186
+ * - `'rejected'`: never executed (parse, validation, variable coercion or limit errors).
187
+ */
188
+ export type GraphQLOperationOutcome = 'success' | 'partial' | 'error' | 'rejected'
189
+
190
+ /** One error of a GraphQL response, as sent to the client (masked when it is unexpected). */
191
+ export interface GraphQLOperationError {
192
+ readonly message: string
193
+ /** `extensions.code` of the error (`FORBIDDEN`, `GRAPHQL_PARSE_FAILED`...). */
194
+ readonly code: string | undefined
195
+ /** Response path of the field that failed; absent for request errors. */
196
+ readonly path?: readonly (string | number)[]
197
+ }
198
+
199
+ /**
200
+ * Instrumentation event of the `graphql:operation` hook, produced by `@znight/graphql` (RFC 0005)
201
+ * once per operation. For a subscription, it covers its whole life: wrappers see it start, and
202
+ * `outcome` is set when it ends. Mutable fields are filled in by the producer before `hooks.run`
203
+ * resolves; listeners see the final values.
204
+ */
205
+ export interface GraphQLOperationEvent {
206
+ /** `undefined` when the request was rejected before an operation was selected (parse error...). */
207
+ readonly operationType: GraphQLOperationType | undefined
208
+ /** `undefined` for an anonymous operation, or when none was selected. */
209
+ readonly operationName: string | undefined
210
+ /** SHA-256 (hex) of the query text, cached with the parsed document; `undefined` without a query. */
211
+ readonly documentId: string | undefined
212
+ readonly transport: GraphQLOperationTransport
213
+ readonly requestId: string
214
+ /** `GraphQLContext` from `@znight/graphql`. */
215
+ readonly context: unknown
216
+ /** `performance.now()` when the operation started. */
217
+ readonly startTime: number
218
+ /** Outcome, set before `hooks.run` resolves. */
219
+ outcome?: GraphQLOperationOutcome
220
+ /** Errors of the response (field and request errors), set before `hooks.run` resolves. */
221
+ errors?: readonly GraphQLOperationError[]
222
+ }
223
+
165
224
  /** Name of a declared hook. */
166
225
  export type HookName = keyof ZnightHooks
167
226
 
package/src/index.ts CHANGED
@@ -38,6 +38,11 @@ export {
38
38
  export { isProviderDefinition } from './definition.ts'
39
39
  export * from './errors.ts'
40
40
  export {
41
+ type GraphQLOperationError,
42
+ type GraphQLOperationEvent,
43
+ type GraphQLOperationOutcome,
44
+ type GraphQLOperationTransport,
45
+ type GraphQLOperationType,
41
46
  type HookEvent,
42
47
  type HookListener,
43
48
  type HookName,