docs: update portal for WRNexusJS 0.8.0
This commit is contained in:
@@ -10,12 +10,25 @@ page wrnexusvalidation {
|
||||
<header class="topbar">
|
||||
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
|
||||
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
|
||||
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.7.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
|
||||
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.8.0</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
|
||||
</header>
|
||||
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
|
||||
<main class="portal-main docs-layout">
|
||||
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/validation</span></nav><section class="doc-intro"><span class="eyebrow">Security · Package reference</span><h1>@wrnexus/validation</h1><p>Typed schemas, coercion, validation, and browser descriptors.</p><div class="doc-meta"><span>v0.7.0</span><span>Private registry</span><span>Security</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/validation@0.7.0</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><blockquote>One fluent schema, validated on the server (API bodies, env vars) and mirrored to an eval-free browser validator for forms.</blockquote>
|
||||
<article id="main" class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/validation</span></nav><section class="doc-intro"><span class="eyebrow">Security · Package reference</span><h1>@wrnexus/validation</h1><p>Typed schemas, coercion, validation, and browser descriptors.</p><div class="doc-meta"><span>v0.8.0</span><span>Private registry</span><span>Security</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/validation@0.8.0</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><blockquote>One fluent schema, validated on the server (API bodies, env vars) and mirrored to an eval-free browser validator for forms.</blockquote>
|
||||
<p>Part of the <strong>WRNexusJS</strong> framework — an SSR-first, Bun-native full-stack web framework.</p>
|
||||
<h3 id="boundary-contracts">Boundary contracts</h3>
|
||||
<p>Use <code>ContractRegistry</code> with <code>defineContract</code> or <code>defineEvent</code> to publish the same schema descriptors for APIs, actions, webhooks, realtime, queues, cron, pub/sub, plugins, configuration, and environment variables.</p>
|
||||
<pre data-language="ts"><code>import { ContractRegistry, defineEvent, v } from "@wrnexus/validation";
|
||||
|
||||
export const contracts = new ContractRegistry().register(
|
||||
defineEvent({
|
||||
name: "user.created",
|
||||
version: 1,
|
||||
consumers: ["notification-worker", "audit-service"],
|
||||
payload: v.object({ userId: v.string().uuid(), createdAt: v.string().date() }),
|
||||
}),
|
||||
);</code></pre>
|
||||
<p>Export the registry from <code>app/contracts.ts</code>, then accept a baseline with <code>wrnexus contracts snapshot</code>. CI can run <code>wrnexus contracts check</code>; removed contracts/fields, required-field additions, type changes, narrowed enums, and tighter validation fail with stable <code>WRN-CONTRACT-*</code> diagnostics and list known consumers. A generated <code>wrnexus.contracts.json</code> can be used instead of a module.</p>
|
||||
<h3 id="overview">Overview</h3>
|
||||
<p>Define a schema once with the fluent <code>v</code> builder, then reuse it in three places: <code>.parse()</code> runs server-side and returns coerced values plus per-field errors; <code>.describe()</code> emits a plain-JSON <code>SchemaDescriptor</code> that the browser runtime interprets (no <code>eval</code>, no bundled validator); and helpers like <code>parseBody</code> and <code>parseEnv</code> wire schemas straight into API routes and startup config. The server rule logic (<code>applyRule</code>/<code>checkField</code>) and the client runtime (<code>VALIDATE_RUNTIME</code>) mirror each other exactly, so a form validates identically in both places. Schemas are conventionally kept in <code>app/schemas/</code>.</p>
|
||||
<pre data-language="bash"><code>bun add @wrnexus/validation</code></pre>
|
||||
@@ -128,7 +141,46 @@ const head = `<script>${renderSchemasScript({ signup: signupSche
|
||||
<li>Refinements (<code>refine</code>) run only server-side and are never serialized — client and server agree on every other rule because both interpret the same <code>RuleDescriptor</code> list.</li>
|
||||
<li>No runtime dependencies. Ships as TypeScript source (<code>src/index.ts</code>) executed directly by Bun.</li>
|
||||
<li>Pairs with the WRNexusJS server (<code>@wrnexus/core</code>) for route handlers and the SSR layer that injects <code>renderSchemasScript</code> / <code>VALIDATE_RUNTIME</code>.</li>
|
||||
</ul></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>/**
|
||||
</ul>
|
||||
<h3 id="helper-and-component-kit">Helper and component kit</h3>
|
||||
<p>The public helper API includes <code>parseOrThrow</code>, <code>ValidationError</code>, <code>validationResponse</code>, <code>firstValidationError</code>, <code>validationSummary</code>, and <code>schemaFieldNames</code>.</p>
|
||||
<p>Schema output is inferred automatically by <code>ObjectSchema</code>, <code>parseOrThrow</code>, <code>parseBody</code>, <code>parseEnv</code>, and <code>asyncSchema</code>. Use <code>InferSchema<typeof schema></code> when a named output type is useful:</p>
|
||||
<pre data-language="ts"><code>const accountSchema = v.object({
|
||||
email: v.string().email(),
|
||||
attempts: v.number().integer(),
|
||||
});
|
||||
|
||||
type AccountInput = InferSchema<typeof accountSchema>;
|
||||
const account = parseOrThrow(accountSchema, input);
|
||||
// account.email: string
|
||||
// account.attempts: number</code></pre>
|
||||
<p>Enable <code>validationPlugin()</code> for:</p>
|
||||
<ul>
|
||||
<li><code><ValidationSummary /></code></li>
|
||||
<li><code><FieldError /></code></li>
|
||||
</ul>
|
||||
<p>The summary block composes <code>Alert</code> from <code>@wrnexus/ui</code>, while <code>FieldError</code> remains a lightweight accessible field-level primitive. Schemas can drive external contracts without maintaining a second definition:</p>
|
||||
<pre data-language="ts"><code>import {
|
||||
localizeDescriptor,
|
||||
openApiRequestBody,
|
||||
parseDescriptor,
|
||||
toJsonSchema,
|
||||
} from "@wrnexus/validation";
|
||||
|
||||
const jsonSchema = toJsonSchema(contactSchema, {
|
||||
id: "urn:example:contact",
|
||||
title: "Contact request",
|
||||
});
|
||||
const requestBody = openApiRequestBody(contactSchema);
|
||||
|
||||
const mr = localizeDescriptor(contactSchema, (key, params) =>
|
||||
translations.t(`validation.${key}`, params),
|
||||
);
|
||||
const result = parseDescriptor(mr, input);</code></pre>
|
||||
<p>JSON Schema output targets draft 2020-12, closes unknown object properties, and maps lengths/ranges/formats/enums/patterns/integer rules. OpenAPI request bodies reuse the same properties. Localized descriptors preserve explicit custom messages and fill default required, type-coercion, and rule messages; the same descriptor is consumable by server parsing and the eval-free browser runtime.</p></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>export { ValidationPluginOptions, validationComponentsDir, default as validationPlugin } from './plugin.js';
|
||||
import '@wrnexus/plugin';
|
||||
|
||||
/**
|
||||
* Client-side validation. `renderSchemasScript` bakes the discovered schema
|
||||
* descriptors into `window.__wireSchemas`; `VALIDATE_RUNTIME` is a generic,
|
||||
* eval-free validator that reads them and validates every `form[data-schema]`
|
||||
@@ -146,16 +198,16 @@ interface AsyncValidationContext<T> {
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
type AsyncRefinement<T> = (context: AsyncValidationContext<T>) => void | Promise<void>;
|
||||
declare class AsyncObjectSchema<T extends Record<string, unknown> = Record<string, unknown>> {
|
||||
declare class AsyncObjectSchema<T extends object = Record<string, unknown>> {
|
||||
#private;
|
||||
readonly base: ObjectSchema;
|
||||
constructor(base: ObjectSchema);
|
||||
readonly base: ObjectSchema<T>;
|
||||
constructor(base: ObjectSchema<T>);
|
||||
refine(refinement: AsyncRefinement<T>): this;
|
||||
describe(): SchemaDescriptor;
|
||||
parse(input: unknown, signal?: AbortSignal): Promise<ParseResult<T>>;
|
||||
}
|
||||
declare function asyncSchema<T extends Record<string, unknown> = Record<string, unknown>>(schema: ObjectSchema): AsyncObjectSchema<T>;
|
||||
declare function parseBodyAsync<T extends Record<string, unknown>>(schema: AsyncObjectSchema<T>, request: Request, signal?: AbortSignal): Promise<{
|
||||
declare function asyncSchema<T extends object>(schema: ObjectSchema<T>): AsyncObjectSchema<T>;
|
||||
declare function parseBodyAsync<T extends object>(schema: AsyncObjectSchema<T>, request: Request, signal?: AbortSignal): Promise<{
|
||||
ok: true;
|
||||
value: T;
|
||||
} | {
|
||||
@@ -170,6 +222,99 @@ interface OpenApiSchema {
|
||||
declare function schemaToOpenApi(schema: ObjectSchema | AsyncObjectSchema): OpenApiSchema;
|
||||
declare function mergeValidationResults<T>(...results: ParseResult<T>[]): ParseResult<T>;
|
||||
|
||||
declare class ValidationError<T = Record<string, unknown>> extends Error {
|
||||
readonly result: ParseResult<T>;
|
||||
constructor(result: ParseResult<T>);
|
||||
}
|
||||
declare function parseOrThrow<T extends object>(schema: ObjectSchema<T>, input: unknown): T;
|
||||
declare function validationResponse(result: ParseResult, options?: {
|
||||
successStatus?: number;
|
||||
failureStatus?: number;
|
||||
}): Response;
|
||||
declare function firstValidationError(errors: Record<string, string>): string | null;
|
||||
declare function validationSummary(errors: Record<string, string>): Array<{
|
||||
field: string;
|
||||
message: string;
|
||||
}>;
|
||||
declare function schemaFieldNames(schema: ObjectSchema | SchemaDescriptor): string[];
|
||||
|
||||
interface JsonSchemaDocument {
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema";
|
||||
$id?: string;
|
||||
title?: string;
|
||||
type: "object";
|
||||
properties: Record<string, Record<string, unknown>>;
|
||||
required?: string[];
|
||||
additionalProperties: false;
|
||||
}
|
||||
declare function toJsonSchema(schema: ObjectSchema | SchemaDescriptor, options?: {
|
||||
id?: string;
|
||||
title?: string;
|
||||
}): JsonSchemaDocument;
|
||||
declare function openApiRequestBody(schema: ObjectSchema | SchemaDescriptor, options?: {
|
||||
description?: string;
|
||||
required?: boolean;
|
||||
contentTypes?: string[];
|
||||
}): {
|
||||
required: boolean;
|
||||
content: {
|
||||
[k: string]: {
|
||||
schema: {
|
||||
$id?: string;
|
||||
title?: string;
|
||||
type: "object";
|
||||
properties: Record<string, Record<string, unknown>>;
|
||||
required?: string[];
|
||||
additionalProperties: false;
|
||||
};
|
||||
};
|
||||
};
|
||||
description?: string | undefined;
|
||||
};
|
||||
type ValidationMessageKey = "required" | "number" | `rule.${RuleDescriptor["kind"]}`;
|
||||
type ValidationMessageTranslator = (key: ValidationMessageKey, params: Record<string, unknown>) => string;
|
||||
declare function localizeDescriptor(schema: ObjectSchema | SchemaDescriptor, translate: ValidationMessageTranslator): SchemaDescriptor;
|
||||
declare function parseDescriptor<T = Record<string, unknown>>(descriptor: SchemaDescriptor, source: Record<string, unknown>): ParseResult<T>;
|
||||
|
||||
type ContractKind = "api" | "action" | "webhook" | "realtime" | "queue" | "cron" | "pubsub" | "plugin" | "config" | "env";
|
||||
interface ContractDefinition<T extends object = Record<string, unknown>> {
|
||||
kind: ContractKind;
|
||||
name: string;
|
||||
version: number;
|
||||
payload: ObjectSchema<T> | SchemaDescriptor;
|
||||
consumers?: string[];
|
||||
description?: string;
|
||||
}
|
||||
interface ContractRecord {
|
||||
kind: ContractKind;
|
||||
name: string;
|
||||
version: number;
|
||||
payload: SchemaDescriptor;
|
||||
consumers: string[];
|
||||
description?: string;
|
||||
}
|
||||
interface ContractSnapshot {
|
||||
format: 1;
|
||||
contracts: ContractRecord[];
|
||||
}
|
||||
interface ContractIssue {
|
||||
code: "WRN-CONTRACT-REMOVED" | "WRN-CONTRACT-FIELD-REMOVED" | "WRN-CONTRACT-FIELD-REQUIRED" | "WRN-CONTRACT-FIELD-TYPE" | "WRN-CONTRACT-RULE-TIGHTENED";
|
||||
contract: string;
|
||||
field?: string;
|
||||
message: string;
|
||||
consumers: string[];
|
||||
}
|
||||
declare function defineContract<T extends object>(definition: ContractDefinition<T>): ContractDefinition<T>;
|
||||
declare function defineEvent<T extends object>(definition: Omit<ContractDefinition<T>, "kind"> & {
|
||||
kind?: "realtime" | "pubsub";
|
||||
}): ContractDefinition<T>;
|
||||
declare class ContractRegistry {
|
||||
private readonly records;
|
||||
register<T extends object>(definition: ContractDefinition<T>): this;
|
||||
snapshot(): ContractSnapshot;
|
||||
}
|
||||
declare function checkContractCompatibility(previous: ContractSnapshot, current: ContractSnapshot): ContractIssue[];
|
||||
|
||||
/**
|
||||
* @wrnexus/validation — one schema, validated on the server (API) and the browser
|
||||
* (forms). A schema is a fluent builder; `.parse()` runs server-side and returns
|
||||
@@ -218,6 +363,8 @@ interface FieldDescriptor {
|
||||
optional?: boolean;
|
||||
/** Message used when a required field is empty. Defaults to "Required". */
|
||||
requiredMessage?: string;
|
||||
/** Message used when coercion to the declared type fails. */
|
||||
typeMessage?: string;
|
||||
label?: string;
|
||||
/** Trim string input before validating. */
|
||||
trim?: boolean;
|
||||
@@ -274,7 +421,9 @@ declare abstract class FieldSchema {
|
||||
runRefinements(value: unknown): string | null;
|
||||
describe(): FieldDescriptor;
|
||||
}
|
||||
declare class StringSchema extends FieldSchema {
|
||||
declare class StringSchema<TValue extends string = string> extends FieldSchema {
|
||||
/** Type-only marker used to preserve literal unions through schema inference. */
|
||||
readonly __value: TValue;
|
||||
readonly type: "string";
|
||||
private _trim;
|
||||
email(message?: string): this;
|
||||
@@ -282,16 +431,18 @@ declare class StringSchema extends FieldSchema {
|
||||
uuid(message?: string): this;
|
||||
date(message?: string): this;
|
||||
length(n: number, message?: string): this;
|
||||
oneOf(values: string[], message?: string): this;
|
||||
oneOf<const TValues extends readonly string[]>(values: TValues, message?: string): StringSchema<TValues extends readonly [string, ...string[]] ? TValues[number] : TValue>;
|
||||
trim(): this;
|
||||
pattern(re: RegExp, message?: string): this;
|
||||
describe(): FieldDescriptor;
|
||||
}
|
||||
declare class NumberSchema extends FieldSchema {
|
||||
declare class NumberSchema<TValue extends number = number> extends FieldSchema {
|
||||
/** Type-only marker used to preserve numeric literal unions through schema inference. */
|
||||
readonly __value: TValue;
|
||||
readonly type: "number";
|
||||
integer(message?: string): this;
|
||||
positive(message?: string): this;
|
||||
oneOf(values: number[], message?: string): this;
|
||||
oneOf<const TValues extends readonly number[]>(values: TValues, message?: string): NumberSchema<TValues extends readonly [number, ...number[]] ? TValues[number] : TValue>;
|
||||
}
|
||||
declare class BooleanSchema extends FieldSchema {
|
||||
readonly type: "boolean";
|
||||
@@ -299,27 +450,37 @@ declare class BooleanSchema extends FieldSchema {
|
||||
declare class UnknownSchema extends FieldSchema {
|
||||
readonly type: "unknown";
|
||||
}
|
||||
type AnyFieldSchema = StringSchema | NumberSchema | BooleanSchema | UnknownSchema;
|
||||
declare class ObjectSchema {
|
||||
type AnyFieldSchema = StringSchema<string> | NumberSchema<number> | BooleanSchema | UnknownSchema;
|
||||
/** Infer the runtime value produced by a field schema. */
|
||||
type InferFieldValue<TField extends FieldSchema> = TField extends StringSchema<infer TValue> ? TValue : TField extends NumberSchema<infer TValue> ? TValue : TField extends BooleanSchema ? boolean : unknown;
|
||||
/** Infer the validated object produced by a field map. */
|
||||
type InferObjectFields<TFields extends Record<string, FieldSchema>> = {
|
||||
[K in keyof TFields]: InferFieldValue<TFields[K]>;
|
||||
};
|
||||
/** Infer the object value produced by an object schema. */
|
||||
type InferSchema<TSchema extends ObjectSchema> = TSchema extends ObjectSchema<infer TValue> ? TValue : never;
|
||||
declare class ObjectSchema<TValue extends object = Record<string, unknown>> {
|
||||
private readonly fields;
|
||||
/** Type-only marker used by helper functions to infer validated output. */
|
||||
readonly __output: TValue;
|
||||
constructor(fields: Record<string, FieldSchema>);
|
||||
/** Return a defensive copy of the schema fields. */
|
||||
getFields(): Readonly<Record<string, FieldSchema>>;
|
||||
/** Create a new schema with fields added or replaced. The original is unchanged. */
|
||||
extend(fields: Record<string, FieldSchema>): ObjectSchema;
|
||||
extend<TFields extends Record<string, FieldSchema>>(fields: TFields): ObjectSchema<Omit<TValue, keyof TFields> & InferObjectFields<TFields>>;
|
||||
/** Create a new schema containing fields from both schemas. */
|
||||
merge(schema: ObjectSchema): ObjectSchema;
|
||||
merge<TOther extends object>(schema: ObjectSchema<TOther>): ObjectSchema<TValue & TOther>;
|
||||
/** Validate an input object; returns coerced values + per-field errors. */
|
||||
parse(input: unknown): ParseResult;
|
||||
parse(input: unknown): ParseResult<TValue>;
|
||||
describe(): SchemaDescriptor;
|
||||
}
|
||||
/** The fluent schema builder. */
|
||||
declare const v: {
|
||||
string: () => StringSchema;
|
||||
number: () => NumberSchema;
|
||||
string: () => StringSchema<string>;
|
||||
number: () => NumberSchema<number>;
|
||||
boolean: () => BooleanSchema;
|
||||
unknown: () => UnknownSchema;
|
||||
object: (fields: Record<string, FieldSchema>) => ObjectSchema;
|
||||
object: <TFields extends Record<string, FieldSchema>>(fields: TFields) => ObjectSchema<InferObjectFields<TFields>>;
|
||||
};
|
||||
/**
|
||||
* Validate environment variables against a schema at startup. Values are read
|
||||
@@ -333,14 +494,14 @@ declare const v: {
|
||||
* PORT: v.number(),
|
||||
* }));
|
||||
*/
|
||||
declare function parseEnv<T = Record<string, unknown>>(schema: ObjectSchema, source?: Record<string, string | undefined>): T;
|
||||
declare function parseEnv<T extends object>(schema: ObjectSchema<T>, source?: Record<string, string | undefined>): T;
|
||||
/** A 400 response carrying field errors, for API routes. */
|
||||
declare function invalid(errors: Record<string, string>): Response;
|
||||
/**
|
||||
* Parse a request's JSON body against a schema. On failure returns
|
||||
* `{ ok: false, response }` (a ready 400); on success `{ ok: true, value }`.
|
||||
*/
|
||||
declare function parseBody<T = Record<string, unknown>>(schema: ObjectSchema, req: Request): Promise<{
|
||||
declare function parseBody<T extends object>(schema: ObjectSchema<T>, req: Request): Promise<{
|
||||
ok: true;
|
||||
value: T;
|
||||
} | {
|
||||
@@ -348,7 +509,7 @@ declare function parseBody<T = Record<string, unknown>>(schema: Obje
|
||||
response: Response;
|
||||
}>;
|
||||
|
||||
export { type AnyFieldSchema, AsyncObjectSchema, type AsyncRefinement, type AsyncValidationContext, BooleanSchema, type FieldDescriptor, FieldSchema, NumberSchema, ObjectSchema, type OpenApiSchema, type ParseResult, type RuleDescriptor, type SchemaDescriptor, StringSchema, UnknownSchema, VALIDATE_RUNTIME, applyRule, asyncSchema, checkField, invalid, mergeValidationResults, parseBody, parseBodyAsync, parseEnv, renderSchemasScript, schemaToOpenApi, v };
|
||||
export { type AnyFieldSchema, AsyncObjectSchema, type AsyncRefinement, type AsyncValidationContext, BooleanSchema, type ContractDefinition, type ContractIssue, type ContractKind, type ContractRecord, ContractRegistry, type ContractSnapshot, type FieldDescriptor, FieldSchema, type InferFieldValue, type InferObjectFields, type InferSchema, type JsonSchemaDocument, NumberSchema, ObjectSchema, type OpenApiSchema, type ParseResult, type RuleDescriptor, type SchemaDescriptor, StringSchema, UnknownSchema, VALIDATE_RUNTIME, ValidationError, type ValidationMessageKey, type ValidationMessageTranslator, applyRule, asyncSchema, checkContractCompatibility, checkField, defineContract, defineEvent, firstValidationError, invalid, localizeDescriptor, mergeValidationResults, openApiRequestBody, parseBody, parseBodyAsync, parseDescriptor, parseEnv, parseOrThrow, renderSchemasScript, schemaFieldNames, schemaToOpenApi, toJsonSchema, v, validationResponse, validationSummary };
|
||||
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>Define a schema and validate an API body</h3><pre data-language="ts"><code>import { v, parseBody } from "@wrnexus/validation";
|
||||
|
||||
export const signupSchema = v.object({
|
||||
@@ -382,9 +543,9 @@ import { signupSchema } from "./app/schemas/signup.ts";
|
||||
const head = `<script>${renderSchemasScript({ signup: signupSchema.describe() })}</script>
|
||||
<script>${VALIDATE_RUNTIME}</script>`;
|
||||
// render a <form data-schema="signup"> with [data-error="email"] etc.</code></pre></article></div></section></article>
|
||||
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-4" href="#the-v-builder">The v builder</a><a class="toc-level-4" href="#objectschema">ObjectSchema</a><a class="toc-level-4" href="#rules-and-coercion">Rules and coercion</a><a class="toc-level-4" href="#api-helpers">API helpers</a><a class="toc-level-4" href="#environment-config">Environment config</a><a class="toc-level-4" href="#client-runtime-from-runtime-ts">Client runtime (from runtime.ts)</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
|
||||
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#boundary-contracts">Boundary contracts</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-4" href="#the-v-builder">The v builder</a><a class="toc-level-4" href="#objectschema">ObjectSchema</a><a class="toc-level-4" href="#rules-and-coercion">Rules and coercion</a><a class="toc-level-4" href="#api-helpers">API helpers</a><a class="toc-level-4" href="#environment-config">Environment config</a><a class="toc-level-4" href="#client-runtime-from-runtime-ts">Client runtime (from runtime.ts)</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-3" href="#helper-and-component-kit">Helper and component kit</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
|
||||
</main>
|
||||
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.7.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
|
||||
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.8.0</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
|
||||
<BackToTop />
|
||||
</div>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user