@zudojs/api 1.0.0 → 1.1.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
@@ -2,6 +2,12 @@
2
2
 
3
3
  Higher-level API layer — operation definitions, execution context, interceptors, and a transport-agnostic executor. Sits above `@zudojs/http` and `@zudojs/cqrs`.
4
4
 
5
+ <!-- zudo-docs:start -->
6
+
7
+ **Documentation:** [zudojs.oyinlola.site/docs/packages-api](https://zudojs.oyinlola.site/docs/packages-api) · **For AI agents:** [Markdown version](https://zudojs.oyinlola.site/docs/packages-api.md), [llms.txt](https://zudojs.oyinlola.site/llms.txt)
8
+
9
+ <!-- zudo-docs:end -->
10
+
5
11
  ## When to use
6
12
 
7
13
  Import this when you need:
@@ -78,7 +84,7 @@ import {
78
84
  // 1. Define the operation. The handler is positional: (input, context).
79
85
  const getUser = defineOperation<{ id: string }, { id: string; name: string }>({
80
86
  name: "users.get",
81
- input: GetUserSchema, // any Standard Schema (Zod, Valibot, ArkType, …)
87
+ input: GetUserSchema, // @zudojs/schema, or any Standard Schema (Zod, Valibot, …)
82
88
  output: UserSchema, // validated too — see "Output validation"
83
89
  timeout: 5_000,
84
90
  metadata: { tags: ["Users"] },
@@ -116,7 +122,25 @@ Results are frozen `{ ok: true, data }` / `{ ok: false, error }` objects — `ex
116
122
 
117
123
  ## Input validation
118
124
 
119
- When `operation.input` is a Standard Schema, the executor validates the input before the handler runs and passes the schema's *transformed* value to the handler. Failures return an `APIValidationError` (422).
125
+ The executor accepts two kinds of schema for `input` and `output`, recognised structurally so the package depends on no validation library:
126
+
127
+ - a `@zudojs/schema` schema, or any other schema with a `safeParse` method returning `{ success, data }` / `{ success: false, issues }` (Zod-style `error.issues` also works);
128
+ - a [Standard Schema](https://standardschema.dev) (`"~standard".validate`): Zod, Valibot, ArkType, ….
129
+
130
+ Anything else fails closed. `defineOperation` and `APIOperationRegistry.register` throw a `TypeError` when `input` or `output` is set to a value that is neither, and the executor answers a hand-rolled operation carrying one with an `APIInternalError` (500) without running the handler. A schema is never silently skipped. `isAPISchema(value)` reports whether a value would be accepted.
131
+
132
+ ```typescript
133
+ import { schema } from "@zudojs/schema";
134
+
135
+ const charge = defineOperation({
136
+ name: "payments.charge",
137
+ input: schema.object({ id: schema.string().uuid(), amount: schema.number().min(1) }),
138
+ output: schema.object({ ok: schema.boolean() }), // strips unknown keys
139
+ handler: async (input) => ({ ok: true }),
140
+ });
141
+ ```
142
+
143
+ The executor validates the input before the handler runs and passes the schema's *transformed* value to the handler. Failures return an `APIValidationError` (422).
120
144
 
121
145
  Schema issue messages routinely interpolate the value that failed, so by default the executor does **not** copy them into the client-facing error: each issue becomes `"<path>: invalid"` (e.g. `"user.email: invalid"`), naming where validation failed without echoing what was submitted. The list is capped at `MAX_VALIDATION_ISSUES` entries with a trailing `"… and N more issue(s) omitted."` marker.
122
146
 
@@ -128,7 +152,7 @@ new APIExecutor({ exposeValidationMessages: true, maxValidationIssues: 10 });
128
152
 
129
153
  ## Output validation
130
154
 
131
- When `operation.output` is a Standard Schema, the handler's return value is validated too, and the validated (possibly stripped or transformed) value becomes `result.data`. A mismatch is a server bug, so it fails with an `APIInternalError` (500, `expose: false`) naming only the failing paths.
155
+ When `operation.output` is set, the handler's return value is validated too, and the validated (possibly stripped or transformed) value becomes `result.data`. A mismatch is a server bug, so it fails with an `APIInternalError` (500, `expose: false`) naming only the failing paths.
132
156
 
133
157
  ## Timeouts
134
158
 
@@ -172,7 +196,11 @@ context.metadata; // read-only snapshot keyed by key name
172
196
 
173
197
  ## Errors
174
198
 
175
- `normalizeAPIError(error, operationName?)` converts anything thrown into an `APIError`. Non-API errors become an `APIInternalError` with a generic message and the original on `cause` — the internal message is deliberately not copied onto the wrapper, because `BaseError.toJSON()` serializes `message`, `stack` and `cause` regardless of `expose`.
199
+ `normalizeAPIError(error, operationName?)` converts anything thrown into an `APIError`. Non-API errors become an `APIInternalError` with a generic message and the original on `cause`, so `result.error.message` never carries a driver or library message.
200
+
201
+ `cause` is there for logging, and `BaseError.toJSON()` (the logging form, also used by `JSON.stringify`) serializes it — message and stack included — regardless of `expose`. Do not hand `result.error` to `res.json()` as-is: pick the fields a client may see (`code`, `statusCode`, and `message` only when `expose` is true), or run it through `ErrorSerializer` from `@zudojs/errors`.
202
+
203
+ Handlers are expected to return a promise, but a hand-rolled operation whose handler returns synchronously is executed the same way.
176
204
 
177
205
  ## License
178
206
 
@@ -53,8 +53,10 @@ export interface APIExecutorOptions {
53
53
  * Executes an API operation through its interceptor pipeline.
54
54
  *
55
55
  * Enforces the operation timeout, honors the context AbortSignal, and
56
- * validates input and output when the operation's `input` / `output` is a
57
- * Standard Schema.
56
+ * validates input and output against the operation's `input` / `output`
57
+ * schema (a Standard Schema or a `safeParse` schema such as
58
+ * `@zudojs/schema`). A declared schema of any other kind fails closed
59
+ * with an `APIInternalError`; it is never skipped.
58
60
  */
59
61
  export declare class APIExecutor {
60
62
  private readonly interceptors;
@@ -67,8 +69,7 @@ export declare class APIExecutor {
67
69
  execute<TInput = unknown, TOutput = unknown>(operation: APIOperation<TInput, TOutput>, input: TInput, context: APIContext): Promise<APIResult<TOutput>>;
68
70
  /**
69
71
  * Invokes the operation handler under its timeout and abort signal, and
70
- * validates the handler's output when `operation.output` is a Standard
71
- * Schema.
72
+ * validates the handler's output against `operation.output`.
72
73
  */
73
74
  private invokeHandler;
74
75
  /**
@@ -1,6 +1,7 @@
1
1
  import { apiFailure, apiSuccess } from "../result/apiResult.type.js";
2
2
  import { resolveOperationTimeout } from "../operation/operation.type.js";
3
3
  import { APIError, APIInternalError, APITimeoutError, APIValidationError, createAPIError, ErrorCode, isAPIError, } from "../errors/index.js";
4
+ import { validateWithSchema } from "../schema/index.js";
4
5
  import { MAX_INTERCEPTORS, MAX_VALIDATION_ISSUES, MAX_VALIDATION_ISSUE_LENGTH, } from "../constants.js";
5
6
  /**
6
7
  * Error normalizer for converting unknown errors into APIError instances.
@@ -45,27 +46,14 @@ function describeValueType(value) {
45
46
  }
46
47
  return typeof value;
47
48
  }
48
- function isStandardSchema(value) {
49
- return (typeof value === "object" &&
50
- value !== null &&
51
- typeof value["~standard"]
52
- ?.validate === "function");
53
- }
54
- /**
55
- * A schema result counts as a failure only when it carries at least one
56
- * issue. Some adapters always populate `issues` and return an empty array
57
- * on success; treating that as a failure produces a 422 with an empty
58
- * issue list and no way to learn what was wrong.
59
- */
60
- function hasIssues(result) {
61
- return Array.isArray(result.issues) && result.issues.length > 0;
62
- }
63
49
  /**
64
50
  * Executes an API operation through its interceptor pipeline.
65
51
  *
66
52
  * Enforces the operation timeout, honors the context AbortSignal, and
67
- * validates input and output when the operation's `input` / `output` is a
68
- * Standard Schema.
53
+ * validates input and output against the operation's `input` / `output`
54
+ * schema (a Standard Schema or a `safeParse` schema such as
55
+ * `@zudojs/schema`). A declared schema of any other kind fails closed
56
+ * with an `APIInternalError`; it is never skipped.
69
57
  */
70
58
  export class APIExecutor {
71
59
  interceptors;
@@ -97,10 +85,10 @@ export class APIExecutor {
97
85
  return apiFailure(abortedError(operation.name));
98
86
  }
99
87
  let effectiveInput = input;
100
- if (isStandardSchema(operation.input)) {
88
+ if (operation.input !== undefined) {
101
89
  try {
102
- const validation = await operation.input["~standard"].validate(input);
103
- if (hasIssues(validation)) {
90
+ const validation = await validateWithSchema(operation.input, input);
91
+ if (!validation.ok) {
104
92
  return apiFailure(new APIValidationError(`Invalid input for operation "${operation.name}".`, this.clientIssues(validation.issues)));
105
93
  }
106
94
  effectiveInput = validation.value;
@@ -127,8 +115,7 @@ export class APIExecutor {
127
115
  }
128
116
  /**
129
117
  * Invokes the operation handler under its timeout and abort signal, and
130
- * validates the handler's output when `operation.output` is a Standard
131
- * Schema.
118
+ * validates the handler's output against `operation.output`.
132
119
  */
133
120
  async invokeHandler(operation, input, context) {
134
121
  if (context.signal?.aborted) {
@@ -154,17 +141,17 @@ export class APIExecutor {
154
141
  * internal audit columns) that should not reach a client.
155
142
  */
156
143
  async validateOutput(operation, output) {
157
- if (!isStandardSchema(operation.output)) {
144
+ if (operation.output === undefined) {
158
145
  return apiSuccess(output);
159
146
  }
160
147
  let validation;
161
148
  try {
162
- validation = await operation.output["~standard"].validate(output);
149
+ validation = await validateWithSchema(operation.output, output);
163
150
  }
164
151
  catch (error) {
165
152
  return apiFailure(normalizeAPIError(error, operation.name));
166
153
  }
167
- if (hasIssues(validation)) {
154
+ if (!validation.ok) {
168
155
  const paths = validation.issues
169
156
  .slice(0, this.maxValidationIssues)
170
157
  .map(formatIssuePath)
@@ -288,7 +275,11 @@ function withDeadline(promise, timeoutMs, operationName, signal) {
288
275
  reject(new APITimeoutError(timeoutMs));
289
276
  }, timeoutMs);
290
277
  signal?.addEventListener("abort", onAbort, { once: true });
291
- promise.then((value) => {
278
+ // `Promise.resolve` rather than `promise.then`: a hand-rolled operation
279
+ // whose handler returns synchronously is a legal JavaScript caller, and
280
+ // calling `.then` on its plain value failed with "promise.then is not a
281
+ // function" reported as an internal error of the operation.
282
+ Promise.resolve(promise).then((value) => {
292
283
  cleanup();
293
284
  resolve(value);
294
285
  }, (error) => {
@@ -23,19 +23,21 @@ export interface APIOperationMetadata {
23
23
  export interface APIOperation<TInput = unknown, TOutput = unknown> {
24
24
  readonly name: string;
25
25
  /**
26
- * Input schema. When this is a Standard Schema
27
- * (https://standardschema.dev), the executor validates input against it
28
- * before invoking the handler; other values are documentation-only.
26
+ * Input schema: a Standard Schema (https://standardschema.dev) or a
27
+ * `safeParse` schema such as `@zudojs/schema`. The executor validates
28
+ * input against it before invoking the handler. Any other non-`undefined`
29
+ * value is rejected by {@link defineOperation} and the registry, and
30
+ * fails closed in the executor.
29
31
  */
30
32
  readonly input?: unknown;
31
33
  /**
32
- * Output schema. When this is a Standard Schema
33
- * (https://standardschema.dev), the executor validates the handler's
34
- * return value against it and returns the validated (possibly
35
- * transformed) value as the result data; a handler returning the wrong
34
+ * Output schema: a Standard Schema or a `safeParse` schema such as
35
+ * `@zudojs/schema`. The executor validates the handler's return value
36
+ * against it and returns the validated (possibly transformed or
37
+ * stripped) value as the result data; a handler returning the wrong
36
38
  * shape fails with an `APIInternalError` (`expose: false`) rather than
37
- * leaking through to the transport. Other values are
38
- * documentation-only.
39
+ * leaking through to the transport. Any other non-`undefined` value is
40
+ * rejected, exactly like {@link APIOperation.input}.
39
41
  */
40
42
  readonly output?: unknown;
41
43
  readonly handler: APIHandler<TInput, TOutput>;
@@ -105,13 +107,16 @@ export declare function resolveOperationTimeout(source: {
105
107
  * `APIOperationRegistry.register`, since `APIOperation` is a bare
106
108
  * interface that callers can satisfy without `defineOperation`.
107
109
  *
108
- * @throws {TypeError} if `name` or `handler` has the wrong type.
110
+ * @throws {TypeError} if `name` or `handler` has the wrong type, or if
111
+ * `input` / `output` is set but is not a recognised schema.
109
112
  * @throws {RangeError} if `name` is empty, over-long, or contains
110
113
  * characters outside `[A-Za-z0-9._:/-]`.
111
114
  */
112
115
  export declare function assertValidOperationShape(operation: {
113
116
  readonly name?: unknown;
114
117
  readonly handler?: unknown;
118
+ readonly input?: unknown;
119
+ readonly output?: unknown;
115
120
  }): void;
116
121
  /**
117
122
  * Deeply freezes an operation's metadata so a registered operation cannot
@@ -125,7 +130,8 @@ export declare function freezeOperationMetadata(metadata: APIOperationMetadata |
125
130
  * unusable timeout fails here, at startup, rather than on the first
126
131
  * request that reaches the operation.
127
132
  *
128
- * @throws {TypeError} if `name` or `handler` has the wrong type.
133
+ * @throws {TypeError} if `name` or `handler` has the wrong type, or if
134
+ * `input` / `output` is set but is not a recognised schema.
129
135
  * @throws {RangeError} if `name` or a supplied `timeout` is out of range.
130
136
  */
131
137
  export declare function defineOperation<TInput = unknown, TOutput = unknown>(options: DefineOperationOptions<TInput, TOutput>): APIOperation<TInput, TOutput>;
@@ -1,3 +1,4 @@
1
+ import { assertAPISchema } from "../schema/index.js";
1
2
  import { DEFAULT_OPERATION_TIMEOUT, MAX_OPERATION_NAME_LENGTH, MAX_OPERATION_TIMEOUT, } from "../constants.js";
2
3
  const OPERATION_NAME_PATTERN = /^[A-Za-z0-9._:/-]+$/;
3
4
  /**
@@ -56,7 +57,8 @@ export function resolveOperationTimeout(source) {
56
57
  * `APIOperationRegistry.register`, since `APIOperation` is a bare
57
58
  * interface that callers can satisfy without `defineOperation`.
58
59
  *
59
- * @throws {TypeError} if `name` or `handler` has the wrong type.
60
+ * @throws {TypeError} if `name` or `handler` has the wrong type, or if
61
+ * `input` / `output` is set but is not a recognised schema.
60
62
  * @throws {RangeError} if `name` is empty, over-long, or contains
61
63
  * characters outside `[A-Za-z0-9._:/-]`.
62
64
  */
@@ -77,6 +79,8 @@ export function assertValidOperationShape(operation) {
77
79
  if (typeof handler !== "function") {
78
80
  throw new TypeError(`Operation "${name}" must have a handler function, received ${typeof handler}.`);
79
81
  }
82
+ assertAPISchema(operation.input, "input", name);
83
+ assertAPISchema(operation.output, "output", name);
80
84
  }
81
85
  /**
82
86
  * Deeply freezes an operation's metadata so a registered operation cannot
@@ -98,7 +102,8 @@ export function freezeOperationMetadata(metadata) {
98
102
  * unusable timeout fails here, at startup, rather than on the first
99
103
  * request that reaches the operation.
100
104
  *
101
- * @throws {TypeError} if `name` or `handler` has the wrong type.
105
+ * @throws {TypeError} if `name` or `handler` has the wrong type, or if
106
+ * `input` / `output` is set but is not a recognised schema.
102
107
  * @throws {RangeError} if `name` or a supplied `timeout` is out of range.
103
108
  */
104
109
  export function defineOperation(options) {
@@ -19,7 +19,7 @@ export declare class APIOperationRegistry {
19
19
  *
20
20
  * @throws {APIDuplicateOperationError} if an operation with the same name is already registered.
21
21
  * @throws {APIError} if the registry is frozen.
22
- * @throws {TypeError | RangeError} if the operation's name or handler is invalid.
22
+ * @throws {TypeError | RangeError} if the operation's name, handler, or input/output schema is invalid.
23
23
  */
24
24
  register(operation: AnyAPIOperation): void;
25
25
  /**
@@ -20,7 +20,7 @@ export class APIOperationRegistry {
20
20
  *
21
21
  * @throws {APIDuplicateOperationError} if an operation with the same name is already registered.
22
22
  * @throws {APIError} if the registry is frozen.
23
- * @throws {TypeError | RangeError} if the operation's name or handler is invalid.
23
+ * @throws {TypeError | RangeError} if the operation's name, handler, or input/output schema is invalid.
24
24
  */
25
25
  register(operation) {
26
26
  if (this.frozen) {
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Schema recognition and validation for operation `input` / `output`.
3
+ *
4
+ * Two contracts are recognised structurally, so the package depends on no
5
+ * particular validation library:
6
+ *
7
+ * 1. Standard Schema (https://standardschema.dev): a `"~standard"` object
8
+ * with a `validate` function (Zod, Valibot, ArkType, …).
9
+ * 2. A `safeParse` schema returning `{ success, data }` /
10
+ * `{ success: false, issues }` (`@zudojs/schema`) or
11
+ * `{ success: false, error: { issues } }` (Zod-style).
12
+ *
13
+ * Anything else is *unrecognised*. The executor fails closed on an
14
+ * unrecognised schema rather than treating it as documentation, because a
15
+ * schema that is silently skipped validates nothing.
16
+ */
17
+ type IssuePathSegment = PropertyKey | {
18
+ readonly key: PropertyKey;
19
+ };
20
+ /** A validation issue normalised from either supported contract. */
21
+ export interface APISchemaIssue {
22
+ readonly message: string;
23
+ readonly path?: ReadonlyArray<IssuePathSegment>;
24
+ }
25
+ /** Normalised validation outcome. */
26
+ export type APISchemaResult = {
27
+ readonly ok: true;
28
+ readonly value: unknown;
29
+ } | {
30
+ readonly ok: false;
31
+ readonly issues: ReadonlyArray<APISchemaIssue>;
32
+ };
33
+ /**
34
+ * Whether `value` is a schema the executor can validate against.
35
+ *
36
+ * `undefined` (no schema declared) is not a schema; callers treat it as
37
+ * "nothing to validate" and must reject every other unrecognised value.
38
+ */
39
+ export declare function isAPISchema(value: unknown): boolean;
40
+ /**
41
+ * Throws when `schema` is declared but is not a recognised schema.
42
+ *
43
+ * @throws {TypeError} naming the operation and the offending field.
44
+ */
45
+ export declare function assertAPISchema(schema: unknown, field: "input" | "output", operationName: string): void;
46
+ /**
47
+ * Validates `value` against a recognised schema.
48
+ *
49
+ * Fails closed: an unrecognised schema, or a result in an unexpected
50
+ * shape, throws rather than letting the value through.
51
+ *
52
+ * @throws {TypeError} for an unrecognised schema or malformed result.
53
+ */
54
+ export declare function validateWithSchema(schema: unknown, value: unknown): Promise<APISchemaResult>;
55
+ export {};
56
+ //# sourceMappingURL=apiSchema.adapter.d.ts.map
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Schema recognition and validation for operation `input` / `output`.
3
+ *
4
+ * Two contracts are recognised structurally, so the package depends on no
5
+ * particular validation library:
6
+ *
7
+ * 1. Standard Schema (https://standardschema.dev): a `"~standard"` object
8
+ * with a `validate` function (Zod, Valibot, ArkType, …).
9
+ * 2. A `safeParse` schema returning `{ success, data }` /
10
+ * `{ success: false, issues }` (`@zudojs/schema`) or
11
+ * `{ success: false, error: { issues } }` (Zod-style).
12
+ *
13
+ * Anything else is *unrecognised*. The executor fails closed on an
14
+ * unrecognised schema rather than treating it as documentation, because a
15
+ * schema that is silently skipped validates nothing.
16
+ */
17
+ function isStandardSchema(value) {
18
+ if (typeof value !== "object" && typeof value !== "function")
19
+ return false;
20
+ if (value === null)
21
+ return false;
22
+ const standard = value["~standard"];
23
+ return typeof standard?.validate === "function";
24
+ }
25
+ function isSafeParseSchema(value) {
26
+ if (typeof value !== "object" && typeof value !== "function")
27
+ return false;
28
+ if (value === null)
29
+ return false;
30
+ return typeof value.safeParse === "function";
31
+ }
32
+ /**
33
+ * Whether `value` is a schema the executor can validate against.
34
+ *
35
+ * `undefined` (no schema declared) is not a schema; callers treat it as
36
+ * "nothing to validate" and must reject every other unrecognised value.
37
+ */
38
+ export function isAPISchema(value) {
39
+ return isStandardSchema(value) || isSafeParseSchema(value);
40
+ }
41
+ /**
42
+ * Throws when `schema` is declared but is not a recognised schema.
43
+ *
44
+ * @throws {TypeError} naming the operation and the offending field.
45
+ */
46
+ export function assertAPISchema(schema, field, operationName) {
47
+ if (schema === undefined || isAPISchema(schema))
48
+ return;
49
+ throw new TypeError(`Operation "${operationName}" declares an ${field} schema that is neither a Standard Schema ("~standard".validate) nor a safeParse schema; refusing to run it unvalidated.`);
50
+ }
51
+ const MALFORMED = "Schema returned a result in an unrecognised shape.";
52
+ function isRecord(value) {
53
+ return typeof value === "object" && value !== null;
54
+ }
55
+ function toIssues(raw) {
56
+ if (!Array.isArray(raw) || raw.length === 0) {
57
+ return [{ message: "Validation failed without a recorded issue." }];
58
+ }
59
+ return raw.map((issue) => {
60
+ const record = isRecord(issue) ? issue : {};
61
+ const path = Array.isArray(record["path"])
62
+ ? record["path"]
63
+ : undefined;
64
+ const message = typeof record["message"] === "string" ? record["message"] : "invalid";
65
+ return path === undefined ? { message } : { message, path };
66
+ });
67
+ }
68
+ function fromStandard(result) {
69
+ if (!isRecord(result))
70
+ throw new TypeError(MALFORMED);
71
+ const issues = result["issues"];
72
+ if (Array.isArray(issues) && issues.length > 0) {
73
+ return { ok: false, issues: toIssues(issues) };
74
+ }
75
+ if (!("value" in result))
76
+ throw new TypeError(MALFORMED);
77
+ return { ok: true, value: result["value"] };
78
+ }
79
+ function fromSafeParse(result) {
80
+ if (!isRecord(result))
81
+ throw new TypeError(MALFORMED);
82
+ if (result["success"] === true) {
83
+ return { ok: true, value: result["data"] };
84
+ }
85
+ if (result["success"] === false) {
86
+ const error = result["error"];
87
+ const issues = result["issues"] ?? (isRecord(error) ? error["issues"] : undefined);
88
+ return { ok: false, issues: toIssues(issues) };
89
+ }
90
+ throw new TypeError(MALFORMED);
91
+ }
92
+ /**
93
+ * Validates `value` against a recognised schema.
94
+ *
95
+ * Fails closed: an unrecognised schema, or a result in an unexpected
96
+ * shape, throws rather than letting the value through.
97
+ *
98
+ * @throws {TypeError} for an unrecognised schema or malformed result.
99
+ */
100
+ export async function validateWithSchema(schema, value) {
101
+ if (isStandardSchema(schema)) {
102
+ return fromStandard(await schema["~standard"].validate(value));
103
+ }
104
+ if (isSafeParseSchema(schema)) {
105
+ return fromSafeParse(await schema.safeParse(value));
106
+ }
107
+ throw new TypeError("Unrecognised schema: refusing to validate.");
108
+ }
109
+ //# sourceMappingURL=apiSchema.adapter.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @zudojs/api/schema
3
+ *
4
+ * Structural recognition of operation schemas (Standard Schema and
5
+ * `safeParse` schemas such as `@zudojs/schema`) and fail-closed validation.
6
+ */
7
+ export { assertAPISchema, isAPISchema, validateWithSchema, } from "./apiSchema.adapter.js";
8
+ export type { APISchemaIssue, APISchemaResult } from "./apiSchema.adapter.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @zudojs/api/schema
3
+ *
4
+ * Structural recognition of operation schemas (Standard Schema and
5
+ * `safeParse` schemas such as `@zudojs/schema`) and fail-closed validation.
6
+ */
7
+ export { assertAPISchema, isAPISchema, validateWithSchema, } from "./apiSchema.adapter.js";
8
+ //# sourceMappingURL=index.js.map
package/dist/index.d.ts CHANGED
@@ -17,7 +17,7 @@
17
17
  *
18
18
  * const getUser = defineOperation({
19
19
  * name: "users.get",
20
- * input: GetUserSchema, // any Standard Schema (Zod, Valibot, ArkType, …)
20
+ * input: GetUserSchema, // @zudojs/schema, or any Standard Schema (Zod, Valibot, …)
21
21
  * output: UserSchema,
22
22
  * handler: async (input, context) => userService.findById(input.id),
23
23
  * });
@@ -44,6 +44,8 @@ export { createAPIContext, createContextKey, isValidRequestId, normalizeRequestI
44
44
  export type { APIHandler } from "./api/handler/handler.type.js";
45
45
  export type { AnyAPIOperation, APIOperation, APIOperationMetadata, DefineOperationOptions, } from "./api/operation/operation.type.js";
46
46
  export { defineOperation, resolveOperationTimeout, } from "./api/operation/operation.type.js";
47
+ export type { APISchemaIssue, APISchemaResult } from "./api/schema/index.js";
48
+ export { isAPISchema } from "./api/schema/index.js";
47
49
  export { APIOperationRegistry } from "./api/registry/index.js";
48
50
  export type { APIInterceptor, APIExecutionContext, } from "./api/interceptors/interceptor.type.js";
49
51
  export { createNoopInterceptor } from "./api/interceptors/interceptor.type.js";
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@
17
17
  *
18
18
  * const getUser = defineOperation({
19
19
  * name: "users.get",
20
- * input: GetUserSchema, // any Standard Schema (Zod, Valibot, ArkType, …)
20
+ * input: GetUserSchema, // @zudojs/schema, or any Standard Schema (Zod, Valibot, …)
21
21
  * output: UserSchema,
22
22
  * handler: async (input, context) => userService.findById(input.id),
23
23
  * });
@@ -40,6 +40,7 @@ export { APIError, APIValidationError, APIAuthenticationError, APIAuthorizationE
40
40
  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";
41
41
  export { createAPIContext, createContextKey, isValidRequestId, normalizeRequestId, RequestIdContextKey, CorrelationIdContextKey, TenantIdContextKey, UserIdContextKey, StartTimeContextKey, } from "./api/context/context.type.js";
42
42
  export { defineOperation, resolveOperationTimeout, } from "./api/operation/operation.type.js";
43
+ export { isAPISchema } from "./api/schema/index.js";
43
44
  // Registry
44
45
  export { APIOperationRegistry } from "./api/registry/index.js";
45
46
  export { createNoopInterceptor } from "./api/interceptors/interceptor.type.js";
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@zudojs/api",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Application-facing API layer for Zudojs — operation definitions, execution context, interceptors, and transport-agnostic contracts.",
5
5
  "license": "MIT",
6
+ "author": {
7
+ "name": "Oluwayemi Oyinlola",
8
+ "url": "https://github.com/oyinlola-tech"
9
+ },
6
10
  "type": "module",
7
11
  "main": "./dist/index.js",
8
12
  "module": "./dist/index.js",
@@ -23,12 +27,10 @@
23
27
  "node": ">=24.0.0"
24
28
  },
25
29
  "dependencies": {
26
- "@zudojs/errors": "1.0.0",
27
- "@zudojs/constants": "1.0.0",
28
- "@zudojs/types": "1.0.0",
29
- "@zudojs/schema": "1.0.0"
30
+ "@zudojs/errors": "1.1.0"
30
31
  },
31
32
  "devDependencies": {
33
+ "@zudojs/schema": "1.1.0",
32
34
  "typescript": "7.0.2",
33
35
  "vitest": "^4.1.11"
34
36
  },