|
1 | 1 | /** |
2 | | - * @fileoverview Universal schema validation — works with TypeBox, Zod (v3 and |
3 | | - * v4), and any Zod-shaped `Schema<T>` duck type. |
| 2 | + * @fileoverview Universal schema validation for Zod-style schemas (Zod v3, |
| 3 | + * v4, and any `safeParse`-shaped duck type). |
4 | 4 | * |
5 | | - * Accepts any supported schema kind and returns a tagged result. |
| 5 | + * Accepts a schema and returns a tagged result. |
6 | 6 | * - `{ ok: true, value }` — validation passed, `value` is typed as the |
7 | | - * schema's inferred output. |
| 7 | + * schema's inferred output (`z.infer<typeof S>`). |
8 | 8 | * - `{ ok: false, errors }` — validation failed, `errors` is a normalized |
9 | | - * list of `{ path, message }` regardless of which validator produced them. |
| 9 | + * list of `{ path, message }`. |
10 | 10 | * |
11 | | - * Types flow through: `validateSchema(ZodSchema, data)` returns |
12 | | - * `{ ok: true, value: z.infer<typeof ZodSchema> } | { ok: false, errors: ... }`. |
13 | | - * `validateSchema(TypeBoxSchema, data)` returns the equivalent using |
14 | | - * `Static<typeof TypeBoxSchema>`. Zod is detected purely structurally via |
15 | | - * `.safeParse` — no runtime import. TypeBox validation lazy-loads the |
16 | | - * bundled `@sinclair/typebox/value` runtime from `src/external/`. |
| 11 | + * Zod is detected purely structurally via `.safeParse` — no runtime import of |
| 12 | + * the `zod` package is required by socket-lib. |
| 13 | + * |
| 14 | + * @internal |
| 15 | + * Socket-lib additionally recognizes TypeBox schemas for its own internal |
| 16 | + * use (e.g. `src/ipc.ts`'s stub-file validation). That path is not a |
| 17 | + * supported consumer API — callers should use Zod. |
17 | 18 | */ |
18 | 19 |
|
19 | 20 | import type { ParseResult, Schema } from './types' |
@@ -158,45 +159,35 @@ function normalizeZodError(err: unknown): ValidationIssue[] { |
158 | 159 | } |
159 | 160 |
|
160 | 161 | /** |
161 | | - * Validate `data` against any supported `schema` kind. Non-throwing. |
| 162 | + * Validate `data` against a Zod-style `schema`. Non-throwing. |
162 | 163 | * |
163 | | - * Supported schema kinds: |
164 | | - * - `@sinclair/typebox` schemas (detected via the `Kind` symbol) |
| 164 | + * Accepted schemas: |
165 | 165 | * - `zod` schemas, v3 and v4 (detected via `.safeParse` on the schema) |
166 | 166 | * - Any object conforming to {@link Schema} (the socket-lib duck type) |
167 | 167 | * |
168 | | - * The return type narrows `value` to {@link Infer | `Infer<S>`}, so Zod users |
169 | | - * get `z.infer<typeof S>` and TypeBox users get `Static<typeof S>` with no |
170 | | - * casts. |
| 168 | + * The return type narrows `value` to {@link Infer | `Infer<S>`}, so callers |
| 169 | + * get `z.infer<typeof S>` with no casts. |
171 | 170 | * |
172 | 171 | * @example |
173 | 172 | * ```ts |
174 | | - * // Zod |
175 | 173 | * import { z } from 'zod' |
176 | 174 | * const U = z.object({ name: z.string() }) |
177 | 175 | * const r = validateSchema(U, data) |
178 | 176 | * if (r.ok) r.value.name // string |
179 | | - * |
180 | | - * // TypeBox |
181 | | - * import { Type } from '@sinclair/typebox' |
182 | | - * const U = Type.Object({ name: Type.String() }) |
183 | | - * const r = validateSchema(U, data) |
184 | | - * if (r.ok) r.value.name // string |
185 | 177 | * ``` |
186 | 178 | * |
187 | 179 | * Errors are normalized to {@link ValidationIssue}: `{ path, message }`. |
188 | | - * TypeBox JSON-Pointer paths are converted to arrays. Numeric segments are |
189 | | - * parsed as numbers. |
190 | 180 | */ |
191 | 181 | export function validateSchema<S>( |
192 | 182 | schema: S, |
193 | 183 | data: unknown, |
194 | 184 | ): ValidateResult<Infer<S>> { |
195 | | - // TypeBox path: check the structural `[Kind]: string` marker. |
| 185 | + // Internal TypeBox path: socket-lib uses TypeBox schemas in a few |
| 186 | + // places (e.g. src/ipc.ts), detected here via the structural |
| 187 | + // `[Kind]: string` marker. Not a supported consumer API — external |
| 188 | + // callers should use Zod. The runtime is loaded lazily from the |
| 189 | + // bundled external under `src/external/` so consumers never see it. |
196 | 190 | if (isTypeBoxSchema(schema)) { |
197 | | - // TypeBox's Value runtime is bundled into socket-lib's dist/external, |
198 | | - // so consumers don't need to install @sinclair/typebox separately — |
199 | | - // they get Value.Check + Value.Errors from our vendored copy. |
200 | 191 | // eslint-disable-next-line @typescript-eslint/no-require-imports |
201 | 192 | const { Value } = require('../external/@sinclair/typebox/value') as { |
202 | 193 | Value: { |
|
0 commit comments