@naturalcycles/nodejs-lib 15.122.2 → 15.122.4

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.
@@ -771,13 +771,13 @@ export class JNumber extends JBuilder {
771
771
  return this;
772
772
  }
773
773
  unixTimestamp() {
774
- return this.integer().min(0).max(TS_2500).branded();
774
+ return this.integer().branded();
775
775
  }
776
776
  unixTimestamp2000() {
777
777
  return this.integer().min(TS_2000).max(TS_2500).branded();
778
778
  }
779
779
  unixTimestampMillis() {
780
- return this.integer().min(0).max(TS_2500_MILLIS).branded();
780
+ return this.integer().branded();
781
781
  }
782
782
  unixTimestamp2000Millis() {
783
783
  return this.integer().min(TS_2000_MILLIS).max(TS_2500_MILLIS).branded();
@@ -1273,18 +1273,14 @@ function applyImprovementsOnErrorMessages(errors, schema) {
1273
1273
  }
1274
1274
  /**
1275
1275
  * Looks up the user-provided custom error message (set via `{ msg }` / `{ name }`)
1276
- * for a given AJV error, walking the schema along the error's instancePath and
1277
- * falling back to top-level `errorMessages` (including through nullable wrappers).
1276
+ * for a given AJV error, resolving the error's schemaPath to the exact subschema that
1277
+ * failed - which, unlike the instancePath, also addresses anyOf/oneOf branches.
1278
1278
  * Returns undefined if no custom message was registered for the failing keyword.
1279
1279
  */
1280
1280
  function resolveCustomErrorMessage(schema, error) {
1281
- const byPath = getErrorMessageForInstancePath(schema, error.instancePath, error.keyword);
1282
- if (byPath)
1283
- return byPath;
1284
- if (schema.errorMessages?.[error.keyword])
1285
- return schema.errorMessages[error.keyword];
1286
- const unwrapped = unwrapNullableAnyOf(schema);
1287
- return unwrapped?.errorMessages?.[error.keyword];
1281
+ if (!error.schemaPath)
1282
+ return undefined;
1283
+ return resolveSchemaPath(schema, error.schemaPath)?.errorMessages?.[error.keyword];
1288
1284
  }
1289
1285
  /**
1290
1286
  * Groups repeated validation errors by rule rather than by unique request content.
@@ -1356,59 +1352,6 @@ function resolveSchemaPath(schema, schemaPath) {
1356
1352
  }
1357
1353
  return current;
1358
1354
  }
1359
- function getErrorMessageForInstancePath(schema, instancePath, keyword) {
1360
- if (!schema || !instancePath)
1361
- return undefined;
1362
- const segments = instancePath.split('/').filter(Boolean);
1363
- return traverseSchemaPath(schema, segments, keyword);
1364
- }
1365
- function traverseSchemaPath(schema, segments, keyword) {
1366
- if (!segments.length)
1367
- return undefined;
1368
- const [currentSegment, ...remainingSegments] = segments;
1369
- const nextSchema = getChildSchema(schema, currentSegment);
1370
- if (!nextSchema)
1371
- return undefined;
1372
- if (nextSchema.errorMessages?.[keyword]) {
1373
- return nextSchema.errorMessages[keyword];
1374
- }
1375
- // Check through nullable wrapper
1376
- const unwrapped = unwrapNullableAnyOf(nextSchema);
1377
- if (unwrapped?.errorMessages?.[keyword]) {
1378
- return unwrapped.errorMessages[keyword];
1379
- }
1380
- if (remainingSegments.length) {
1381
- return traverseSchemaPath(nextSchema, remainingSegments, keyword);
1382
- }
1383
- return undefined;
1384
- }
1385
- function getChildSchema(schema, segment) {
1386
- if (!segment)
1387
- return undefined;
1388
- // Unwrap nullable anyOf to find properties/items through nullable wrappers
1389
- const effectiveSchema = unwrapNullableAnyOf(schema) ?? schema;
1390
- if (/^\d+$/.test(segment) && effectiveSchema.items) {
1391
- return getArrayItemSchema(effectiveSchema, segment);
1392
- }
1393
- return getObjectPropertySchema(effectiveSchema, segment);
1394
- }
1395
- function getArrayItemSchema(schema, indexSegment) {
1396
- if (!schema.items)
1397
- return undefined;
1398
- if (Array.isArray(schema.items)) {
1399
- return schema.items[Number(indexSegment)];
1400
- }
1401
- return schema.items;
1402
- }
1403
- function getObjectPropertySchema(schema, segment) {
1404
- return schema.properties?.[segment];
1405
- }
1406
- function unwrapNullableAnyOf(schema) {
1407
- const nullIndex = unwrapNullableAnyOfIndex(schema);
1408
- if (nullIndex === -1)
1409
- return undefined;
1410
- return schema.anyOf[1 - nullIndex];
1411
- }
1412
1355
  function unwrapNullableAnyOfIndex(schema) {
1413
1356
  if (schema.anyOf?.length !== 2)
1414
1357
  return -1;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/nodejs-lib",
3
3
  "type": "module",
4
- "version": "15.122.2",
4
+ "version": "15.122.4",
5
5
  "dependencies": {
6
6
  "@naturalcycles/js-lib": "^15",
7
7
  "@standard-schema/spec": "^1",
@@ -1030,7 +1030,7 @@ export class JNumber<
1030
1030
  }
1031
1031
 
1032
1032
  unixTimestamp(): JNumber<UnixTimestamp, Opt> {
1033
- return this.integer().min(0).max(TS_2500).branded<UnixTimestamp>()
1033
+ return this.integer().branded<UnixTimestamp>()
1034
1034
  }
1035
1035
 
1036
1036
  unixTimestamp2000(): JNumber<UnixTimestamp, Opt> {
@@ -1038,7 +1038,7 @@ export class JNumber<
1038
1038
  }
1039
1039
 
1040
1040
  unixTimestampMillis(): JNumber<UnixTimestampMillis, Opt> {
1041
- return this.integer().min(0).max(TS_2500_MILLIS).branded<UnixTimestampMillis>()
1041
+ return this.integer().branded<UnixTimestampMillis>()
1042
1042
  }
1043
1043
 
1044
1044
  unixTimestamp2000Millis(): JNumber<UnixTimestampMillis, Opt> {
@@ -1822,16 +1822,13 @@ function applyImprovementsOnErrorMessages(
1822
1822
 
1823
1823
  /**
1824
1824
  * Looks up the user-provided custom error message (set via `{ msg }` / `{ name }`)
1825
- * for a given AJV error, walking the schema along the error's instancePath and
1826
- * falling back to top-level `errorMessages` (including through nullable wrappers).
1825
+ * for a given AJV error, resolving the error's schemaPath to the exact subschema that
1826
+ * failed - which, unlike the instancePath, also addresses anyOf/oneOf branches.
1827
1827
  * Returns undefined if no custom message was registered for the failing keyword.
1828
1828
  */
1829
1829
  function resolveCustomErrorMessage(schema: JsonSchema, error: ErrorObject): string | undefined {
1830
- const byPath = getErrorMessageForInstancePath(schema, error.instancePath, error.keyword)
1831
- if (byPath) return byPath
1832
- if (schema.errorMessages?.[error.keyword]) return schema.errorMessages[error.keyword]
1833
- const unwrapped = unwrapNullableAnyOf(schema)
1834
- return unwrapped?.errorMessages?.[error.keyword]
1830
+ if (!error.schemaPath) return undefined
1831
+ return resolveSchemaPath(schema, error.schemaPath)?.errorMessages?.[error.keyword]
1835
1832
  }
1836
1833
 
1837
1834
  /**
@@ -1912,79 +1909,6 @@ function resolveSchemaPath(schema: JsonSchema, schemaPath: string): JsonSchema |
1912
1909
  return current as JsonSchema | undefined
1913
1910
  }
1914
1911
 
1915
- function getErrorMessageForInstancePath(
1916
- schema: JsonSchema | undefined,
1917
- instancePath: string,
1918
- keyword: string,
1919
- ): string | undefined {
1920
- if (!schema || !instancePath) return undefined
1921
-
1922
- const segments = instancePath.split('/').filter(Boolean)
1923
- return traverseSchemaPath(schema, segments, keyword)
1924
- }
1925
-
1926
- function traverseSchemaPath(
1927
- schema: JsonSchema,
1928
- segments: string[],
1929
- keyword: string,
1930
- ): string | undefined {
1931
- if (!segments.length) return undefined
1932
-
1933
- const [currentSegment, ...remainingSegments] = segments
1934
-
1935
- const nextSchema = getChildSchema(schema, currentSegment)
1936
- if (!nextSchema) return undefined
1937
-
1938
- if (nextSchema.errorMessages?.[keyword]) {
1939
- return nextSchema.errorMessages[keyword]
1940
- }
1941
-
1942
- // Check through nullable wrapper
1943
- const unwrapped = unwrapNullableAnyOf(nextSchema)
1944
- if (unwrapped?.errorMessages?.[keyword]) {
1945
- return unwrapped.errorMessages[keyword]
1946
- }
1947
-
1948
- if (remainingSegments.length) {
1949
- return traverseSchemaPath(nextSchema, remainingSegments, keyword)
1950
- }
1951
-
1952
- return undefined
1953
- }
1954
-
1955
- function getChildSchema(schema: JsonSchema, segment: string | undefined): JsonSchema | undefined {
1956
- if (!segment) return undefined
1957
-
1958
- // Unwrap nullable anyOf to find properties/items through nullable wrappers
1959
- const effectiveSchema = unwrapNullableAnyOf(schema) ?? schema
1960
-
1961
- if (/^\d+$/.test(segment) && effectiveSchema.items) {
1962
- return getArrayItemSchema(effectiveSchema, segment)
1963
- }
1964
-
1965
- return getObjectPropertySchema(effectiveSchema, segment)
1966
- }
1967
-
1968
- function getArrayItemSchema(schema: JsonSchema, indexSegment: string): JsonSchema | undefined {
1969
- if (!schema.items) return undefined
1970
-
1971
- if (Array.isArray(schema.items)) {
1972
- return schema.items[Number(indexSegment)]
1973
- }
1974
-
1975
- return schema.items
1976
- }
1977
-
1978
- function getObjectPropertySchema(schema: JsonSchema, segment: string): JsonSchema | undefined {
1979
- return schema.properties?.[segment as keyof typeof schema.properties]
1980
- }
1981
-
1982
- function unwrapNullableAnyOf(schema: JsonSchema): JsonSchema | undefined {
1983
- const nullIndex = unwrapNullableAnyOfIndex(schema)
1984
- if (nullIndex === -1) return undefined
1985
- return schema.anyOf![1 - nullIndex]!
1986
- }
1987
-
1988
1912
  function unwrapNullableAnyOfIndex(schema: JsonSchema): number {
1989
1913
  if (schema.anyOf?.length !== 2) return -1
1990
1914
  const nullIndex = schema.anyOf.findIndex(s => s.type === 'null')