@jarenjs/formats 0.8.3 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +128 -2
- package/dist/types/datetime.d.ts +109 -0
- package/dist/types/index.d.ts +22 -0
- package/dist/types/json.d.ts +71 -0
- package/dist/types/number.d.ts +144 -0
- package/dist/types/string.d.ts +379 -0
- package/dist/types/testers.d.ts +31 -0
- package/package.json +28 -8
- package/src/datetime.js +373 -0
- package/src/index.js +31 -0
- package/src/json.js +90 -0
- package/src/number.js +219 -0
- package/src/string.js +548 -0
- package/src/testers.js +216 -0
- package/dist/index.js +0 -679
- package/dist/index.js.map +0 -7
- package/dist/index.min.js +0 -2
- package/dist/index.min.js.map +0 -7
package/src/datetime.js
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
isStringType,
|
|
5
|
+
getInclusiveExclusiveBounds,
|
|
6
|
+
} from '@jarenjs/core';
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
isDateType,
|
|
10
|
+
getDateTypeOfDateTimeRFC3339,
|
|
11
|
+
getDateTypeOfDateOnlyRFC3339,
|
|
12
|
+
getDateTypeOfTimeOnlyRFC3339,
|
|
13
|
+
isValidDuration,
|
|
14
|
+
isValidISODateTime,
|
|
15
|
+
isValidISOTime,
|
|
16
|
+
getDateTypeOfISODateTime,
|
|
17
|
+
getDateTypeOfISOTime,
|
|
18
|
+
} from '@jarenjs/core/dates';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @typedef {{format?: string, formatMinimum?: string, formatExclusiveMinimum?: string, formatMaximum?: string, formatExclusiveMaximum?: string}} JSONSchema
|
|
22
|
+
* @typedef {{
|
|
23
|
+
* options: {skipErrors: boolean},
|
|
24
|
+
* createErrorHandler: (expected: any, key: string, ...details: any[]) => (data: any, dataPath?: string) => boolean
|
|
25
|
+
* }} ValidationObject
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compiles a format minimum validator function for date/time types.
|
|
30
|
+
* Supports both inclusive (formatMinimum) and exclusive (formatExclusiveMinimum) bounds.
|
|
31
|
+
*
|
|
32
|
+
* @param {(value: string) => Date | undefined} parseType - Function to parse string into Date
|
|
33
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
34
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing format constraints
|
|
35
|
+
* @returns {((date: Date, dataPath?: string) => boolean) | undefined} A validator function or undefined if no minimum constraint
|
|
36
|
+
*/
|
|
37
|
+
function compileFormatMinimumByType(parseType, schemaObj, jsonSchema) {
|
|
38
|
+
const [min, emin] = getInclusiveExclusiveBounds(
|
|
39
|
+
parseType,
|
|
40
|
+
jsonSchema.formatMinimum,
|
|
41
|
+
jsonSchema.formatExclusiveMinimum,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (emin != null) {
|
|
45
|
+
const addError = schemaObj.createErrorHandler(emin, 'formatExclusiveMinimum');
|
|
46
|
+
|
|
47
|
+
return function isFormatExclusiveMinimum(date, dataPath) {
|
|
48
|
+
return date > emin
|
|
49
|
+
|| addError(date, dataPath);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
else if (min) {
|
|
53
|
+
const addError = schemaObj.createErrorHandler(min, 'formatMinimum');
|
|
54
|
+
|
|
55
|
+
return function isFormatMinimum(date, dataPath) {
|
|
56
|
+
return date >= min
|
|
57
|
+
|| addError(date, dataPath);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Compiles a format maximum validator function for date/time types.
|
|
66
|
+
* Supports both inclusive (formatMaximum) and exclusive (formatExclusiveMaximum) bounds.
|
|
67
|
+
*
|
|
68
|
+
* @param {(value: string) => Date | undefined} parseType - Function to parse string into Date
|
|
69
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
70
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing format constraints
|
|
71
|
+
* @returns {((date: Date, dataPath?: string) => boolean) | undefined} A validator function or undefined if no maximum constraint
|
|
72
|
+
*/
|
|
73
|
+
function compileFormatMaximumByType(parseType, schemaObj, jsonSchema) {
|
|
74
|
+
const [max, emax] = getInclusiveExclusiveBounds(
|
|
75
|
+
parseType,
|
|
76
|
+
jsonSchema.formatMaximum,
|
|
77
|
+
jsonSchema.formatExclusiveMaximum,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (emax != null) {
|
|
81
|
+
const addError = schemaObj.createErrorHandler(emax, 'formatExclusiveMaximum');
|
|
82
|
+
|
|
83
|
+
return function isFormatExclusiveMaximum(date, dataPath) {
|
|
84
|
+
return date < emax
|
|
85
|
+
|| addError(date, dataPath);
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
else if (max) {
|
|
89
|
+
const addError = schemaObj.createErrorHandler(max, 'formatMaximum');
|
|
90
|
+
|
|
91
|
+
return function isFormatMaximum(date, dataPath) {
|
|
92
|
+
return date <= max
|
|
93
|
+
|| addError(date, dataPath);
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Creates a date/time format compiler with range validation support.
|
|
102
|
+
* Combines format validation with optional minimum and maximum bounds.
|
|
103
|
+
*
|
|
104
|
+
* @param {string} name - The name of the format (e.g., 'date-time', 'date', 'time')
|
|
105
|
+
* @param {(value: string) => Date | undefined} parseType - Function to parse string into Date
|
|
106
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
107
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
108
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
109
|
+
* @example
|
|
110
|
+
* // Basic format validation
|
|
111
|
+
* compileFormatByType('date', getDateTypeOfDateOnlyRFC3339, schemaObj, { format: 'date' })('2024-01-15'); // true
|
|
112
|
+
*
|
|
113
|
+
* // With range constraints
|
|
114
|
+
* compileFormatByType('date-time', getDateTypeOfDateTimeRFC3339, schemaObj, {
|
|
115
|
+
* format: 'date-time',
|
|
116
|
+
* formatMinimum: '2024-01-01T00:00:00Z'
|
|
117
|
+
* })('2024-06-15T12:00:00Z'); // true
|
|
118
|
+
*/
|
|
119
|
+
function compileFormatByType(name, parseType, schemaObj, jsonSchema) {
|
|
120
|
+
if (jsonSchema.format !== name)
|
|
121
|
+
throw new Error('ERROR: This should not happen!');
|
|
122
|
+
|
|
123
|
+
const addError = schemaObj.createErrorHandler(jsonSchema.format, 'format');
|
|
124
|
+
|
|
125
|
+
const validateMin = compileFormatMinimumByType(
|
|
126
|
+
parseType,
|
|
127
|
+
schemaObj,
|
|
128
|
+
jsonSchema,
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
const validateMax = compileFormatMaximumByType(
|
|
132
|
+
parseType,
|
|
133
|
+
schemaObj,
|
|
134
|
+
jsonSchema,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
if (validateMin != null && validateMax != null) {
|
|
138
|
+
return function validateFormatBetween(data, dataPath) {
|
|
139
|
+
if (isStringType(data)) {
|
|
140
|
+
const date = parseType(data);
|
|
141
|
+
return date == null
|
|
142
|
+
? addError(data, dataPath)
|
|
143
|
+
: validateMin(date, dataPath)
|
|
144
|
+
&& validateMax(date, dataPath);
|
|
145
|
+
}
|
|
146
|
+
else if (isDateType(data))
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
return validateMin(data, dataPath)
|
|
149
|
+
// @ts-ignore
|
|
150
|
+
&& validateMax(data, dataPath);
|
|
151
|
+
else
|
|
152
|
+
return true;
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (validateMin != null) {
|
|
156
|
+
return function validateFormatMinimum(data, dataPath) {
|
|
157
|
+
if (isStringType(data)) {
|
|
158
|
+
const date = parseType(data);
|
|
159
|
+
return date == null
|
|
160
|
+
? addError(data, dataPath)
|
|
161
|
+
: validateMin(date, dataPath);
|
|
162
|
+
}
|
|
163
|
+
else if (isDateType(data))
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
return validateMin(data, dataPath);
|
|
166
|
+
else
|
|
167
|
+
return true;
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (validateMax != null) {
|
|
171
|
+
return function validateFormatMaximum(data, dataPath) {
|
|
172
|
+
if (isStringType(data)) {
|
|
173
|
+
const date = parseType(data);
|
|
174
|
+
return date == null
|
|
175
|
+
? addError(data, dataPath)
|
|
176
|
+
: validateMax(date);
|
|
177
|
+
}
|
|
178
|
+
else if (isDateType(data))
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
return validateMax(data, dataPath);
|
|
181
|
+
else
|
|
182
|
+
return true;
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return function validateDateTime(data, dataPath) {
|
|
187
|
+
if (isStringType(data)) {
|
|
188
|
+
const date = parseType(data);
|
|
189
|
+
return date == null
|
|
190
|
+
? addError(data, dataPath)
|
|
191
|
+
: true;
|
|
192
|
+
}
|
|
193
|
+
else
|
|
194
|
+
return true;
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// =============================================================================
|
|
199
|
+
// Date-Time Format Compilers
|
|
200
|
+
// =============================================================================
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Compiles a validator for the 'date-time' format.
|
|
204
|
+
* Validates date-time strings per RFC 3339 (ISO 8601 profile).
|
|
205
|
+
* Supports formatMinimum, formatMaximum, formatExclusiveMinimum, formatExclusiveMaximum.
|
|
206
|
+
*
|
|
207
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
208
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
209
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
210
|
+
* @example
|
|
211
|
+
* compileDateTimeFormat(schemaObj, { format: 'date-time' })('2024-01-15T12:30:00Z'); // true
|
|
212
|
+
* compileDateTimeFormat(schemaObj, { format: 'date-time' })('2024-01-15T12:30:00+01:00'); // true
|
|
213
|
+
* compileDateTimeFormat(schemaObj, { format: 'date-time' })('invalid'); // false (with error)
|
|
214
|
+
*/
|
|
215
|
+
export function compileDateTimeFormat(schemaObj, jsonSchema) {
|
|
216
|
+
return compileFormatByType(
|
|
217
|
+
'date-time',
|
|
218
|
+
getDateTypeOfDateTimeRFC3339,
|
|
219
|
+
schemaObj,
|
|
220
|
+
jsonSchema,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Compiles a validator for the 'date' format.
|
|
226
|
+
* Validates date-only strings (YYYY-MM-DD) per RFC 3339.
|
|
227
|
+
* Supports formatMinimum, formatMaximum, formatExclusiveMinimum, formatExclusiveMaximum.
|
|
228
|
+
*
|
|
229
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
230
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
231
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
232
|
+
* @example
|
|
233
|
+
* compileDateOnlyFormat(schemaObj, { format: 'date' })('2024-01-15'); // true
|
|
234
|
+
* compileDateOnlyFormat(schemaObj, { format: 'date' })('2024-13-45'); // false (with error)
|
|
235
|
+
*/
|
|
236
|
+
export function compileDateOnlyFormat(schemaObj, jsonSchema) {
|
|
237
|
+
return compileFormatByType(
|
|
238
|
+
'date',
|
|
239
|
+
getDateTypeOfDateOnlyRFC3339,
|
|
240
|
+
schemaObj,
|
|
241
|
+
jsonSchema,
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Compiles a validator for the 'time' format.
|
|
247
|
+
* Validates time-only strings (HH:MM:SS or HH:MM:SS.sss) per RFC 3339.
|
|
248
|
+
* Supports formatMinimum, formatMaximum, formatExclusiveMinimum, formatExclusiveMaximum.
|
|
249
|
+
*
|
|
250
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
251
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
252
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
253
|
+
* @example
|
|
254
|
+
* compileTimeOnlyFormat(schemaObj, { format: 'time' })('12:30:00'); // true
|
|
255
|
+
* compileTimeOnlyFormat(schemaObj, { format: 'time' })('12:30:00.123'); // true
|
|
256
|
+
* compileTimeOnlyFormat(schemaObj, { format: 'time' })('25:00:00'); // false (with error)
|
|
257
|
+
*/
|
|
258
|
+
export function compileTimeOnlyFormat(schemaObj, jsonSchema) {
|
|
259
|
+
return compileFormatByType(
|
|
260
|
+
'time',
|
|
261
|
+
getDateTypeOfTimeOnlyRFC3339,
|
|
262
|
+
schemaObj,
|
|
263
|
+
jsonSchema,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// =============================================================================
|
|
268
|
+
// Duration Format Compiler (RFC 3339)
|
|
269
|
+
// =============================================================================
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Compiles a validator for the 'duration' format.
|
|
273
|
+
* Validates duration strings per RFC 3339.
|
|
274
|
+
* Format: P[n]Y[n]M[n]DT[n]H[n]M[n]S or P[n]W
|
|
275
|
+
* Examples: P1Y2M3DT4H5M6S, P1W, PT1H
|
|
276
|
+
*
|
|
277
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
278
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
279
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
280
|
+
* @example
|
|
281
|
+
* compileDurationFormat(schemaObj, { format: 'duration' })('P1Y2M3DT4H5M6S'); // true
|
|
282
|
+
* compileDurationFormat(schemaObj, { format: 'duration' })('P1W'); // true
|
|
283
|
+
* compileDurationFormat(schemaObj, { format: 'duration' })('PT1H30M'); // true
|
|
284
|
+
* compileDurationFormat(schemaObj, { format: 'duration' })('P'); // false (with error)
|
|
285
|
+
*/
|
|
286
|
+
export function compileDurationFormat(schemaObj, jsonSchema) {
|
|
287
|
+
if (jsonSchema.format !== 'duration')
|
|
288
|
+
throw new Error('ERROR: This should not happen!');
|
|
289
|
+
|
|
290
|
+
// when skipErrors is true, we don't need to create error objects
|
|
291
|
+
if (schemaObj.options.skipErrors) {
|
|
292
|
+
return function validateDurationFast(data, dataPath) {
|
|
293
|
+
return isStringType(data)
|
|
294
|
+
? isValidDuration(data)
|
|
295
|
+
: true;
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const addError = schemaObj.createErrorHandler('duration', 'format');
|
|
300
|
+
|
|
301
|
+
return function validateDuration(data, dataPath) {
|
|
302
|
+
return isStringType(data)
|
|
303
|
+
? isValidDuration(data) || addError(data, dataPath)
|
|
304
|
+
: true;
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// =============================================================================
|
|
309
|
+
// ISO Date-Time and ISO Time Format Compilers
|
|
310
|
+
// =============================================================================
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Compiles a validator for the 'iso-date-time' format.
|
|
314
|
+
* Validates ISO 8601 date-time strings with optional timezone.
|
|
315
|
+
* Unlike RFC 3339 date-time, the timezone is optional.
|
|
316
|
+
* Supports formatMinimum, formatMaximum, formatExclusiveMinimum, formatExclusiveMaximum.
|
|
317
|
+
*
|
|
318
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
319
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
320
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
321
|
+
* @example
|
|
322
|
+
* compileISODateTimeFormat(schemaObj, { format: 'iso-date-time' })('2024-01-15T12:30:00Z'); // true
|
|
323
|
+
* compileISODateTimeFormat(schemaObj, { format: 'iso-date-time' })('2024-01-15T12:30:00+01:00'); // true
|
|
324
|
+
* compileISODateTimeFormat(schemaObj, { format: 'iso-date-time' })('2024-01-15T12:30:00'); // true (no timezone)
|
|
325
|
+
* compileISODateTimeFormat(schemaObj, { format: 'iso-date-time' })('2024-13-15T12:30:00'); // false (with error)
|
|
326
|
+
*/
|
|
327
|
+
export function compileISODateTimeFormat(schemaObj, jsonSchema) {
|
|
328
|
+
return compileFormatByType(
|
|
329
|
+
'iso-date-time',
|
|
330
|
+
getDateTypeOfISODateTime,
|
|
331
|
+
schemaObj,
|
|
332
|
+
jsonSchema,
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Compiles a validator for the 'iso-time' format.
|
|
338
|
+
* Validates ISO 8601 time strings with optional timezone.
|
|
339
|
+
* Unlike RFC 3339 time, the timezone is optional.
|
|
340
|
+
* Supports formatMinimum, formatMaximum, formatExclusiveMinimum, formatExclusiveMaximum.
|
|
341
|
+
*
|
|
342
|
+
* @param {ValidationObject} schemaObj - The validation object for error handling and options
|
|
343
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
344
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
345
|
+
* @example
|
|
346
|
+
* compileISOTimeFormat(schemaObj, { format: 'iso-time' })('12:30:00Z'); // true
|
|
347
|
+
* compileISOTimeFormat(schemaObj, { format: 'iso-time' })('12:30:00+01:00'); // true
|
|
348
|
+
* compileISOTimeFormat(schemaObj, { format: 'iso-time' })('12:30:00'); // true (no timezone)
|
|
349
|
+
* compileISOTimeFormat(schemaObj, { format: 'iso-time' })('25:00:00'); // false (with error)
|
|
350
|
+
*/
|
|
351
|
+
export function compileISOTimeFormat(schemaObj, jsonSchema) {
|
|
352
|
+
return compileFormatByType(
|
|
353
|
+
'iso-time',
|
|
354
|
+
getDateTypeOfISOTime,
|
|
355
|
+
schemaObj,
|
|
356
|
+
jsonSchema,
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Object mapping date/time format names to their compiler functions.
|
|
362
|
+
* Used for backward compatibility and aggregate imports.
|
|
363
|
+
*
|
|
364
|
+
* @type {Record<string, (schemaObj: ValidationObject, jsonSchema: JSONSchema) => (data: unknown, dataPath?: string) => boolean>}
|
|
365
|
+
*/
|
|
366
|
+
export const formatValidators = {
|
|
367
|
+
'date-time': compileDateTimeFormat,
|
|
368
|
+
date: compileDateOnlyFormat,
|
|
369
|
+
time: compileTimeOnlyFormat,
|
|
370
|
+
duration: compileDurationFormat,
|
|
371
|
+
'iso-date-time': compileISODateTimeFormat,
|
|
372
|
+
'iso-time': compileISOTimeFormat,
|
|
373
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A compiled format validator: tests one instance value against the
|
|
5
|
+
* format. `dataPath` is the value's RFC 6901 location, used in error
|
|
6
|
+
* reporting when error collection is enabled.
|
|
7
|
+
* @typedef {(data: unknown, dataPath?: string) => boolean} FormatValidator
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A format compiler as consumed by the JarenValidator's addFormat and
|
|
12
|
+
* addFormats methods of @jarenjs/validate: called once per schema
|
|
13
|
+
* location at compile time with the compiling validation object and the
|
|
14
|
+
* schema declaring the format, it returns the FormatValidator invoked for
|
|
15
|
+
* each instance value. Typed structurally so @jarenjs/formats stays free
|
|
16
|
+
* of a dependency on @jarenjs/validate.
|
|
17
|
+
* @typedef {(schemaObj: import('./string.js').ValidationObject, jsonSchema: import('./string.js').JSONSchema) => FormatValidator} FormatCompiler
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
export { formatValidators as dateTimeFormats } from './datetime.js';
|
|
21
|
+
export { formatValidators as stringFormats } from './string.js';
|
|
22
|
+
export { formatValidators as numberFormats } from './number.js';
|
|
23
|
+
export { formatValidators as jsonFormats } from './json.js';
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
formatTesters,
|
|
27
|
+
stringFormatTesters,
|
|
28
|
+
jsonFormatTesters,
|
|
29
|
+
dateTimeFormatTesters,
|
|
30
|
+
numberFormatTesters,
|
|
31
|
+
} from './testers.js';
|
package/src/json.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//@ts-check
|
|
2
|
+
|
|
3
|
+
// The name -> predicate bindings live in ONE place: testers.js. This
|
|
4
|
+
// module only wraps them in the validator's compiler contract.
|
|
5
|
+
import { jsonFormatTesters } from './testers.js';
|
|
6
|
+
|
|
7
|
+
import { createStringFormatCompiler } from './string.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{format?: string, formatMinimum?: string, formatExclusiveMinimum?: string, formatMaximum?: string, formatExclusiveMaximum?: string}} JSONSchema
|
|
11
|
+
* @typedef {{
|
|
12
|
+
* options: {skipErrors: boolean},
|
|
13
|
+
* createErrorHandler: (expected: any, key: string, ...details: any[]) => (data: any, dataPath?: string) => boolean
|
|
14
|
+
* }} ValidationObject
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// JSON Pointer Format Compilers
|
|
19
|
+
// =============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Compiles a validator for the 'json-pointer' format.
|
|
23
|
+
* Validates JSON Pointer strings per RFC 6901.
|
|
24
|
+
*
|
|
25
|
+
* @param {ValidationObject} schemaObj - The validation JSONSchema for error handling and options
|
|
26
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
27
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
28
|
+
*/
|
|
29
|
+
export const compileJsonPointerFormat = createStringFormatCompiler('json-pointer', jsonFormatTesters['json-pointer']);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Compiles a validator for the 'json-pointer-uri-fragment' format.
|
|
33
|
+
* Validates JSON Pointer URI fragment strings (e.g., #/foo/bar).
|
|
34
|
+
*
|
|
35
|
+
* @param {ValidationObject} schemaObj - The validation JSONSchema for error handling and options
|
|
36
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
37
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
38
|
+
*/
|
|
39
|
+
export const compileJsonPointerUriFragmentFormat = createStringFormatCompiler('json-pointer-uri-fragment', jsonFormatTesters['json-pointer-uri-fragment']);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Compiles a validator for the 'relative-json-pointer' format.
|
|
43
|
+
* Validates Relative JSON Pointer strings.
|
|
44
|
+
*
|
|
45
|
+
* @param {ValidationObject} schemaObj - The validation JSONSchema for error handling and options
|
|
46
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
47
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
48
|
+
*/
|
|
49
|
+
export const compileRelativeJsonPointerFormat = createStringFormatCompiler('relative-json-pointer', jsonFormatTesters['relative-json-pointer']);
|
|
50
|
+
|
|
51
|
+
// =============================================================================
|
|
52
|
+
// JSONPath Format Compiler (RFC 9535)
|
|
53
|
+
// =============================================================================
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Compiles a validator for the 'json-path' format.
|
|
57
|
+
* Validates JSONPath query expressions strictly against the complete
|
|
58
|
+
* RFC 9535 grammar, using the parser of the JSONPath compiler in
|
|
59
|
+
* `@jarenjs/json`. This includes the well-typedness rules for
|
|
60
|
+
* function expressions, so queries like `$[?length(@)]` or comparisons
|
|
61
|
+
* against non-singular queries are rejected.
|
|
62
|
+
*
|
|
63
|
+
* @param {ValidationObject} schemaObj - The validation JSONSchema for error handling and options
|
|
64
|
+
* @param {JSONSchema} jsonSchema - The JSON schema containing the format definition
|
|
65
|
+
* @returns {(data: unknown, dataPath?: string) => boolean} A validator function
|
|
66
|
+
* @example
|
|
67
|
+
* compileJsonPathFormat(schemaObj, { format: 'json-path' })('$.store.book[0].title'); // true
|
|
68
|
+
* compileJsonPathFormat(schemaObj, { format: 'json-path' })("$..book[?@.price < 10]"); // true
|
|
69
|
+
* compileJsonPathFormat(schemaObj, { format: 'json-path' })('@.name'); // false (queries start at $)
|
|
70
|
+
* compileJsonPathFormat(schemaObj, { format: 'json-path' })('$.foo '); // false (trailing whitespace)
|
|
71
|
+
*/
|
|
72
|
+
export const compileJsonPathFormat = createStringFormatCompiler('json-path', jsonFormatTesters['json-path']);
|
|
73
|
+
|
|
74
|
+
// =============================================================================
|
|
75
|
+
// Aggregated Format Validators Object
|
|
76
|
+
// =============================================================================
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Object mapping JSON-related format names to their compiler functions.
|
|
80
|
+
*
|
|
81
|
+
* @type {Record<string, (schemaObj: ValidationObject, jsonSchema: JSONSchema) => (data: unknown, dataPath?: string) => boolean>}
|
|
82
|
+
*/
|
|
83
|
+
export const formatValidators = {
|
|
84
|
+
// JSON Pointer
|
|
85
|
+
'json-pointer': compileJsonPointerFormat,
|
|
86
|
+
'json-pointer-uri-fragment': compileJsonPointerUriFragmentFormat,
|
|
87
|
+
'relative-json-pointer': compileRelativeJsonPointerFormat,
|
|
88
|
+
// JSONPath
|
|
89
|
+
'json-path': compileJsonPathFormat,
|
|
90
|
+
};
|