@naturalcycles/nodejs-lib 15.37.2 → 15.39.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.
@@ -1,4 +1,4 @@
1
1
  /**
2
- * CommonLogger that logs to process.stdout directly (bypassing console.log).
2
+ * CommonLogger that logs to process.stdout directly (bypassing console.log)!
3
3
  */
4
4
  export declare const stdoutLogger: any;
@@ -1,7 +1,7 @@
1
1
  import { commonLoggerCreate } from '@naturalcycles/js-lib/log';
2
2
  import { _inspect } from '../string/inspect.js';
3
3
  /**
4
- * CommonLogger that logs to process.stdout directly (bypassing console.log).
4
+ * CommonLogger that logs to process.stdout directly (bypassing console.log)!
5
5
  */
6
6
  export const stdoutLogger = commonLoggerCreate((_level, args) => {
7
7
  process.stdout.write(args.map(a => _inspect(a)).join(' ') + '\n');
@@ -4,7 +4,7 @@ This file is "vendored" from Nanoid, all credit is to Nanoid authors:
4
4
  https://github.com/ai/nanoid/
5
5
 
6
6
  */
7
- /* eslint-disable */
7
+ // oxlint-disable no-bitwise -- NanoID implementation relies on bitwise operations
8
8
  import { randomFillSync } from 'node:crypto';
9
9
  export const ALPHABET_NONAMBIGUOUS = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
10
10
  export const ALPHABET_NUMBER = '0123456789';
@@ -1,10 +1,59 @@
1
1
  import { type ValidationFunction, type ValidationFunctionResult } from '@naturalcycles/js-lib';
2
- import type { JsonSchema, JsonSchemaBuilder } from '@naturalcycles/js-lib/json-schema';
3
- import type { AnyObject } from '@naturalcycles/js-lib/types';
4
- import { ZodType } from '@naturalcycles/js-lib/zod';
2
+ import { type AnyObject } from '@naturalcycles/js-lib/types';
3
+ import type { ZodType } from '@naturalcycles/js-lib/zod';
5
4
  import type { Ajv } from 'ajv';
6
5
  import { AjvValidationError } from './ajvValidationError.js';
7
- export type SchemaHandledByAjv<T> = JsonSchemaBuilder<T> | JsonSchema<T> | AjvSchema<T> | ZodType<T>;
6
+ import { type JsonSchema, JsonSchemaAnyBuilder } from './jsonSchemaBuilder.js';
7
+ /**
8
+ * On creation - compiles ajv validation function.
9
+ * Provides convenient methods, error reporting, etc.
10
+ */
11
+ export declare class AjvSchema<IN = unknown, OUT = IN> {
12
+ schema: JsonSchema<IN, OUT>;
13
+ private constructor();
14
+ /**
15
+ * Shortcut for AjvSchema.create(schema, { lazy: true })
16
+ */
17
+ static createLazy<IN, OUT>(schema: SchemaHandledByAjv<IN, OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<IN, OUT>;
18
+ /**
19
+ * Conveniently allows to pass either JsonSchema or JsonSchemaBuilder, or existing AjvSchema.
20
+ * If it's already an AjvSchema - it'll just return it without any processing.
21
+ * If it's a Builder - will call `build` before proceeding.
22
+ * Otherwise - will construct AjvSchema instance ready to be used.
23
+ *
24
+ * Implementation note: JsonSchemaBuilder goes first in the union type, otherwise TypeScript fails to infer <T> type
25
+ * correctly for some reason.
26
+ */
27
+ static create<IN, OUT = IN>(schema: SchemaHandledByAjv<IN, OUT>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<IN, OUT>;
28
+ /**
29
+ * @deprecated Use `j` to build schemas, not `z` or `zod`.
30
+ */
31
+ static createFromZod<T extends ZodType<any, any, any>>(schema: T): AjvSchema<T['_input'], T['_output']>;
32
+ static isJsonSchemaBuilder<IN, OUT>(schema: unknown): schema is JsonSchemaAnyBuilder<IN, OUT, any>;
33
+ readonly cfg: AjvSchemaCfg;
34
+ /**
35
+ * It returns the original object just for convenience.
36
+ * Reminder: Ajv will MUTATE your object under 2 circumstances:
37
+ * 1. `useDefaults` option (enabled by default!), which will set missing/empty values that have `default` set in the schema.
38
+ * 2. `coerceTypes` (false by default).
39
+ *
40
+ * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
41
+ */
42
+ validate(input: IN, opt?: AjvValidationOptions): OUT;
43
+ isValid(input: IN, opt?: AjvValidationOptions): boolean;
44
+ getValidationResult(input: IN, opt?: AjvValidationOptions): ValidationFunctionResult<OUT, AjvValidationError>;
45
+ getValidationFunction(): ValidationFunction<IN, OUT, AjvValidationError>;
46
+ static isSchemaWithCachedAjvSchema<Base, IN, OUT>(schema: Base): schema is WithCachedAjvSchema<Base, IN, OUT>;
47
+ static cacheAjvSchema<Base extends AnyObject, IN, OUT>(schema: Base, ajvSchema: AjvSchema<IN, OUT>): WithCachedAjvSchema<Base, IN, OUT>;
48
+ static requireCachedAjvSchema<Base, IN, OUT>(schema: WithCachedAjvSchema<Base, IN, OUT>): AjvSchema<IN, OUT>;
49
+ private getAJVValidateFunction;
50
+ private static requireValidJsonSchema;
51
+ private applyImprovementsOnErrorMessages;
52
+ }
53
+ export declare const HIDDEN_AJV_SCHEMA: unique symbol;
54
+ export type WithCachedAjvSchema<Base, IN, OUT> = Base & {
55
+ [HIDDEN_AJV_SCHEMA]: AjvSchema<IN, OUT>;
56
+ };
8
57
  export interface AjvValidationOptions {
9
58
  /**
10
59
  * Defaults to true,
@@ -45,54 +94,4 @@ export interface AjvSchemaCfg {
45
94
  */
46
95
  lazy?: boolean;
47
96
  }
48
- /**
49
- * On creation - compiles ajv validation function.
50
- * Provides convenient methods, error reporting, etc.
51
- */
52
- export declare class AjvSchema<T = unknown> {
53
- schema: JsonSchema<T>;
54
- private constructor();
55
- /**
56
- * Shortcut for AjvSchema.create(schema, { lazy: true })
57
- */
58
- static createLazy<T>(schema: JsonSchemaBuilder<T> | JsonSchema<T> | AjvSchema<T>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<T>;
59
- /**
60
- * Conveniently allows to pass either JsonSchema or JsonSchemaBuilder, or existing AjvSchema.
61
- * If it's already an AjvSchema - it'll just return it without any processing.
62
- * If it's a Builder - will call `build` before proceeding.
63
- * Otherwise - will construct AjvSchema instance ready to be used.
64
- *
65
- * Implementation note: JsonSchemaBuilder goes first in the union type, otherwise TypeScript fails to infer <T> type
66
- * correctly for some reason.
67
- */
68
- static create<T>(schema: SchemaHandledByAjv<T>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<T>;
69
- /**
70
- * @deprecated
71
- *
72
- * Use `AjvSchema.create`
73
- */
74
- static createFromZod<T>(zodSchema: ZodType<T>, cfg?: Partial<AjvSchemaCfg>): AjvSchema<T>;
75
- static isJsonSchemaBuilder<T>(schema: unknown): schema is JsonSchemaBuilder<T>;
76
- static isZodSchema<T>(schema: unknown): schema is ZodType<T>;
77
- readonly cfg: AjvSchemaCfg;
78
- /**
79
- * It returns the original object just for convenience.
80
- * Reminder: Ajv will MUTATE your object under 2 circumstances:
81
- * 1. `useDefaults` option (enabled by default!), which will set missing/empty values that have `default` set in the schema.
82
- * 2. `coerceTypes` (false by default).
83
- *
84
- * Returned object is always the same object (`===`) that was passed, so it is returned just for convenience.
85
- */
86
- validate(input: T, opt?: AjvValidationOptions): T;
87
- isValid(input: T, opt?: AjvValidationOptions): boolean;
88
- getValidationResult(input: T, opt?: AjvValidationOptions): ValidationFunctionResult<T, AjvValidationError>;
89
- getValidationFunction(): ValidationFunction<T, AjvValidationError>;
90
- static isSchemaWithCachedAjvSchema<Base, T>(schema: Base): schema is WithCachedAjvSchema<Base, T>;
91
- static cacheAjvSchema<Base extends AnyObject, T>(schema: Base, ajvSchema: AjvSchema<T>): WithCachedAjvSchema<Base, T>;
92
- static requireCachedAjvSchema<Base, T>(schema: WithCachedAjvSchema<Base, T>): AjvSchema<T>;
93
- private getAJVValidateFunction;
94
- }
95
- export declare const HIDDEN_AJV_SCHEMA: unique symbol;
96
- export type WithCachedAjvSchema<Base, T> = Base & {
97
- [HIDDEN_AJV_SCHEMA]: AjvSchema<T>;
98
- };
97
+ export type SchemaHandledByAjv<IN, OUT = IN> = JsonSchemaAnyBuilder<IN, OUT, any> | JsonSchema<IN, OUT> | AjvSchema<IN, OUT>;
@@ -1,11 +1,13 @@
1
1
  import { _isObject, _lazyValue, } from '@naturalcycles/js-lib';
2
- import { JsonSchemaAnyBuilder } from '@naturalcycles/js-lib/json-schema';
2
+ import { _assert } from '@naturalcycles/js-lib/error';
3
3
  import { _deepCopy, _filterNullishValues } from '@naturalcycles/js-lib/object';
4
4
  import { _substringBefore } from '@naturalcycles/js-lib/string';
5
- import { z, ZodType } from '@naturalcycles/js-lib/zod';
5
+ import { _typeCast } from '@naturalcycles/js-lib/types';
6
+ import { z } from '@naturalcycles/js-lib/zod';
6
7
  import { _inspect } from '../../string/inspect.js';
7
8
  import { AjvValidationError } from './ajvValidationError.js';
8
9
  import { getAjv } from './getAjv.js';
10
+ import { JsonSchemaAnyBuilder } from './jsonSchemaBuilder.js';
9
11
  /**
10
12
  * On creation - compiles ajv validation function.
11
13
  * Provides convenient methods, error reporting, etc.
@@ -52,9 +54,7 @@ export class AjvSchema {
52
54
  let jsonSchema;
53
55
  if (AjvSchema.isJsonSchemaBuilder(schema)) {
54
56
  jsonSchema = schema.build();
55
- }
56
- else if (AjvSchema.isZodSchema(schema)) {
57
- jsonSchema = z.toJSONSchema(schema, { target: 'draft-7' });
57
+ AjvSchema.requireValidJsonSchema(jsonSchema);
58
58
  }
59
59
  else {
60
60
  jsonSchema = schema;
@@ -64,19 +64,17 @@ export class AjvSchema {
64
64
  return ajvSchema;
65
65
  }
66
66
  /**
67
- * @deprecated
68
- *
69
- * Use `AjvSchema.create`
67
+ * @deprecated Use `j` to build schemas, not `z` or `zod`.
70
68
  */
71
- static createFromZod(zodSchema, cfg) {
72
- return AjvSchema.create(zodSchema, cfg);
69
+ static createFromZod(schema) {
70
+ const jsonSchema = z.toJSONSchema(schema, {
71
+ target: 'draft-7',
72
+ });
73
+ return AjvSchema.create(jsonSchema);
73
74
  }
74
75
  static isJsonSchemaBuilder(schema) {
75
76
  return schema instanceof JsonSchemaAnyBuilder;
76
77
  }
77
- static isZodSchema(schema) {
78
- return schema instanceof ZodType;
79
- }
80
78
  cfg;
81
79
  /**
82
80
  * It returns the original object just for convenience.
@@ -104,11 +102,13 @@ export class AjvSchema {
104
102
  ? input // mutate
105
103
  : _deepCopy(input); // not mutate
106
104
  const valid = fn(item); // mutates item
105
+ _typeCast(item);
107
106
  if (valid)
108
107
  return [null, item];
109
108
  const errors = fn.errors;
110
109
  const { inputId = _isObject(input) ? input['id'] : undefined, inputName = this.cfg.inputName || 'Object', } = opt;
111
110
  const dataVar = [inputName, inputId].filter(Boolean).join('.');
111
+ this.applyImprovementsOnErrorMessages(errors);
112
112
  let message = this.cfg.ajv.errorsText(errors, {
113
113
  dataVar,
114
114
  separator,
@@ -143,6 +143,23 @@ export class AjvSchema {
143
143
  return schema[HIDDEN_AJV_SCHEMA];
144
144
  }
145
145
  getAJVValidateFunction = _lazyValue(() => this.cfg.ajv.compile(this.schema));
146
+ static requireValidJsonSchema(schema) {
147
+ // For object schemas we require that it is type checked against an external type, e.g.:
148
+ // interface Foo { name: string }
149
+ // const schema = j.object({ name: j.string() }).ofType<Foo>()
150
+ _assert(schema.type !== 'object' || schema.hasIsOfTypeCheck, 'The schema must be type checked against a type or interface, using the `.isOfType()` helper in `j`.');
151
+ }
152
+ applyImprovementsOnErrorMessages(errors) {
153
+ if (!errors)
154
+ return;
155
+ const { errorMessages } = this.schema;
156
+ for (const error of errors) {
157
+ if (errorMessages?.[error.keyword]) {
158
+ error.message = errorMessages[error.keyword];
159
+ }
160
+ error.instancePath = error.instancePath.replaceAll(/\/(\d+)/g, `[$1]`).replaceAll('/', '.');
161
+ }
162
+ }
146
163
  }
147
164
  const separator = '\n';
148
165
  export const HIDDEN_AJV_SCHEMA = Symbol('HIDDEN_AJV_SCHEMA');
@@ -1,5 +1,4 @@
1
- import type { Options } from 'ajv';
2
- import { Ajv } from 'ajv';
1
+ import { Ajv, type Options } from 'ajv';
3
2
  /**
4
3
  * Return cached instance of Ajv with default (recommended) options.
5
4
  *
@@ -1,9 +1,10 @@
1
- /* eslint-disable @typescript-eslint/prefer-string-starts-ends-with */
2
- /* eslint-disable unicorn/prefer-code-point */
3
1
  import { _lazyValue } from '@naturalcycles/js-lib';
4
- import { Ajv } from 'ajv';
5
- import ajvFormats from 'ajv-formats';
6
- import ajvKeywords from 'ajv-keywords';
2
+ import { Set2 } from '@naturalcycles/js-lib/object';
3
+ import { _substringAfterLast } from '@naturalcycles/js-lib/string';
4
+ import { _, Ajv } from 'ajv';
5
+ import { validTLDs } from './tlds.js';
6
+ /* eslint-disable @typescript-eslint/prefer-string-starts-ends-with */
7
+ // oxlint-disable unicorn/prefer-code-point
7
8
  const AJV_OPTIONS = {
8
9
  removeAdditional: true,
9
10
  allErrors: true,
@@ -44,91 +45,238 @@ export function createAjv(opt) {
44
45
  ...AJV_OPTIONS,
45
46
  ...opt,
46
47
  });
47
- // Add custom formats
48
- addCustomAjvFormats(ajv);
49
- // todo: review and possibly cherry-pick/vendor the formats
50
- // Adds ajv "formats"
51
- // https://ajv.js.org/guide/formats.html
52
- // @ts-expect-error types are wrong
53
- ajvFormats(ajv);
54
- // https://ajv.js.org/packages/ajv-keywords.html
55
- // @ts-expect-error types are wrong
56
- ajvKeywords(ajv, [
57
- 'transform', // trim, toLowerCase, etc.
58
- 'uniqueItemProperties',
59
- 'instanceof',
60
- ]);
61
48
  // Adds $merge, $patch keywords
62
49
  // https://github.com/ajv-validator/ajv-merge-patch
63
50
  // Kirill: temporarily disabled, as it creates a noise of CVE warnings
64
51
  // require('ajv-merge-patch')(ajv)
65
- return ajv;
66
- }
67
- const TS_2500 = 16725225600; // 2500-01-01
68
- const TS_2500_MILLIS = TS_2500 * 1000;
69
- const TS_2000 = 946684800; // 2000-01-01
70
- const TS_2000_MILLIS = TS_2000 * 1000;
71
- const monthLengths = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
72
- function addCustomAjvFormats(ajv) {
73
- return (ajv
74
- .addFormat('id', /^[a-z0-9_]{6,64}$/)
75
- .addFormat('slug', /^[a-z0-9-]+$/)
76
- .addFormat('semVer', /^[0-9]+\.[0-9]+\.[0-9]+$/)
77
- // IETF language tag (https://en.wikipedia.org/wiki/IETF_language_tag)
78
- .addFormat('languageTag', /^[a-z]{2}(-[A-Z]{2})?$/)
79
- .addFormat('countryCode', /^[A-Z]{2}$/)
80
- .addFormat('currency', /^[A-Z]{3}$/)
81
- .addFormat('unixTimestamp', {
82
- type: 'number',
83
- validate: (n) => {
84
- return n >= 0 && n < TS_2500;
85
- },
86
- })
87
- .addFormat('unixTimestamp2000', {
88
- type: 'number',
89
- validate: (n) => {
90
- return n >= TS_2000 && n < TS_2500;
52
+ ajv.addKeyword({
53
+ keyword: 'transform',
54
+ type: 'string',
55
+ modifying: true,
56
+ schemaType: 'object',
57
+ errors: true,
58
+ code(ctx) {
59
+ const { gen, data, schema, it } = ctx;
60
+ const { parentData, parentDataProperty } = it;
61
+ if (schema.trim) {
62
+ gen.assign(_ `${data}`, _ `${data}.trim()`);
63
+ }
64
+ if (schema.toLowerCase) {
65
+ gen.assign(_ `${data}`, _ `${data}.toLowerCase()`);
66
+ }
67
+ if (schema.toUpperCase) {
68
+ gen.assign(_ `${data}`, _ `${data}.toUpperCase()`);
69
+ }
70
+ if (typeof schema.truncate === 'number' && schema.truncate >= 0) {
71
+ gen.assign(_ `${data}`, _ `${data}.slice(0, ${schema.truncate})`);
72
+ if (schema.trim) {
73
+ gen.assign(_ `${data}`, _ `${data}.trim()`);
74
+ }
75
+ }
76
+ gen.if(_ `${parentData} !== undefined`, () => {
77
+ gen.assign(_ `${parentData}[${parentDataProperty}]`, data);
78
+ });
91
79
  },
92
- })
93
- .addFormat('unixTimestampMillis', {
94
- type: 'number',
95
- validate: (n) => {
96
- return n >= 0 && n < TS_2500_MILLIS;
80
+ });
81
+ ajv.addKeyword({
82
+ keyword: 'instanceof',
83
+ modifying: true,
84
+ schemaType: 'string',
85
+ validate(instanceOf, data, _schema, _ctx) {
86
+ if (typeof data !== 'object')
87
+ return false;
88
+ if (data === null)
89
+ return false;
90
+ let proto = Object.getPrototypeOf(data);
91
+ while (proto) {
92
+ if (proto.constructor?.name === instanceOf)
93
+ return true;
94
+ proto = Object.getPrototypeOf(proto);
95
+ }
96
+ return false;
97
97
  },
98
- })
99
- .addFormat('unixTimestampMillis2000', {
100
- type: 'number',
101
- validate: (n) => {
102
- return n >= TS_2000_MILLIS && n < TS_2500_MILLIS;
98
+ });
99
+ ajv.addKeyword({
100
+ keyword: 'Set2',
101
+ type: ['array', 'object'],
102
+ modifying: true,
103
+ errors: true,
104
+ schemaType: 'object',
105
+ compile(innerSchema, _parentSchema, _it) {
106
+ const validateItem = ajv.compile(innerSchema);
107
+ function validateSet(data, ctx) {
108
+ let set;
109
+ const isIterable = data === null || typeof data[Symbol.iterator] === 'function';
110
+ if (data instanceof Set2) {
111
+ set = data;
112
+ }
113
+ else if (isIterable && ctx?.parentData) {
114
+ set = new Set2(data);
115
+ }
116
+ else if (isIterable && !ctx?.parentData) {
117
+ ;
118
+ validateSet.errors = [
119
+ {
120
+ instancePath: ctx?.instancePath ?? '',
121
+ message: 'can only transform an Iterable into a Set2 when the schema is in an object or an array schema. This is an Ajv limitation.',
122
+ },
123
+ ];
124
+ return false;
125
+ }
126
+ else {
127
+ ;
128
+ validateSet.errors = [
129
+ {
130
+ instancePath: ctx?.instancePath ?? '',
131
+ message: 'must be a Set2 object (or optionally an Iterable in some cases)',
132
+ },
133
+ ];
134
+ return false;
135
+ }
136
+ let idx = 0;
137
+ for (const value of set.values()) {
138
+ if (!validateItem(value)) {
139
+ ;
140
+ validateSet.errors = [
141
+ {
142
+ instancePath: (ctx?.instancePath ?? '') + '/' + idx,
143
+ message: `invalid set item at index ${idx}`,
144
+ params: { errors: validateItem.errors },
145
+ },
146
+ ];
147
+ return false;
148
+ }
149
+ idx++;
150
+ }
151
+ if (ctx?.parentData && ctx.parentDataProperty) {
152
+ ctx.parentData[ctx.parentDataProperty] = set;
153
+ }
154
+ return true;
155
+ }
156
+ return validateSet;
103
157
  },
104
- })
105
- .addFormat('utcOffset', {
106
- type: 'number',
107
- validate: (n) => {
108
- // min: -14 hours
109
- // max +14 hours
110
- // multipleOf 15 (minutes)
111
- return n >= -14 * 60 && n <= 14 * 60 && Number.isInteger(n);
158
+ });
159
+ ajv.addKeyword({
160
+ keyword: 'Buffer',
161
+ modifying: true,
162
+ errors: true,
163
+ schemaType: 'boolean',
164
+ compile(_innerSchema, _parentSchema, _it) {
165
+ function validateBuffer(data, ctx) {
166
+ let buffer;
167
+ if (data === null)
168
+ return false;
169
+ const isValid = data instanceof Buffer ||
170
+ data instanceof ArrayBuffer ||
171
+ Array.isArray(data) ||
172
+ typeof data === 'string';
173
+ if (!isValid)
174
+ return false;
175
+ if (data instanceof Buffer) {
176
+ buffer = data;
177
+ }
178
+ else if (isValid && ctx?.parentData) {
179
+ buffer = Buffer.from(data);
180
+ }
181
+ else if (isValid && !ctx?.parentData) {
182
+ ;
183
+ validateBuffer.errors = [
184
+ {
185
+ instancePath: ctx?.instancePath ?? '',
186
+ message: 'can only transform data into a Buffer when the schema is in an object or an array schema. This is an Ajv limitation.',
187
+ },
188
+ ];
189
+ return false;
190
+ }
191
+ else {
192
+ ;
193
+ validateBuffer.errors = [
194
+ {
195
+ instancePath: ctx?.instancePath ?? '',
196
+ message: 'must be a Buffer object (or optionally an Array-like object or ArrayBuffer in some cases)',
197
+ },
198
+ ];
199
+ return false;
200
+ }
201
+ if (ctx?.parentData && ctx.parentDataProperty) {
202
+ ctx.parentData[ctx.parentDataProperty] = buffer;
203
+ }
204
+ return true;
205
+ }
206
+ return validateBuffer;
112
207
  },
113
- })
114
- .addFormat('utcOffsetHours', {
115
- type: 'number',
116
- validate: (n) => {
117
- // min: -14 hours
118
- // max +14 hours
119
- // multipleOf 15 (minutes)
120
- return n >= -14 && n <= 14 && Number.isInteger(n);
208
+ });
209
+ ajv.addKeyword({
210
+ keyword: 'email',
211
+ type: 'string',
212
+ modifying: false,
213
+ errors: true,
214
+ schemaType: 'object',
215
+ validate: function validate(opt, data, _schema, ctx) {
216
+ const { checkTLD } = opt;
217
+ if (!checkTLD)
218
+ return true;
219
+ const tld = _substringAfterLast(data, '.');
220
+ if (validTLDs.has(tld))
221
+ return true;
222
+ validate.errors = [
223
+ {
224
+ instancePath: ctx?.instancePath ?? '',
225
+ message: `has an invalid TLD`,
226
+ },
227
+ ];
228
+ return false;
121
229
  },
122
- })
123
- .addFormat('IsoDate', {
230
+ });
231
+ ajv.addKeyword({
232
+ keyword: 'IsoDate',
124
233
  type: 'string',
125
- validate: isIsoDateValid,
126
- })
127
- .addFormat('IsoDateTime', {
234
+ modifying: false,
235
+ errors: true,
236
+ schemaType: 'boolean',
237
+ validate: function validate(_opt, data, _schema, ctx) {
238
+ const isValid = isIsoDateValid(data);
239
+ if (isValid)
240
+ return true;
241
+ validate.errors = [
242
+ {
243
+ instancePath: ctx?.instancePath ?? '',
244
+ message: `is an invalid IsoDate`,
245
+ },
246
+ ];
247
+ return false;
248
+ },
249
+ });
250
+ ajv.addKeyword({
251
+ keyword: 'IsoDateTime',
128
252
  type: 'string',
129
- validate: isIsoDateTimeValid,
130
- }));
253
+ modifying: false,
254
+ errors: true,
255
+ schemaType: 'boolean',
256
+ validate: function validate(_opt, data, _schema, ctx) {
257
+ const isValid = isIsoDateTimeValid(data);
258
+ if (isValid)
259
+ return true;
260
+ validate.errors = [
261
+ {
262
+ instancePath: ctx?.instancePath ?? '',
263
+ message: `is an invalid IsoDateTime`,
264
+ },
265
+ ];
266
+ return false;
267
+ },
268
+ });
269
+ ajv.addKeyword({
270
+ keyword: 'errorMessages',
271
+ schemaType: 'object',
272
+ });
273
+ ajv.addKeyword({
274
+ keyword: 'hasIsOfTypeCheck',
275
+ schemaType: 'boolean',
276
+ });
277
+ return ajv;
131
278
  }
279
+ const monthLengths = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
132
280
  const DASH_CODE = '-'.charCodeAt(0);
133
281
  const ZERO_CODE = '0'.charCodeAt(0);
134
282
  const PLUS_CODE = '+'.charCodeAt(0);
@@ -2,4 +2,5 @@ import Ajv from 'ajv';
2
2
  export * from './ajvSchema.js';
3
3
  export * from './ajvValidationError.js';
4
4
  export * from './getAjv.js';
5
+ export * from './jsonSchemaBuilder.js';
5
6
  export { Ajv };
@@ -2,4 +2,5 @@ import Ajv from 'ajv';
2
2
  export * from './ajvSchema.js';
3
3
  export * from './ajvValidationError.js';
4
4
  export * from './getAjv.js';
5
+ export * from './jsonSchemaBuilder.js';
5
6
  export { Ajv };