@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/README.md CHANGED
@@ -338,12 +338,13 @@ return what is known (`[]`).
338
338
  declared in core, so producers and observers (`@znight/observability`, your plugins) share them
339
339
  without depending on each other:
340
340
 
341
- | Hook | Event | Produced by |
342
- | ------------------- | ---------------------- | ---------------------------------------------------------------------------- |
343
- | `http:request` | `HttpRequestEvent` | `@znight/http`, one request |
344
- | `messaging:message` | `MessageDeliveryEvent` | `@znight/messaging`, one delivery |
345
- | `messaging:publish` | `MessagePublishEvent` | `@znight/messaging`, one `MessageBroker` publication |
346
- | `schedule:run` | `ScheduledRunEvent` | `@znight/schedule`, one occurrence of a job (executed or not, see `outcome`) |
341
+ | Hook | Event | Produced by |
342
+ | ------------------- | ----------------------- | ---------------------------------------------------------------------------- |
343
+ | `http:request` | `HttpRequestEvent` | `@znight/http`, one request |
344
+ | `messaging:message` | `MessageDeliveryEvent` | `@znight/messaging`, one delivery |
345
+ | `messaging:publish` | `MessagePublishEvent` | `@znight/messaging`, one `MessageBroker` publication |
346
+ | `schedule:run` | `ScheduledRunEvent` | `@znight/schedule`, one occurrence of a job (executed or not, see `outcome`) |
347
+ | `graphql:operation` | `GraphQLOperationEvent` | `@znight/graphql` (planned, RFC 0005), one GraphQL operation |
347
348
 
348
349
  `ScheduledRunEvent` carries `job`, `kind` (`cron` / `interval` / `timeout`), `host`, `method`,
349
350
  `runId`, `trigger` (`schedule` / `start` / `manual` / `queued`), `scheduledAt` (epoch ms),
@@ -358,6 +359,13 @@ wrappers waited (job removed or paused, scheduler stopping), or a wrapper threw
358
359
  rejects). The producer settles it after `hooks.run` (`skipped`, or `failed` for a wrapper that
359
360
  threw), so a wrapper that reports it reads `event.outcome ?? (nextRejected ? 'failed' : 'skipped')`.
360
361
 
362
+ `GraphQLOperationEvent` carries `operationType` (`query` / `mutation` / `subscription`, `undefined`
363
+ when the request was rejected before an operation was selected), `operationName`, `documentId`
364
+ (SHA-256 of the query text), `transport` (`http` / `sse` / `direct`), `requestId`, `context` (the
365
+ `GraphQLContext`), `startTime`, and, once settled, `outcome` (`success` / `partial` / `error` /
366
+ `rejected`) and `errors` (`{ message, code, path? }`, as sent to the client). A subscription is one
367
+ operation from its start to its end.
368
+
361
369
  Other packages declare their hooks by augmenting `ZnightHooks`:
362
370
 
363
371
  ```ts
@@ -421,6 +429,6 @@ the [architecture specification](../../docs/internals/architecture.md#48-validat
421
429
  The catalogue is shared by the compiler and every first-party package. `ZNIGHT001`–`ZNIGHT029`
422
430
  belong to the core, the compiler and the features of the first release (`ZNIGHT023`, a missing
423
431
  route decision, is reported by `@znight/http`). From `ZNIGHT030`, each package owns a block of ten:
424
- `ZNIGHT030`–`039` `@znight/openapi`, `ZNIGHT040`–`049` `@znight/schedule` (`050`–`059` and
425
- `060`–`069` are reserved for `@znight/websocket` and `@znight/graphql`, planned for v0.2). Inside a
426
- block, codes are allocated in order; third-party packages get no `ZNIGHT` code.
432
+ `ZNIGHT030`–`039` `@znight/openapi`, `ZNIGHT040`–`049` `@znight/schedule`, `ZNIGHT060`–`069`
433
+ `@znight/graphql` (RFC 0005, planned for v0.2; `050`–`059` are reserved for `@znight/websocket`).
434
+ Inside a block, codes are allocated in order; third-party packages get no `ZNIGHT` code.
package/dist/index.d.mts 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
@@ -96,6 +96,32 @@ export declare const ErrorCode: {
96
96
  readonly MissingLockStore: "ZNIGHT043";
97
97
  /** A scheduled run was aborted (`ctx.signal.reason`, `JobAbortedError`); never thrown by the framework. */
98
98
  readonly JobAborted: "ZNIGHT044";
99
+ /** A TypeScript type cannot be mapped to a GraphQL type, or a resolver lacks the annotation it needs. */
100
+ readonly InvalidGraphQLType: "ZNIGHT060";
101
+ /** Two declarations or root fields share a GraphQL name, or a name is invalid or reserved. */
102
+ readonly GraphQLNameConflict: "ZNIGHT061";
103
+ /**
104
+ * Invalid resolver structure: `@ResolveField` without `@Parent()`, a subscription not returning an
105
+ * async iterable, no `@Query`, inherited handlers, resolvers in a compiled library.
106
+ */
107
+ readonly InvalidResolver: "ZNIGHT062";
108
+ /**
109
+ * Invalid input position: a type used as input and output, a getter, a union, a cycle of non-null
110
+ * input fields, a default value not matching its type.
111
+ */
112
+ readonly InvalidGraphQLInput: "ZNIGHT063";
113
+ /** The members of a GraphQL union cannot be told apart at runtime. */
114
+ readonly UnresolvableAbstractType: "ZNIGHT064";
115
+ /**
116
+ * Invalid loader: `@Loader()` on a type that is not `Loader<L>`, `L` not a `BatchLoad`; at runtime,
117
+ * a batch function returning another number of values than keys.
118
+ */
119
+ readonly InvalidLoader: "ZNIGHT065";
120
+ /**
121
+ * Invalid GraphQL setup at boot: malformed or version-skewed metadata, invalid schema, invalid
122
+ * `GraphQLPlugin` options, missing `HttpPlugin`, scalar name mismatch.
123
+ */
124
+ readonly InvalidGraphQLSetup: "ZNIGHT066";
99
125
  };
100
126
  export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
101
127
  /** Short human readable description of every error code. */
@@ -610,6 +636,12 @@ interface ZnightHooks {
610
636
  * drop, a wrapper that threw first): see `ScheduledRunEvent.outcome`.
611
637
  */
612
638
  "schedule:run": ScheduledRunEvent;
639
+ /**
640
+ * One GraphQL operation handled by `@znight/graphql` (RFC 0005): a query or a mutation, or a whole
641
+ * subscription from its start to its end. Wrapped with `hooks.run` when wrappers exist, then
642
+ * emitted when listeners exist.
643
+ */
644
+ "graphql:operation": GraphQLOperationEvent;
613
645
  }
614
646
  /**
615
647
  * Instrumentation event of the `http:request` hook. Defined in core so that producers
@@ -737,6 +769,54 @@ interface ScheduledRunEvent {
737
769
  /** Set when the run's signal was aborted. */
738
770
  aborted?: ScheduledRunAbortReason;
739
771
  }
772
+ /** Type of a GraphQL operation (`GraphQLOperationEvent.operationType`). */
773
+ type GraphQLOperationType = "query" | "mutation" | "subscription";
774
+ /**
775
+ * How a GraphQL operation reached the server (`GraphQLOperationEvent.transport`): GraphQL over HTTP,
776
+ * GraphQL over Server-Sent Events, or a direct call (`execute()` / `subscribe()` of the plugin).
777
+ */
778
+ type GraphQLOperationTransport = "http" | "sse" | "direct";
779
+ /**
780
+ * Outcome of a GraphQL operation (`GraphQLOperationEvent.outcome`):
781
+ *
782
+ * - `'success'`: executed, no error;
783
+ * - `'partial'`: executed, with data and field errors;
784
+ * - `'error'`: executed, without data (a non-null root field failed, or the execution threw);
785
+ * - `'rejected'`: never executed (parse, validation, variable coercion or limit errors).
786
+ */
787
+ type GraphQLOperationOutcome = "success" | "partial" | "error" | "rejected";
788
+ /** One error of a GraphQL response, as sent to the client (masked when it is unexpected). */
789
+ interface GraphQLOperationError {
790
+ readonly message: string;
791
+ /** `extensions.code` of the error (`FORBIDDEN`, `GRAPHQL_PARSE_FAILED`...). */
792
+ readonly code: string | undefined;
793
+ /** Response path of the field that failed; absent for request errors. */
794
+ readonly path?: readonly (string | number)[];
795
+ }
796
+ /**
797
+ * Instrumentation event of the `graphql:operation` hook, produced by `@znight/graphql` (RFC 0005)
798
+ * once per operation. For a subscription, it covers its whole life: wrappers see it start, and
799
+ * `outcome` is set when it ends. Mutable fields are filled in by the producer before `hooks.run`
800
+ * resolves; listeners see the final values.
801
+ */
802
+ interface GraphQLOperationEvent {
803
+ /** `undefined` when the request was rejected before an operation was selected (parse error...). */
804
+ readonly operationType: GraphQLOperationType | undefined;
805
+ /** `undefined` for an anonymous operation, or when none was selected. */
806
+ readonly operationName: string | undefined;
807
+ /** SHA-256 (hex) of the query text, cached with the parsed document; `undefined` without a query. */
808
+ readonly documentId: string | undefined;
809
+ readonly transport: GraphQLOperationTransport;
810
+ readonly requestId: string;
811
+ /** `GraphQLContext` from `@znight/graphql`. */
812
+ readonly context: unknown;
813
+ /** `performance.now()` when the operation started. */
814
+ readonly startTime: number;
815
+ /** Outcome, set before `hooks.run` resolves. */
816
+ outcome?: GraphQLOperationOutcome;
817
+ /** Errors of the response (field and request errors), set before `hooks.run` resolves. */
818
+ errors?: readonly GraphQLOperationError[];
819
+ }
740
820
  /** Name of a declared hook. */
741
821
  type HookName = keyof ZnightHooks;
742
822
  /** Event type of hook `K`. */
@@ -1094,5 +1174,5 @@ export declare class ZnightAggregateError extends ZnightError {
1094
1174
  * that were attached to it instead of being thrown. Empty when there are none.
1095
1175
  */
1096
1176
  export declare function getSuppressedErrors(error: unknown): readonly unknown[];
1097
- export type { ApplicationOptions, ApplicationState, ClassKey, ClassMarker, ConsoleLike, ConsoleLoggerOptions, CoreLogger, HookEvent, HookListener, HookName, HookWrapper, HooksOptions, HotContext, HttpRequestEvent, InitOptions, InjectableOptions, InterceptMethodOptions, InterceptOptionsArgs, InterceptorClass, InterceptorLink, LogContext, LogLevel, ManagedInstance, MessageDeliveryEvent, MessagePublishEvent, MethodInterceptor, MethodInvocation, MethodMarker, OnReady, OnStart, OnStop, OpenedScope, ParameterMarker, Plugin, PluginContext, PluginHook, PluginOptions, PluginRootsContext, ProcessLike, ProviderKey, ProviderValues, ProvidesOptions, ScheduledRunAbortReason, ScheduledRunEvent, ScheduledRunOutcome, ScheduledRunTrigger, ScopeContext, ScopeValues, ShutdownOptions, ShutdownSignal, TypedToken, ZnightHooks };
1177
+ export type { ApplicationOptions, ApplicationState, ClassKey, ClassMarker, ConsoleLike, ConsoleLoggerOptions, CoreLogger, GraphQLOperationError, GraphQLOperationEvent, GraphQLOperationOutcome, GraphQLOperationTransport, GraphQLOperationType, HookEvent, HookListener, HookName, HookWrapper, HooksOptions, HotContext, HttpRequestEvent, InitOptions, InjectableOptions, InterceptMethodOptions, InterceptOptionsArgs, InterceptorClass, InterceptorLink, LogContext, LogLevel, ManagedInstance, MessageDeliveryEvent, MessagePublishEvent, MethodInterceptor, MethodInvocation, MethodMarker, OnReady, OnStart, OnStop, OpenedScope, ParameterMarker, Plugin, PluginContext, PluginHook, PluginOptions, PluginRootsContext, ProcessLike, ProviderKey, ProviderValues, ProvidesOptions, ScheduledRunAbortReason, ScheduledRunEvent, ScheduledRunOutcome, ScheduledRunTrigger, ScopeContext, ScopeValues, ShutdownOptions, ShutdownSignal, TypedToken, ZnightHooks };
1098
1178
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
9
9
  * messaging, config, observability).
10
10
  * - From `ZNIGHT030`, each first-party package reserves a block of ten: `ZNIGHT030`–`039`
11
11
  * `@znight/openapi`, `ZNIGHT040`–`049` `@znight/schedule`, `ZNIGHT050`–`059` `@znight/websocket`
12
- * (reserved), `ZNIGHT060`–`069` `@znight/graphql` (reserved).
12
+ * (reserved), `ZNIGHT060`–`069` `@znight/graphql`.
13
13
  *
14
14
  * Within a range, codes are allocated in order without gaps. A package uses its block for its own
15
15
  * failure modes, with one catch-all code for invalid usage and options, and reuses a lower code
@@ -97,7 +97,33 @@ const ErrorCode = {
97
97
  /** A job requires a lock but `SchedulePlugin` has no lock store. */
98
98
  MissingLockStore: "ZNIGHT043",
99
99
  /** A scheduled run was aborted (`ctx.signal.reason`, `JobAbortedError`); never thrown by the framework. */
100
- JobAborted: "ZNIGHT044"
100
+ JobAborted: "ZNIGHT044",
101
+ /** A TypeScript type cannot be mapped to a GraphQL type, or a resolver lacks the annotation it needs. */
102
+ InvalidGraphQLType: "ZNIGHT060",
103
+ /** Two declarations or root fields share a GraphQL name, or a name is invalid or reserved. */
104
+ GraphQLNameConflict: "ZNIGHT061",
105
+ /**
106
+ * Invalid resolver structure: `@ResolveField` without `@Parent()`, a subscription not returning an
107
+ * async iterable, no `@Query`, inherited handlers, resolvers in a compiled library.
108
+ */
109
+ InvalidResolver: "ZNIGHT062",
110
+ /**
111
+ * Invalid input position: a type used as input and output, a getter, a union, a cycle of non-null
112
+ * input fields, a default value not matching its type.
113
+ */
114
+ InvalidGraphQLInput: "ZNIGHT063",
115
+ /** The members of a GraphQL union cannot be told apart at runtime. */
116
+ UnresolvableAbstractType: "ZNIGHT064",
117
+ /**
118
+ * Invalid loader: `@Loader()` on a type that is not `Loader<L>`, `L` not a `BatchLoad`; at runtime,
119
+ * a batch function returning another number of values than keys.
120
+ */
121
+ InvalidLoader: "ZNIGHT065",
122
+ /**
123
+ * Invalid GraphQL setup at boot: malformed or version-skewed metadata, invalid schema, invalid
124
+ * `GraphQLPlugin` options, missing `HttpPlugin`, scalar name mismatch.
125
+ */
126
+ InvalidGraphQLSetup: "ZNIGHT066"
101
127
  };
102
128
  /** Short human readable description of every error code. */
103
129
  const ERROR_DESCRIPTIONS = {
@@ -136,7 +162,14 @@ const ERROR_DESCRIPTIONS = {
136
162
  ZNIGHT041: "Duplicate job: two jobs share a name",
137
163
  ZNIGHT042: "Unknown job: no job has this name",
138
164
  ZNIGHT043: "Missing lock store: a job requires a lock but SchedulePlugin has no store",
139
- ZNIGHT044: "Job aborted: a scheduled run was aborted (timeout, lost lock, removal or shutdown)"
165
+ ZNIGHT044: "Job aborted: a scheduled run was aborted (timeout, lost lock, removal or shutdown)",
166
+ ZNIGHT060: "Invalid GraphQL type: a TypeScript type cannot be mapped to a GraphQL type",
167
+ ZNIGHT061: "GraphQL name conflict: two types or root fields share a name, or a name is invalid or reserved",
168
+ ZNIGHT062: "Invalid resolver: the structure of a GraphQL resolver is invalid",
169
+ ZNIGHT063: "Invalid GraphQL input: a type cannot be used in an input position",
170
+ ZNIGHT064: "Unresolvable abstract type: the members of a GraphQL union cannot be told apart at runtime",
171
+ ZNIGHT065: "Invalid loader: not a Loader of a BatchLoad provider, or a batch returning the wrong number of values",
172
+ ZNIGHT066: "Invalid GraphQL setup: metadata, schema, GraphQLPlugin options or HttpPlugin missing"
140
173
  };
141
174
  /** Base class of every error thrown by Znight at runtime. */
142
175
  var ZnightError = class extends Error {