@naturalcycles/nodejs-lib 15.105.0 → 15.106.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.
@@ -52,6 +52,15 @@ export declare const j: {
52
52
  */
53
53
  withEnumKeys: typeof withEnumKeys;
54
54
  withRegexKeys: typeof withRegexKeys;
55
+ /**
56
+ * Validates that the value is an instance of the given class/constructor.
57
+ *
58
+ * ```ts
59
+ * j.object.instanceOf(Date) // typed as Date
60
+ * j.object.instanceOf(Date).optional() // typed as Date | undefined
61
+ * ```
62
+ */
63
+ instanceOf<T>(ctor: new (...args: any[]) => T): JBuilder<T, false>;
55
64
  };
56
65
  array<OUT, Opt>(itemSchema: JSchema<OUT, Opt>): JArray<OUT, Opt>;
57
66
  tuple<const S extends JSchema<any, any>[]>(items: S): JTuple<S>;
@@ -69,7 +78,7 @@ export declare const j: {
69
78
  * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
70
79
  * Use `oneOf` when schemas are mutually exclusive.
71
80
  */
72
- oneOf<B extends readonly JSchema<any, boolean>[], OUT = BuilderOutUnion<B>>(items: [...B]): JBuilder<OUT, false>;
81
+ oneOf<B extends readonly JSchema<any, boolean>[]>(items: [...B]): JBuilder<BuilderOutUnion<B>, false>;
73
82
  /**
74
83
  * Use only with primitive values, otherwise this function will throw to avoid bugs.
75
84
  * To validate objects, use `anyOfBy` or `anyOfThese`.
@@ -81,7 +90,7 @@ export declare const j: {
81
90
  * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
82
91
  * Use `oneOf` when schemas are mutually exclusive.
83
92
  */
84
- anyOf<B extends readonly JSchema<any, boolean>[], OUT = BuilderOutUnion<B>>(items: [...B]): JBuilder<OUT, false>;
93
+ anyOf<B extends readonly JSchema<any, boolean>[]>(items: [...B]): JBuilder<BuilderOutUnion<B>, false>;
85
94
  /**
86
95
  * Pick validation schema for an object based on the value of a specific property.
87
96
  *
@@ -94,7 +103,7 @@ export declare const j: {
94
103
  * const schema = j.anyOfBy('success', schemaMap)
95
104
  * ```
96
105
  */
97
- anyOfBy<D extends Record<PropertyKey, JSchema<any, any>>, OUT = AnyOfByOut<D>>(propertyName: string, schemaDictionary: D): JBuilder<OUT, false>;
106
+ anyOfBy<D extends Record<PropertyKey, JSchema<any, any>>>(propertyName: string, schemaDictionary: D): JBuilder<AnyOfByOut<D>, false>;
98
107
  /**
99
108
  * Custom version of `anyOf` which - in contrast to the original function - does not mutate the input.
100
109
  * This comes with a performance penalty, so do not use it where performance matters.
@@ -103,7 +112,7 @@ export declare const j: {
103
112
  * const schema = j.anyOfThese([successSchema, errorSchema])
104
113
  * ```
105
114
  */
106
- anyOfThese<B extends readonly JSchema<any, boolean>[], OUT = BuilderOutUnion<B>>(items: [...B]): JBuilder<OUT, false>;
115
+ anyOfThese<B extends readonly JSchema<any, boolean>[]>(items: [...B]): JBuilder<BuilderOutUnion<B>, false>;
107
116
  and(): {
108
117
  silentBob: () => never;
109
118
  };
@@ -410,9 +419,9 @@ export declare class JTuple<ITEMS extends JSchema<any, any>[]> extends JBuilder<
410
419
  constructor(items: ITEMS);
411
420
  }
412
421
  declare function object(props: AnyObject): never;
413
- declare function object<OUT extends AnyObject>(props: {
422
+ declare function object<OUT extends AnyObject>(props: [keyof OUT] extends [never] ? Record<string, never> : {
414
423
  [K in keyof Required<OUT>]-?: JSchema<OUT[K], any>;
415
- }): JObject<OUT, false>;
424
+ }): [keyof OUT] extends [never] ? never : JObject<OUT, false>;
416
425
  declare function objectInfer<P extends Record<string, JSchema<any, any>>>(props: P): JObjectInfer<P, false>;
417
426
  declare function objectDbEntity(props: AnyObject): never;
418
427
  declare function objectDbEntity<OUT extends BaseDBEntity, EXTRA_KEYS extends Exclude<keyof OUT, keyof BaseDBEntity> = Exclude<keyof OUT, keyof BaseDBEntity>>(props: {
@@ -81,6 +81,21 @@ export const j = {
81
81
  */
82
82
  withEnumKeys,
83
83
  withRegexKeys,
84
+ /**
85
+ * Validates that the value is an instance of the given class/constructor.
86
+ *
87
+ * ```ts
88
+ * j.object.instanceOf(Date) // typed as Date
89
+ * j.object.instanceOf(Date).optional() // typed as Date | undefined
90
+ * ```
91
+ */
92
+ instanceOf(ctor) {
93
+ return new JBuilder({
94
+ type: 'object',
95
+ instanceof: ctor.name,
96
+ hasIsOfTypeCheck: true,
97
+ });
98
+ },
84
99
  }),
85
100
  array(itemSchema) {
86
101
  return new JArray(itemSchema);
@@ -1061,7 +1076,6 @@ export class AjvSchema {
1061
1076
  }
1062
1077
  let jsonSchema;
1063
1078
  if (schema instanceof JSchema) {
1064
- // oxlint-disable typescript-eslint(no-unnecessary-type-assertion)
1065
1079
  jsonSchema = schema.build();
1066
1080
  AjvSchema.requireValidJsonSchema(jsonSchema);
1067
1081
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.105.0",
4
+ "version": "15.106.1",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@standard-schema/spec": "^1",
@@ -135,6 +135,22 @@ export const j = {
135
135
  */
136
136
  withEnumKeys,
137
137
  withRegexKeys,
138
+
139
+ /**
140
+ * Validates that the value is an instance of the given class/constructor.
141
+ *
142
+ * ```ts
143
+ * j.object.instanceOf(Date) // typed as Date
144
+ * j.object.instanceOf(Date).optional() // typed as Date | undefined
145
+ * ```
146
+ */
147
+ instanceOf<T>(ctor: new (...args: any[]) => T): JBuilder<T, false> {
148
+ return new JBuilder<T, false>({
149
+ type: 'object',
150
+ instanceof: ctor.name,
151
+ hasIsOfTypeCheck: true,
152
+ })
153
+ },
138
154
  }),
139
155
 
140
156
  array<OUT, Opt>(itemSchema: JSchema<OUT, Opt>): JArray<OUT, Opt> {
@@ -203,16 +219,16 @@ export const j = {
203
219
  * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
204
220
  * Use `oneOf` when schemas are mutually exclusive.
205
221
  */
206
- oneOf<B extends readonly JSchema<any, boolean>[], OUT = BuilderOutUnion<B>>(
222
+ oneOf<B extends readonly JSchema<any, boolean>[]>(
207
223
  items: [...B],
208
- ): JBuilder<OUT, false> {
224
+ ): JBuilder<BuilderOutUnion<B>, false> {
209
225
  const schemas = items.map(b => b.build())
210
226
  _assert(
211
227
  schemas.every(hasNoObjectSchemas),
212
228
  'Do not use `oneOf` validation with non-primitive types!',
213
229
  )
214
230
 
215
- return new JBuilder<OUT, false>({
231
+ return new JBuilder<BuilderOutUnion<B>, false>({
216
232
  oneOf: schemas,
217
233
  })
218
234
  },
@@ -228,16 +244,16 @@ export const j = {
228
244
  * Use `anyOf` when schemas may overlap (e.g., AccountId | PartnerId with same format).
229
245
  * Use `oneOf` when schemas are mutually exclusive.
230
246
  */
231
- anyOf<B extends readonly JSchema<any, boolean>[], OUT = BuilderOutUnion<B>>(
247
+ anyOf<B extends readonly JSchema<any, boolean>[]>(
232
248
  items: [...B],
233
- ): JBuilder<OUT, false> {
249
+ ): JBuilder<BuilderOutUnion<B>, false> {
234
250
  const schemas = items.map(b => b.build())
235
251
  _assert(
236
252
  schemas.every(hasNoObjectSchemas),
237
253
  'Do not use `anyOf` validation with non-primitive types!',
238
254
  )
239
255
 
240
- return new JBuilder<OUT, false>({
256
+ return new JBuilder<BuilderOutUnion<B>, false>({
241
257
  anyOf: schemas,
242
258
  })
243
259
  },
@@ -254,16 +270,16 @@ export const j = {
254
270
  * const schema = j.anyOfBy('success', schemaMap)
255
271
  * ```
256
272
  */
257
- anyOfBy<D extends Record<PropertyKey, JSchema<any, any>>, OUT = AnyOfByOut<D>>(
273
+ anyOfBy<D extends Record<PropertyKey, JSchema<any, any>>>(
258
274
  propertyName: string,
259
275
  schemaDictionary: D,
260
- ): JBuilder<OUT, false> {
276
+ ): JBuilder<AnyOfByOut<D>, false> {
261
277
  const builtSchemaDictionary: Record<string, JsonSchema> = {}
262
278
  for (const [key, schema] of Object.entries(schemaDictionary)) {
263
279
  builtSchemaDictionary[key] = schema.build()
264
280
  }
265
281
 
266
- return new JBuilder<OUT, false>({
282
+ return new JBuilder<AnyOfByOut<D>, false>({
267
283
  type: 'object',
268
284
  hasIsOfTypeCheck: true,
269
285
  anyOfBy: {
@@ -281,10 +297,10 @@ export const j = {
281
297
  * const schema = j.anyOfThese([successSchema, errorSchema])
282
298
  * ```
283
299
  */
284
- anyOfThese<B extends readonly JSchema<any, boolean>[], OUT = BuilderOutUnion<B>>(
300
+ anyOfThese<B extends readonly JSchema<any, boolean>[]>(
285
301
  items: [...B],
286
- ): JBuilder<OUT, false> {
287
- return new JBuilder<OUT, false>({
302
+ ): JBuilder<BuilderOutUnion<B>, false> {
303
+ return new JBuilder<BuilderOutUnion<B>, false>({
288
304
  anyOfThese: items.map(b => b.build()),
289
305
  })
290
306
  },
@@ -1323,9 +1339,11 @@ export class JTuple<ITEMS extends JSchema<any, any>[]> extends JBuilder<TupleOut
1323
1339
  // ==== Standalone functions for j.object ====
1324
1340
 
1325
1341
  function object(props: AnyObject): never
1326
- function object<OUT extends AnyObject>(props: {
1327
- [K in keyof Required<OUT>]-?: JSchema<OUT[K], any>
1328
- }): JObject<OUT, false>
1342
+ function object<OUT extends AnyObject>(
1343
+ props: [keyof OUT] extends [never]
1344
+ ? Record<string, never>
1345
+ : { [K in keyof Required<OUT>]-?: JSchema<OUT[K], any> },
1346
+ ): [keyof OUT] extends [never] ? never : JObject<OUT, false>
1329
1347
 
1330
1348
  function object<OUT extends AnyObject>(props: {
1331
1349
  [key in keyof OUT]: JSchema<OUT[key], any>
@@ -1531,8 +1549,7 @@ export class AjvSchema<OUT> {
1531
1549
  let jsonSchema: JsonSchema<OUT>
1532
1550
 
1533
1551
  if (schema instanceof JSchema) {
1534
- // oxlint-disable typescript-eslint(no-unnecessary-type-assertion)
1535
- jsonSchema = (schema as JSchema<OUT, any>).build()
1552
+ jsonSchema = schema.build()
1536
1553
  AjvSchema.requireValidJsonSchema(jsonSchema)
1537
1554
  } else {
1538
1555
  jsonSchema = schema
@@ -1654,7 +1671,7 @@ function executeValidation<OUT>(
1654
1671
  const [err, result] = _try(() => builtSchema.postValidation!(output))
1655
1672
  if (err) {
1656
1673
  valid = false
1657
- ;(fn as any).errors = [
1674
+ fn.errors = [
1658
1675
  {
1659
1676
  instancePath: '',
1660
1677
  message: err.message,