@amritk/generate-parsers 0.7.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +1 -1
  2. package/dist/generators/build-schema.d.ts +0 -1
  3. package/dist/generators/generate-default-from-pattern.d.ts +0 -1
  4. package/dist/generators/generate-discriminated-union-validation.d.ts +0 -1
  5. package/dist/generators/generate-enum-check.d.ts +0 -1
  6. package/dist/generators/generate-files.d.ts +0 -1
  7. package/dist/generators/generate-non-discriminated-union-validation.d.ts +0 -1
  8. package/dist/generators/generate-parser-function.d.ts +3 -3
  9. package/dist/generators/generate-parser-function.js +267 -32
  10. package/dist/generators/generate-schema-checks.d.ts +0 -1
  11. package/dist/generators/generate-strict-assertion.d.ts +0 -1
  12. package/dist/generators/generate-validation-expression.d.ts +0 -1
  13. package/dist/helpers/apply-schema-extensions.d.ts +0 -1
  14. package/dist/helpers/collect-helpers.d.ts +0 -1
  15. package/dist/helpers/collect-imports.d.ts +0 -1
  16. package/dist/helpers/find-discriminator.d.ts +0 -1
  17. package/dist/helpers/get-default-value.d.ts +0 -1
  18. package/dist/helpers/get-discriminator-value.d.ts +0 -1
  19. package/dist/index.d.ts +0 -1
  20. package/dist/types/schema-extensions.d.ts +0 -1
  21. package/package.json +3 -5
  22. package/dist/generators/build-schema.d.ts.map +0 -1
  23. package/dist/generators/generate-default-from-pattern.d.ts.map +0 -1
  24. package/dist/generators/generate-discriminated-union-validation.d.ts.map +0 -1
  25. package/dist/generators/generate-enum-check.d.ts.map +0 -1
  26. package/dist/generators/generate-files.d.ts.map +0 -1
  27. package/dist/generators/generate-non-discriminated-union-validation.d.ts.map +0 -1
  28. package/dist/generators/generate-parser-function.d.ts.map +0 -1
  29. package/dist/generators/generate-schema-checks.d.ts.map +0 -1
  30. package/dist/generators/generate-strict-assertion.d.ts.map +0 -1
  31. package/dist/generators/generate-validation-expression.d.ts.map +0 -1
  32. package/dist/helpers/apply-schema-extensions.d.ts.map +0 -1
  33. package/dist/helpers/collect-helpers.d.ts.map +0 -1
  34. package/dist/helpers/collect-imports.d.ts.map +0 -1
  35. package/dist/helpers/find-discriminator.d.ts.map +0 -1
  36. package/dist/helpers/get-default-value.d.ts.map +0 -1
  37. package/dist/helpers/get-discriminator-value.d.ts.map +0 -1
  38. package/dist/index.d.ts.map +0 -1
  39. package/dist/types/schema-extensions.d.ts.map +0 -1
  40. package/src/generators/build-schema.test.ts +0 -854
  41. package/src/generators/build-schema.ts +0 -147
  42. package/src/generators/generate-default-from-pattern.test.ts +0 -81
  43. package/src/generators/generate-default-from-pattern.ts +0 -39
  44. package/src/generators/generate-discriminated-union-validation.test.ts +0 -84
  45. package/src/generators/generate-discriminated-union-validation.ts +0 -54
  46. package/src/generators/generate-enum-check.test.ts +0 -45
  47. package/src/generators/generate-enum-check.ts +0 -8
  48. package/src/generators/generate-files.test.ts +0 -448
  49. package/src/generators/generate-files.ts +0 -155
  50. package/src/generators/generate-non-discriminated-union-validation.test.ts +0 -74
  51. package/src/generators/generate-non-discriminated-union-validation.ts +0 -40
  52. package/src/generators/generate-parser-function.test.ts +0 -1794
  53. package/src/generators/generate-parser-function.ts +0 -1340
  54. package/src/generators/generate-schema-checks.test.ts +0 -330
  55. package/src/generators/generate-schema-checks.ts +0 -128
  56. package/src/generators/generate-strict-assertion.test.ts +0 -67
  57. package/src/generators/generate-strict-assertion.ts +0 -243
  58. package/src/generators/generate-validation-expression.test.ts +0 -831
  59. package/src/generators/generate-validation-expression.ts +0 -327
  60. package/src/helpers/apply-schema-extensions.test.ts +0 -194
  61. package/src/helpers/apply-schema-extensions.ts +0 -63
  62. package/src/helpers/collect-helpers.test.ts +0 -115
  63. package/src/helpers/collect-helpers.ts +0 -79
  64. package/src/helpers/collect-imports.test.ts +0 -547
  65. package/src/helpers/collect-imports.ts +0 -275
  66. package/src/helpers/find-discriminator.test.ts +0 -88
  67. package/src/helpers/find-discriminator.ts +0 -39
  68. package/src/helpers/get-default-value.test.ts +0 -139
  69. package/src/helpers/get-default-value.ts +0 -95
  70. package/src/helpers/get-discriminator-value.test.ts +0 -83
  71. package/src/helpers/get-discriminator-value.ts +0 -21
  72. package/src/index.ts +0 -1
  73. package/src/types/schema-extensions.ts +0 -35
@@ -1,243 +0,0 @@
1
- import { escapeRegexPattern } from '@amritk/helpers/escape-regex-pattern'
2
- import { getMjstInstanceOf, getMjstPrimitive } from '@amritk/helpers/mjst-extension'
3
- import { safeAccessor } from '@amritk/helpers/safe-accessor'
4
- import {
5
- hasEnum,
6
- hasExclusiveMaximum,
7
- hasExclusiveMinimum,
8
- hasMaximum,
9
- hasMaxLength,
10
- hasMinimum,
11
- hasMinLength,
12
- hasMultipleOf,
13
- hasPattern,
14
- hasProperties,
15
- hasRef,
16
- hasRequired,
17
- hasType,
18
- isSchemaObject,
19
- } from '@amritk/helpers/schema-guards'
20
- import type { JSONSchema } from 'json-schema-typed/draft-2020-12'
21
-
22
- /**
23
- * Returns the inline condition that is true when `accessor` is the wrong type
24
- * for the given JSON Schema primitive type.
25
- */
26
- const wrongTypeCondition = (accessor: string, type: string): string | null => {
27
- switch (type) {
28
- case 'string':
29
- return `typeof ${accessor} !== "string"`
30
- case 'number':
31
- case 'integer':
32
- return `typeof ${accessor} !== "number"`
33
- case 'boolean':
34
- return `typeof ${accessor} !== "boolean"`
35
- case 'array':
36
- return `!Array.isArray(${accessor})`
37
- case 'object':
38
- return `!isObject(${accessor})`
39
- default:
40
- return null
41
- }
42
- }
43
-
44
- /**
45
- * Maps a JSON Schema type to the label used in error messages.
46
- * `integer` collapses to `number` since both are validated via `typeof === "number"`.
47
- */
48
- const typeLabel = (type: string): string => (type === 'integer' ? 'number' : type)
49
-
50
- /**
51
- * Generates strict-mode constraint checks for a typed property
52
- * (pattern, length, min/max, multipleOf).
53
- */
54
- const generateConstraintChecks = (acc: string, propSchema: JSONSchema, typeName: string, key: string): string[] => {
55
- if (!isSchemaObject(propSchema) || !hasType(propSchema)) return []
56
- const t = propSchema.type as string
57
- const lines: string[] = []
58
-
59
- if (t === 'string') {
60
- if (hasPattern(propSchema)) {
61
- const pattern = escapeRegexPattern(propSchema.pattern)
62
- lines.push(
63
- ` if (typeof ${acc} === "string" && !/${pattern}/.test(${acc})) throw new Error('[${typeName}] field "${key}" must match pattern ${propSchema.pattern}');`,
64
- )
65
- }
66
- if (hasMinLength(propSchema)) {
67
- lines.push(
68
- ` if (typeof ${acc} === "string" && ${acc}.length < ${propSchema.minLength}) throw new Error('[${typeName}] field "${key}" must have at least ${propSchema.minLength} characters');`,
69
- )
70
- }
71
- if (hasMaxLength(propSchema)) {
72
- lines.push(
73
- ` if (typeof ${acc} === "string" && ${acc}.length > ${propSchema.maxLength}) throw new Error('[${typeName}] field "${key}" must have at most ${propSchema.maxLength} characters');`,
74
- )
75
- }
76
- }
77
-
78
- if (t === 'number' || t === 'integer') {
79
- if (hasMinimum(propSchema)) {
80
- lines.push(
81
- ` if (typeof ${acc} === "number" && ${acc} < ${propSchema.minimum}) throw new Error('[${typeName}] field "${key}" must be >= ${propSchema.minimum}');`,
82
- )
83
- }
84
- if (hasMaximum(propSchema)) {
85
- lines.push(
86
- ` if (typeof ${acc} === "number" && ${acc} > ${propSchema.maximum}) throw new Error('[${typeName}] field "${key}" must be <= ${propSchema.maximum}');`,
87
- )
88
- }
89
- if (hasExclusiveMinimum(propSchema)) {
90
- lines.push(
91
- ` if (typeof ${acc} === "number" && ${acc} <= ${propSchema.exclusiveMinimum}) throw new Error('[${typeName}] field "${key}" must be > ${propSchema.exclusiveMinimum}');`,
92
- )
93
- }
94
- if (hasExclusiveMaximum(propSchema)) {
95
- lines.push(
96
- ` if (typeof ${acc} === "number" && ${acc} >= ${propSchema.exclusiveMaximum}) throw new Error('[${typeName}] field "${key}" must be < ${propSchema.exclusiveMaximum}');`,
97
- )
98
- }
99
- if (hasMultipleOf(propSchema)) {
100
- lines.push(
101
- ` if (typeof ${acc} === "number" && ${acc} % ${propSchema.multipleOf} !== 0) throw new Error('[${typeName}] field "${key}" must be a multiple of ${propSchema.multipleOf}');`,
102
- )
103
- }
104
- }
105
-
106
- return lines
107
- }
108
-
109
- /**
110
- * Generates strict-mode lines for a single property of an object schema.
111
- * Properties with a `$ref` are skipped here — the nested parser handles its own
112
- * strict check when called from the parent's slow path.
113
- */
114
- const generatePropertyAssertion = (
115
- key: string,
116
- propSchema: JSONSchema,
117
- isRequired: boolean,
118
- typeName: string,
119
- ): string[] => {
120
- const acc = safeAccessor('input', key)
121
- const lines: string[] = []
122
-
123
- if (isRequired) {
124
- lines.push(
125
- ` if (!(${JSON.stringify(key)} in input)) throw new Error('[${typeName}] missing required property "${key}"');`,
126
- )
127
- }
128
-
129
- if (!isSchemaObject(propSchema)) return lines
130
- if (hasRef(propSchema)) return lines
131
-
132
- const instanceOf = getMjstInstanceOf(propSchema)
133
- if (instanceOf) {
134
- if (isRequired) {
135
- lines.push(
136
- ` if (!(${acc} instanceof ${instanceOf})) throw new Error('[${typeName}] field "${key}" must be ${instanceOf}');`,
137
- )
138
- } else {
139
- lines.push(
140
- ` if (${acc} !== undefined && !(${acc} instanceof ${instanceOf})) throw new Error('[${typeName}] field "${key}" must be ${instanceOf}');`,
141
- )
142
- }
143
- return lines
144
- }
145
-
146
- const primitive = getMjstPrimitive(propSchema)
147
- if (primitive) {
148
- if (isRequired) {
149
- lines.push(
150
- ` if (typeof ${acc} !== "${primitive}") throw new Error('[${typeName}] field "${key}" must be ${primitive}');`,
151
- )
152
- } else {
153
- lines.push(
154
- ` if (${acc} !== undefined && typeof ${acc} !== "${primitive}") throw new Error('[${typeName}] field "${key}" must be ${primitive}');`,
155
- )
156
- }
157
- return lines
158
- }
159
-
160
- if (hasEnum(propSchema)) {
161
- const allowed = JSON.stringify(propSchema.enum)
162
- const label = (propSchema.enum as unknown[]).map((v) => JSON.stringify(v)).join(', ')
163
- if (isRequired) {
164
- lines.push(
165
- ` if (!(${allowed} as readonly unknown[]).includes(${acc})) throw new Error('[${typeName}] field "${key}" must be one of: ${label}');`,
166
- )
167
- } else {
168
- lines.push(
169
- ` if (${acc} !== undefined && !(${allowed} as readonly unknown[]).includes(${acc})) throw new Error('[${typeName}] field "${key}" must be one of: ${label}');`,
170
- )
171
- }
172
- return lines
173
- }
174
-
175
- if (hasType(propSchema)) {
176
- const t = propSchema.type as string
177
- const wrongType = wrongTypeCondition(acc, t)
178
- if (wrongType) {
179
- if (isRequired) {
180
- lines.push(
181
- ` if (${wrongType}) throw new Error(\`[${typeName}] field "${key}" expected ${typeLabel(t)}, got \${typeof ${acc}}\`);`,
182
- )
183
- } else {
184
- lines.push(
185
- ` if (${acc} !== undefined && (${wrongType})) throw new Error(\`[${typeName}] field "${key}" expected ${typeLabel(t)}, got \${typeof ${acc}}\`);`,
186
- )
187
- }
188
- }
189
- lines.push(...generateConstraintChecks(acc, propSchema, typeName, key))
190
- }
191
-
192
- return lines
193
- }
194
-
195
- /**
196
- * Generates strict-mode assertions for the body of an object parser.
197
- * Throws on:
198
- * - non-object input
199
- * - missing required property
200
- * - property of the wrong primitive type
201
- * - enum / pattern / length / min / max / multipleOf violations
202
- *
203
- * Properties with a `$ref` are validated by the nested parser's own strict
204
- * check when that parser is invoked downstream.
205
- */
206
- export const generateObjectStrictAssertion = (schema: JSONSchema, typeName: string): string[] => {
207
- const lines: string[] = []
208
- lines.push(
209
- ` if (!isObject(input)) throw new Error(\`[${typeName}] expected object, got \${input === null ? "null" : typeof input}\`);`,
210
- )
211
-
212
- if (!hasProperties(schema) || !isSchemaObject(schema)) return lines
213
-
214
- const required = new Set<string>(hasRequired(schema) ? schema.required : [])
215
-
216
- for (const [key, propSchema] of Object.entries(schema.properties)) {
217
- lines.push(...generatePropertyAssertion(key, propSchema, required.has(key), typeName))
218
- }
219
-
220
- return lines
221
- }
222
-
223
- /**
224
- * Generates a single strict-mode assertion line for a non-object scalar parser.
225
- * Returns null when the schema has no type information to assert on.
226
- */
227
- export const generateScalarStrictAssertion = (schema: JSONSchema, typeName: string): string | null => {
228
- const instanceOf = getMjstInstanceOf(schema)
229
- if (instanceOf) {
230
- return ` if (!(input instanceof ${instanceOf})) throw new Error(\`[${typeName}] expected ${instanceOf}, got \${input === null ? "null" : typeof input}\`);`
231
- }
232
-
233
- const primitive = getMjstPrimitive(schema)
234
- if (primitive) {
235
- return ` if (typeof input !== "${primitive}") throw new Error(\`[${typeName}] expected ${primitive}, got \${input === null ? "null" : typeof input}\`);`
236
- }
237
-
238
- if (!isSchemaObject(schema) || !hasType(schema)) return null
239
- const t = schema.type as string
240
- const wrongType = wrongTypeCondition('input', t)
241
- if (!wrongType) return null
242
- return ` if (${wrongType}) throw new Error(\`[${typeName}] expected ${typeLabel(t)}, got \${input === null ? "null" : typeof input}\`);`
243
- }