@naturalcycles/nodejs-lib 15.47.1 → 15.49.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.
@@ -3,7 +3,7 @@ import { type AnyObject } from '@naturalcycles/js-lib/types';
3
3
  import type { ZodType } from '@naturalcycles/js-lib/zod';
4
4
  import type { Ajv } from 'ajv';
5
5
  import { AjvValidationError } from './ajvValidationError.js';
6
- import { type JsonSchema, JsonSchemaAnyBuilder } from './jsonSchemaBuilder.js';
6
+ import { type JsonSchema, JsonSchemaTerminal } from './jsonSchemaBuilder.js';
7
7
  /**
8
8
  * On creation - compiles ajv validation function.
9
9
  * Provides convenient methods, error reporting, etc.
@@ -29,7 +29,7 @@ export declare class AjvSchema<IN = unknown, OUT = IN> {
29
29
  * @deprecated Use `j` to build schemas, not `z` or `zod`.
30
30
  */
31
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>;
32
+ static isJsonSchemaBuilder<IN, OUT>(schema: unknown): schema is JsonSchemaTerminal<IN, OUT, any>;
33
33
  readonly cfg: AjvSchemaCfg;
34
34
  /**
35
35
  * It returns the original object just for convenience.
@@ -94,4 +94,4 @@ export interface AjvSchemaCfg {
94
94
  */
95
95
  lazy?: boolean;
96
96
  }
97
- export type SchemaHandledByAjv<IN, OUT = IN> = JsonSchemaAnyBuilder<IN, OUT, any> | JsonSchema<IN, OUT> | AjvSchema<IN, OUT>;
97
+ export type SchemaHandledByAjv<IN, OUT = IN> = JsonSchemaTerminal<IN, OUT, any> | JsonSchema<IN, OUT> | AjvSchema<IN, OUT>;
@@ -7,7 +7,7 @@ import { z } from '@naturalcycles/js-lib/zod';
7
7
  import { _inspect } from '../../string/inspect.js';
8
8
  import { AjvValidationError } from './ajvValidationError.js';
9
9
  import { getAjv } from './getAjv.js';
10
- import { JsonSchemaAnyBuilder } from './jsonSchemaBuilder.js';
10
+ import { JsonSchemaTerminal } from './jsonSchemaBuilder.js';
11
11
  /**
12
12
  * On creation - compiles ajv validation function.
13
13
  * Provides convenient methods, error reporting, etc.
@@ -73,7 +73,7 @@ export class AjvSchema {
73
73
  return AjvSchema.create(jsonSchema);
74
74
  }
75
75
  static isJsonSchemaBuilder(schema) {
76
- return schema instanceof JsonSchemaAnyBuilder;
76
+ return schema instanceof JsonSchemaTerminal;
77
77
  }
78
78
  cfg;
79
79
  /**
@@ -15,9 +15,23 @@ export declare const j: {
15
15
  enum<const T extends readonly (string | number | boolean | null)[] | StringEnum | NumberEnum>(input: T, opt?: JsonBuilderRuleOpt): JsonSchemaEnumBuilder<T extends readonly (infer U)[] ? U : T extends StringEnum ? T[keyof T] : T extends NumberEnum ? T[keyof T] : never>;
16
16
  oneOf<B extends readonly JsonSchemaAnyBuilder<any, any, boolean>[], IN = BuilderInUnion<B>, OUT = BuilderOutUnion<B>>(items: [...B]): JsonSchemaAnyBuilder<IN, OUT, false>;
17
17
  };
18
- export declare class JsonSchemaAnyBuilder<IN, OUT, Opt> {
18
+ export declare class JsonSchemaTerminal<IN, OUT, Opt> {
19
19
  protected schema: JsonSchema;
20
20
  constructor(schema: JsonSchema);
21
+ getSchema(): JsonSchema;
22
+ /**
23
+ * Produces a "clean schema object" without methods.
24
+ * Same as if it would be JSON.stringified.
25
+ */
26
+ build(): JsonSchema<IN, OUT>;
27
+ clone(): JsonSchemaAnyBuilder<IN, OUT, Opt>;
28
+ /**
29
+ * @experimental
30
+ */
31
+ in: IN;
32
+ out: OUT;
33
+ }
34
+ export declare class JsonSchemaAnyBuilder<IN, OUT, Opt> extends JsonSchemaTerminal<IN, OUT, Opt> {
21
35
  protected setErrorMessage(ruleName: string, errorMessage: string | undefined): void;
22
36
  /**
23
37
  * A helper function that takes a type parameter and compares it with the type inferred from the schema.
@@ -33,7 +47,6 @@ export declare class JsonSchemaAnyBuilder<IN, OUT, Opt> {
33
47
  * ```
34
48
  */
35
49
  isOfType<ExpectedType>(): ExactMatch<ExpectedType, OUT> extends true ? this : never;
36
- getSchema(): JsonSchema;
37
50
  $schema($schema: string): this;
38
51
  $schemaDraft7(): this;
39
52
  $id($id: string): this;
@@ -45,22 +58,15 @@ export declare class JsonSchemaAnyBuilder<IN, OUT, Opt> {
45
58
  instanceof(of: string): this;
46
59
  optional(): JsonSchemaAnyBuilder<IN | undefined, OUT | undefined, true>;
47
60
  nullable(): JsonSchemaAnyBuilder<IN | null, OUT | null, Opt>;
48
- /**
49
- * Produces a "clean schema object" without methods.
50
- * Same as if it would be JSON.stringified.
51
- */
52
- build(): JsonSchema<IN, OUT>;
53
- clone(): JsonSchemaAnyBuilder<IN, OUT, Opt>;
54
61
  /**
55
62
  * @deprecated
56
63
  * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
57
64
  */
58
65
  castAs<T>(): JsonSchemaAnyBuilder<T, T, Opt>;
59
66
  /**
60
- * @experimental
67
+ * Locks the given schema chain and no other modification can be done to it.
61
68
  */
62
- in: IN;
63
- out: OUT;
69
+ final(): JsonSchemaTerminal<IN, OUT, Opt>;
64
70
  }
65
71
  export declare class JsonSchemaStringBuilder<IN extends string = string, OUT = IN, Opt extends boolean = false> extends JsonSchemaAnyBuilder<IN, OUT, Opt> {
66
72
  constructor();
@@ -163,6 +169,8 @@ export declare class JsonSchemaObjectBuilder<IN extends AnyObject, OUT extends A
163
169
  * Extends the current schema with `id`, `created` and `updated` according to NC DB conventions.
164
170
  */
165
171
  dbEntity(): JsonSchemaObjectBuilder<any, any, Opt>;
172
+ minProperties(minProperties: number): this;
173
+ maxProperties(maxProperties: number): this;
166
174
  }
167
175
  export declare class JsonSchemaObjectInferringBuilder<PROPS extends Record<string, JsonSchemaAnyBuilder<any, any, any>>, Opt extends boolean = false> extends JsonSchemaAnyBuilder<Expand<{
168
176
  [K in keyof PROPS as PROPS[K] extends JsonSchemaAnyBuilder<any, any, infer IsOpt> ? IsOpt extends true ? never : K : never]: PROPS[K] extends JsonSchemaAnyBuilder<infer IN, any, any> ? IN : never;
@@ -78,11 +78,31 @@ const TS_2000_MILLIS = TS_2000 * 1000;
78
78
  which means that the `foo` property would be mandatory, it's just that its value can be `undefined` as well.
79
79
  With `Opt`, we can infer it as `{ foo?: string | undefined }`.
80
80
  */
81
- export class JsonSchemaAnyBuilder {
81
+ export class JsonSchemaTerminal {
82
82
  schema;
83
83
  constructor(schema) {
84
84
  this.schema = schema;
85
85
  }
86
+ getSchema() {
87
+ return this.schema;
88
+ }
89
+ /**
90
+ * Produces a "clean schema object" without methods.
91
+ * Same as if it would be JSON.stringified.
92
+ */
93
+ build() {
94
+ return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER);
95
+ }
96
+ clone() {
97
+ return new JsonSchemaAnyBuilder(_deepCopy(this.schema));
98
+ }
99
+ /**
100
+ * @experimental
101
+ */
102
+ in;
103
+ out;
104
+ }
105
+ export class JsonSchemaAnyBuilder extends JsonSchemaTerminal {
86
106
  setErrorMessage(ruleName, errorMessage) {
87
107
  if (_isUndefined(errorMessage))
88
108
  return;
@@ -106,9 +126,6 @@ export class JsonSchemaAnyBuilder {
106
126
  _objectAssign(this.schema, { hasIsOfTypeCheck: true });
107
127
  return this;
108
128
  }
109
- getSchema() {
110
- return this.schema;
111
- }
112
129
  $schema($schema) {
113
130
  _objectAssign(this.schema, { $schema });
114
131
  return this;
@@ -154,16 +171,6 @@ export class JsonSchemaAnyBuilder {
154
171
  anyOf: [this.build(), { type: 'null' }],
155
172
  });
156
173
  }
157
- /**
158
- * Produces a "clean schema object" without methods.
159
- * Same as if it would be JSON.stringified.
160
- */
161
- build() {
162
- return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER);
163
- }
164
- clone() {
165
- return new JsonSchemaAnyBuilder(_deepCopy(this.schema));
166
- }
167
174
  /**
168
175
  * @deprecated
169
176
  * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
@@ -172,10 +179,11 @@ export class JsonSchemaAnyBuilder {
172
179
  return this;
173
180
  }
174
181
  /**
175
- * @experimental
182
+ * Locks the given schema chain and no other modification can be done to it.
176
183
  */
177
- in;
178
- out;
184
+ final() {
185
+ return new JsonSchemaTerminal(this.schema);
186
+ }
179
187
  }
180
188
  export class JsonSchemaStringBuilder extends JsonSchemaAnyBuilder {
181
189
  constructor() {
@@ -496,6 +504,14 @@ export class JsonSchemaObjectBuilder extends JsonSchemaAnyBuilder {
496
504
  updated: j.number().unixTimestamp2000(),
497
505
  });
498
506
  }
507
+ minProperties(minProperties) {
508
+ Object.assign(this.schema, { minProperties });
509
+ return this;
510
+ }
511
+ maxProperties(maxProperties) {
512
+ Object.assign(this.schema, { maxProperties });
513
+ return this;
514
+ }
499
515
  }
500
516
  export class JsonSchemaObjectInferringBuilder extends JsonSchemaAnyBuilder {
501
517
  constructor(props) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.47.1",
4
+ "version": "15.49.0",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@types/js-yaml": "^4",
@@ -14,7 +14,7 @@ import type { Ajv, ErrorObject } from 'ajv'
14
14
  import { _inspect } from '../../string/inspect.js'
15
15
  import { AjvValidationError } from './ajvValidationError.js'
16
16
  import { getAjv } from './getAjv.js'
17
- import { type JsonSchema, JsonSchemaAnyBuilder } from './jsonSchemaBuilder.js'
17
+ import { type JsonSchema, JsonSchemaTerminal } from './jsonSchemaBuilder.js'
18
18
 
19
19
  /**
20
20
  * On creation - compiles ajv validation function.
@@ -73,10 +73,10 @@ export class AjvSchema<IN = unknown, OUT = IN> {
73
73
  let jsonSchema: JsonSchema<IN, OUT>
74
74
 
75
75
  if (AjvSchema.isJsonSchemaBuilder(schema)) {
76
- jsonSchema = (schema as JsonSchemaAnyBuilder<IN, OUT, any>).build()
76
+ jsonSchema = (schema as JsonSchemaTerminal<IN, OUT, any>).build()
77
77
  AjvSchema.requireValidJsonSchema(jsonSchema)
78
78
  } else {
79
- jsonSchema = schema as JsonSchema<IN, OUT>
79
+ jsonSchema = schema
80
80
  }
81
81
 
82
82
  const ajvSchema = new AjvSchema<IN, OUT>(jsonSchema, cfg)
@@ -98,10 +98,8 @@ export class AjvSchema<IN = unknown, OUT = IN> {
98
98
  return AjvSchema.create(jsonSchema)
99
99
  }
100
100
 
101
- static isJsonSchemaBuilder<IN, OUT>(
102
- schema: unknown,
103
- ): schema is JsonSchemaAnyBuilder<IN, OUT, any> {
104
- return schema instanceof JsonSchemaAnyBuilder
101
+ static isJsonSchemaBuilder<IN, OUT>(schema: unknown): schema is JsonSchemaTerminal<IN, OUT, any> {
102
+ return schema instanceof JsonSchemaTerminal
105
103
  }
106
104
 
107
105
  readonly cfg: AjvSchemaCfg
@@ -286,6 +284,6 @@ export interface AjvSchemaCfg {
286
284
  }
287
285
 
288
286
  export type SchemaHandledByAjv<IN, OUT = IN> =
289
- | JsonSchemaAnyBuilder<IN, OUT, any>
287
+ | JsonSchemaTerminal<IN, OUT, any>
290
288
  | JsonSchema<IN, OUT>
291
289
  | AjvSchema<IN, OUT>
@@ -134,9 +134,37 @@ const TS_2000_MILLIS = TS_2000 * 1000
134
134
  With `Opt`, we can infer it as `{ foo?: string | undefined }`.
135
135
  */
136
136
 
137
- export class JsonSchemaAnyBuilder<IN, OUT, Opt> {
138
- constructor(protected schema: JsonSchema) {}
137
+ export class JsonSchemaTerminal<IN, OUT, Opt> {
138
+ protected schema: JsonSchema
139
139
 
140
+ constructor(schema: JsonSchema) {
141
+ this.schema = schema
142
+ }
143
+
144
+ getSchema(): JsonSchema {
145
+ return this.schema
146
+ }
147
+
148
+ /**
149
+ * Produces a "clean schema object" without methods.
150
+ * Same as if it would be JSON.stringified.
151
+ */
152
+ build(): JsonSchema<IN, OUT> {
153
+ return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER)
154
+ }
155
+
156
+ clone(): JsonSchemaAnyBuilder<IN, OUT, Opt> {
157
+ return new JsonSchemaAnyBuilder<IN, OUT, Opt>(_deepCopy(this.schema))
158
+ }
159
+
160
+ /**
161
+ * @experimental
162
+ */
163
+ in!: IN
164
+ out!: OUT
165
+ }
166
+
167
+ export class JsonSchemaAnyBuilder<IN, OUT, Opt> extends JsonSchemaTerminal<IN, OUT, Opt> {
140
168
  protected setErrorMessage(ruleName: string, errorMessage: string | undefined): void {
141
169
  if (_isUndefined(errorMessage)) return
142
170
 
@@ -162,10 +190,6 @@ export class JsonSchemaAnyBuilder<IN, OUT, Opt> {
162
190
  return this as any
163
191
  }
164
192
 
165
- getSchema(): JsonSchema {
166
- return this.schema
167
- }
168
-
169
193
  $schema($schema: string): this {
170
194
  _objectAssign(this.schema, { $schema })
171
195
  return this
@@ -222,18 +246,6 @@ export class JsonSchemaAnyBuilder<IN, OUT, Opt> {
222
246
  })
223
247
  }
224
248
 
225
- /**
226
- * Produces a "clean schema object" without methods.
227
- * Same as if it would be JSON.stringified.
228
- */
229
- build(): JsonSchema<IN, OUT> {
230
- return _sortObject(JSON.parse(JSON.stringify(this.schema)), JSON_SCHEMA_ORDER)
231
- }
232
-
233
- clone(): JsonSchemaAnyBuilder<IN, OUT, Opt> {
234
- return new JsonSchemaAnyBuilder<IN, OUT, Opt>(_deepCopy(this.schema))
235
- }
236
-
237
249
  /**
238
250
  * @deprecated
239
251
  * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
@@ -243,10 +255,11 @@ export class JsonSchemaAnyBuilder<IN, OUT, Opt> {
243
255
  }
244
256
 
245
257
  /**
246
- * @experimental
258
+ * Locks the given schema chain and no other modification can be done to it.
247
259
  */
248
- in!: IN
249
- out!: OUT
260
+ final(): JsonSchemaTerminal<IN, OUT, Opt> {
261
+ return new JsonSchemaTerminal<IN, OUT, Opt>(this.schema)
262
+ }
250
263
  }
251
264
 
252
265
  export class JsonSchemaStringBuilder<
@@ -672,6 +685,16 @@ export class JsonSchemaObjectBuilder<
672
685
  updated: j.number().unixTimestamp2000(),
673
686
  })
674
687
  }
688
+
689
+ minProperties(minProperties: number): this {
690
+ Object.assign(this.schema, { minProperties })
691
+ return this
692
+ }
693
+
694
+ maxProperties(maxProperties: number): this {
695
+ Object.assign(this.schema, { maxProperties })
696
+ return this
697
+ }
675
698
  }
676
699
 
677
700
  export class JsonSchemaObjectInferringBuilder<