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.
Files changed (66) hide show
  1. package/README.md +113 -688
  2. package/dist/cjs/core/schema/extensions/mods/typescript-generator.js +45 -16
  3. package/dist/cjs/core/schema/extensions/mods/typescript-generator.js.map +1 -1
  4. package/dist/cjs/core/schema/mode/interfaces/Interface.js +0 -12
  5. package/dist/cjs/core/schema/mode/interfaces/Interface.js.map +1 -1
  6. package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js +34 -3
  7. package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -1
  8. package/dist/cjs/core/schema/mode/interfaces/errors/SchemaValidationError.js +16 -0
  9. package/dist/cjs/core/schema/mode/interfaces/errors/SchemaValidationError.js.map +1 -0
  10. package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +119 -0
  11. package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -1
  12. package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +49 -0
  13. package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -1
  14. package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -1
  15. package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js +6 -0
  16. package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -1
  17. package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js +7 -0
  18. package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -1
  19. package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js +1 -1
  20. package/dist/cjs/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -1
  21. package/dist/cjs/core/utils/Mod.js +33 -4
  22. package/dist/cjs/core/utils/Mod.js.map +1 -1
  23. package/dist/cjs/index.js +74 -1
  24. package/dist/cjs/index.js.map +1 -1
  25. package/dist/esm/core/schema/extensions/mods/typescript-generator.js +45 -16
  26. package/dist/esm/core/schema/extensions/mods/typescript-generator.js.map +1 -1
  27. package/dist/esm/core/schema/mode/interfaces/Interface.js +1 -12
  28. package/dist/esm/core/schema/mode/interfaces/Interface.js.map +1 -1
  29. package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js +32 -1
  30. package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -1
  31. package/dist/esm/core/schema/mode/interfaces/errors/SchemaValidationError.js +14 -0
  32. package/dist/esm/core/schema/mode/interfaces/errors/SchemaValidationError.js.map +1 -0
  33. package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +119 -0
  34. package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -1
  35. package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +49 -0
  36. package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -1
  37. package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -1
  38. package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js +6 -0
  39. package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -1
  40. package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js +7 -0
  41. package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -1
  42. package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js +1 -1
  43. package/dist/esm/core/schema/mode/interfaces/validators/mods/securityValidator.js.map +1 -1
  44. package/dist/esm/core/utils/Mod.js +33 -4
  45. package/dist/esm/core/utils/Mod.js.map +1 -1
  46. package/dist/esm/index.js +78 -1
  47. package/dist/esm/index.js.map +1 -1
  48. package/dist/schema.d.ts +44 -3
  49. package/docs/FUNCTION-TYPES.md +120 -0
  50. package/docs/GETTING-STARTED.md +56 -53
  51. package/docs/VSCODE-EXTENSION.md +58 -47
  52. package/package.json +4 -4
  53. package/src/core/schema/extensions/components/AutoDocumentation/Docs.ts +1 -1
  54. package/src/core/schema/extensions/mods/typescript-generator.ts +342 -295
  55. package/src/core/schema/mode/interfaces/Interface.ts +1 -13
  56. package/src/core/schema/mode/interfaces/InterfaceSchema.ts +41 -1
  57. package/src/core/schema/mode/interfaces/errors/SchemaValidationError.ts +13 -0
  58. package/src/core/schema/mode/interfaces/precompilation/FieldPrecompilers.ts +146 -0
  59. package/src/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.ts +79 -0
  60. package/src/core/schema/mode/interfaces/typescript/TypeInference.ts +67 -16
  61. package/src/core/schema/mode/interfaces/validators/ConstraintParser.ts +8 -0
  62. package/src/core/schema/mode/interfaces/validators/TypeGuards.ts +19 -5
  63. package/src/core/schema/mode/interfaces/validators/mods/securityValidator.ts +1 -1
  64. package/src/core/types/SchemaValidator.type.ts +4 -0
  65. package/src/core/utils/Mod.ts +35 -4
  66. package/src/index.ts +9 -0
@@ -349,16 +349,4 @@ export { Mod } from "../../../utils/Mod";
349
349
  */
350
350
  export { Make } from "../../../utils/Make";
351
351
 
352
- /**
353
- * Custom error class for schema validation
354
- */
355
- export class SchemaValidationError extends Error {
356
- constructor(
357
- message: string,
358
- public errors: string[],
359
- public warnings: string[]
360
- ) {
361
- super(message);
362
- this.name = "SchemaValidationError";
363
- }
364
- }
352
+ export { SchemaValidationError } from "./errors/SchemaValidationError";
@@ -35,7 +35,7 @@ import {
35
35
  OptimizationLevel,
36
36
  } from "./precompilation/SchemaPrecompiler";
37
37
  import { MAX_OBJECT_DEPTH } from "../../../../constants/VALIDATION_CONSTANTS";
38
- import { SchemaValidationError } from "./Interface";
38
+ import { SchemaValidationError } from "./errors/SchemaValidationError";
39
39
  import { ErrorCode } from "./errors/types/errors.type";
40
40
 
41
41
  /**
@@ -54,6 +54,46 @@ export class InterfaceSchema<T = any> {
54
54
  private precompiledValidator?: PrecompiledValidator;
55
55
  private optimizationLevel: OptimizationLevel = OptimizationLevel.NONE;
56
56
 
57
+ /**
58
+ * Static generator for TypeScript types
59
+ * This is set by the extension system to avoid circular dependencies
60
+ */
61
+ public static tsGenerator?: (definition: SchemaInterface, options?: SchemaOptions) => string;
62
+
63
+ /**
64
+ * Get the TypeScript type definition for this schema.
65
+ * At runtime, this returns the TypeScript interface/type as a string.
66
+ * For TypeScript, this property has the inferred type T.
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const UserSchema = Interface({ name: "string" });
71
+ * type User = typeof UserSchema.types;
72
+ * console.log(UserSchema.types); // Outputs the TS interface string
73
+ * ```
74
+ */
75
+ get types(): T {
76
+ if (InterfaceSchema.tsGenerator) {
77
+ return InterfaceSchema.tsGenerator(this.definition, this.options) as any;
78
+ }
79
+
80
+ // Fallback: Generate a simple representation if generator not registered
81
+ let output = `export interface ${this.options.name || 'Schema'} {\n`;
82
+ for (const [key, value] of Object.entries(this.definition)) {
83
+ const isOptional = typeof value === 'string' && value.endsWith('?');
84
+ output += ` ${key}${isOptional ? '?' : ''}: any;\n`;
85
+ }
86
+ output += "}\n";
87
+ return output as any;
88
+ }
89
+
90
+ /**
91
+ * Alias for types property to support different coding styles
92
+ */
93
+ public getTypes(): T {
94
+ return this.types;
95
+ }
96
+
57
97
  constructor(
58
98
  private definition: SchemaInterface,
59
99
  private options: SchemaOptions = {}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Custom error class for schema validation
3
+ */
4
+ export class SchemaValidationError extends Error {
5
+ constructor(
6
+ message: string,
7
+ public errors: string[],
8
+ public warnings: string[] = []
9
+ ) {
10
+ super(message);
11
+ this.name = "SchemaValidationError";
12
+ }
13
+ }
@@ -703,6 +703,146 @@ export class FieldPrecompilers {
703
703
  return validator as CompiledFieldValidator;
704
704
  }
705
705
 
706
+ /**
707
+ * Precompile function field types (fn(() => void), etc.)
708
+ * ENHANCED: Implements function wrapping to validate arguments and return values at runtime.
709
+ */
710
+ static precompileFunction(functionType: string): CompiledFieldValidator {
711
+ const validator = (value: any): SchemaValidationResult => {
712
+ if (typeof value !== "function") {
713
+ return {
714
+ success: false,
715
+ errors: [ErrorHandler.createTypeError([], "function", value)],
716
+ warnings: [],
717
+ data: undefined,
718
+ };
719
+ }
720
+
721
+ // Extract signature: fn((args) => returnType)
722
+ const type = functionType.endsWith("?")
723
+ ? functionType.slice(0, -1)
724
+ : functionType;
725
+ const signature = type.slice(3, -1); // remove fn( and )
726
+
727
+ const arrowIndex = signature.lastIndexOf("=>");
728
+ if (arrowIndex === -1) {
729
+ return { success: true, errors: [], warnings: [], data: value };
730
+ }
731
+
732
+ const argsPart = signature.slice(0, arrowIndex).trim();
733
+ const returnPart = signature.slice(arrowIndex + 2).trim();
734
+
735
+ // Clean argsPart: remove outer parentheses if present
736
+ const cleanArgsPart =
737
+ argsPart.startsWith("(") && argsPart.endsWith(")")
738
+ ? argsPart.slice(1, -1)
739
+ : argsPart;
740
+
741
+ // Create a wrapped function that validates on call
742
+ const ReliantFunction = (...args: any[]) => {
743
+ // 1. Validate Arguments
744
+ if (cleanArgsPart && cleanArgsPart !== "()") {
745
+ const argDefs = cleanArgsPart.split(",").map((s) => s.trim());
746
+
747
+ for (let i = 0; i < argDefs.length; i++) {
748
+ const def = argDefs[i];
749
+ // Parse definition: name?: type or ...name: type
750
+ const parts = def.split(":");
751
+ const namePart = parts[0].trim();
752
+ let typePart = parts.slice(1).join(":").trim() || "any";
753
+
754
+ // Handle TYPE placeholder as any
755
+ if (typePart === "TYPE") typePart = "any";
756
+
757
+ const isRest = namePart.startsWith("...");
758
+ const isOptional = namePart.endsWith("?") || typePart.endsWith("?");
759
+
760
+ // Check for missing required arguments
761
+ // We check if the index exists in args. explicitly passing undefined is allowed if the type allows it,
762
+ // but not passing it at all is a missing argument error for required params.
763
+ if (!isRest && !isOptional && i >= args.length) {
764
+ throw new Error(
765
+ `[ReliantType] Missing required argument at index ${i} ('${namePart}'). Expected ${typePart}.`
766
+ );
767
+ }
768
+
769
+ if (isRest) {
770
+ const restType = typePart.endsWith("[]")
771
+ ? typePart.slice(0, -2)
772
+ : typePart;
773
+ const restArgs = args.slice(i);
774
+ const restValidator = FieldPrecompilers.parseAndCompile(restType);
775
+ for (const restArg of restArgs) {
776
+ const res = restValidator(restArg);
777
+ if (!res.success) {
778
+ throw new Error(
779
+ `[ReliantType] Argument validation failed for rest parameter at index ${i}: ${res.errors[0].message}`
780
+ );
781
+ }
782
+ }
783
+ break; // Rest is always last
784
+ } else {
785
+ // If argument is provided (or undefined but present), validate it
786
+ if (i < args.length) {
787
+ const argValidator =
788
+ FieldPrecompilers.parseAndCompile(typePart);
789
+ const res = argValidator(args[i]);
790
+ if (!res.success) {
791
+ throw new Error(
792
+ `[ReliantType] Argument validation failed for argument at index ${i} ('${namePart}'): ${res.errors[0].message}`
793
+ );
794
+ }
795
+ }
796
+ }
797
+ }
798
+ }
799
+
800
+ // 2. Execute original function
801
+ const result = value(...args);
802
+
803
+ // 3. Validate Return Value
804
+ if (returnPart && returnPart !== "void") {
805
+ // Handle TYPE placeholder as any
806
+ const returnType = returnPart === "TYPE" ? "any" : returnPart;
807
+
808
+ if (returnType !== "any") {
809
+ const returnValidator =
810
+ FieldPrecompilers.parseAndCompile(returnType);
811
+ const res = returnValidator(result);
812
+ if (!res.success) {
813
+ throw new Error(
814
+ `[ReliantType] Return value validation failed for ${functionType}. Expected ${returnType}, got ${typeof result}: ${res.errors[0].message}`
815
+ );
816
+ }
817
+ }
818
+ }
819
+
820
+ return result;
821
+ };
822
+
823
+ // Force function name for better debugging
824
+ try {
825
+ Object.defineProperty(ReliantFunction, "name", {
826
+ value: `ReliantFunction_${functionType.replace(/[^a-zA-Z0-9]/g, "_")}`,
827
+ configurable: true,
828
+ });
829
+ } catch (e) {
830
+ /* ignore */
831
+ }
832
+
833
+ return {
834
+ success: true,
835
+ errors: [],
836
+ warnings: [],
837
+ data: ReliantFunction,
838
+ };
839
+ };
840
+
841
+ (validator as any)._fieldType = functionType;
842
+ (validator as any)._isCompiled = true;
843
+ return validator as CompiledFieldValidator;
844
+ }
845
+
706
846
  /**
707
847
  * Precompile special field types (email, url, json, etc.)
708
848
  */
@@ -764,6 +904,12 @@ export class FieldPrecompilers {
764
904
  return isOptional ? this.precompileOptional(validator) : validator;
765
905
  }
766
906
 
907
+ // Handle function types (fn(() => void), etc.)
908
+ if (baseType.startsWith("fn(") && baseType.endsWith(")")) {
909
+ const validator = this.precompileFunction(baseType);
910
+ return isOptional ? this.precompileOptional(validator) : validator;
911
+ }
912
+
767
913
  // Handle basic types with constraints (including URL args like url.https)
768
914
  const constraintMatch = baseType.match(/^([\w.]+)(?:\(([^)]*)\))?$/);
769
915
  if (constraintMatch) {
@@ -16,6 +16,7 @@ import { MAX_COMPILATION_DEPTH as IMPORTED_MAX_COMPILATION_DEPTH } from "../../.
16
16
  import { ErrorHandler } from "../errors/ErrorHandler";
17
17
  import { ErrorCode } from "../errors/types/errors.type";
18
18
  import { SUPPORTED_VALIDATOR_TYPES } from "../../../../types/ValidatorTypes";
19
+ import { TypeGuards } from "../validators/TypeGuards";
19
20
 
20
21
  // Precompiled validator function signature
21
22
  export interface PrecompiledValidator {
@@ -208,6 +209,22 @@ export class SchemaPrecompiler {
208
209
  // OPTIMIZED: Process simple fields first (fastest path)
209
210
  for (const field of simpleFields) {
210
211
  const value = data[field.fieldName];
212
+
213
+ // Handle optional fields
214
+ if (value === undefined) {
215
+ if (!field.isOptional) {
216
+ errors.push(
217
+ ErrorHandler.createMissingFieldError(
218
+ [field.fieldName],
219
+ field.fieldName
220
+ )
221
+ );
222
+ } else if (field.hasDefault) {
223
+ validatedData[field.fieldName] = field.defaultValue;
224
+ }
225
+ continue;
226
+ }
227
+
211
228
  const result = field.validator(value);
212
229
 
213
230
  if (!result.success) {
@@ -228,6 +245,22 @@ export class SchemaPrecompiler {
228
245
  // OPTIMIZED: Process union fields with precompiled validators
229
246
  for (const field of unionFields) {
230
247
  const value = data[field.fieldName];
248
+
249
+ // Handle optional fields
250
+ if (value === undefined) {
251
+ if (!field.isOptional) {
252
+ errors.push(
253
+ ErrorHandler.createMissingFieldError(
254
+ [field.fieldName],
255
+ field.fieldName
256
+ )
257
+ );
258
+ } else if (field.hasDefault) {
259
+ validatedData[field.fieldName] = field.defaultValue;
260
+ }
261
+ continue;
262
+ }
263
+
231
264
  const result = field.validator(value);
232
265
 
233
266
  if (!result.success) {
@@ -248,6 +281,22 @@ export class SchemaPrecompiler {
248
281
  // OPTIMIZED: Process array fields
249
282
  for (const field of arrayFields) {
250
283
  const value = data[field.fieldName];
284
+
285
+ // Handle optional fields
286
+ if (value === undefined) {
287
+ if (!field.isOptional) {
288
+ errors.push(
289
+ ErrorHandler.createMissingFieldError(
290
+ [field.fieldName],
291
+ field.fieldName
292
+ )
293
+ );
294
+ } else if (field.hasDefault) {
295
+ validatedData[field.fieldName] = field.defaultValue;
296
+ }
297
+ continue;
298
+ }
299
+
251
300
  const result = field.validator(value);
252
301
 
253
302
  if (!result.success) {
@@ -268,6 +317,22 @@ export class SchemaPrecompiler {
268
317
  // OPTIMIZED: Process nested fields last
269
318
  for (const field of nestedFields) {
270
319
  const value = data[field.fieldName];
320
+
321
+ // Handle optional fields
322
+ if (value === undefined) {
323
+ if (!field.isOptional) {
324
+ errors.push(
325
+ ErrorHandler.createMissingFieldError(
326
+ [field.fieldName],
327
+ field.fieldName
328
+ )
329
+ );
330
+ } else if (field.hasDefault) {
331
+ validatedData[field.fieldName] = field.defaultValue;
332
+ }
333
+ continue;
334
+ }
335
+
271
336
  const result = field.validator(value);
272
337
 
273
338
  if (!result.success) {
@@ -391,6 +456,20 @@ export class SchemaPrecompiler {
391
456
  options: SchemaOptions,
392
457
  depth: number = 0
393
458
  ): FieldCompilation {
459
+ // Handle OptionalSchemaInterface wrapper (used by Mod.deepPartial and Mod.makeOptional)
460
+ if (TypeGuards.isOptionalSchemaInterface(fieldType)) {
461
+ const compilation = this.compileField(
462
+ fieldName,
463
+ fieldType.schema,
464
+ options,
465
+ depth
466
+ );
467
+ return {
468
+ ...compilation,
469
+ isOptional: true,
470
+ };
471
+ }
472
+
394
473
  // Handle nested objects properly
395
474
  if (
396
475
  typeof fieldType === "object" &&
@@ -53,16 +53,20 @@ export type CoreTypeMap = {
53
53
 
54
54
  // Special types
55
55
  unknown: unknown;
56
- void: undefined;
56
+ void: void;
57
57
  null: null;
58
58
  undefined: undefined;
59
+ TYPE: any;
59
60
  };
60
61
 
61
62
  /**
62
63
  * Extract base type from field type string (removes constraints and modifiers)
63
64
  */
64
- export type ExtractBaseType<T extends string> =
65
- T extends `${infer Base}(${string})`
65
+ export type ExtractBaseType<T extends string> = T extends
66
+ | `fn(${infer Sig})`
67
+ | `fn(${infer Sig})?`
68
+ ? `fn(${Sig})`
69
+ : T extends `${infer Base}(${string})`
66
70
  ? Base
67
71
  : T extends `${infer Base}?`
68
72
  ? Base
@@ -139,19 +143,22 @@ export type MapFieldType<T extends string> =
139
143
  : // Handle conditional expressions (contains "when" and "*?")
140
144
  T extends `when ${string} *? ${string}`
141
145
  ? InferConditionalType<T>
142
- : // Handle union types (contains |) - check after removing optional and parentheses
143
- ExtractBaseType<T> extends `${string}|${string}`
144
- ? ParseUnionType<ExtractBaseType<T>>
145
- : // Handle constant types (starts with =)
146
- T extends `=${infer Value}?`
147
- ? Value | undefined
148
- : T extends `=${infer Value}`
149
- ? Value
150
- : // Handle core types
151
- ExtractBaseType<T> extends keyof CoreTypeMap
152
- ? CoreTypeMap[ExtractBaseType<T>]
153
- : // Fallback to any for unknown types
154
- any;
146
+ : // Handle function types (fn((args) => void))
147
+ ExtractBaseType<T> extends `fn(${infer Sig})`
148
+ ? ParseFunctionType<Sig>
149
+ : // Handle union types (contains |) - check after removing optional and parentheses
150
+ ExtractBaseType<T> extends `${string}|${string}`
151
+ ? ParseUnionType<ExtractBaseType<T>>
152
+ : // Handle constant types (starts with =)
153
+ T extends `=${infer Value}?`
154
+ ? Value | undefined
155
+ : T extends `=${infer Value}`
156
+ ? Value
157
+ : // Handle core types
158
+ ExtractBaseType<T> extends keyof CoreTypeMap
159
+ ? CoreTypeMap[ExtractBaseType<T>]
160
+ : // Fallback to any for unknown types
161
+ any;
155
162
 
156
163
  /**
157
164
  * Utility type to trim whitespace from string literal types
@@ -174,6 +181,50 @@ export type ParseUnionType<T extends string> =
174
181
  ? Trim<First> | ParseUnionType<Rest>
175
182
  : Trim<T>;
176
183
 
184
+ /**
185
+ * Parse function signature string into a real TypeScript function type
186
+ */
187
+ export type ParseFunctionType<S extends string> =
188
+ S extends `(${infer Args}) => ${infer Return}`
189
+ ? (...args: ParseArgs<Args>) => ParseReturnType<Return>
190
+ : S extends `${infer Args} => ${infer Return}`
191
+ ? (...args: ParseArgs<Args>) => ParseReturnType<Return>
192
+ : (...args: any[]) => any;
193
+
194
+ /**
195
+ * Parse return type of a function
196
+ */
197
+ export type ParseReturnType<T extends string> =
198
+ Trim<T> extends "void"
199
+ ? void
200
+ : Trim<T> extends "TYPE"
201
+ ? any
202
+ : MapFieldType<Trim<T>>;
203
+
204
+ /**
205
+ * Parse arguments of a function into a tuple
206
+ */
207
+ export type ParseArgs<T extends string> =
208
+ Trim<T> extends ""
209
+ ? []
210
+ : Trim<T> extends `${infer First},${infer Rest}`
211
+ ? [...ParseArgAsTuple<First>, ...ParseArgs<Rest>]
212
+ : ParseArgAsTuple<T>;
213
+
214
+ /**
215
+ * Parse a single argument into a tuple element (handles rest parameters)
216
+ */
217
+ export type ParseArgAsTuple<T extends string> =
218
+ Trim<T> extends `${infer Name}:${infer Type}`
219
+ ? Name extends `...${infer RestName}`
220
+ ? MapFieldType<Trim<Type>> extends (infer U)[]
221
+ ? [...args: U[]]
222
+ : [...args: any[]]
223
+ : Name extends `${infer ArgName}?`
224
+ ? [arg?: MapFieldType<Trim<Type>> | undefined]
225
+ : [arg: MapFieldType<Trim<Type>>]
226
+ : [any];
227
+
177
228
  /**
178
229
  * Handle optional fields
179
230
  */
@@ -80,6 +80,9 @@ export class ConstraintParser {
80
80
 
81
81
  // Colon split for key-value pairs
82
82
  colonSplit: /\s*:\s*/,
83
+
84
+ // Function type detection
85
+ functionType: /^fn\(.*\)$/,
83
86
  } as const;
84
87
 
85
88
  // Character codes for optimized checks
@@ -201,6 +204,11 @@ export class ConstraintParser {
201
204
  return { type, constraints: {}, optional, required };
202
205
  }
203
206
 
207
+ // Handle function types (fn(() => void), etc.)
208
+ if (this._patterns.functionType.test(type)) {
209
+ return { type, constraints: {}, optional, required };
210
+ }
211
+
204
212
  // Enhanced constraint parsing with robust validation
205
213
  const constraintMatch = this._parseBalancedConstraints(type);
206
214
  if (constraintMatch) {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Type Guards Module
3
- *
3
+ *
4
4
  * Contains all type guard functions extracted from InterfaceSchema
5
5
  * to improve maintainability and reduce file size.
6
6
  */
@@ -12,7 +12,7 @@ import {
12
12
  OptionalSchemaInterface,
13
13
  UnionValue,
14
14
  } from "../../../../types/SchemaValidator.type";
15
-
15
+
16
16
  /**
17
17
  * Type guard functions for schema validation
18
18
  */
@@ -33,7 +33,9 @@ export class TypeGuards {
33
33
  /**
34
34
  * Check if value is a constant value
35
35
  */
36
- static isConstantValue(value: any): value is ConstantValue | OptionalConstantValue {
36
+ static isConstantValue(
37
+ value: any
38
+ ): value is ConstantValue | OptionalConstantValue {
37
39
  return (
38
40
  typeof value === "object" &&
39
41
  value !== null &&
@@ -45,7 +47,9 @@ export class TypeGuards {
45
47
  /**
46
48
  * Check if value is an optional schema interface
47
49
  */
48
- static isOptionalSchemaInterface(value: any): value is OptionalSchemaInterface {
50
+ static isOptionalSchemaInterface(
51
+ value: any
52
+ ): value is OptionalSchemaInterface {
49
53
  return (
50
54
  typeof value === "object" &&
51
55
  value !== null &&
@@ -137,6 +141,14 @@ export class TypeGuards {
137
141
  return fieldType.startsWith("record<") && fieldType.endsWith(">");
138
142
  }
139
143
 
144
+ /**
145
+ * Check if string is a function type
146
+ */
147
+ static isFunctionType(fieldType: string): boolean {
148
+ const type = fieldType.endsWith("?") ? fieldType.slice(0, -1) : fieldType;
149
+ return type.startsWith("fn(") && type.endsWith(")");
150
+ }
151
+
140
152
  /**
141
153
  * Check if string has constraints (contains parentheses)
142
154
  */
@@ -184,7 +196,9 @@ export class TypeGuards {
184
196
  * Check if value is a valid UUID format
185
197
  */
186
198
  static isValidUuid(value: string): boolean {
187
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
199
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(
200
+ value
201
+ );
188
202
  }
189
203
 
190
204
  /**
@@ -44,7 +44,7 @@ export class SecurityValidators {
44
44
  // security schema with more comprehensive protections
45
45
  this.ajv.addSchema(
46
46
  {
47
- $id: "https://nehonix.space/lib/v/reliant-type",
47
+ $id: "https://nehonix.com/lib/v/reliant-type",
48
48
  type: ["object", "array", "string", "number", "boolean", "null"],
49
49
  definitions: {
50
50
  secureObject: {
@@ -189,6 +189,10 @@ export interface SchemaOptions {
189
189
  enableOptimizations?: boolean;
190
190
  cacheValidation?: boolean;
191
191
  skipOptimization?: boolean; // Skip optimization to prevent circular dependency
192
+
193
+ // Metadata options
194
+ name?: string;
195
+ description?: string;
192
196
  }
193
197
 
194
198
  // Helper type for schemas that allow unknown properties
@@ -176,8 +176,22 @@ export class Mod {
176
176
 
177
177
  const partialDefinition: SchemaInterface = {};
178
178
  for (const [key, value] of Object.entries(definition)) {
179
- if (typeof value === "string" && !value.endsWith("?")) {
180
- partialDefinition[key] = value + "?";
179
+ if (typeof value === "string") {
180
+ partialDefinition[key] = value.endsWith("?") ? value : value + "?";
181
+ } else if (
182
+ typeof value === "object" &&
183
+ value !== null &&
184
+ !Array.isArray(value)
185
+ ) {
186
+ // For objects, wrap in optional schema interface if not already optional
187
+ if ("optional" in value && (value as any).optional === true) {
188
+ partialDefinition[key] = value;
189
+ } else {
190
+ partialDefinition[key] = {
191
+ schema: value,
192
+ optional: true,
193
+ };
194
+ }
181
195
  } else {
182
196
  partialDefinition[key] = value;
183
197
  }
@@ -195,8 +209,25 @@ export class Mod {
195
209
 
196
210
  const requiredDefinition: SchemaInterface = {};
197
211
  for (const [key, value] of Object.entries(definition)) {
198
- if (typeof value === "string" && value.endsWith("?")) {
199
- requiredDefinition[key] = value.slice(0, -1);
212
+ if (typeof value === "string") {
213
+ requiredDefinition[key] = value.endsWith("?")
214
+ ? value.slice(0, -1)
215
+ : value;
216
+ } else if (
217
+ typeof value === "object" &&
218
+ value !== null &&
219
+ !Array.isArray(value)
220
+ ) {
221
+ // Unwrap optional schema interface if present
222
+ if (
223
+ "optional" in value &&
224
+ (value as any).optional === true &&
225
+ "schema" in value
226
+ ) {
227
+ requiredDefinition[key] = (value as any).schema;
228
+ } else {
229
+ requiredDefinition[key] = value;
230
+ }
200
231
  } else {
201
232
  requiredDefinition[key] = value;
202
233
  }
package/src/index.ts CHANGED
@@ -122,3 +122,12 @@ export type {
122
122
  SchemaType,
123
123
  SchemaConfig,
124
124
  } from "./core/types/types";
125
+ import { InterfaceSchema } from "./core/schema/mode/interfaces/InterfaceSchema";
126
+ import { TSGenerator } from "./core/schema/extensions/mods/typescript-generator";
127
+
128
+ // Register the TypeScript generator for InterfaceSchema to enable .types property
129
+ InterfaceSchema.tsGenerator = (definition, options) => {
130
+ return TSGenerator.generateInterface(definition, {
131
+ exportName: options?.name || "Schema"
132
+ });
133
+ };