rustica 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rustica contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,289 @@
1
+ # Rustica
2
+
3
+ ![Rustica - Validate 'Em All'](./assets/rustica-banner.png)
4
+
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/)
7
+ [![Rust](https://img.shields.io/badge/Rust-1.70+-orange)](https://www.rust-lang.org/)
8
+ [![WebAssembly](https://img.shields.io/badge/WebAssembly-✓-blueviolet)](https://webassembly.org/)
9
+
10
+ Production-grade schema and form validation system powered by Rust and WebAssembly.
11
+
12
+ ## ✨ Features
13
+
14
+ <table>
15
+ <tr>
16
+ <td width="50%">
17
+
18
+ ### 🦀 Rust Core
19
+
20
+ - **WASM-powered** validation
21
+ - **Zero-copy** architecture
22
+ - **~0.1-0.5ms** per validation
23
+ - **Single call** per validation
24
+
25
+ </td>
26
+ <td width="50%">
27
+
28
+ ### 📝 TypeScript API
29
+
30
+ - **Fluent API** like Zod
31
+ - **Full type inference**
32
+ - **Schema serialization**
33
+ - **UI metadata** support
34
+
35
+ </td>
36
+ </tr>
37
+ <tr>
38
+ <td width="50%">
39
+
40
+ ### ⚛️ React Integration
41
+
42
+ - **useWasmForm** hook
43
+ - **Field registration**
44
+ - **Auto re-rendering**
45
+ - **RHF-compatible** API
46
+
47
+ </td>
48
+ <td width="50%">
49
+
50
+ ### 🔧 Framework Agnostic
51
+
52
+ - **createForm** for any framework
53
+ - **Vanilla JS** support
54
+ - **Node.js** compatible
55
+ - **Browser** ready
56
+
57
+ </td>
58
+ </tr>
59
+ </table>
60
+
61
+ ## Installation
62
+
63
+ ```bash
64
+ npm install rustica
65
+ ```
66
+
67
+ ## Quick Start
68
+
69
+ ```typescript
70
+ import { r, useWasmForm } from 'rustica';
71
+
72
+ // Define schema with optional custom error messages
73
+ // WASM auto-initializes on first validation - no setup needed!
74
+ const loginSchema = r.object({
75
+ email: r.string()
76
+ .min(3)
77
+ .email()
78
+ .ui({ label: "Email" })
79
+ .messages({
80
+ email: "Please enter a valid email address",
81
+ min: "Email must be at least 3 characters"
82
+ }),
83
+ password: r.string()
84
+ .min(8)
85
+ .ui({ label: "Password" })
86
+ .messages({
87
+ min: "Password must be at least 8 characters for security"
88
+ })
89
+ });
90
+
91
+ // Infer types
92
+ type LoginForm = r.Infer<typeof loginSchema>;
93
+
94
+ // Use in React - works immediately!
95
+ function LoginForm() {
96
+ const form = useWasmForm({
97
+ schema: loginSchema,
98
+ defaultValues: { email: '', password: '' },
99
+ onSubmit: async (data) => {
100
+ console.log('Valid data:', data);
101
+ }
102
+ });
103
+
104
+ return (
105
+ <form onSubmit={form.handleSubmit}>
106
+ <input {...form.register('email')} />
107
+ {form.errors.email && <span>{form.errors.email.message}</span>}
108
+
109
+ <input type="password" {...form.register('password')} />
110
+ {form.errors.password && <span>{form.errors.password.message}</span>}
111
+
112
+ <button type="submit">Login</button>
113
+ </form>
114
+ );
115
+ }
116
+ ```
117
+
118
+ **Note**: WASM auto-initializes on the first validation call. For eager loading (optional), you can manually call `await initWasm()` at app startup.
119
+
120
+ ````
121
+
122
+ ## Custom Error Messages (Optional)
123
+
124
+ Customize validation error messages for better UX:
125
+
126
+ ```typescript
127
+ // String validation with custom messages
128
+ const usernameSchema = r.string().min(3).max(20).messages({
129
+ invalid_type: "Username must be text",
130
+ min: "Username is too short - minimum 3 characters",
131
+ max: "Username is too long - maximum 20 characters",
132
+ });
133
+
134
+ // Number validation with custom messages
135
+ const ageSchema = r.number().min(18).integer().messages({
136
+ invalid_type: "Age must be a number",
137
+ min: "You must be at least 18 years old",
138
+ integer: "Age must be a whole number",
139
+ });
140
+
141
+ // Object validation with custom messages
142
+ const formSchema = r
143
+ .object({
144
+ email: r.string().email().messages({
145
+ email: "Please enter a valid email like user@example.com",
146
+ }),
147
+ terms: r.boolean().messages({
148
+ invalid_type: "You must accept the terms and conditions",
149
+ }),
150
+ })
151
+ .messages({
152
+ invalid_type: "Form data must be an object",
153
+ required: "This field is required",
154
+ });
155
+ ````
156
+
157
+ **Available message keys by type:**
158
+
159
+ - **String**: `invalid_type`, `min`, `max`, `email`, `url`, `pattern`
160
+ - **Number**: `invalid_type`, `min`, `max`, `integer`, `positive`
161
+ - **Boolean**: `invalid_type`
162
+ - **Object**: `invalid_type`, `required`
163
+
164
+ If not provided, default messages are used. See [examples/custom-messages.ts](./examples/custom-messages.ts) for more examples.
165
+
166
+ ## Building from Source
167
+
168
+ ```bash
169
+ # Quick setup (recommended)
170
+ chmod +x scripts/setup.sh
171
+ ./scripts/setup.sh
172
+
173
+ # Or manual setup
174
+ npm install
175
+ npm run build
176
+ ```
177
+
178
+ See [Getting Started Guide](./docs/GETTING_STARTED.md) for detailed instructions.
179
+
180
+ ## Architecture
181
+
182
+ - **Rust Core** (`src/lib.rs`, `src/schema.rs`, `src/validator.rs`) - Schema definitions and validation logic
183
+ - **WASM Interface** (`src/wasm.rs`) - WebAssembly bindings with wasm-bindgen
184
+ - **TypeScript Schema Builder** (`src/schema/`) - Fluent API for schema definition
185
+ - **Form Runtime** (`src/form/`) - Form state management
186
+ - **React Hook** (`src/react/`) - React integration
187
+
188
+ ## Documentation
189
+
190
+ - 📖 **[Complete Documentation Index](./docs/INDEX.md)** - All docs in one place
191
+ - 🚀 **[Getting Started Guide](./docs/GETTING_STARTED.md)** - Quick start tutorial
192
+ - 📚 **[API Reference](./docs/API.md)** - Complete API documentation
193
+ - 🏗️ **[Architecture Guide](./docs/ARCHITECTURE.md)** - How it works
194
+ - 📊 **[Feature Comparison](./docs/COMPARISON.md)** - vs Zod, Yup, Joi
195
+ - 🤝 **[Contributing Guide](./CONTRIBUTING.md)** - How to contribute
196
+
197
+ ## Project Structure
198
+
199
+ ```
200
+ rustica/
201
+ ├── src/ # Rust source (validation core)
202
+ │ ├── lib.rs # Module exports
203
+ │ ├── schema.rs # Schema AST types
204
+ │ ├── validator.rs # Validation engine
205
+ │ └── wasm.rs # WASM bindings
206
+ ├── src/ # TypeScript source
207
+ │ ├── schema/ # Schema builders (r.string(), etc.)
208
+ │ ├── validator/ # WASM wrapper
209
+ │ ├── form/ # Form runtime
210
+ │ ├── react/ # React hooks
211
+ │ └── index.ts # Main entry point
212
+ ├── examples/ # Usage examples
213
+ │ ├── quick-test.ts # Basic validation tests
214
+ │ ├── standalone.ts # Standalone examples
215
+ │ ├── forms.tsx # Form component examples
216
+ │ └── react-form-app/ # Full React app with API integration
217
+ ├── tests/ # Test suite
218
+ ├── docs/ # Documentation
219
+ └── scripts/ # Build scripts
220
+ ```
221
+
222
+ ## Commands
223
+
224
+ ```bash
225
+ # Development
226
+ make install # Install dependencies
227
+ make build # Build WASM + TypeScript
228
+ make test # Run all tests
229
+ make dev # Watch mode
230
+
231
+ # Quick Commands
232
+ make example # Run quick test
233
+ make clean # Clean build artifacts
234
+ make help # Show all commands
235
+ ```
236
+
237
+ ## Performance
238
+
239
+ <table>
240
+ <tr>
241
+ <td><b>Metric</b></td>
242
+ <td><b>Value</b></td>
243
+ <td><b>Notes</b></td>
244
+ </tr>
245
+ <tr>
246
+ <td>Validation Speed</td>
247
+ <td>~0.1-0.5ms</td>
248
+ <td>Per validation (warm)</td>
249
+ </tr>
250
+ <tr>
251
+ <td>Throughput</td>
252
+ <td>5,000-10,000/sec</td>
253
+ <td>1000 validations in ~100-200ms</td>
254
+ </tr>
255
+ <tr>
256
+ <td>WASM Size</td>
257
+ <td>~15-20KB</td>
258
+ <td>Gzipped: ~8-10KB</td>
259
+ </tr>
260
+ <tr>
261
+ <td>Overhead</td>
262
+ <td>Single call</td>
263
+ <td>Zero-copy where possible</td>
264
+ </tr>
265
+ </table>
266
+
267
+ See [Performance Comparison](./docs/COMPARISON.md) for detailed benchmarks.
268
+
269
+ ## Contributing
270
+
271
+ We welcome contributions! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
272
+
273
+ ## Roadmap
274
+
275
+ - [x] Core validation (string, number, boolean, object)
276
+ - [x] React hooks
277
+ - [x] Form runtime
278
+ - [x] Type inference
279
+ - [x] Custom error messages (optional)
280
+ - [ ] Array/tuple schemas
281
+ - [ ] Union/intersection types
282
+ - [ ] Async validation helpers
283
+ - [ ] i18n support
284
+
285
+ See [CHANGELOG.md](./CHANGELOG.md) for version history.
286
+
287
+ ## License
288
+
289
+ MIT
@@ -0,0 +1,60 @@
1
+ import type { Schema, ValidationError } from "../schema/types";
2
+ import type { SchemaBuilder } from "../schema/builders";
3
+ /**
4
+ * Form field state
5
+ */
6
+ export interface FieldState {
7
+ value: any;
8
+ touched: boolean;
9
+ error: ValidationError | null;
10
+ }
11
+ /**
12
+ * Form state
13
+ */
14
+ export interface FormState<T extends Record<string, any>> {
15
+ values: T;
16
+ touched: Record<keyof T, boolean>;
17
+ errors: Record<keyof T, ValidationError | null>;
18
+ isSubmitting: boolean;
19
+ isValid: boolean;
20
+ }
21
+ /**
22
+ * Form configuration
23
+ */
24
+ export interface FormConfig<T extends Record<string, any>> {
25
+ schema: SchemaBuilder<T> | Schema;
26
+ defaultValues: T;
27
+ onSubmit: (data: T) => void | Promise<void>;
28
+ validateOnBlur?: boolean;
29
+ validateOnChange?: boolean;
30
+ }
31
+ /**
32
+ * Form instance API
33
+ */
34
+ export interface Form<T extends Record<string, any>> {
35
+ values: T;
36
+ touched: Record<keyof T, boolean>;
37
+ errors: Record<keyof T, ValidationError | null>;
38
+ isSubmitting: boolean;
39
+ isValid: boolean;
40
+ setValue(field: keyof T, value: any): void;
41
+ setTouched(field: keyof T, touched: boolean): void;
42
+ validateField(field: keyof T): Promise<ValidationError | null>;
43
+ validateForm(): Promise<Record<keyof T, ValidationError | null>>;
44
+ handleBlur(field: keyof T): void;
45
+ handleChange(field: keyof T, value: any): void;
46
+ handleSubmit(event?: Event): Promise<void>;
47
+ reset(): void;
48
+ subscribe(listener: (state: FormState<T>) => void): () => void;
49
+ }
50
+ /**
51
+ * Create a form instance with validation
52
+ *
53
+ * This is the core form runtime that manages:
54
+ * - Form values
55
+ * - Touch state
56
+ * - Validation errors
57
+ * - Submit handling
58
+ */
59
+ export declare function createForm<T extends Record<string, any>>(config: FormConfig<T>): Form<T>;
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/form/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,GAAG,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,eAAe,GAAG,IAAI,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IACtD,MAAM,EAAE,CAAC,CAAC;IACV,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC,CAAC;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IACvD,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAClC,aAAa,EAAE,CAAC,CAAC;IACjB,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAEjD,MAAM,EAAE,CAAC,CAAC;IACV,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC,CAAC;IAChD,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IAGjB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAC3C,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACnD,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAC/D,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC,CAAC,CAAC;IACjE,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;IAC/C,YAAY,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,KAAK,IAAI,IAAI,CAAC;IACd,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAChE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACtD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GACpB,IAAI,CAAC,CAAC,CAAC,CAuOT"}
@@ -0,0 +1,194 @@
1
+ import { Validator } from "../validator";
2
+ /**
3
+ * Create a form instance with validation
4
+ *
5
+ * This is the core form runtime that manages:
6
+ * - Form values
7
+ * - Touch state
8
+ * - Validation errors
9
+ * - Submit handling
10
+ */
11
+ export function createForm(config) {
12
+ const { schema, defaultValues, onSubmit, validateOnBlur = true, validateOnChange = false, } = config;
13
+ // Internal state
14
+ let state = {
15
+ values: { ...defaultValues },
16
+ touched: Object.keys(defaultValues).reduce((acc, key) => ({ ...acc, [key]: false }), {}),
17
+ errors: Object.keys(defaultValues).reduce((acc, key) => ({ ...acc, [key]: null }), {}),
18
+ isSubmitting: false,
19
+ isValid: true,
20
+ };
21
+ // Subscribers for reactive updates
22
+ const listeners = new Set();
23
+ /**
24
+ * Notify all subscribers of state change
25
+ */
26
+ function notify() {
27
+ listeners.forEach((listener) => listener(state));
28
+ }
29
+ /**
30
+ * Update isValid flag based on errors
31
+ */
32
+ function updateValidity() {
33
+ state.isValid = Object.values(state.errors).every((error) => error === null);
34
+ }
35
+ /**
36
+ * Validate a single field
37
+ */
38
+ async function validateField(field) {
39
+ const path = [String(field)];
40
+ const result = await Validator.validateAtPath(schema, state.values, path);
41
+ if (!result.success && result.errors && result.errors.length > 0) {
42
+ // Return the first error for this field
43
+ return result.errors[0];
44
+ }
45
+ return null;
46
+ }
47
+ /**
48
+ * Validate entire form
49
+ */
50
+ async function validateForm() {
51
+ const result = await Validator.validate(schema, state.values);
52
+ const fieldErrors = {
53
+ ...state.errors,
54
+ };
55
+ // Clear all errors first
56
+ for (const key in fieldErrors) {
57
+ fieldErrors[key] = null;
58
+ }
59
+ // Populate errors from validation result
60
+ if (!result.success && result.errors) {
61
+ for (const error of result.errors) {
62
+ if (error.path.length > 0) {
63
+ const fieldName = error.path[0];
64
+ if (fieldName in fieldErrors) {
65
+ fieldErrors[fieldName] = error;
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return fieldErrors;
71
+ }
72
+ /**
73
+ * Set field value
74
+ */
75
+ function setValue(field, value) {
76
+ state.values[field] = value;
77
+ if (validateOnChange) {
78
+ validateField(field).then((error) => {
79
+ state.errors[field] = error;
80
+ updateValidity();
81
+ notify();
82
+ });
83
+ }
84
+ notify();
85
+ }
86
+ /**
87
+ * Set field touched state
88
+ */
89
+ function setTouched(field, touched) {
90
+ state.touched[field] = touched;
91
+ notify();
92
+ }
93
+ /**
94
+ * Handle field blur event
95
+ */
96
+ function handleBlur(field) {
97
+ state.touched[field] = true;
98
+ if (validateOnBlur) {
99
+ validateField(field).then((error) => {
100
+ state.errors[field] = error;
101
+ updateValidity();
102
+ notify();
103
+ });
104
+ }
105
+ else {
106
+ notify();
107
+ }
108
+ }
109
+ /**
110
+ * Handle field change event
111
+ */
112
+ function handleChange(field, value) {
113
+ setValue(field, value);
114
+ }
115
+ /**
116
+ * Handle form submission
117
+ */
118
+ async function handleSubmit(event) {
119
+ if (event) {
120
+ event.preventDefault();
121
+ }
122
+ // Mark all fields as touched
123
+ for (const key in state.values) {
124
+ state.touched[key] = true;
125
+ }
126
+ // Validate entire form
127
+ state.errors = await validateForm();
128
+ updateValidity();
129
+ state.isSubmitting = true;
130
+ notify();
131
+ // If valid, call onSubmit
132
+ if (state.isValid) {
133
+ try {
134
+ await onSubmit(state.values);
135
+ }
136
+ catch (error) {
137
+ console.error("Form submission error:", error);
138
+ }
139
+ }
140
+ state.isSubmitting = false;
141
+ notify();
142
+ }
143
+ /**
144
+ * Reset form to default values
145
+ */
146
+ function reset() {
147
+ state = {
148
+ values: { ...defaultValues },
149
+ touched: Object.keys(defaultValues).reduce((acc, key) => ({ ...acc, [key]: false }), {}),
150
+ errors: Object.keys(defaultValues).reduce((acc, key) => ({ ...acc, [key]: null }), {}),
151
+ isSubmitting: false,
152
+ isValid: true,
153
+ };
154
+ notify();
155
+ }
156
+ /**
157
+ * Subscribe to form state changes
158
+ */
159
+ function subscribe(listener) {
160
+ listeners.add(listener);
161
+ // Return unsubscribe function
162
+ return () => {
163
+ listeners.delete(listener);
164
+ };
165
+ }
166
+ // Return form instance
167
+ return {
168
+ get values() {
169
+ return state.values;
170
+ },
171
+ get touched() {
172
+ return state.touched;
173
+ },
174
+ get errors() {
175
+ return state.errors;
176
+ },
177
+ get isSubmitting() {
178
+ return state.isSubmitting;
179
+ },
180
+ get isValid() {
181
+ return state.isValid;
182
+ },
183
+ setValue,
184
+ setTouched,
185
+ validateField,
186
+ validateForm,
187
+ handleBlur,
188
+ handleChange,
189
+ handleSubmit,
190
+ reset,
191
+ subscribe,
192
+ };
193
+ }
194
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/form/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Rustica
3
+ * Production-grade schema and form validation powered by Rust and WebAssembly
4
+ */
5
+ export { r, type Infer, type UiConfig } from "./schema";
6
+ export type { Schema, StringSchema, NumberSchema, BooleanSchema, ObjectSchema, ValidationError, ValidationResult, } from "./schema/types";
7
+ export { ZString, ZNumber, ZBoolean, ZObject, SchemaBuilder, } from "./schema/builders";
8
+ export { Validator, ValidationException, initWasm, createValidator, } from "./validator";
9
+ export { createForm, type Form, type FormConfig, type FormState, type FieldState, } from "./form";
10
+ export { useWasmForm, useFieldError, useFieldHasError, type UseWasmFormReturn, type FieldRegistration, } from "./react";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,CAAC,EAAE,KAAK,KAAK,EAAE,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EACV,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,eAAe,EACf,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,OAAO,EACP,OAAO,EACP,QAAQ,EACR,OAAO,EACP,aAAa,GACd,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,UAAU,EACV,KAAK,IAAI,EACT,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EACL,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,GACvB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Rustica
3
+ * Production-grade schema and form validation powered by Rust and WebAssembly
4
+ */
5
+ // Schema builder API
6
+ export { r } from "./schema";
7
+ export { ZString, ZNumber, ZBoolean, ZObject, SchemaBuilder, } from "./schema/builders";
8
+ // Validator
9
+ export { Validator, ValidationException, initWasm, createValidator, } from "./validator";
10
+ // Form runtime
11
+ export { createForm, } from "./form";
12
+ // React hooks (optional peer dependency)
13
+ export { useWasmForm, useFieldError, useFieldHasError, } from "./react";
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,qBAAqB;AACrB,OAAO,EAAE,CAAC,EAA6B,MAAM,UAAU,CAAC;AAUxD,OAAO,EACL,OAAO,EACP,OAAO,EACP,QAAQ,EACR,OAAO,EACP,aAAa,GACd,MAAM,mBAAmB,CAAC;AAE3B,YAAY;AACZ,OAAO,EACL,SAAS,EACT,mBAAmB,EACnB,QAAQ,EACR,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,eAAe;AACf,OAAO,EACL,UAAU,GAKX,MAAM,QAAQ,CAAC;AAEhB,yCAAyC;AACzC,OAAO,EACL,WAAW,EACX,aAAa,EACb,gBAAgB,GAGjB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,55 @@
1
+ import type { ValidationError } from "../schema/types";
2
+ import { type FormConfig } from "../form";
3
+ /**
4
+ * Form field registration return type
5
+ * Compatible with React Hook Form style
6
+ */
7
+ export interface FieldRegistration {
8
+ name: string;
9
+ value: any;
10
+ onChange: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
11
+ onBlur: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
12
+ }
13
+ /**
14
+ * React form hook return type
15
+ */
16
+ export interface UseWasmFormReturn<T extends Record<string, any>> {
17
+ register: (name: keyof T) => FieldRegistration;
18
+ values: T;
19
+ errors: Record<keyof T, ValidationError | null>;
20
+ touched: Record<keyof T, boolean>;
21
+ isSubmitting: boolean;
22
+ isValid: boolean;
23
+ setValue: (field: keyof T, value: any) => void;
24
+ setError: (field: keyof T, error: ValidationError | null) => void;
25
+ handleSubmit: (event?: React.FormEvent<HTMLFormElement>) => Promise<void>;
26
+ reset: () => void;
27
+ }
28
+ /**
29
+ * React hook for WASM-powered form validation
30
+ *
31
+ * Usage:
32
+ * ```tsx
33
+ * const form = useWasmForm({
34
+ * schema: loginSchema,
35
+ * defaultValues: { email: '', password: '' },
36
+ * onSubmit: async (data) => console.log(data)
37
+ * });
38
+ *
39
+ * <form onSubmit={form.handleSubmit}>
40
+ * <input {...form.register('email')} />
41
+ * {form.errors.email && <span>{form.errors.email.message}</span>}
42
+ * </form>
43
+ * ```
44
+ */
45
+ export declare function useWasmForm<T extends Record<string, any>>(config: FormConfig<T>): UseWasmFormReturn<T>;
46
+ /**
47
+ * Hook to get field error message
48
+ * Returns error message if field is touched and has error
49
+ */
50
+ export declare function useFieldError<T extends Record<string, any>>(form: UseWasmFormReturn<T>, field: keyof T): string | null;
51
+ /**
52
+ * Hook to check if field has error
53
+ */
54
+ export declare function useFieldHasError<T extends Record<string, any>>(form: UseWasmFormReturn<T>, field: keyof T): boolean;
55
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/react/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAEtD;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CACR,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KAC7D,IAAI,CAAC;IACV,MAAM,EAAE,CACN,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB,GAAG,mBAAmB,CAAC,KAC5D,IAAI,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAE9D,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,iBAAiB,CAAC;IAG/C,MAAM,EAAE,CAAC,CAAC;IACV,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC,CAAC;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IAClC,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IAGjB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;IAClE,YAAY,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,eAAe,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACvD,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,GACpB,iBAAiB,CAAC,CAAC,CAAC,CAwGtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzD,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC1B,KAAK,EAAE,MAAM,CAAC,GACb,MAAM,GAAG,IAAI,CASf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5D,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC1B,KAAK,EAAE,MAAM,CAAC,GACb,OAAO,CAKT"}