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
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<const T extends string | number | boolean>(
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<typeof DatabaseConfigSchema>;
// {
// 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<const T extends readonly string[]>(
...values: T
): UnionValue<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 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<typeof StatusSchema>;
// { 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<const T extends readonly string[]>(
...values: T
): UnionValue<T> & { 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<typeof Schema>;
// { 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>