reliant-type 1.0.0 → 2.1.3

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 (58) hide show
  1. package/dist/cjs/core/schema/extensions/mods/typescript-generator.js +45 -16
  2. package/dist/cjs/core/schema/extensions/mods/typescript-generator.js.map +1 -1
  3. package/dist/cjs/core/schema/mode/interfaces/Interface.js +0 -12
  4. package/dist/cjs/core/schema/mode/interfaces/Interface.js.map +1 -1
  5. package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js +34 -3
  6. package/dist/cjs/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -1
  7. package/dist/cjs/core/schema/mode/interfaces/errors/SchemaValidationError.js +16 -0
  8. package/dist/cjs/core/schema/mode/interfaces/errors/SchemaValidationError.js.map +1 -0
  9. package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +119 -0
  10. package/dist/cjs/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -1
  11. package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +49 -0
  12. package/dist/cjs/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -1
  13. package/dist/cjs/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -1
  14. package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js +6 -0
  15. package/dist/cjs/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -1
  16. package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js +7 -0
  17. package/dist/cjs/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -1
  18. package/dist/cjs/core/utils/Mod.js +33 -4
  19. package/dist/cjs/core/utils/Mod.js.map +1 -1
  20. package/dist/cjs/index.js +74 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/esm/core/schema/extensions/mods/typescript-generator.js +45 -16
  23. package/dist/esm/core/schema/extensions/mods/typescript-generator.js.map +1 -1
  24. package/dist/esm/core/schema/mode/interfaces/Interface.js +1 -12
  25. package/dist/esm/core/schema/mode/interfaces/Interface.js.map +1 -1
  26. package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js +32 -1
  27. package/dist/esm/core/schema/mode/interfaces/InterfaceSchema.js.map +1 -1
  28. package/dist/esm/core/schema/mode/interfaces/errors/SchemaValidationError.js +14 -0
  29. package/dist/esm/core/schema/mode/interfaces/errors/SchemaValidationError.js.map +1 -0
  30. package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js +119 -0
  31. package/dist/esm/core/schema/mode/interfaces/precompilation/FieldPrecompilers.js.map +1 -1
  32. package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js +49 -0
  33. package/dist/esm/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.js.map +1 -1
  34. package/dist/esm/core/schema/mode/interfaces/typescript/TypeInference.js.map +1 -1
  35. package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js +6 -0
  36. package/dist/esm/core/schema/mode/interfaces/validators/ConstraintParser.js.map +1 -1
  37. package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js +7 -0
  38. package/dist/esm/core/schema/mode/interfaces/validators/TypeGuards.js.map +1 -1
  39. package/dist/esm/core/utils/Mod.js +33 -4
  40. package/dist/esm/core/utils/Mod.js.map +1 -1
  41. package/dist/esm/index.js +78 -1
  42. package/dist/esm/index.js.map +1 -1
  43. package/dist/schema.d.ts +44 -3
  44. package/docs/FUNCTION-TYPES.md +120 -0
  45. package/package.json +4 -4
  46. package/src/core/schema/extensions/components/AutoDocumentation/Docs.ts +1 -1
  47. package/src/core/schema/extensions/mods/typescript-generator.ts +342 -295
  48. package/src/core/schema/mode/interfaces/Interface.ts +1 -13
  49. package/src/core/schema/mode/interfaces/InterfaceSchema.ts +41 -1
  50. package/src/core/schema/mode/interfaces/errors/SchemaValidationError.ts +13 -0
  51. package/src/core/schema/mode/interfaces/precompilation/FieldPrecompilers.ts +146 -0
  52. package/src/core/schema/mode/interfaces/precompilation/SchemaPrecompiler.ts +79 -0
  53. package/src/core/schema/mode/interfaces/typescript/TypeInference.ts +67 -16
  54. package/src/core/schema/mode/interfaces/validators/ConstraintParser.ts +8 -0
  55. package/src/core/schema/mode/interfaces/validators/TypeGuards.ts +19 -5
  56. package/src/core/types/SchemaValidator.type.ts +4 -0
  57. package/src/core/utils/Mod.ts +35 -4
  58. package/src/index.ts +9 -0
@@ -6,237 +6,284 @@
6
6
  */
7
7
 
8
8
  import { SchemaInterface } from "../../mode/interfaces/Interface";
9
+ import { TypeGuards } from "../../mode/interfaces/validators/TypeGuards";
9
10
 
10
11
  /**
11
12
  * TypeScript code generator for schema definitions
12
13
  */
13
14
  export class TypeScriptGenerator {
14
- /**
15
- * Generate TypeScript interface from schema
16
- */
17
- static generateInterface(
18
- schema: SchemaInterface,
19
- options: TypeScriptOptions = {}
20
- ): string {
21
- const { exportName = "Schema", namespace, exportType = "interface" } = options;
22
-
23
- // Extract the actual field definitions from the schema
24
- const fieldDefinitions = this.extractFieldDefinitions(schema);
25
-
26
- let output = "";
27
-
28
- // Add namespace if specified
29
- if (namespace) {
30
- output += `export namespace ${namespace} {\n`;
31
- }
32
-
33
- // Generate interface or type
34
- if (exportType === "interface") {
35
- output += this.generateInterfaceDefinition(fieldDefinitions, exportName, namespace ? 1 : 0);
36
- } else {
37
- output += this.generateTypeDefinition(fieldDefinitions, exportName, namespace ? 1 : 0);
38
- }
15
+ /**
16
+ * Generate TypeScript interface from schema
17
+ */
18
+ static generateInterface(
19
+ schema: SchemaInterface,
20
+ options: TypeScriptOptions = {}
21
+ ): string {
22
+ const {
23
+ exportName = "Schema",
24
+ namespace,
25
+ exportType = "interface",
26
+ } = options;
27
+
28
+ // Extract the actual field definitions from the schema
29
+ const fieldDefinitions = this.extractFieldDefinitions(schema);
30
+
31
+ let output = "";
32
+
33
+ // Add namespace if specified
34
+ if (namespace) {
35
+ output += `export namespace ${namespace} {\n`;
36
+ }
39
37
 
40
- // Close namespace if specified
41
- if (namespace) {
42
- output += "}\n";
43
- }
38
+ // Generate interface or type
39
+ if (exportType === "interface") {
40
+ output += this.generateInterfaceDefinition(
41
+ fieldDefinitions,
42
+ exportName,
43
+ namespace ? 1 : 0
44
+ );
45
+ } else {
46
+ output += this.generateTypeDefinition(
47
+ fieldDefinitions,
48
+ exportName,
49
+ namespace ? 1 : 0
50
+ );
51
+ }
44
52
 
45
- return output;
53
+ // Close namespace if specified
54
+ if (namespace) {
55
+ output += "}\n";
46
56
  }
47
57
 
48
- /**
49
- * Extract field definitions from schema object
50
- */
51
- private static extractFieldDefinitions(schema: any): Record<string, any> {
52
- // If schema has a definition property, use that
53
- if (schema && typeof schema === 'object' && schema.definition) {
54
- return schema.definition;
55
- }
58
+ return output;
59
+ }
56
60
 
57
- // Otherwise, assume the schema itself contains the field definitions
58
- return schema;
61
+ /**
62
+ * Extract field definitions from schema object
63
+ */
64
+ private static extractFieldDefinitions(schema: any): Record<string, any> {
65
+ // If schema has a definition property, use that
66
+ if (schema && typeof schema === "object" && schema.definition) {
67
+ return schema.definition;
59
68
  }
60
69
 
61
- /**
62
- * Generate interface definition
63
- */
64
- private static generateInterfaceDefinition(
65
- schema: SchemaInterface,
66
- name: string,
67
- indentLevel: number = 0
68
- ): string {
69
- const indent = " ".repeat(indentLevel);
70
- let output = `${indent}export interface ${name} {\n`;
71
-
72
- Object.entries(schema).forEach(([fieldName, fieldType]) => {
73
- const tsType = this.convertToTypeScript(fieldType);
74
- const optional = this.isOptionalField(fieldType) ? "?" : "";
75
- output += `${indent} ${fieldName}${optional}: ${tsType};\n`;
76
- });
77
-
78
- output += `${indent}}\n`;
79
- return output;
70
+ // Otherwise, assume the schema itself contains the field definitions
71
+ return schema;
72
+ }
73
+
74
+ /**
75
+ * Generate interface definition
76
+ */
77
+ private static generateInterfaceDefinition(
78
+ schema: SchemaInterface,
79
+ name: string,
80
+ indentLevel: number = 0
81
+ ): string {
82
+ const indent = " ".repeat(indentLevel);
83
+ let output = `${indent}export interface ${name} {\n`;
84
+
85
+ Object.entries(schema).forEach(([fieldName, fieldType]) => {
86
+ const tsType = this.convertToTypeScript(fieldType, indentLevel + 1);
87
+ const optional = this.isOptionalField(fieldType) ? "?" : "";
88
+ output += `${indent} ${fieldName}${optional}: ${tsType};\n`;
89
+ });
90
+
91
+ output += `${indent}}\n`;
92
+ return output;
93
+ }
94
+
95
+ /**
96
+ * Generate type alias definition
97
+ */
98
+ private static generateTypeDefinition(
99
+ schema: SchemaInterface,
100
+ name: string,
101
+ indentLevel: number = 0
102
+ ): string {
103
+ const indent = " ".repeat(indentLevel);
104
+ const objectType = this.convertObjectToTypeScript(schema, indentLevel);
105
+ return `${indent}export type ${name} = ${objectType};\n`;
106
+ }
107
+
108
+ /**
109
+ * Convert schema field to TypeScript type
110
+ */
111
+ private static convertToTypeScript(
112
+ fieldType: any,
113
+ indentLevel: number = 0
114
+ ): string {
115
+ // Handle OptionalSchemaInterface wrapper
116
+ if (TypeGuards.isOptionalSchemaInterface(fieldType)) {
117
+ return this.convertToTypeScript(fieldType.schema, indentLevel);
80
118
  }
81
119
 
82
- /**
83
- * Generate type alias definition
84
- */
85
- private static generateTypeDefinition(
86
- schema: SchemaInterface,
87
- name: string,
88
- indentLevel: number = 0
89
- ): string {
90
- const indent = " ".repeat(indentLevel);
91
- const objectType = this.convertObjectToTypeScript(schema);
92
- return `${indent}export type ${name} = ${objectType};\n`;
120
+ if (typeof fieldType === "string") {
121
+ return this.convertStringToTypeScript(fieldType);
93
122
  }
94
123
 
95
- /**
96
- * Convert schema field to TypeScript type
97
- */
98
- private static convertToTypeScript(fieldType: any): string {
99
- if (typeof fieldType === "string") {
100
- return this.convertStringToTypeScript(fieldType);
101
- }
102
-
103
- if (typeof fieldType === "object" && !Array.isArray(fieldType)) {
104
- // Handle Make.union() objects
105
- if (fieldType.union && Array.isArray(fieldType.union)) {
106
- return fieldType.union.map((value: any) => `"${value}"`).join(" | ");
107
- }
108
-
109
- // Handle Make.const() objects
110
- if (fieldType.const !== undefined) {
111
- return `"${fieldType.const}"`;
112
- }
124
+ if (typeof fieldType === "object" && !Array.isArray(fieldType)) {
125
+ // Handle Make.union() objects
126
+ if (fieldType.union && Array.isArray(fieldType.union)) {
127
+ return fieldType.union.map((value: any) => `"${value}"`).join(" | ");
128
+ }
113
129
 
114
- return this.convertObjectToTypeScript(fieldType);
115
- }
130
+ // Handle Make.const() objects
131
+ if (fieldType.const !== undefined) {
132
+ return `"${fieldType.const}"`;
133
+ }
116
134
 
117
- return "any";
135
+ return this.convertObjectToTypeScript(fieldType, indentLevel);
118
136
  }
119
137
 
120
- /**
121
- * Convert string-based field to TypeScript type
122
- */
123
- private static convertStringToTypeScript(fieldType: string): string {
124
- const cleanType = fieldType.replace("?", "");
125
-
126
- // Handle arrays FIRST - before other checks
127
- if (cleanType.includes("[]")) {
128
- const elementType = cleanType.replace("[]", "").replace(/\([^)]*\)/, ""); // Remove constraints
129
- const tsElementType = this.convertStringToTypeScript(elementType);
130
- return `${tsElementType}[]`;
131
- }
132
-
133
- // Handle number types with constraints
134
- if (cleanType.startsWith("number(") || cleanType.includes("number(")) {
135
- return "number";
136
- }
137
-
138
- // Basic type mappings
139
- const typeMappings: Record<string, string> = {
140
- email: "string",
141
- url: "string",
142
- uuid: "string",
143
- phone: "string",
144
- date: "Date",
145
- number: "number",
146
- positive: "number",
147
- int: "number",
148
- boolean: "boolean",
149
- string: "string"
150
- };
151
-
152
- // Check for direct mapping
153
- if (typeMappings[cleanType]) {
154
- return typeMappings[cleanType];
155
- }
138
+ if (Array.isArray(fieldType) && fieldType.length === 1) {
139
+ return `${this.convertToTypeScript(fieldType[0], indentLevel)}[]`;
140
+ }
156
141
 
157
- // Handle string with constraints
158
- if (cleanType.startsWith("string")) {
159
- return "string";
160
- }
142
+ return "any";
143
+ }
161
144
 
162
- // Handle union types (pipe-separated values)
163
- if (cleanType.includes("|")) {
164
- const unionTypes = cleanType.split("|").map(t => `"${t.trim()}"`);
165
- return unionTypes.join(" | ");
166
- }
145
+ /**
146
+ * Convert string-based field to TypeScript type
147
+ */
148
+ private static convertStringToTypeScript(fieldType: string): string {
149
+ const cleanType = fieldType.replace("?", "");
167
150
 
168
- return "string";
151
+ // Handle function types
152
+ if (TypeGuards.isFunctionType(fieldType)) {
153
+ const type = fieldType.endsWith("?") ? fieldType.slice(0, -1) : fieldType;
154
+ const signature = type.slice(3, -1); // remove fn( and )
155
+ return signature.replace(/TYPE/g, "any");
169
156
  }
170
157
 
171
- /**
172
- * Convert object to TypeScript type
173
- */
174
- private static convertObjectToTypeScript(obj: any): string {
175
- if (typeof obj !== "object" || obj === null) {
176
- return "any";
177
- }
158
+ // Handle arrays FIRST - before other checks
159
+ if (cleanType.includes("[]")) {
160
+ const elementType = cleanType.replace("[]", "").replace(/\([^)]*\)/, ""); // Remove constraints
161
+ const tsElementType = this.convertStringToTypeScript(elementType);
162
+ return `${tsElementType}[]`;
163
+ }
178
164
 
179
- const properties: string[] = [];
165
+ // Handle number types with constraints
166
+ if (cleanType.startsWith("number(") || cleanType.includes("number(")) {
167
+ return "number";
168
+ }
180
169
 
181
- Object.entries(obj).forEach(([key, value]) => {
182
- const tsType = this.convertToTypeScript(value);
183
- const optional = this.isOptionalField(value) ? "?" : "";
184
- properties.push(`${key}${optional}: ${tsType}`);
185
- });
170
+ // Basic type mappings
171
+ const typeMappings: Record<string, string> = {
172
+ email: "string",
173
+ url: "string",
174
+ uuid: "string",
175
+ phone: "string",
176
+ date: "Date",
177
+ number: "number",
178
+ positive: "number",
179
+ int: "number",
180
+ boolean: "boolean",
181
+ string: "string",
182
+ object: "Record<string, any>",
183
+ any: "any",
184
+ record: "Record<string, any>",
185
+ };
186
+
187
+ // Check for direct mapping
188
+ if (typeMappings[cleanType]) {
189
+ return typeMappings[cleanType];
190
+ }
186
191
 
187
- return `{\n ${properties.join(";\n ")};\n}`;
192
+ // Handle string with constraints
193
+ if (cleanType.startsWith("string")) {
194
+ return "string";
188
195
  }
189
196
 
190
- /**
191
- * Check if field is optional
192
- */
193
- private static isOptionalField(fieldType: any): boolean {
194
- if (typeof fieldType === "string") {
195
- return fieldType.includes("?");
196
- }
197
- return false;
197
+ // Handle union types (pipe-separated values)
198
+ if (cleanType.includes("|")) {
199
+ const unionTypes = cleanType.split("|").map((t) => {
200
+ const trimmed = t.trim();
201
+ // If it's a known type, use its mapping, otherwise treat as literal
202
+ return typeMappings[trimmed] || `"${trimmed}"`;
203
+ });
204
+ return unionTypes.join(" | ");
198
205
  }
199
206
 
200
- /**
201
- * Generate utility types for schema
202
- */
203
- static generateUtilityTypes(
204
- schema: SchemaInterface,
205
- baseName: string
206
- ): string {
207
- let output = "";
208
-
209
- // Generate partial type
210
- output += `export type Partial${baseName} = Partial<${baseName}>;\n\n`;
211
-
212
- // Generate required type
213
- output += `export type Required${baseName} = Required<${baseName}>;\n\n`;
214
-
215
- // Generate pick types for common field combinations
216
- const fields = Object.keys(schema);
217
- if (fields.length > 1) {
218
- output += `export type ${baseName}Keys = keyof ${baseName};\n\n`;
219
-
220
- // Generate create type (without optional fields)
221
- const requiredFields = fields.filter(field =>
222
- !this.isOptionalField(schema[field])
223
- );
224
-
225
- if (requiredFields.length > 0 && requiredFields.length < fields.length) {
226
- output += `export type Create${baseName} = Pick<${baseName}, ${
227
- requiredFields.map(f => `"${f}"`).join(" | ")
228
- }>;\n\n`;
229
- }
230
- }
207
+ return "any"; // Changed fallback from "string" to "any"
208
+ }
209
+
210
+ /**
211
+ * Convert object to TypeScript type
212
+ */
213
+ private static convertObjectToTypeScript(
214
+ obj: any,
215
+ indentLevel: number = 0
216
+ ): string {
217
+ if (typeof obj !== "object" || obj === null) {
218
+ return "any";
219
+ }
231
220
 
232
- return output;
221
+ const indent = " ".repeat(indentLevel);
222
+ const nextIndent = " ".repeat(indentLevel + 1);
223
+ const properties: string[] = [];
224
+
225
+ Object.entries(obj).forEach(([key, value]) => {
226
+ const tsType = this.convertToTypeScript(value, indentLevel + 1);
227
+ const optional = this.isOptionalField(value) ? "?" : "";
228
+ properties.push(`${nextIndent}${key}${optional}: ${tsType}`);
229
+ });
230
+
231
+ return `{\n${properties.join(";\n")};\n${indent}}`;
232
+ }
233
+
234
+ /**
235
+ * Check if field is optional
236
+ */
237
+ private static isOptionalField(fieldType: any): boolean {
238
+ if (TypeGuards.isOptionalSchemaInterface(fieldType)) {
239
+ return true;
240
+ }
241
+ if (typeof fieldType === "string") {
242
+ return fieldType.includes("?");
243
+ }
244
+ return false;
245
+ }
246
+
247
+ /**
248
+ * Generate utility types for schema
249
+ */
250
+ static generateUtilityTypes(
251
+ schema: SchemaInterface,
252
+ baseName: string
253
+ ): string {
254
+ let output = "";
255
+
256
+ // Generate partial type
257
+ output += `export type Partial${baseName} = Partial<${baseName}>;\n\n`;
258
+
259
+ // Generate required type
260
+ output += `export type Required${baseName} = Required<${baseName}>;\n\n`;
261
+
262
+ // Generate pick types for common field combinations
263
+ const fields = Object.keys(schema);
264
+ if (fields.length > 1) {
265
+ output += `export type ${baseName}Keys = keyof ${baseName};\n\n`;
266
+
267
+ // Generate create type (without optional fields)
268
+ const requiredFields = fields.filter(
269
+ (field) => !this.isOptionalField(schema[field])
270
+ );
271
+
272
+ if (requiredFields.length > 0 && requiredFields.length < fields.length) {
273
+ output += `export type Create${baseName} = Pick<${baseName}, ${requiredFields
274
+ .map((f) => `"${f}"`)
275
+ .join(" | ")}>;\n\n`;
276
+ }
233
277
  }
234
278
 
235
- /**
236
- * Generate validation function types
237
- */
238
- static generateValidationTypes(baseName: string): string {
239
- return `
279
+ return output;
280
+ }
281
+
282
+ /**
283
+ * Generate validation function types
284
+ */
285
+ static generateValidationTypes(baseName: string): string {
286
+ return `
240
287
  export interface ${baseName}ValidationResult {
241
288
  isValid: boolean;
242
289
  data: ${baseName};
@@ -256,124 +303,124 @@ export interface ${baseName}ParseResult {
256
303
  };
257
304
  }
258
305
  `;
306
+ }
307
+
308
+ /**
309
+ * Generate complete TypeScript module
310
+ */
311
+ static generateModule(
312
+ schema: SchemaInterface,
313
+ options: ModuleOptions
314
+ ): string {
315
+ const {
316
+ moduleName,
317
+ exportName = "Schema",
318
+ includeUtilities = true,
319
+ includeValidation = true,
320
+ header,
321
+ } = options;
322
+
323
+ let output = "";
324
+
325
+ // Add header comment
326
+ if (header) {
327
+ output += `/**\n * ${header}\n */\n\n`;
259
328
  }
260
329
 
261
- /**
262
- * Generate complete TypeScript module
263
- */
264
- static generateModule(
265
- schema: SchemaInterface,
266
- options: ModuleOptions
267
- ): string {
268
- const {
269
- moduleName,
270
- exportName = "Schema",
271
- includeUtilities = true,
272
- includeValidation = true,
273
- header
274
- } = options;
275
-
276
- let output = "";
277
-
278
- // Add header comment
279
- if (header) {
280
- output += `/**\n * ${header}\n */\n\n`;
281
- }
282
-
283
- // Generate main interface
284
- output += this.generateInterface(schema, { exportName });
285
- output += "\n";
286
-
287
- // Generate utility types
288
- if (includeUtilities) {
289
- output += this.generateUtilityTypes(schema, exportName);
290
- }
291
-
292
- // Generate validation types
293
- if (includeValidation) {
294
- output += this.generateValidationTypes(exportName);
295
- }
296
-
297
- // Add module export
298
- if (moduleName) {
299
- output += `\nexport const ${moduleName} = {\n`;
300
- output += ` name: "${exportName}",\n`;
301
- output += ` fields: ${JSON.stringify(Object.keys(schema), null, 2)}\n`;
302
- output += "};\n";
303
- }
330
+ // Generate main interface
331
+ output += this.generateInterface(schema, { exportName });
332
+ output += "\n";
304
333
 
305
- return output;
334
+ // Generate utility types
335
+ if (includeUtilities) {
336
+ output += this.generateUtilityTypes(schema, exportName);
306
337
  }
307
338
 
308
- /**
309
- * Generate JSDoc comments for schema fields
310
- */
311
- static generateJSDoc(schema: SchemaInterface): Record<string, string> {
312
- const docs: Record<string, string> = {};
313
-
314
- Object.entries(schema).forEach(([fieldName, fieldType]) => {
315
- docs[fieldName] = this.generateFieldJSDoc(fieldName, fieldType);
316
- });
339
+ // Generate validation types
340
+ if (includeValidation) {
341
+ output += this.generateValidationTypes(exportName);
342
+ }
317
343
 
318
- return docs;
344
+ // Add module export
345
+ if (moduleName) {
346
+ output += `\nexport const ${moduleName} = {\n`;
347
+ output += ` name: "${exportName}",\n`;
348
+ output += ` fields: ${JSON.stringify(Object.keys(schema), null, 2)}\n`;
349
+ output += "};\n";
319
350
  }
320
351
 
321
- /**
322
- * Generate JSDoc for a single field
323
- */
324
- private static generateFieldJSDoc(fieldName: string, fieldType: any): string {
325
- if (typeof fieldType === "string") {
326
- const cleanType = fieldType.replace("?", "");
327
- const isOptional = fieldType.includes("?");
328
-
329
- let description = `${fieldName} field`;
330
-
331
- // Add type-specific descriptions
332
- if (cleanType === "email") description = "Email address";
333
- else if (cleanType === "url") description = "URL address";
334
- else if (cleanType === "uuid") description = "Unique identifier";
335
- else if (cleanType === "date") description = "Date and time";
336
- else if (cleanType === "positive") description = "Positive number";
337
- else if (cleanType.startsWith("string")) description = "Text value";
338
- else if (cleanType.includes("[]")) description = "Array of values";
339
-
340
- let jsdoc = `/**\n * ${description}`;
341
-
342
- if (isOptional) {
343
- jsdoc += "\n * @optional";
344
- }
345
-
346
- // Add constraints info
347
- if (cleanType.includes("(")) {
348
- const match = cleanType.match(/\(([^)]+)\)/);
349
- if (match) {
350
- jsdoc += `\n * @constraints ${match[1]}`;
351
- }
352
- }
353
-
354
- jsdoc += "\n */";
355
- return jsdoc;
352
+ return output;
353
+ }
354
+
355
+ /**
356
+ * Generate JSDoc comments for schema fields
357
+ */
358
+ static generateJSDoc(schema: SchemaInterface): Record<string, string> {
359
+ const docs: Record<string, string> = {};
360
+
361
+ Object.entries(schema).forEach(([fieldName, fieldType]) => {
362
+ docs[fieldName] = this.generateFieldJSDoc(fieldName, fieldType);
363
+ });
364
+
365
+ return docs;
366
+ }
367
+
368
+ /**
369
+ * Generate JSDoc for a single field
370
+ */
371
+ private static generateFieldJSDoc(fieldName: string, fieldType: any): string {
372
+ if (typeof fieldType === "string") {
373
+ const cleanType = fieldType.replace("?", "");
374
+ const isOptional = fieldType.includes("?");
375
+
376
+ let description = `${fieldName} field`;
377
+
378
+ // Add type-specific descriptions
379
+ if (cleanType === "email") description = "Email address";
380
+ else if (cleanType === "url") description = "URL address";
381
+ else if (cleanType === "uuid") description = "Unique identifier";
382
+ else if (cleanType === "date") description = "Date and time";
383
+ else if (cleanType === "positive") description = "Positive number";
384
+ else if (cleanType.startsWith("string")) description = "Text value";
385
+ else if (cleanType.includes("[]")) description = "Array of values";
386
+
387
+ let jsdoc = `/**\n * ${description}`;
388
+
389
+ if (isOptional) {
390
+ jsdoc += "\n * @optional";
391
+ }
392
+
393
+ // Add constraints info
394
+ if (cleanType.includes("(")) {
395
+ const match = cleanType.match(/\(([^)]+)\)/);
396
+ if (match) {
397
+ jsdoc += `\n * @constraints ${match[1]}`;
356
398
  }
399
+ }
357
400
 
358
- return `/**\n * ${fieldName} field\n */`;
401
+ jsdoc += "\n */";
402
+ return jsdoc;
359
403
  }
404
+
405
+ return `/**\n * ${fieldName} field\n */`;
406
+ }
360
407
  }
361
408
 
362
409
  /**
363
410
  * Type definitions
364
411
  */
365
412
  export interface TypeScriptOptions {
366
- exportName?: string;
367
- namespace?: string;
368
- exportType?: "interface" | "type";
413
+ exportName?: string;
414
+ namespace?: string;
415
+ exportType?: "interface" | "type";
369
416
  }
370
417
 
371
418
  export interface ModuleOptions {
372
- moduleName?: string;
373
- exportName?: string;
374
- includeUtilities?: boolean;
375
- includeValidation?: boolean;
376
- header?: string;
419
+ moduleName?: string;
420
+ exportName?: string;
421
+ includeUtilities?: boolean;
422
+ includeValidation?: boolean;
423
+ header?: string;
377
424
  }
378
425
 
379
- export {TypeScriptGenerator as TSGenerator}
426
+ export { TypeScriptGenerator as TSGenerator };