@naturalcycles/nodejs-lib 15.97.3 → 15.97.5

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.
@@ -180,6 +180,11 @@ export declare class JSchema<OUT, Opt> implements StandardSchemaV1<unknown, OUT>
180
180
  }
181
181
  export declare class JBuilder<OUT, Opt> extends JSchema<OUT, Opt> {
182
182
  protected setErrorMessage(ruleName: string, errorMessage: string | undefined): void;
183
+ /**
184
+ * @deprecated
185
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
186
+ */
187
+ castAs<T>(): JBuilder<T, Opt>;
183
188
  $schema($schema: string): this;
184
189
  $schemaDraft7(): this;
185
190
  $id($id: string): this;
@@ -425,7 +430,7 @@ declare function objectDbEntity<OUT extends BaseDBEntity, EXTRA_KEYS extends Exc
425
430
  } : {
426
431
  updated: BuilderFor<OUT['updated']>;
427
432
  })): JObject<OUT, false>;
428
- declare function record<KS extends JSchema<any, any>, VS extends JSchema<any, any>, Opt extends boolean = SchemaOpt<VS>>(keySchema: KS, valueSchema: VS): JObject<Opt extends true ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>> : Record<SchemaOut<KS>, SchemaOut<VS>>, false>;
433
+ declare function record<KS extends JSchema<any, any>, VS extends JSchema<any, any>, Opt extends boolean = SchemaOpt<VS>>(keySchema: KS, valueSchema: VS): SchemaOut<KS> extends string ? JObject<Opt extends true ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>> : Record<SchemaOut<KS>, SchemaOut<VS>>, false> : never;
429
434
  declare function withRegexKeys<S extends JSchema<any, any>>(keyRegex: RegExp | string, schema: S): JObject<StringMap<SchemaOut<S>>, false>;
430
435
  /**
431
436
  * Builds the object schema with the indicated `keys` and uses the `schema` for their validation.
@@ -642,7 +647,7 @@ export interface JsonBuilderRuleOpt {
642
647
  */
643
648
  name?: string;
644
649
  }
645
- type EnumKeyUnion<T> = T extends readonly (infer U)[] ? U : T extends StringEnum | NumberEnum ? T[keyof T] : never;
650
+ type EnumKeyUnion<T> = T extends readonly (infer U)[] ? `${U & (string | number)}` : T extends StringEnum | NumberEnum ? `${T[keyof T] & (string | number)}` : never;
646
651
  type SchemaOut<S> = S extends JSchema<infer OUT, any> ? OUT : never;
647
652
  type SchemaOpt<S> = S extends JSchema<any, infer Opt> ? (Opt extends true ? true : false) : false;
648
653
  type TupleOut<T extends readonly JSchema<any, any>[]> = {
@@ -385,6 +385,13 @@ export class JBuilder extends JSchema {
385
385
  this.schema.errorMessages ||= {};
386
386
  this.schema.errorMessages[ruleName] = errorMessage;
387
387
  }
388
+ /**
389
+ * @deprecated
390
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
391
+ */
392
+ castAs() {
393
+ return this;
394
+ }
388
395
  $schema($schema) {
389
396
  return this.cloneAndUpdateSchema({ $schema });
390
397
  }
@@ -957,6 +964,7 @@ function objectDbEntity(props) {
957
964
  }
958
965
  function record(keySchema, valueSchema) {
959
966
  const keyJsonSchema = keySchema.build();
967
+ _assert(keyJsonSchema.type !== 'number' && keyJsonSchema.type !== 'integer', 'record() key schema must validate strings, not numbers. JSON object keys are always strings.');
960
968
  // Check if value schema is optional before build() strips the optionalField flag
961
969
  const isValueOptional = valueSchema.getSchema().optionalField;
962
970
  const valueJsonSchema = valueSchema.build();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.97.3",
4
+ "version": "15.97.5",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@standard-schema/spec": "^1",
@@ -19,7 +19,7 @@
19
19
  "yargs": "^18"
20
20
  },
21
21
  "devDependencies": {
22
- "@typescript/native-preview": "7.0.0-dev.20260201.1",
22
+ "@typescript/native-preview": "7.0.0-dev.20260301.1",
23
23
  "@naturalcycles/dev-lib": "18.4.2"
24
24
  },
25
25
  "exports": {
@@ -539,6 +539,14 @@ export class JBuilder<OUT, Opt> extends JSchema<OUT, Opt> {
539
539
  this.schema.errorMessages[ruleName] = errorMessage
540
540
  }
541
541
 
542
+ /**
543
+ * @deprecated
544
+ * The usage of this function is discouraged as it defeats the purpose of having type-safe validation.
545
+ */
546
+ override castAs<T>(): JBuilder<T, Opt> {
547
+ return this as unknown as JBuilder<T, Opt>
548
+ }
549
+
542
550
  $schema($schema: string): this {
543
551
  return this.cloneAndUpdateSchema({ $schema })
544
552
  }
@@ -1372,13 +1380,20 @@ function record<
1372
1380
  >(
1373
1381
  keySchema: KS,
1374
1382
  valueSchema: VS,
1375
- ): JObject<
1376
- Opt extends true
1377
- ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>>
1378
- : Record<SchemaOut<KS>, SchemaOut<VS>>,
1379
- false
1380
- > {
1383
+ ): SchemaOut<KS> extends string
1384
+ ? JObject<
1385
+ Opt extends true
1386
+ ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>>
1387
+ : Record<SchemaOut<KS>, SchemaOut<VS>>,
1388
+ false
1389
+ >
1390
+ : never {
1381
1391
  const keyJsonSchema = keySchema.build()
1392
+
1393
+ _assert(
1394
+ keyJsonSchema.type !== 'number' && keyJsonSchema.type !== 'integer',
1395
+ 'record() key schema must validate strings, not numbers. JSON object keys are always strings.',
1396
+ )
1382
1397
  // Check if value schema is optional before build() strips the optionalField flag
1383
1398
  const isValueOptional = (valueSchema as JSchema<any, any>).getSchema().optionalField
1384
1399
  const valueJsonSchema = valueSchema.build()
@@ -1388,18 +1403,13 @@ function record<
1388
1403
  ? { anyOf: [{ isUndefined: true }, valueJsonSchema] }
1389
1404
  : valueJsonSchema
1390
1405
 
1391
- return new JObject<
1392
- Opt extends true
1393
- ? Partial<Record<SchemaOut<KS>, SchemaOut<VS>>>
1394
- : Record<SchemaOut<KS>, SchemaOut<VS>>,
1395
- false
1396
- >([], {
1406
+ return new JObject([], {
1397
1407
  hasIsOfTypeCheck: false,
1398
1408
  keySchema: keyJsonSchema,
1399
1409
  patternProperties: {
1400
1410
  ['^.*$']: finalValueSchema,
1401
1411
  },
1402
- })
1412
+ }) as any
1403
1413
  }
1404
1414
 
1405
1415
  function withRegexKeys<S extends JSchema<any, any>>(
@@ -2143,12 +2153,12 @@ export interface JsonBuilderRuleOpt {
2143
2153
  }
2144
2154
 
2145
2155
  type EnumKeyUnion<T> =
2146
- // array of literals -> union of its elements
2156
+ // array of literals -> union of its elements (stringified)
2147
2157
  T extends readonly (infer U)[]
2148
- ? U
2149
- : // enum object -> union of its values
2158
+ ? `${U & (string | number)}`
2159
+ : // enum object -> union of its values (stringified)
2150
2160
  T extends StringEnum | NumberEnum
2151
- ? T[keyof T]
2161
+ ? `${T[keyof T] & (string | number)}`
2152
2162
  : never
2153
2163
 
2154
2164
  type SchemaOut<S> = S extends JSchema<infer OUT, any> ? OUT : never