UNPKG

fortify-schema

Version:

A modern TypeScript validation library designed around familiar interface syntax and powerful conditional validation. Experience schema validation that feels natural to TypeScript developers while unlocking advanced runtime validation capabilities.

427 lines (371 loc) โ€ข 16.6 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Make Utility - Fortify Schema</title> <script src="https://cdn.tailwindcss.com"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <link rel="stylesheet" href="styles.css"> </head> <body class="bg-gray-50"> <!-- Header --> <header class="gradient-bg text-white shadow-lg"> <div class="container mx-auto px-6 py-8"> <h1 class="text-4xl font-bold mb-2">๐Ÿ”ง Make Utility</h1> <p class="text-xl text-purple-100">Create type-safe schema values</p> </div> </header> <!-- Navigation --> <nav class="bg-white shadow-md sticky top-0 z-50"> <div class="container mx-auto px-6"> <div class="flex space-x-8 overflow-x-auto py-4"> <a href="index.html" class="nav-link">๐Ÿ  Home</a> <a href="bug-fixes.html" class="nav-link">๐Ÿ› Bug Fixes</a> <a href="make-utility.html" class="nav-link active">๐Ÿ”ง Make</a> <a href="mod-utility.html" class="nav-link">โš™๏ธ Mod</a> <a href="examples.html" class="nav-link">๐Ÿ“š Examples</a> <a href="api-reference.html" class="nav-link">๐Ÿ“– API</a> </div> </div> </nav> <!-- Main Content --> <main class="container mx-auto px-6 py-12"> <!-- Introduction --> <section class="mb-12"> <div class="section-card"> <h2 class="text-3xl font-bold text-gray-800 mb-4">Overview</h2> <p class="text-gray-600 mb-4"> The <code>Make</code> utility provides helper methods for creating type-safe schema values. It ensures proper type inference and validation for constants, unions, and other special values. </p> <div class="bg-purple-50 border-l-4 border-purple-500 p-4"> <p class="text-purple-900"> <strong>๐Ÿ’ก Pro Tip:</strong> Use <code>Make</code> for values that need strict type safety and <code>Mod</code> for transforming existing schemas. </p> </div> </div> </section> <!-- Make.const() --> <section class="mb-12"> <div class="section-card"> <div class="flex items-start justify-between mb-6"> <h2 class="text-3xl font-bold text-gray-800">Make.const()</h2> <span class="badge badge-purple">Method</span> </div> <p class="text-gray-600 mb-6"> Create a constant value that must match exactly. Safer than using raw values because it provides better type inference and validation. </p> <h3 class="text-xl font-semibold text-gray-700 mb-3">Signature</h3> <pre class="code-block mb-6"><code class="language-typescript">static const&lt;const T extends string | number | boolean&gt;( value: T ): ConstantValue & { const: T }</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Basic Usage</h3> <pre class="code-block mb-6"><code class="language-typescript">import { Interface, Make } from "fortify-schema"; const ConfigSchema = Interface({ // String constants apiVersion: Make.const("v2.1"), environment: Make.const("production"), // Numeric constants maxRetries: Make.const(3), timeout: Make.const(5000), // Boolean constants enableLogging: Make.const(true), debugMode: Make.const(false) }); // Valid data ConfigSchema.parse({ apiVersion: "v2.1", // โœ… Matches exactly environment: "production", // โœ… Matches exactly maxRetries: 3, // โœ… Matches exactly timeout: 5000, // โœ… Matches exactly enableLogging: true, // โœ… Matches exactly debugMode: false // โœ… Matches exactly }); // Invalid data ConfigSchema.parse({ apiVersion: "v2.0", // โŒ Must be "v2.1" environment: "staging", // โŒ Must be "production" maxRetries: 5, // โŒ Must be 3 timeout: 3000, // โŒ Must be 5000 enableLogging: false, // โŒ Must be true debugMode: true // โŒ Must be false });</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Use Cases</h3> <div class="grid md:grid-cols-2 gap-4 mb-6"> <div class="bg-gray-50 rounded-lg p-4"> <h4 class="font-semibold text-gray-800 mb-2">๐Ÿ”’ API Versioning</h4> <p class="text-sm text-gray-600">Enforce specific API versions in requests</p> </div> <div class="bg-gray-50 rounded-lg p-4"> <h4 class="font-semibold text-gray-800 mb-2">โš™๏ธ Configuration</h4> <p class="text-sm text-gray-600">Lock down critical config values</p> </div> <div class="bg-gray-50 rounded-lg p-4"> <h4 class="font-semibold text-gray-800 mb-2">๐ŸŽฏ Feature Flags</h4> <p class="text-sm text-gray-600">Validate feature flag states</p> </div> <div class="bg-gray-50 rounded-lg p-4"> <h4 class="font-semibold text-gray-800 mb-2">๐Ÿ“ Protocol Compliance</h4> <p class="text-sm text-gray-600">Ensure protocol-specific values</p> </div> </div> <h3 class="text-xl font-semibold text-gray-700 mb-3">Advanced Example</h3> <pre class="code-block"><code class="language-typescript">// Complex configuration with constants const DatabaseConfigSchema = Interface({ driver: Make.const("postgresql"), version: Make.const("14.5"), ssl: Make.const(true), poolSize: Make.const(20), // Mix with other types host: "string", port: "number", database: "string", username: "string", password: "string" }); // Type inference works perfectly type DatabaseConfig = InferType&lt;typeof DatabaseConfigSchema&gt;; // { // driver: "postgresql"; // Literal type // version: "14.5"; // Literal type // ssl: true; // Literal type // poolSize: 20; // Literal type // host: string; // port: number; // database: string; // username: string; // password: string; // }</code></pre> </div> </section> <!-- Make.union() --> <section class="mb-12"> <div class="section-card"> <div class="flex items-start justify-between mb-6"> <h2 class="text-3xl font-bold text-gray-800">Make.union()</h2> <span class="badge badge-purple">Method</span> </div> <p class="text-gray-600 mb-6"> Create a union type with multiple allowed values. Provides proper type inference for all possible values. </p> <h3 class="text-xl font-semibold text-gray-700 mb-3">Signature</h3> <pre class="code-block mb-6"><code class="language-typescript">static union&lt;const T extends readonly string[]&gt;( ...values: T ): UnionValue&lt;T&gt;</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Basic Usage</h3> <pre class="code-block mb-6"><code class="language-typescript">import { Interface, Make } from "fortify-schema"; const UserSchema = Interface({ // Status with 3 possible values status: Make.union("pending", "accepted", "rejected"), // Priority levels priority: Make.union("low", "medium", "high", "critical"), // User roles role: Make.union("admin", "moderator", "user", "guest") }); // Valid data UserSchema.parse({ status: "pending", // โœ… One of the allowed values priority: "high", // โœ… One of the allowed values role: "admin" // โœ… One of the allowed values }); // Invalid data UserSchema.parse({ status: "approved", // โŒ Not in union priority: "urgent", // โŒ Not in union role: "superadmin" // โŒ Not in union });</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Type Inference</h3> <pre class="code-block mb-6"><code class="language-typescript">const StatusSchema = Interface({ status: Make.union("pending", "accepted", "rejected") }); type Status = InferType&lt;typeof StatusSchema&gt;; // { status: "pending" | "accepted" | "rejected" } // TypeScript autocomplete works perfectly const handleStatus = (data: Status) => { if (data.status === "pending") { // Handle pending } else if (data.status === "accepted") { // Handle accepted } else if (data.status === "rejected") { // Handle rejected } // TypeScript knows all possible values! };</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Real-World Example</h3> <pre class="code-block"><code class="language-typescript">// E-commerce order schema const OrderSchema = Interface({ orderId: "uuid", // Order status workflow status: Make.union( "cart", "pending_payment", "payment_failed", "paid", "processing", "shipped", "delivered", "cancelled", "refunded" ), // Payment method paymentMethod: Make.union( "credit_card", "debit_card", "paypal", "stripe", "bank_transfer" ), // Shipping method shippingMethod: Make.union( "standard", "express", "overnight", "pickup" ), items: "array", total: "number", createdAt: "date" });</code></pre> </div> </section> <!-- Make.unionOptional() --> <section class="mb-12"> <div class="section-card"> <div class="flex items-start justify-between mb-6"> <h2 class="text-3xl font-bold text-gray-800">Make.unionOptional()</h2> <span class="badge badge-purple">Method</span> </div> <p class="text-gray-600 mb-6"> Create an optional union type. The field can be one of the specified values or undefined. </p> <h3 class="text-xl font-semibold text-gray-700 mb-3">Signature</h3> <pre class="code-block mb-6"><code class="language-typescript">static unionOptional&lt;const T extends readonly string[]&gt;( ...values: T ): UnionValue&lt;T&gt; & { optional: true }</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Basic Usage</h3> <pre class="code-block mb-6"><code class="language-typescript">import { Interface, Make } from "fortify-schema"; const ProductSchema = Interface({ id: "uuid", name: "string", // Optional shipping type shippingType: Make.unionOptional("standard", "express", "overnight"), // Optional gift wrapping giftWrap: Make.unionOptional("basic", "premium", "deluxe") }); // All valid ProductSchema.parse({ id: "123", name: "Product", shippingType: "express" // โœ… Specified }); ProductSchema.parse({ id: "123", name: "Product" // โœ… shippingType and giftWrap omitted }); ProductSchema.parse({ id: "123", name: "Product", shippingType: "standard", giftWrap: "premium" // โœ… Both specified });</code></pre> <h3 class="text-xl font-semibold text-gray-700 mb-3">Type Inference</h3> <pre class="code-block"><code class="language-typescript">const Schema = Interface({ type: Make.unionOptional("standard", "express", "overnight") }); type Inferred = InferType&lt;typeof Schema&gt;; // { type?: "standard" | "express" | "overnight" | undefined } // TypeScript handles optional correctly const process = (data: Inferred) => { if (data.type) { // data.type is "standard" | "express" | "overnight" console.log(`Shipping type: ${data.type}`); } else { console.log("No shipping type specified"); } };</code></pre> </div> </section> <!-- Comparison Table --> <section class="mb-12"> <div class="section-card"> <h2 class="text-3xl font-bold text-gray-800 mb-6">Method Comparison</h2> <div class="overflow-x-auto"> <table> <thead> <tr> <th>Method</th> <th>Purpose</th> <th>Required</th> <th>Example</th> </tr> </thead> <tbody> <tr> <td><code>Make.const()</code></td> <td>Single exact value</td> <td>Yes</td> <td><code>Make.const("v1.0")</code></td> </tr> <tr> <td><code>Make.union()</code></td> <td>Multiple allowed values</td> <td>Yes</td> <td><code>Make.union("a", "b", "c")</code></td> </tr> <tr> <td><code>Make.unionOptional()</code></td> <td>Optional multiple values</td> <td>No</td> <td><code>Make.unionOptional("x", "y")</code></td> </tr> </tbody> </table> </div> </div> </section> <!-- Best Practices --> <section> <div class="section-card bg-blue-50 border-l-4 border-blue-500"> <h2 class="text-2xl font-bold text-gray-800 mb-4">โœจ Best Practices</h2> <div class="space-y-4"> <div> <h3 class="font-semibold text-gray-800 mb-2">1. Use Make.const() for Fixed Values</h3> <p class="text-gray-700">When a value must never change (API versions, protocol identifiers), use <code>Make.const()</code>.</p> </div> <div> <h3 class="font-semibold text-gray-800 mb-2">2. Prefer Make.union() Over String Literals</h3> <p class="text-gray-700">Use <code>Make.union()</code> instead of <code>"a|b|c"</code> for better type inference and IDE support.</p> </div> <div> <h3 class="font-semibold text-gray-800 mb-2">3. Keep Union Values Descriptive</h3> <p class="text-gray-700">Use clear, descriptive values: <code>"pending_payment"</code> instead of <code>"pp"</code>.</p> </div> <div> <h3 class="font-semibold text-gray-800 mb-2">4. Document Complex Unions</h3> <p class="text-gray-700">Add comments explaining what each union value represents in your business logic.</p> </div> </div> </div> </section> </main> <!-- Footer --> <footer class="bg-gray-800 text-white mt-16 py-8"> <div class="container mx-auto px-6 text-center"> <p class="mb-2">ยฉ 2025 Nehonix Team. All rights reserved.</p> <p class="text-gray-400 text-sm"> <a href="https://github.com/Nehonix-Team/fortify-schema" class="hover:text-white">GitHub</a> ยท <a href="https://www.npmjs.com/package/fortify-schema" class="hover:text-white">NPM</a> </p> </div> </footer> <script> hljs.highlightAll(); </script> </body> </html>