@amritk/generate-parsers 0.5.0 → 0.6.1

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.
@@ -53,6 +53,11 @@ type GenerateParserOptions = {
53
53
  * with a path-aware Error. Unknown extra keys are still allowed.
54
54
  */
55
55
  readonly strict?: boolean
56
+ /**
57
+ * Suffix appended to every type/parser name derived from a `$ref`. Must match
58
+ * the suffix used when generating the referenced files. Defaults to `''`.
59
+ */
60
+ readonly typeSuffix?: string
56
61
  }
57
62
 
58
63
  /**
@@ -87,60 +92,60 @@ const isPropertyRequired = (key: string, schema: JSONSchema): boolean => {
87
92
 
88
93
  /**
89
94
  * Generates a parser call expression for a required $ref property.
90
- * Example: parseContactObject(input.contact)
95
+ * Example: parseContact(input.contact)
91
96
  */
92
- const generateRequiredRefCall = (key: string, ref: string): string => {
97
+ const generateRequiredRefCall = (key: string, ref: string, suffix: string): string => {
93
98
  const acc = safeAccessor('input', key)
94
- const parserName = generateParserName(refToName(ref))
99
+ const parserName = generateParserName(refToName(ref, suffix))
95
100
  return `${parserName}(${acc})`
96
101
  }
97
102
 
98
103
  /**
99
104
  * Generates a parser call expression for an optional $ref property.
100
- * Example: ...(input.contact && { contact: parseContactObject(input.contact) })
105
+ * Example: ...(input.contact && { contact: parseContact(input.contact) })
101
106
  */
102
- const generateOptionalRefCall = (key: string, ref: string): string => {
107
+ const generateOptionalRefCall = (key: string, ref: string, suffix: string): string => {
103
108
  const acc = safeAccessor('input', key)
104
- const parserName = generateParserName(refToName(ref))
109
+ const parserName = generateParserName(refToName(ref, suffix))
105
110
  return `...(${acc} && { ${safeKey(key)}: ${parserName}(${acc}) })`
106
111
  }
107
112
 
108
113
  /**
109
114
  * Generates a validateArray call for required array properties with $ref items.
110
- * Example: validateArray(input.contacts, parseContactObject)
115
+ * Example: validateArray(input.contacts, parseContact)
111
116
  */
112
- const generateRequiredArrayRefCall = (key: string, ref: string): string => {
113
- const parserName = generateParserName(refToName(ref))
117
+ const generateRequiredArrayRefCall = (key: string, ref: string, suffix: string): string => {
118
+ const parserName = generateParserName(refToName(ref, suffix))
114
119
  return `validateArray(${safeAccessor('input', key)}, ${parserName})`
115
120
  }
116
121
 
117
122
  /**
118
123
  * Generates a validateArray call for optional array properties with $ref items.
119
- * Example: ...(input.contacts && { contacts: validateArray(input.contacts, parseContactObject) })
124
+ * Example: ...(input.contacts && { contacts: validateArray(input.contacts, parseContact) })
120
125
  */
121
- const generateOptionalArrayRefCall = (key: string, ref: string): string => {
122
- const parserName = generateParserName(refToName(ref))
126
+ const generateOptionalArrayRefCall = (key: string, ref: string, suffix: string): string => {
127
+ const parserName = generateParserName(refToName(ref, suffix))
123
128
  const acc = safeAccessor('input', key)
124
129
  return `...(${acc} && { ${safeKey(key)}: validateArray(${acc}, ${parserName}) })`
125
130
  }
126
131
 
127
132
  /**
128
133
  * Generates a validateRecord call for required object properties with additionalProperties $ref.
129
- * Example: validateRecord(input.responses, parseResponseObject)
134
+ * Example: validateRecord(input.responses, parseResponse)
130
135
  */
131
- const generateRequiredRecordRefCall = (key: string, ref: string): string => {
136
+ const generateRequiredRecordRefCall = (key: string, ref: string, suffix: string): string => {
132
137
  const acc = safeAccessor('input', key)
133
- const parserName = generateParserName(refToName(ref))
138
+ const parserName = generateParserName(refToName(ref, suffix))
134
139
  return `validateRecord(${acc}, ${parserName})`
135
140
  }
136
141
 
137
142
  /**
138
143
  * Generates a validateRecord call for optional object properties with additionalProperties $ref.
139
- * Example: ...(input.responses && { responses: validateRecord(input.responses, parseResponseObject) })
144
+ * Example: ...(input.responses && { responses: validateRecord(input.responses, parseResponse) })
140
145
  */
141
- const generateOptionalRecordRefCall = (key: string, ref: string): string => {
146
+ const generateOptionalRecordRefCall = (key: string, ref: string, suffix: string): string => {
142
147
  const acc = safeAccessor('input', key)
143
- const parserName = generateParserName(refToName(ref))
148
+ const parserName = generateParserName(refToName(ref, suffix))
144
149
  return `...(${acc} && { ${safeKey(key)}: validateRecord(${acc}, ${parserName}) })`
145
150
  }
146
151
 
@@ -214,25 +219,28 @@ const generatePropertyValue = (
214
219
  propSchema: JSONSchema,
215
220
  isRequired: boolean,
216
221
  useRefImports: boolean,
222
+ suffix: string,
217
223
  ): string => {
218
224
  // Handle direct $ref properties
219
225
  if (shouldUseRefImport(propSchema, useRefImports)) {
220
226
  const ref = (propSchema as { $ref: string }).$ref
221
- return isRequired ? generateRequiredRefCall(key, ref) : generateOptionalRefCall(key, ref)
227
+ return isRequired ? generateRequiredRefCall(key, ref, suffix) : generateOptionalRefCall(key, ref, suffix)
222
228
  }
223
229
 
224
230
  // Handle array properties with $ref items
225
231
  if (shouldUseArrayRefImport(propSchema, useRefImports)) {
226
232
  const items = (propSchema as { items: { $ref: string } }).items
227
233
  const ref = items.$ref
228
- return isRequired ? generateRequiredArrayRefCall(key, ref) : generateOptionalArrayRefCall(key, ref)
234
+ return isRequired ? generateRequiredArrayRefCall(key, ref, suffix) : generateOptionalArrayRefCall(key, ref, suffix)
229
235
  }
230
236
 
231
237
  // Handle object properties with additionalProperties $ref
232
238
  if (shouldUseRecordRefImport(propSchema, useRefImports)) {
233
239
  const additionalProps = (propSchema as { additionalProperties: { $ref: string } }).additionalProperties
234
240
  const ref = additionalProps.$ref
235
- return isRequired ? generateRequiredRecordRefCall(key, ref) : generateOptionalRecordRefCall(key, ref)
241
+ return isRequired
242
+ ? generateRequiredRecordRefCall(key, ref, suffix)
243
+ : generateOptionalRecordRefCall(key, ref, suffix)
236
244
  }
237
245
 
238
246
  // Handle non-schema object properties (true/false)
@@ -249,7 +257,7 @@ const generatePropertyValue = (
249
257
  /**
250
258
  * Generates property entries for all properties in the schema.
251
259
  */
252
- const generatePropertyEntries = (schema: JSONSchema, useRefImports: boolean): PropertyEntry[] => {
260
+ const generatePropertyEntries = (schema: JSONSchema, useRefImports: boolean, suffix: string): PropertyEntry[] => {
253
261
  if (!hasProperties(schema)) {
254
262
  return []
255
263
  }
@@ -258,7 +266,7 @@ const generatePropertyEntries = (schema: JSONSchema, useRefImports: boolean): Pr
258
266
 
259
267
  for (const [key, propSchema] of Object.entries(schema.properties)) {
260
268
  const isRequired = isPropertyRequired(key, schema)
261
- const value = generatePropertyValue(key, propSchema, isRequired, useRefImports)
269
+ const value = generatePropertyValue(key, propSchema, isRequired, useRefImports, suffix)
262
270
 
263
271
  // Determine if the property uses spread syntax (making it optional in the object literal)
264
272
  const isOptional = value.startsWith('...')
@@ -274,11 +282,11 @@ const generatePropertyEntries = (schema: JSONSchema, useRefImports: boolean): Pr
274
282
  * This returns simple type-based defaults without pattern inference,
275
283
  * matching TypeBox's coercion behavior.
276
284
  */
277
- const generateFallbackValue = (_: string, propSchema: JSONSchema, useRefImports: boolean): string => {
285
+ const generateFallbackValue = (_: string, propSchema: JSONSchema, useRefImports: boolean, suffix: string): string => {
278
286
  // Handle direct $ref properties - call the parser with undefined
279
287
  if (useRefImports && hasRef(propSchema)) {
280
288
  const ref = (propSchema as { $ref: string }).$ref
281
- const parserName = generateParserName(refToName(ref))
289
+ const parserName = generateParserName(refToName(ref, suffix))
282
290
  return `${parserName}(undefined)`
283
291
  }
284
292
 
@@ -352,7 +360,12 @@ const generateFallbackValue = (_: string, propSchema: JSONSchema, useRefImports:
352
360
  * Generates a fallback object with required properties filled with default values.
353
361
  * This is used when input is not an object (undefined, null, etc.).
354
362
  */
355
- const generateFallbackObject = (schema: JSONSchema, useRefImports: boolean, typeName: string): string => {
363
+ const generateFallbackObject = (
364
+ schema: JSONSchema,
365
+ useRefImports: boolean,
366
+ typeName: string,
367
+ suffix: string,
368
+ ): string => {
356
369
  if (!hasProperties(schema)) {
357
370
  return `{} as ${typeName}`
358
371
  }
@@ -369,7 +382,7 @@ const generateFallbackObject = (schema: JSONSchema, useRefImports: boolean, type
369
382
  for (const [key, propSchema] of Object.entries(schema.properties)) {
370
383
  const isRequired = isPropertyRequired(key, schema)
371
384
  if (isRequired) {
372
- const fallbackValue = generateFallbackValue(key, propSchema, useRefImports)
385
+ const fallbackValue = generateFallbackValue(key, propSchema, useRefImports, suffix)
373
386
  if (fallbackValue === 'undefined') {
374
387
  return `{} as ${typeName}`
375
388
  }
@@ -467,12 +480,17 @@ const shapeValidatorName = (typeName: string): string => `validate${typeName}Sha
467
480
  * checked by calling the imported shape predicate, allowing parent parsers
468
481
  * to fast-path through nested ref types without recursing into their parsers.
469
482
  */
470
- const generatePropertyTypeCheck = (varName: string, schema: JSONSchema, useRefImports: boolean): string | null => {
483
+ const generatePropertyTypeCheck = (
484
+ varName: string,
485
+ schema: JSONSchema,
486
+ useRefImports: boolean,
487
+ suffix: string,
488
+ ): string | null => {
471
489
  if (!isSchemaObject(schema)) return null
472
490
 
473
491
  // $ref via shape predicate (deep fast-path through nested types).
474
492
  if (useRefImports && hasRef(schema)) {
475
- const refName = refToName((schema as { $ref: string }).$ref)
493
+ const refName = refToName((schema as { $ref: string }).$ref, suffix)
476
494
  return `${shapeValidatorName(refName)}(${varName})`
477
495
  }
478
496
 
@@ -498,7 +516,7 @@ const generatePropertyTypeCheck = (varName: string, schema: JSONSchema, useRefIm
498
516
  isSchemaObject(schema.items) &&
499
517
  hasRef(schema.items)
500
518
  ) {
501
- const refName = refToName((schema.items as { $ref: string }).$ref)
519
+ const refName = refToName((schema.items as { $ref: string }).$ref, suffix)
502
520
  return `Array.isArray(${varName}) && ${varName}.every(${shapeValidatorName(refName)})`
503
521
  }
504
522
 
@@ -575,6 +593,7 @@ const generateObjectParser = (
575
593
  schema: JSONSchema,
576
594
  typeName: string,
577
595
  useRefImports: boolean,
596
+ suffix: string,
578
597
  logWarnings?: boolean,
579
598
  strict?: boolean,
580
599
  ): string => {
@@ -587,7 +606,7 @@ const generateObjectParser = (
587
606
  return `export const ${functionName} = (input: unknown): ${typeName} => isObject(input) ? input as ${typeName} : {} as ${typeName};`
588
607
  }
589
608
 
590
- const fallbackObject = generateFallbackObject(schema, useRefImports, typeName)
609
+ const fallbackObject = generateFallbackObject(schema, useRefImports, typeName, suffix)
591
610
  const properties = Object.entries((schema as { properties: Record<string, JSONSchema> }).properties)
592
611
 
593
612
  const lines: string[] = []
@@ -631,7 +650,7 @@ const generateObjectParser = (
631
650
  if (shouldUseRecordRefImport(propSchema, useRefImports)) {
632
651
  canFastPath = false
633
652
  } else {
634
- const check = generatePropertyTypeCheck(varName, propSchema, useRefImports)
653
+ const check = generatePropertyTypeCheck(varName, propSchema, useRefImports, suffix)
635
654
  if (check === null) {
636
655
  canFastPath = false
637
656
  } else {
@@ -681,7 +700,7 @@ const generateObjectParser = (
681
700
  if (useRefImports && isSchemaObject(schema) && hasAllOf(schema)) {
682
701
  for (const entry of schema.allOf) {
683
702
  if (isSchemaObject(entry) && hasRef(entry)) {
684
- const parserName = generateParserName(refToName(entry.$ref))
703
+ const parserName = generateParserName(refToName(entry.$ref, suffix))
685
704
  objectLines.push(` ...(${parserName}(input) as Record<string, unknown>),`)
686
705
  }
687
706
  }
@@ -694,7 +713,7 @@ const generateObjectParser = (
694
713
  // Handle direct $ref properties via imported parsers
695
714
  if (shouldUseRefImport(propSchema, useRefImports)) {
696
715
  const ref = (propSchema as { $ref: string }).$ref
697
- const parserName = generateParserName(refToName(ref))
716
+ const parserName = generateParserName(refToName(ref, suffix))
698
717
  if (isRequired) {
699
718
  objectLines.push(` ${safeKey(key)}: ${parserName}(${accessor}),`)
700
719
  } else {
@@ -707,7 +726,7 @@ const generateObjectParser = (
707
726
  if (shouldUseArrayRefImport(propSchema, useRefImports)) {
708
727
  const items = (propSchema as { items: { $ref: string } }).items
709
728
  const ref = items.$ref
710
- const parserName = generateParserName(refToName(ref))
729
+ const parserName = generateParserName(refToName(ref, suffix))
711
730
  if (isRequired) {
712
731
  objectLines.push(` ${safeKey(key)}: validateArray(${accessor}, ${parserName}),`)
713
732
  } else {
@@ -722,7 +741,7 @@ const generateObjectParser = (
722
741
  if (shouldUseRecordRefImport(propSchema, useRefImports)) {
723
742
  const additionalProps = (propSchema as { additionalProperties: { $ref: string } }).additionalProperties
724
743
  const ref = additionalProps.$ref
725
- const parserName = generateParserName(refToName(ref))
744
+ const parserName = generateParserName(refToName(ref, suffix))
726
745
  if (isRequired) {
727
746
  objectLines.push(` ${safeKey(key)}: validateRecord(${accessor}, ${parserName}),`)
728
747
  } else {
@@ -790,11 +809,12 @@ const generateCombinedObjectParser = (
790
809
  schema: JSONSchema,
791
810
  typeName: string,
792
811
  useRefImports: boolean,
812
+ suffix: string,
793
813
  logWarnings?: boolean,
794
814
  strict?: boolean,
795
815
  ): string => {
796
816
  const functionName = generateParserName(typeName)
797
- const entries = generatePropertyEntries(schema, useRefImports)
817
+ const entries = generatePropertyEntries(schema, useRefImports, suffix)
798
818
 
799
819
  // Build the known property lines for the initial object
800
820
  const propertyLines = entries.map((entry) => {
@@ -806,7 +826,7 @@ const generateCombinedObjectParser = (
806
826
 
807
827
  // Find the first pattern with a $ref for parser delegation
808
828
  if (!isSchemaObject(schema) || !('patternProperties' in schema)) {
809
- return generateObjectParser(schema, typeName, useRefImports, logWarnings, strict)
829
+ return generateObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict)
810
830
  }
811
831
 
812
832
  const patternProps = schema.patternProperties as Record<string, JSONSchema>
@@ -814,12 +834,12 @@ const generateCombinedObjectParser = (
814
834
  const refPattern = patterns.find(([, ps]) => isSchemaObject(ps) && hasRef(ps))
815
835
 
816
836
  if (!refPattern || !useRefImports) {
817
- return generateObjectParser(schema, typeName, useRefImports, logWarnings, strict)
837
+ return generateObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict)
818
838
  }
819
839
 
820
840
  const [pattern, patternSchema] = refPattern
821
841
  const ref = (patternSchema as { $ref: string }).$ref
822
- const parserName = generateParserName(refToName(ref))
842
+ const parserName = generateParserName(refToName(ref, suffix))
823
843
  const assignmentCode = `(result as Record<string, unknown>)[key] = ${parserName}(value);`
824
844
 
825
845
  const escapedPattern = escapeRegexPattern(pattern)
@@ -860,6 +880,7 @@ const generateAdditionalPropertiesParser = (
860
880
  schema: JSONSchema.Object,
861
881
  typeName: string,
862
882
  useRefImports: boolean,
883
+ suffix: string,
863
884
  strict?: boolean,
864
885
  ): string => {
865
886
  const functionName = generateParserName(typeName)
@@ -873,7 +894,7 @@ const generateAdditionalPropertiesParser = (
873
894
  // If additionalProperties is a $ref and useRefImports is true, generate a loop
874
895
  if (useRefImports && isSchemaObject(additionalProps) && hasRef(additionalProps)) {
875
896
  const ref = additionalProps.$ref
876
- const parserName = generateParserName(refToName(ref))
897
+ const parserName = generateParserName(refToName(ref, suffix))
877
898
 
878
899
  if (strict) {
879
900
  return `export const ${functionName} = (input: unknown): ${typeName} => {\n if (!isObject(input)) throw new Error(\`[${typeName}] expected object, got \${input === null ? "null" : typeof input}\`);\n return validateRecord(input, ${parserName}) as ${typeName};\n};`
@@ -943,6 +964,7 @@ const generatePatternPropertiesParser = (
943
964
  schema: JSONSchema.Object,
944
965
  typeName: string,
945
966
  useRefImports: boolean,
967
+ suffix: string,
946
968
  strict?: boolean,
947
969
  ): string => {
948
970
  const functionName = generateParserName(typeName)
@@ -965,7 +987,7 @@ const generatePatternPropertiesParser = (
965
987
  // Use imported parser when pattern schema points to a $ref.
966
988
  if (useRefImports && isSchemaObject(patternSchema) && hasRef(patternSchema)) {
967
989
  const ref = patternSchema.$ref
968
- const parserName = generateParserName(refToName(ref))
990
+ const parserName = generateParserName(refToName(ref, suffix))
969
991
  patternAssignment = `(result as Record<string, unknown>)[key] = ${parserName}(value);`
970
992
  } else if (patternSchema === false) {
971
993
  // `false` means no values are allowed for matching keys.
@@ -1002,7 +1024,7 @@ ${notObjectBranch}
1002
1024
  * This always generates parser calls regardless of useRefImports setting,
1003
1025
  * because conditional logic requires delegating to the appropriate parser.
1004
1026
  */
1005
- const generateConditionalParser = (schema: JSONSchema.Object, typeName: string): string => {
1027
+ const generateConditionalParser = (schema: JSONSchema.Object, typeName: string, suffix: string): string => {
1006
1028
  const functionName = generateParserName(typeName)
1007
1029
 
1008
1030
  // Extract the condition and branches
@@ -1020,7 +1042,7 @@ const generateConditionalParser = (schema: JSONSchema.Object, typeName: string):
1020
1042
  // regular object parser from the merged property set.
1021
1043
  const mergedSchema = getConditionalObjectSchema(schema)
1022
1044
  if (mergedSchema) {
1023
- return generateObjectParser(mergedSchema, typeName, false)
1045
+ return generateObjectParser(mergedSchema, typeName, false, suffix)
1024
1046
  }
1025
1047
  return generateEmptyObjectParser(typeName)
1026
1048
  }
@@ -1037,7 +1059,7 @@ const generateConditionalParser = (schema: JSONSchema.Object, typeName: string):
1037
1059
  // Condition is not a $ref check — flatten into an object parser
1038
1060
  const mergedSchema = getConditionalObjectSchema(schema)
1039
1061
  if (mergedSchema) {
1040
- return generateObjectParser(mergedSchema, typeName, false)
1062
+ return generateObjectParser(mergedSchema, typeName, false, suffix)
1041
1063
  }
1042
1064
  return generateEmptyObjectParser(typeName)
1043
1065
  }
@@ -1045,9 +1067,9 @@ const generateConditionalParser = (schema: JSONSchema.Object, typeName: string):
1045
1067
  const thenRef = thenSchema.$ref
1046
1068
  const elseRef = elseSchema.$ref
1047
1069
 
1048
- const thenParserName = generateParserName(refToName(thenRef))
1049
- const elseParserName = generateParserName(refToName(elseRef))
1050
- const thenTypeName = refToName(thenRef)
1070
+ const thenParserName = generateParserName(refToName(thenRef, suffix))
1071
+ const elseParserName = generateParserName(refToName(elseRef, suffix))
1072
+ const thenTypeName = refToName(thenRef, suffix)
1051
1073
 
1052
1074
  return `export const ${functionName} = (input: unknown): ${typeName} | ${thenTypeName} =>
1053
1075
  hasRef(input) ? ${thenParserName}(input) : ${elseParserName}(input)
@@ -1149,9 +1171,11 @@ const selectParserStrategy = (schema: JSONSchema, typeName: string, options?: Ge
1149
1171
  const useRefImports = options?.useRefImports ?? false
1150
1172
  const logWarnings = options?.logWarnings ?? false
1151
1173
  const strict = options?.strict ?? false
1174
+ const suffix = options?.typeSuffix ?? ''
1152
1175
 
1153
- // Special case for SchemaObject - it can be any JSON Schema
1154
- if (typeName === 'SchemaObject') {
1176
+ // Special case for the self-referential JSON Schema meta-schema type (e.g.
1177
+ // `Schema` / `SchemaObject`) - it can be any JSON Schema.
1178
+ if (typeName === `Schema${suffix}`) {
1155
1179
  return generateSchemaObjectParser(typeName)
1156
1180
  }
1157
1181
 
@@ -1168,7 +1192,7 @@ const selectParserStrategy = (schema: JSONSchema, typeName: string, options?: Ge
1168
1192
  // This generates a parser that handles known properties and also iterates
1169
1193
  // pattern-matched keys (e.g. responses with "default" + "200", "4XX").
1170
1194
  if (hasProperties(schema) && isSchemaObject(schema) && 'patternProperties' in schema) {
1171
- return generateCombinedObjectParser(schema, typeName, useRefImports, logWarnings, strict)
1195
+ return generateCombinedObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict)
1172
1196
  }
1173
1197
 
1174
1198
  // Handle schemas that have explicit properties — generate a full object parser.
@@ -1176,19 +1200,19 @@ const selectParserStrategy = (schema: JSONSchema, typeName: string, options?: Ge
1176
1200
  // properties AND conditional keywords use all declared properties rather than
1177
1201
  // only the if/then fragment.
1178
1202
  if (hasProperties(schema)) {
1179
- return generateObjectParser(schema, typeName, useRefImports, logWarnings, strict)
1203
+ return generateObjectParser(schema, typeName, useRefImports, suffix, logWarnings, strict)
1180
1204
  }
1181
1205
 
1182
1206
  // Handle conditional schemas (if/then/else) for schemas without explicit properties.
1183
1207
  if (isSchemaObject(schema) && 'if' in schema && 'then' in schema && 'else' in schema) {
1184
- return generateConditionalParser(schema as JSONSchema.Object, typeName)
1208
+ return generateConditionalParser(schema as JSONSchema.Object, typeName, suffix)
1185
1209
  }
1186
1210
 
1187
1211
  // Handle conditional schemas that only define if/then object fragments.
1188
1212
  // We flatten the fragments into a regular object parser.
1189
1213
  const conditionalObjectSchema = getConditionalObjectSchema(schema)
1190
1214
  if (conditionalObjectSchema) {
1191
- return generateObjectParser(conditionalObjectSchema, typeName, useRefImports, logWarnings, strict)
1215
+ return generateObjectParser(conditionalObjectSchema, typeName, useRefImports, suffix, logWarnings, strict)
1192
1216
  }
1193
1217
 
1194
1218
  // Handle non-object schemas with type-appropriate validation (no properties, no conditionals)
@@ -1198,7 +1222,7 @@ const selectParserStrategy = (schema: JSONSchema, typeName: string, options?: Ge
1198
1222
 
1199
1223
  // Handle schemas with patternProperties (but no properties)
1200
1224
  if ('patternProperties' in schema) {
1201
- return generatePatternPropertiesParser(schema as JSONSchema.Object, typeName, useRefImports, strict)
1225
+ return generatePatternPropertiesParser(schema as JSONSchema.Object, typeName, useRefImports, suffix, strict)
1202
1226
  }
1203
1227
 
1204
1228
  // Handle schemas with additionalProperties as true or false (but no properties)
@@ -1211,7 +1235,7 @@ const selectParserStrategy = (schema: JSONSchema, typeName: string, options?: Ge
1211
1235
  }
1212
1236
 
1213
1237
  // Otherwise, handle as a schema (could be a $ref or object schema)
1214
- return generateAdditionalPropertiesParser(schema as JSONSchema.Object, typeName, useRefImports, strict)
1238
+ return generateAdditionalPropertiesParser(schema as JSONSchema.Object, typeName, useRefImports, suffix, strict)
1215
1239
  }
1216
1240
 
1217
1241
  // Handle empty object schemas
@@ -1259,7 +1283,12 @@ export const shapeValidatorFunctionName = (typeName: string): string => shapeVal
1259
1283
  * in additionalProperties). The stub is safe: parents calling it will fall
1260
1284
  * through to the slow path, matching the pre-deep-fast-path behavior.
1261
1285
  */
1262
- export const generateShapeValidator = (schema: JSONSchema, typeName: string, useRefImports: boolean): string => {
1286
+ export const generateShapeValidator = (
1287
+ schema: JSONSchema,
1288
+ typeName: string,
1289
+ useRefImports: boolean,
1290
+ suffix = '',
1291
+ ): string => {
1263
1292
  const fnName = shapeValidatorName(typeName)
1264
1293
  const stub = `export const ${fnName} = (_input: unknown): boolean => false;`
1265
1294
 
@@ -1291,7 +1320,7 @@ export const generateShapeValidator = (schema: JSONSchema, typeName: string, use
1291
1320
 
1292
1321
  const accessor = safeAccessor('input', key)
1293
1322
  const isRequired = isPropertyRequired(key, schema)
1294
- const check = generatePropertyTypeCheck(accessor, propSchema, useRefImports)
1323
+ const check = generatePropertyTypeCheck(accessor, propSchema, useRefImports, suffix)
1295
1324
  if (check === null) {
1296
1325
  return stub
1297
1326
  }