@zudojs/api 1.2.1 → 1.2.3

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
@@ -59,6 +59,7 @@ import {
59
59
  type APIExecutionContext,
60
60
  type APIExecutorOptions,
61
61
  type APIHandler,
62
+ type APIHandlerContext,
62
63
  type APIInterceptor,
63
64
  type APIOperation,
64
65
  type APIOperationMetadata,
@@ -308,6 +309,8 @@ Every operation has a deadline. `timeout` must be a positive, finite integer of
308
309
 
309
310
  The handler always receives a `context.signal`, even when the caller supplied none. It aborts when the deadline elapses (its `reason` is the `APITimeoutError` the call fails with, 504) or when the caller's signal aborts (its `reason` is the `ErrorCode.OPERATION_CANCELLED` error the call fails with), so pass it into anything that supports it (`fetch`, a driver query, a loop check) and the work stops instead of running on and repeating side effects after the caller has given up. The signal is not aborted when the handler completes normally. Everything else on the handler's context (`requestId`, `state`, `get`/`set`, `metadata`) is the caller's context. Branch on `ErrorCode.OPERATION_CANCELLED` rather than on the (nginx-convention) 499 status.
310
311
 
312
+ The type says so too: a handler's context is `APIHandlerContext` (`APIContext & { readonly signal: AbortSignal }`), so `context.signal` needs no `!` under strict TypeScript. Only the handler's view is narrowed; a context you build with `createAPIContext` and pass to `executor.execute(op, input, context)` may still omit the signal, and a handler annotated with the plain `APIContext` is still accepted.
313
+
311
314
  ```typescript
312
315
  const exportReport = defineOperation({
313
316
  name: "reports.export",
@@ -341,7 +344,7 @@ At most `MAX_INTERCEPTORS` interceptors per executor, and each `next()` may be a
341
344
 
342
345
  ## Context
343
346
 
344
- `APIContext` carries the request id, an optional `AbortSignal`, caller state, and typed key/value slots. Keys carry their own identity, so two keys created with the same name never collide:
347
+ `APIContext` carries the request id, an optional `AbortSignal` (always present on the handler's `APIHandlerContext`), caller state, and typed key/value slots. Keys carry their own identity, so two keys created with the same name never collide:
345
348
 
346
349
  ```typescript
347
350
  const FeatureFlagsKey = createContextKey<readonly string[]>("featureFlags");
@@ -1,4 +1,5 @@
1
1
  import type { APIContext } from "../context/context.type.js";
2
+ import type { APIHandlerContext } from "../handler/handler.type.js";
2
3
  import type { APIError } from "../errors/index.js";
3
4
  /**
4
5
  * Error for an execution cancelled by the caller's `AbortSignal`.
@@ -19,7 +20,7 @@ export declare function abortedError(operationName: string): APIError;
19
20
  * is visible to the handler and vice versa, and any extra members of a
20
21
  * hand-rolled context are reachable through the prototype chain.
21
22
  */
22
- export declare function withContextSignal(context: APIContext, signal: AbortSignal): APIContext;
23
+ export declare function withContextSignal(context: APIContext, signal: AbortSignal): APIHandlerContext;
23
24
  /**
24
25
  * Runs `run` under a deadline and the caller's abort signal.
25
26
  *
@@ -1,4 +1,16 @@
1
1
  import type { APIContext } from "../context/context.type.js";
2
+ /**
3
+ * The context an operation handler receives.
4
+ *
5
+ * The caller's {@link APIContext} with a non-optional `signal`: the
6
+ * executor always derives one, which aborts when the operation's deadline
7
+ * elapses or the caller's own signal aborts, even when the caller passed
8
+ * no signal. Contexts built by callers (`createAPIContext`,
9
+ * `executor.execute(op, input, context)`) may still omit it.
10
+ */
11
+ export type APIHandlerContext<TState = unknown> = APIContext<TState> & {
12
+ readonly signal: AbortSignal;
13
+ };
2
14
  /**
3
15
  * Handler for an API operation.
4
16
  *
@@ -8,8 +20,8 @@ import type { APIContext } from "../context/context.type.js";
8
20
  * validated value; without one, input is passed through as-is and the
9
21
  * handler must validate it itself.
10
22
  *
11
- * `context.signal` aborts when the operation's deadline elapses or the
12
- * caller aborts; pass it to anything cancellable.
23
+ * `context.signal` is always present. It aborts when the operation's
24
+ * deadline elapses or the caller aborts; pass it to anything cancellable.
13
25
  */
14
- export type APIHandler<TInput = unknown, TOutput = unknown> = (input: TInput, context: APIContext) => Promise<TOutput>;
26
+ export type APIHandler<TInput = unknown, TOutput = unknown> = (input: TInput, context: APIHandlerContext) => Promise<TOutput>;
15
27
  //# sourceMappingURL=handler.type.d.ts.map
package/dist/index.d.ts CHANGED
@@ -43,7 +43,7 @@ export { APIError, APIValidationError, APIAuthenticationError, APIAuthorizationE
43
43
  export { DEFAULT_OPERATION_TIMEOUT, MAX_OPERATION_TIMEOUT, MAX_INTERCEPTORS, MAX_VALIDATION_ISSUES, MAX_VALIDATION_ISSUE_LENGTH, MAX_OPERATION_NAME_LENGTH, MAX_REQUEST_ID_LENGTH, } from "./api/constants.js";
44
44
  export type { APIContext, APIContextKey, APITransportKind, } from "./api/context/context.type.js";
45
45
  export { createAPIContext, createContextKey, isValidRequestId, normalizeRequestId, RequestIdContextKey, CorrelationIdContextKey, TenantIdContextKey, UserIdContextKey, StartTimeContextKey, TransportContextKey, } from "./api/context/context.type.js";
46
- export type { APIHandler } from "./api/handler/handler.type.js";
46
+ export type { APIHandler, APIHandlerContext, } from "./api/handler/handler.type.js";
47
47
  export type { AnyAPIOperation, APIOperation, APIOperationMetadata, DefineOperationOptions, } from "./api/operation/operation.type.js";
48
48
  export { defineOperation, resolveOperationTimeout, } from "./api/operation/operation.type.js";
49
49
  export type { APIInputSchema, DefineOperationWithSchemaOptions, InferAPISchemaOutput, } from "./api/operation/operationSchema.type.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zudojs/api",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "description": "Application-facing API layer for Zudojs — operation definitions, execution context, interceptors, and transport-agnostic contracts.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -27,13 +27,13 @@
27
27
  "node": ">=24.0.0"
28
28
  },
29
29
  "dependencies": {
30
- "@zudojs/errors": "1.3.0",
31
- "@zudojs/openapi": "1.5.0",
32
- "@zudojs/queue": "1.4.1",
33
- "@zudojs/rpc": "1.4.1",
34
- "@zudojs/schema": "1.2.1",
35
- "@zudojs/security": "1.3.1",
36
- "@zudojs/serialization": "1.2.1",
30
+ "@zudojs/errors": "1.3.2",
31
+ "@zudojs/openapi": "1.5.2",
32
+ "@zudojs/queue": "1.5.1",
33
+ "@zudojs/rpc": "1.4.3",
34
+ "@zudojs/schema": "1.2.3",
35
+ "@zudojs/security": "1.3.3",
36
+ "@zudojs/serialization": "1.2.3",
37
37
  "@zudojs/types": "1.2.0"
38
38
  },
39
39
  "devDependencies": {