reliant-type 1.0.0 → 2.1.4
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/README.md +113 -688
- package/dist/cjs/core/schema/extensions/mods/typescript-generator.js +45 -16
- package/dist/cjs/core/schema/extensions/mods/typescript-generator.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/Interface.js +0 -12
- package/dist/cjs/core/schema/mode/interfaces/Interface.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js +34 -3
- package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/errors/SchemaValidationError.js +16 -0
- package/dist/cjs/core/schema/mode/interfaces/errors/SchemaValidationError.js.map +1 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +119 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +49 -0
- package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js +6 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js +7 -0
- package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -1
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js +1 -1
- package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -1
- package/dist/cjs/core/utils/Mod.js +33 -4
- package/dist/cjs/core/utils/Mod.js.map +1 -1
- package/dist/cjs/index.js +74 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/core/schema/extensions/mods/typescript-generator.js +45 -16
- package/dist/esm/core/schema/extensions/mods/typescript-generator.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/Interface.js +1 -12
- package/dist/esm/core/schema/mode/interfaces/Interface.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js +32 -1
- package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/errors/SchemaValidationError.js +14 -0
- package/dist/esm/core/schema/mode/interfaces/errors/SchemaValidationError.js.map +1 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +119 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +49 -0
- package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js +6 -0
- package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js +7 -0
- package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -1
- package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js +1 -1
- package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -1
- package/dist/esm/core/utils/Mod.js +33 -4
- package/dist/esm/core/utils/Mod.js.map +1 -1
- package/dist/esm/index.js +78 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/schema.d.ts +44 -3
- package/docs/FUNCTION-TYPES.md +120 -0
- package/docs/GETTING-STARTED.md +56 -53
- package/docs/VSCODE-EXTENSION.md +58 -47
- package/package.json +4 -4
- package/src/core/schema/extensions/components/AutoDocumentation/Docs.ts +1 -1
- package/src/core/schema/extensions/mods/typescript-generator.ts +342 -295
- package/src/core/schema/mode/interfaces/Interface.ts +1 -13
- package/src/core/schema/mode/interfaces/InterfaceSchema.ts +41 -1
- package/src/core/schema/mode/interfaces/errors/SchemaValidationError.ts +13 -0
- package/src/core/schema/mode/interfaces/precompilation/FieldPrecompilers.ts +146 -0
- package/src/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.ts +79 -0
- package/src/core/schema/mode/interfaces/typescript/TypeInference.ts +67 -16
- package/src/core/schema/mode/interfaces/validators/ConstraintParser.ts +8 -0
- package/src/core/schema/mode/interfaces/validators/TypeGuards.ts +19 -5
- package/src/core/schema/mode/interfaces/validators/mods/securityValidator.ts +1 -1
- package/src/core/types/SchemaValidator.type.ts +4 -0
- package/src/core/utils/Mod.ts +35 -4
- package/src/index.ts +9 -0
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { FieldTypes, Interface, QuickSchemas } from './core/schema/mode/interfaces/Interface.js';
|
|
2
2
|
export { Extensions, Quick } from './core/schema/extensions/index.js';
|
|
3
|
-
|
|
3
|
+
import { InterfaceSchema } from './core/schema/mode/interfaces/InterfaceSchema.js';
|
|
4
4
|
export { PerformanceMonitor } from './core/schema/optimization/PerformanceMonitor.js';
|
|
5
|
+
import { TypeScriptGenerator } from './core/schema/extensions/mods/typescript-generator.js';
|
|
5
6
|
export { Make } from './core/utils/Make.js';
|
|
6
7
|
export { Mod } from './core/utils/Mod.js';
|
|
7
8
|
export { Smart } from './core/schema/extensions/SmartInference.js';
|
|
@@ -9,4 +10,80 @@ export { When } from './core/schema/extensions/components/ConditionalValidation/
|
|
|
9
10
|
export { Live } from './core/schema/extensions/components/RealtimeValidation/index.js';
|
|
10
11
|
export { Docs } from './core/schema/extensions/components/AutoDocumentation/Docs.js';
|
|
11
12
|
export { TypeScriptGenerator } from './core/schema/extensions/components/AutoDocumentation/TypeScriptGenerator.js';
|
|
13
|
+
|
|
14
|
+
/***************************************************************************
|
|
15
|
+
* ReliantType - TypeScript Interface-like Schema Validation
|
|
16
|
+
*
|
|
17
|
+
* @file index.ts
|
|
18
|
+
*
|
|
19
|
+
* @author Nehonix
|
|
20
|
+
* @license MIT
|
|
21
|
+
*
|
|
22
|
+
* Copyright (c) 2025 Nehonix Team. All rights reserved.
|
|
23
|
+
*
|
|
24
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
25
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
26
|
+
* in the Software without restriction, including without limitation the rights
|
|
27
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
28
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
29
|
+
* furnished to do so, subject to the following conditions:
|
|
30
|
+
*
|
|
31
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
32
|
+
* copies or substantial portions of the Software.
|
|
33
|
+
*
|
|
34
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
35
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
36
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
37
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
38
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
39
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
40
|
+
* SOFTWARE.
|
|
41
|
+
*
|
|
42
|
+
****************************************************************************/
|
|
43
|
+
/**
|
|
44
|
+
* ReliantType - TypeScript Interface-like Schema Validation
|
|
45
|
+
*
|
|
46
|
+
* A schema validation system with TypeScript interface-like syntax
|
|
47
|
+
* that's incredibly easy to use and much safer than traditional schema libraries.
|
|
48
|
+
*
|
|
49
|
+
* @example Interface-based (Recommended)
|
|
50
|
+
* ```typescript
|
|
51
|
+
* import { Interface, Make, Mod } from 'reliant-type';
|
|
52
|
+
*
|
|
53
|
+
* const UserSchema = Interface({
|
|
54
|
+
* id: "number",
|
|
55
|
+
* email: "email",
|
|
56
|
+
* name: "string",
|
|
57
|
+
* age: "number?", // Optional
|
|
58
|
+
* status: Make.union("active", "inactive"),
|
|
59
|
+
* role: Make.const("user") // Safe constant
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Transform schemas easily
|
|
63
|
+
* const PublicUserSchema = Mod.omit(UserSchema, ["password"]);
|
|
64
|
+
* const PartialUserSchema = Mod.partial(UserSchema);
|
|
65
|
+
*
|
|
66
|
+
* const result = UserSchema.safeParse(userData);
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @example Traditional Fluent API
|
|
70
|
+
* ```typescript
|
|
71
|
+
* import { Schema } from 'reliant-type';
|
|
72
|
+
*
|
|
73
|
+
* const UserSchema = Schema.object({
|
|
74
|
+
* id: Schema.number().int().positive(),
|
|
75
|
+
* email: Schema.string().email(),
|
|
76
|
+
* name: Schema.string().min(2).max(50)
|
|
77
|
+
* });
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
// Main Interface-based API
|
|
81
|
+
// Register the TypeScript generator for InterfaceSchema to enable .types property
|
|
82
|
+
InterfaceSchema.tsGenerator = (definition, options) => {
|
|
83
|
+
return TypeScriptGenerator.generateInterface(definition, {
|
|
84
|
+
exportName: options?.name || "Schema"
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export { InterfaceSchema };
|
|
12
89
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":[null],"names":["TSGenerator"],"mappings":";;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4B8E;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCG;AAEH;AA2DA;AACA,eAAe,CAAC,WAAW,GAAG,CAAC,UAAU,EAAE,OAAO,KAAI;AACpD,IAAA,OAAOA,mBAAW,CAAC,iBAAiB,CAAC,UAAU,EAAE;AAC/C,QAAA,UAAU,EAAE,OAAO,EAAE,IAAI,IAAI,QAAQ;AACtC,KAAA,CAAC,CAAC;AACL,CAAC;;;;"}
|
package/dist/schema.d.ts
CHANGED
|
@@ -160,6 +160,8 @@ interface SchemaOptions {
|
|
|
160
160
|
enableOptimizations?: boolean;
|
|
161
161
|
cacheValidation?: boolean;
|
|
162
162
|
skipOptimization?: boolean;
|
|
163
|
+
name?: string;
|
|
164
|
+
description?: string;
|
|
163
165
|
}
|
|
164
166
|
type AllowUnknownSchema<T> = T & Record<string, any>;
|
|
165
167
|
|
|
@@ -184,6 +186,28 @@ declare class InterfaceSchema<T = any> {
|
|
|
184
186
|
private isOptimized;
|
|
185
187
|
private precompiledValidator?;
|
|
186
188
|
private optimizationLevel;
|
|
189
|
+
/**
|
|
190
|
+
* Static generator for TypeScript types
|
|
191
|
+
* This is set by the extension system to avoid circular dependencies
|
|
192
|
+
*/
|
|
193
|
+
static tsGenerator?: (definition: SchemaInterface, options?: SchemaOptions) => string;
|
|
194
|
+
/**
|
|
195
|
+
* Get the TypeScript type definition for this schema.
|
|
196
|
+
* At runtime, this returns the TypeScript interface/type as a string.
|
|
197
|
+
* For TypeScript, this property has the inferred type T.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const UserSchema = Interface({ name: "string" });
|
|
202
|
+
* type User = typeof UserSchema.types;
|
|
203
|
+
* console.log(UserSchema.types); // Outputs the TS interface string
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
get types(): T;
|
|
207
|
+
/**
|
|
208
|
+
* Alias for types property to support different coding styles
|
|
209
|
+
*/
|
|
210
|
+
getTypes(): T;
|
|
187
211
|
constructor(definition: SchemaInterface, options?: SchemaOptions);
|
|
188
212
|
/**
|
|
189
213
|
* Check if a field type uses conditional syntax using secure regex pattern
|
|
@@ -361,14 +385,15 @@ type CoreTypeMap = {
|
|
|
361
385
|
float: number;
|
|
362
386
|
double: number;
|
|
363
387
|
unknown: unknown;
|
|
364
|
-
void:
|
|
388
|
+
void: void;
|
|
365
389
|
null: null;
|
|
366
390
|
undefined: undefined;
|
|
391
|
+
TYPE: any;
|
|
367
392
|
};
|
|
368
393
|
/**
|
|
369
394
|
* Extract base type from field type string (removes constraints and modifiers)
|
|
370
395
|
*/
|
|
371
|
-
type ExtractBaseType<T extends string> = T extends `${infer Base}(${string})` ? Base : T extends `${infer Base}?` ? Base : T extends `${infer Base}[]` ? Base : T extends `${infer Base}[]?` ? Base : T extends `${infer Base}!` ? Base : T extends `(${infer Content})?` ? Content : T extends `(${infer Content})` ? Content : T;
|
|
396
|
+
type ExtractBaseType<T extends string> = T extends `fn(${infer Sig})` | `fn(${infer Sig})?` ? `fn(${Sig})` : T extends `${infer Base}(${string})` ? Base : T extends `${infer Base}?` ? Base : T extends `${infer Base}[]` ? Base : T extends `${infer Base}[]?` ? Base : T extends `${infer Base}!` ? Base : T extends `(${infer Content})?` ? Content : T extends `(${infer Content})` ? Content : T;
|
|
372
397
|
/**
|
|
373
398
|
* Check if field type is optional
|
|
374
399
|
*/
|
|
@@ -384,7 +409,7 @@ type ExtractElementType<T extends string> = T extends `${infer Element}[]` ? Ele
|
|
|
384
409
|
/**
|
|
385
410
|
* Map field type string to TypeScript type
|
|
386
411
|
*/
|
|
387
|
-
type MapFieldType<T extends string> = IsArray<T> extends true ? Array<MapFieldType<ExtractElementType<T>>> : T extends `record<${infer K}, ${infer V}>` ? Record<MapFieldType<K> extends string | number | symbol ? MapFieldType<K> : string, MapFieldType<V>> : T extends `Record<${infer K}, ${infer V}>` ? Record<MapFieldType<K> extends string | number | symbol ? MapFieldType<K> : string, MapFieldType<V>> : T extends `when ${string} *? ${string}` ? InferConditionalType<T> : ExtractBaseType<T> extends `${string}|${string}` ? ParseUnionType<ExtractBaseType<T>> : T extends `=${infer Value}?` ? Value | undefined : T extends `=${infer Value}` ? Value : ExtractBaseType<T> extends keyof CoreTypeMap ? CoreTypeMap[ExtractBaseType<T>] : any;
|
|
412
|
+
type MapFieldType<T extends string> = IsArray<T> extends true ? Array<MapFieldType<ExtractElementType<T>>> : T extends `record<${infer K}, ${infer V}>` ? Record<MapFieldType<K> extends string | number | symbol ? MapFieldType<K> : string, MapFieldType<V>> : T extends `Record<${infer K}, ${infer V}>` ? Record<MapFieldType<K> extends string | number | symbol ? MapFieldType<K> : string, MapFieldType<V>> : T extends `when ${string} *? ${string}` ? InferConditionalType<T> : ExtractBaseType<T> extends `fn(${infer Sig})` ? ParseFunctionType<Sig> : ExtractBaseType<T> extends `${string}|${string}` ? ParseUnionType<ExtractBaseType<T>> : T extends `=${infer Value}?` ? Value | undefined : T extends `=${infer Value}` ? Value : ExtractBaseType<T> extends keyof CoreTypeMap ? CoreTypeMap[ExtractBaseType<T>] : any;
|
|
388
413
|
/**
|
|
389
414
|
* Utility type to trim whitespace from string literal types
|
|
390
415
|
*/
|
|
@@ -393,6 +418,22 @@ type Trim<T extends string> = T extends ` ${infer Rest}` ? Trim<Rest> : T extend
|
|
|
393
418
|
* Parse union type string into union of literal types
|
|
394
419
|
*/
|
|
395
420
|
type ParseUnionType<T extends string> = T extends `(${infer Content})` ? ParseUnionType<Trim<Content>> : T extends `${infer First}|${infer Rest}` ? Trim<First> | ParseUnionType<Rest> : Trim<T>;
|
|
421
|
+
/**
|
|
422
|
+
* Parse function signature string into a real TypeScript function type
|
|
423
|
+
*/
|
|
424
|
+
type ParseFunctionType<S extends string> = S extends `(${infer Args}) => ${infer Return}` ? (...args: ParseArgs<Args>) => ParseReturnType<Return> : S extends `${infer Args} => ${infer Return}` ? (...args: ParseArgs<Args>) => ParseReturnType<Return> : (...args: any[]) => any;
|
|
425
|
+
/**
|
|
426
|
+
* Parse return type of a function
|
|
427
|
+
*/
|
|
428
|
+
type ParseReturnType<T extends string> = Trim<T> extends "void" ? void : Trim<T> extends "TYPE" ? any : MapFieldType<Trim<T>>;
|
|
429
|
+
/**
|
|
430
|
+
* Parse arguments of a function into a tuple
|
|
431
|
+
*/
|
|
432
|
+
type ParseArgs<T extends string> = Trim<T> extends "" ? [] : Trim<T> extends `${infer First},${infer Rest}` ? [...ParseArgAsTuple<First>, ...ParseArgs<Rest>] : ParseArgAsTuple<T>;
|
|
433
|
+
/**
|
|
434
|
+
* Parse a single argument into a tuple element (handles rest parameters)
|
|
435
|
+
*/
|
|
436
|
+
type ParseArgAsTuple<T extends string> = Trim<T> extends `${infer Name}:${infer Type}` ? Name extends `...${infer RestName}` ? MapFieldType<Trim<Type>> extends (infer U)[] ? [...args: U[]] : [...args: any[]] : Name extends `${infer ArgName}?` ? [arg?: MapFieldType<Trim<Type>> | undefined] : [arg: MapFieldType<Trim<Type>>] : [any];
|
|
396
437
|
/**
|
|
397
438
|
* Handle optional fields
|
|
398
439
|
*/
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Function Types
|
|
2
|
+
|
|
3
|
+
ReliantType introduces powerful runtime and compile-time validation for function signatures using the `fn` type. This feature allows you to define strict contracts for functions within your schema, ensuring that both arguments and return values adhere to specified types during execution.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The `fn` type enables you to describe function signatures using a syntax similar to TypeScript arrow functions. These definitions are used to:
|
|
8
|
+
|
|
9
|
+
1. **Validate at Runtime**: Wraps the function to strictly enforce argument types, argument count, and return types every time the function is called.
|
|
10
|
+
2. **Infer TypeScript Types**: Automatically generates accurate TypeScript definitions for your IDE, including argument names, types, and return values.
|
|
11
|
+
|
|
12
|
+
## Syntax
|
|
13
|
+
|
|
14
|
+
The general syntax follows the pattern:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
"fn((argument_list) => return_type)";
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Components
|
|
21
|
+
|
|
22
|
+
- **`fn(...)`**: The wrapper indicating a function type.
|
|
23
|
+
- **`argument_list`**: A comma-separated list of arguments in the format `name: type`.
|
|
24
|
+
- **`return_type`**: The expected return type of the function.
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
### 1. Basic Function Signatures
|
|
29
|
+
|
|
30
|
+
Define functions with specific argument types and return types.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
const schema = Interface({
|
|
34
|
+
// Function taking a string and returning a boolean
|
|
35
|
+
isValid: "fn((input: string) => boolean)",
|
|
36
|
+
|
|
37
|
+
// Function taking two numbers and returning a number
|
|
38
|
+
add: "fn((a: number, b: number) => number)",
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Optional Arguments
|
|
43
|
+
|
|
44
|
+
Mark arguments as optional using the `?` suffix on the argument name or type.
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
const schema = Interface({
|
|
48
|
+
// 'context' is optional
|
|
49
|
+
log: "fn((message: string, context?: object) => void)",
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Rest Parameters (Spread Operator)
|
|
54
|
+
|
|
55
|
+
Support for variadic functions using the spread operator (`...`). This is fully supported in both runtime validation and TypeScript inference.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const schema = Interface({
|
|
59
|
+
// Accepts any number of numeric arguments
|
|
60
|
+
sum: "fn((...numbers: number[]) => number)",
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 4. The `TYPE` Placeholder
|
|
65
|
+
|
|
66
|
+
Use `TYPE` as a placeholder for `any`. This is useful when you want to enforce the presence of an argument or a return value without strictly validating its content, or when the type is too complex to describe in a string.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
const schema = Interface({
|
|
70
|
+
// Accepts a generic input and returns a generic output
|
|
71
|
+
transform: "fn((input: TYPE) => TYPE)",
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 5. Void Return Type
|
|
76
|
+
|
|
77
|
+
Use `void` to indicate that the function should not return a value (or that the return value should be ignored).
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
const schema = Interface({
|
|
81
|
+
callback: "fn(() => void)",
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Runtime Validation Behavior
|
|
86
|
+
|
|
87
|
+
ReliantType enforces a **Strict Contract** policy for functions. When a function defined in a schema is accessed, it is wrapped in a validation proxy.
|
|
88
|
+
|
|
89
|
+
- **Argument Count**: Throws an error if required arguments are missing.
|
|
90
|
+
- **Argument Types**: Throws an error if an argument does not match its defined type.
|
|
91
|
+
- **Return Type**: Throws an error if the function returns a value that does not match the defined return type.
|
|
92
|
+
|
|
93
|
+
### Example of Validation Failure
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const config = {
|
|
97
|
+
// Incorrect implementation: returns a string instead of a number
|
|
98
|
+
calculator: (a, b) => "result",
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const schema = Interface({
|
|
102
|
+
calculator: "fn((a: number, b: number) => number)",
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const result = schema.parse(config);
|
|
106
|
+
|
|
107
|
+
// This call will THROW an Error:
|
|
108
|
+
// "[ReliantType] Return value validation failed... Expected number, got string"
|
|
109
|
+
result.calculator(10, 20);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## TypeScript Integration
|
|
113
|
+
|
|
114
|
+
The `fn` syntax is fully compatible with ReliantType's type inference system.
|
|
115
|
+
|
|
116
|
+
- `fn((a: string) => number)` infers to `(a: string) => number`
|
|
117
|
+
- `fn((...args: string[]) => void)` infers to `(...args: string[]) => void`
|
|
118
|
+
- `fn((opt?: string) => boolean)` infers to `(opt?: string | undefined) => boolean`
|
|
119
|
+
|
|
120
|
+
This ensures that your IDE provides correct autocompletion and type checking for implementation code.
|
package/docs/GETTING-STARTED.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Getting Started with ReliantType
|
|
2
2
|
|
|
3
3
|
Welcome to ReliantType! This guide will get you up and running in minutes with TypeScript-first validation using interface-native syntax.
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
## 🚀 Installation
|
|
6
6
|
|
|
7
7
|
### Requirements
|
|
8
|
+
|
|
8
9
|
- **TypeScript 4.5+** or **JavaScript ES2020+**
|
|
9
10
|
- **Node.js 14+** (for Node.js projects)
|
|
10
11
|
- **Modern browser** (for browser projects)
|
|
@@ -31,7 +32,7 @@ For the best development experience, install our VS Code extension:
|
|
|
31
32
|
|
|
32
33
|
```bash
|
|
33
34
|
# Download and install
|
|
34
|
-
curl -L https://
|
|
35
|
+
curl -L https://dll.nehonix.com/pkgs/mods/vscode/latest/reliant-type.vsix -o reliant-type.vsix
|
|
35
36
|
code --install-extension reliant-type.vsix
|
|
36
37
|
```
|
|
37
38
|
|
|
@@ -52,8 +53,8 @@ const UserSchema = Interface({
|
|
|
52
53
|
id: "number",
|
|
53
54
|
email: "email",
|
|
54
55
|
name: "string",
|
|
55
|
-
age: "number?",
|
|
56
|
-
isActive: "boolean"
|
|
56
|
+
age: "number?", // Optional field
|
|
57
|
+
isActive: "boolean",
|
|
57
58
|
});
|
|
58
59
|
```
|
|
59
60
|
|
|
@@ -66,7 +67,7 @@ const userData = {
|
|
|
66
67
|
email: "john@example.com",
|
|
67
68
|
name: "John Doe",
|
|
68
69
|
age: 30,
|
|
69
|
-
isActive: true
|
|
70
|
+
isActive: true,
|
|
70
71
|
};
|
|
71
72
|
|
|
72
73
|
// Validate with safeParse (recommended)
|
|
@@ -91,13 +92,13 @@ ReliantType uses familiar TypeScript interface syntax:
|
|
|
91
92
|
```typescript
|
|
92
93
|
// Looks like a TypeScript interface!
|
|
93
94
|
const ProductSchema = Interface({
|
|
94
|
-
id: "uuid",
|
|
95
|
-
name: "string(1,100)",
|
|
95
|
+
id: "uuid", // UUID validation
|
|
96
|
+
name: "string(1,100)", // String with length constraints
|
|
96
97
|
price: "number(0.01,9999.99)", // Number with range constraints
|
|
97
98
|
category: "electronics|books|clothing", // Union types
|
|
98
99
|
inStock: "boolean",
|
|
99
|
-
tags: "string[]?",
|
|
100
|
-
createdAt: "date"
|
|
100
|
+
tags: "string[]?", // Optional array
|
|
101
|
+
createdAt: "date", // Date validation
|
|
101
102
|
});
|
|
102
103
|
```
|
|
103
104
|
|
|
@@ -149,17 +150,17 @@ const BasicSchema = Interface({
|
|
|
149
150
|
age: "number",
|
|
150
151
|
active: "boolean",
|
|
151
152
|
birthday: "date",
|
|
152
|
-
|
|
153
|
+
|
|
153
154
|
// Optional types (add ?)
|
|
154
155
|
nickname: "string?",
|
|
155
156
|
bio: "string?",
|
|
156
|
-
|
|
157
|
+
|
|
157
158
|
// Arrays
|
|
158
159
|
tags: "string[]",
|
|
159
160
|
scores: "number[]?",
|
|
160
|
-
|
|
161
|
+
|
|
161
162
|
// Any type (use sparingly)
|
|
162
|
-
metadata: "any"
|
|
163
|
+
metadata: "any",
|
|
163
164
|
});
|
|
164
165
|
```
|
|
165
166
|
|
|
@@ -168,18 +169,18 @@ const BasicSchema = Interface({
|
|
|
168
169
|
```typescript
|
|
169
170
|
const ConstrainedSchema = Interface({
|
|
170
171
|
// String constraints
|
|
171
|
-
username: "string(3,20)",
|
|
172
|
-
password: "string(8,)",
|
|
173
|
-
code: "string(6,6)",
|
|
174
|
-
|
|
172
|
+
username: "string(3,20)", // 3-20 characters
|
|
173
|
+
password: "string(8,)", // Minimum 8 characters
|
|
174
|
+
code: "string(6,6)", // Exactly 6 characters
|
|
175
|
+
|
|
175
176
|
// Number constraints
|
|
176
|
-
age: "number(0,120)",
|
|
177
|
-
price: "number(0.01,)",
|
|
178
|
-
discount: "number(,0.5)",
|
|
179
|
-
|
|
177
|
+
age: "number(0,120)", // Range 0-120
|
|
178
|
+
price: "number(0.01,)", // Minimum 0.01
|
|
179
|
+
discount: "number(,0.5)", // Maximum 0.5
|
|
180
|
+
|
|
180
181
|
// Array constraints
|
|
181
|
-
tags: "string[](1,5)",
|
|
182
|
-
scores: "number[](,10)"
|
|
182
|
+
tags: "string[](1,5)", // 1-5 items
|
|
183
|
+
scores: "number[](,10)", // Maximum 10 items
|
|
183
184
|
});
|
|
184
185
|
```
|
|
185
186
|
|
|
@@ -191,10 +192,10 @@ const FormatSchema = Interface({
|
|
|
191
192
|
website: "url",
|
|
192
193
|
phone: "phone",
|
|
193
194
|
userId: "uuid",
|
|
194
|
-
|
|
195
|
+
|
|
195
196
|
// Custom regex patterns
|
|
196
197
|
zipCode: "string(/^\\d{5}(-\\d{4})?$/)",
|
|
197
|
-
productCode: "string(/^[A-Z]{2}\\d{4}$/)"
|
|
198
|
+
productCode: "string(/^[A-Z]{2}\\d{4}$/)",
|
|
198
199
|
});
|
|
199
200
|
```
|
|
200
201
|
|
|
@@ -205,10 +206,10 @@ const UnionSchema = Interface({
|
|
|
205
206
|
status: "active|inactive|pending",
|
|
206
207
|
role: "admin|user|guest|moderator",
|
|
207
208
|
theme: "light|dark|auto",
|
|
208
|
-
|
|
209
|
+
|
|
209
210
|
// Mixed type unions
|
|
210
211
|
id: "string|number",
|
|
211
|
-
value: "string|number|boolean"
|
|
212
|
+
value: "string|number|boolean",
|
|
212
213
|
});
|
|
213
214
|
```
|
|
214
215
|
|
|
@@ -222,11 +223,11 @@ ReliantType V2 introduces powerful conditional validation with runtime property
|
|
|
222
223
|
const ConditionalSchema = Interface({
|
|
223
224
|
role: "admin|user|guest",
|
|
224
225
|
config: "any?",
|
|
225
|
-
|
|
226
|
+
|
|
226
227
|
// V2 Runtime Methods
|
|
227
228
|
hasPermissions: "when config.permissions.$exists() *? boolean : =false",
|
|
228
229
|
isAdmin: "when role=admin *? boolean : =false",
|
|
229
|
-
canEdit: "when role.$in(admin,moderator) *? boolean : =false"
|
|
230
|
+
canEdit: "when role.$in(admin,moderator) *? boolean : =false",
|
|
230
231
|
});
|
|
231
232
|
```
|
|
232
233
|
|
|
@@ -235,26 +236,28 @@ const ConditionalSchema = Interface({
|
|
|
235
236
|
```typescript
|
|
236
237
|
const V2MethodsSchema = Interface({
|
|
237
238
|
data: "any?",
|
|
238
|
-
|
|
239
|
+
|
|
239
240
|
// Property existence
|
|
240
241
|
hasData: "when data.field.$exists() *? boolean : =false",
|
|
241
|
-
|
|
242
|
+
|
|
242
243
|
// Empty checking
|
|
243
244
|
isEmpty: "when data.list.$empty() *? boolean : =true",
|
|
244
|
-
|
|
245
|
+
|
|
245
246
|
// Null checking
|
|
246
247
|
isNull: "when data.value.$null() *? boolean : =false",
|
|
247
|
-
|
|
248
|
+
|
|
248
249
|
// String methods
|
|
249
|
-
containsText:
|
|
250
|
+
containsText:
|
|
251
|
+
"when data.description.$contains(important) *? boolean : =false",
|
|
250
252
|
startsWithPrefix: "when data.code.$startsWith(PRE) *? boolean : =false",
|
|
251
253
|
endsWithSuffix: "when data.filename.$endsWith(.pdf) *? boolean : =false",
|
|
252
|
-
|
|
254
|
+
|
|
253
255
|
// Numeric range
|
|
254
256
|
inRange: "when data.score.$between(0,100) *? boolean : =false",
|
|
255
|
-
|
|
257
|
+
|
|
256
258
|
// Value inclusion
|
|
257
|
-
isValidStatus:
|
|
259
|
+
isValidStatus:
|
|
260
|
+
"when data.status.$in(active,pending,inactive) *? boolean : =false",
|
|
258
261
|
});
|
|
259
262
|
```
|
|
260
263
|
|
|
@@ -270,15 +273,15 @@ const UserRegistrationSchema = Interface({
|
|
|
270
273
|
email: "email",
|
|
271
274
|
password: "string(8,128)",
|
|
272
275
|
confirmPassword: "string(8,128)",
|
|
273
|
-
|
|
276
|
+
|
|
274
277
|
// Profile
|
|
275
278
|
profile: {
|
|
276
279
|
firstName: "string(1,50)",
|
|
277
280
|
lastName: "string(1,50)",
|
|
278
281
|
dateOfBirth: "date?",
|
|
279
|
-
avatar: "url?"
|
|
282
|
+
avatar: "url?",
|
|
280
283
|
},
|
|
281
|
-
|
|
284
|
+
|
|
282
285
|
// Preferences
|
|
283
286
|
preferences: {
|
|
284
287
|
theme: "light|dark|auto",
|
|
@@ -286,23 +289,23 @@ const UserRegistrationSchema = Interface({
|
|
|
286
289
|
notifications: {
|
|
287
290
|
email: "boolean",
|
|
288
291
|
push: "boolean",
|
|
289
|
-
sms: "boolean"
|
|
290
|
-
}
|
|
292
|
+
sms: "boolean",
|
|
293
|
+
},
|
|
291
294
|
},
|
|
292
|
-
|
|
295
|
+
|
|
293
296
|
// Terms and conditions
|
|
294
297
|
acceptedTerms: "boolean",
|
|
295
298
|
acceptedPrivacy: "boolean",
|
|
296
|
-
|
|
299
|
+
|
|
297
300
|
// Optional marketing consent
|
|
298
301
|
marketingConsent: "boolean?",
|
|
299
|
-
|
|
302
|
+
|
|
300
303
|
// Runtime configuration for conditional validation
|
|
301
304
|
config: "any?",
|
|
302
|
-
|
|
305
|
+
|
|
303
306
|
// Conditional fields based on configuration
|
|
304
307
|
betaFeatures: "when config.beta.$exists() *? string[] : =[]",
|
|
305
|
-
premiumFeatures: "when config.premium.$exists() *? any : =null"
|
|
308
|
+
premiumFeatures: "when config.premium.$exists() *? any : =null",
|
|
306
309
|
});
|
|
307
310
|
|
|
308
311
|
// Usage
|
|
@@ -313,7 +316,7 @@ const registrationData = {
|
|
|
313
316
|
profile: {
|
|
314
317
|
firstName: "John",
|
|
315
318
|
lastName: "Doe",
|
|
316
|
-
dateOfBirth: new Date("1990-01-01")
|
|
319
|
+
dateOfBirth: new Date("1990-01-01"),
|
|
317
320
|
},
|
|
318
321
|
preferences: {
|
|
319
322
|
theme: "dark",
|
|
@@ -321,12 +324,12 @@ const registrationData = {
|
|
|
321
324
|
notifications: {
|
|
322
325
|
email: true,
|
|
323
326
|
push: false,
|
|
324
|
-
sms: false
|
|
325
|
-
}
|
|
327
|
+
sms: false,
|
|
328
|
+
},
|
|
326
329
|
},
|
|
327
330
|
acceptedTerms: true,
|
|
328
331
|
acceptedPrivacy: true,
|
|
329
|
-
marketingConsent: false
|
|
332
|
+
marketingConsent: false,
|
|
330
333
|
};
|
|
331
334
|
|
|
332
335
|
const result = UserRegistrationSchema.safeParse(registrationData);
|
|
@@ -336,8 +339,8 @@ if (result.success) {
|
|
|
336
339
|
// Process registration with result.data
|
|
337
340
|
} else {
|
|
338
341
|
console.log("❌ Validation errors:");
|
|
339
|
-
result.errors.forEach(error => {
|
|
340
|
-
console.log(`- ${error.path.join(
|
|
342
|
+
result.errors.forEach((error) => {
|
|
343
|
+
console.log(`- ${error.path.join(".")}: ${error.message}`);
|
|
341
344
|
});
|
|
342
345
|
}
|
|
343
346
|
```
|