@drzl/analyzer 1.17.3 → 1.17.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.
package/dist/index.cjs CHANGED
@@ -141,6 +141,10 @@ function describeV1Column(column) {
141
141
  out.integer = false;
142
142
  out.tsType = "number";
143
143
  out.dbType = semantic === "float" ? "REAL" : "DOUBLE";
144
+ if (codec === "float4" || codec === "float8") {
145
+ out.allowsNaN = true;
146
+ out.allowsInfinity = true;
147
+ }
144
148
  break;
145
149
  }
146
150
  case "uuid":
@@ -250,6 +254,10 @@ function describeV1Column(column) {
250
254
  out.dbType = "NUMERIC";
251
255
  out.integer = false;
252
256
  [out.min, out.max] = JS_SAFE_INTEGER_BOUNDS;
257
+ if (codec === "numeric:number") {
258
+ out.allowsNaN = true;
259
+ out.allowsInfinity = false;
260
+ }
253
261
  } else if (js === "string") {
254
262
  out.tsType = "string";
255
263
  out.dbType = codec === "varchar" ? "VARCHAR" : codec === "char" ? "CHAR" : "TEXT";
@@ -569,6 +577,11 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
569
577
  if (inexact) [out.min, out.max] = inexact;
570
578
  out.integer = false;
571
579
  }
580
+ const nonFinite = _SchemaAnalyzer.PG_NON_FINITE[ctor];
581
+ if (nonFinite) {
582
+ out.allowsNaN = nonFinite.nan;
583
+ out.allowsInfinity = nonFinite.infinity;
584
+ }
572
585
  if (/^(Pg)?UUID$/i.test(ctor) || /Uuid$/i.test(ctor)) out.format = "uuid";
573
586
  return out;
574
587
  }
@@ -1235,6 +1248,28 @@ _SchemaAnalyzer.INEXACT_RANGES = {
1235
1248
  // column, which Postgres caps far lower: it refuses 2147483648 into a `numeric(10,2)`.
1236
1249
  PgNumericNumber: JS_SAFE_INTEGER_BOUNDS
1237
1250
  };
1251
+ /**
1252
+ * The Postgres number columns that hold a non-finite double, and which of the three each holds.
1253
+ *
1254
+ * The class-name half of what `describeV1Column` reads off the codec, and the two must agree: a
1255
+ * fact stated on one path and not the other is a schema that changes when the user upgrades
1256
+ * drizzle, which the cross-major diff in `verify-packed.sh` fails on. These three class names are
1257
+ * the same on both majors, read off real `pgTable` columns on 0.45.2 and on 1.0.0-rc.4, so this
1258
+ * table also answers for a v1 column and the two answers are identical rather than merely
1259
+ * compatible. non-finite-numbers.spec.ts asserts that agreement through the real analyzer.
1260
+ *
1261
+ * Postgres only. No MySQL, SingleStore or SQLite class belongs here: MySQL refuses all three on a
1262
+ * `float`/`double` and stores `0.00` for a `decimal`, and SQLite returns both infinities while
1263
+ * silently turning `NaN` into NULL, which is a different answer that has to arrive whole.
1264
+ *
1265
+ * `PgNumeric` is absent because its value is a string, and its pattern already accepts `NaN` and
1266
+ * `Infinity`. `PgNumericNumber` states `infinity: false` on purpose; see `Column.allowsNaN`.
1267
+ */
1268
+ _SchemaAnalyzer.PG_NON_FINITE = {
1269
+ PgReal: { nan: true, infinity: true },
1270
+ PgDoublePrecision: { nan: true, infinity: true },
1271
+ PgNumericNumber: { nan: true, infinity: false }
1272
+ };
1238
1273
  var SchemaAnalyzer = _SchemaAnalyzer;
1239
1274
  var index_default = SchemaAnalyzer;
1240
1275
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.d.cts CHANGED
@@ -62,6 +62,34 @@ interface Column {
62
62
  * generators fall back to the old inference there.
63
63
  */
64
64
  integer?: boolean;
65
+ /**
66
+ * Whether the column stores and returns `NaN`, and whether it does the same for an infinity.
67
+ *
68
+ * A range cannot say this. `>=`/`<=` refuses `Infinity` whatever the two numbers are, and `NaN`
69
+ * compares false against both ends, so a bounded float column described by its range alone
70
+ * refused three values Postgres stores in it and hands back on SELECT. That is a read-path
71
+ * defect: every read of such a row fails validation on a column behaving exactly as documented.
72
+ * The generators render these as a union beside the range rather than as a wider range.
73
+ *
74
+ * Measured against PostgreSQL 18.3 through PGlite, on the bound-parameter path a validator
75
+ * guards. `real` and `double precision` return all three unchanged. An unconstrained `numeric`
76
+ * does too, but a `numeric(10,2)` refuses either infinity with `22003 numeric field overflow`
77
+ * while still taking `NaN`, and `integer`/`bigint` refuse all three.
78
+ *
79
+ * So `numeric` in `{ mode: 'number' }` states `allowsInfinity: false` deliberately, and it is a
80
+ * narrowing rather than an oversight: nothing here reads a column's precision or scale, so the
81
+ * two `numeric` declarations are indistinguishable, and admitting the infinities would make the
82
+ * schema promise what the server refuses for the commoner of the two.
83
+ *
84
+ * Postgres only, today. MySQL refuses all three on a `float`/`double` and silently stores `0.00`
85
+ * for a `decimal`. SQLite returns both infinities and silently turns `NaN` into NULL, which is
86
+ * real and is filed on its own: a column needs both halves of that answer or none.
87
+ *
88
+ * Absent on every other column, including the string mode of `numeric`, which already carries the
89
+ * same fact as a pattern; see `COLUMN_FORMATS.numeric` in `@drzl/validation-core`.
90
+ */
91
+ allowsNaN?: boolean;
92
+ allowsInfinity?: boolean;
65
93
  /**
66
94
  * A string column whose contents have a shape the database enforces.
67
95
  *
@@ -451,6 +479,24 @@ declare class SchemaAnalyzer {
451
479
  * `number double` on drizzle v1, which is where these pairings come from.
452
480
  */
453
481
  private static readonly INEXACT_RANGES;
482
+ /**
483
+ * The Postgres number columns that hold a non-finite double, and which of the three each holds.
484
+ *
485
+ * The class-name half of what `describeV1Column` reads off the codec, and the two must agree: a
486
+ * fact stated on one path and not the other is a schema that changes when the user upgrades
487
+ * drizzle, which the cross-major diff in `verify-packed.sh` fails on. These three class names are
488
+ * the same on both majors, read off real `pgTable` columns on 0.45.2 and on 1.0.0-rc.4, so this
489
+ * table also answers for a v1 column and the two answers are identical rather than merely
490
+ * compatible. non-finite-numbers.spec.ts asserts that agreement through the real analyzer.
491
+ *
492
+ * Postgres only. No MySQL, SingleStore or SQLite class belongs here: MySQL refuses all three on a
493
+ * `float`/`double` and stores `0.00` for a `decimal`, and SQLite returns both infinities while
494
+ * silently turning `NaN` into NULL, which is a different answer that has to arrive whole.
495
+ *
496
+ * `PgNumeric` is absent because its value is a string, and its pattern already accepts `NaN` and
497
+ * `Infinity`. `PgNumericNumber` states `infinity: false` on purpose; see `Column.allowsNaN`.
498
+ */
499
+ private static readonly PG_NON_FINITE;
454
500
  /**
455
501
  * Constraints the column definition already carries, which the analysis used to throw away.
456
502
  *
package/dist/index.d.ts CHANGED
@@ -62,6 +62,34 @@ interface Column {
62
62
  * generators fall back to the old inference there.
63
63
  */
64
64
  integer?: boolean;
65
+ /**
66
+ * Whether the column stores and returns `NaN`, and whether it does the same for an infinity.
67
+ *
68
+ * A range cannot say this. `>=`/`<=` refuses `Infinity` whatever the two numbers are, and `NaN`
69
+ * compares false against both ends, so a bounded float column described by its range alone
70
+ * refused three values Postgres stores in it and hands back on SELECT. That is a read-path
71
+ * defect: every read of such a row fails validation on a column behaving exactly as documented.
72
+ * The generators render these as a union beside the range rather than as a wider range.
73
+ *
74
+ * Measured against PostgreSQL 18.3 through PGlite, on the bound-parameter path a validator
75
+ * guards. `real` and `double precision` return all three unchanged. An unconstrained `numeric`
76
+ * does too, but a `numeric(10,2)` refuses either infinity with `22003 numeric field overflow`
77
+ * while still taking `NaN`, and `integer`/`bigint` refuse all three.
78
+ *
79
+ * So `numeric` in `{ mode: 'number' }` states `allowsInfinity: false` deliberately, and it is a
80
+ * narrowing rather than an oversight: nothing here reads a column's precision or scale, so the
81
+ * two `numeric` declarations are indistinguishable, and admitting the infinities would make the
82
+ * schema promise what the server refuses for the commoner of the two.
83
+ *
84
+ * Postgres only, today. MySQL refuses all three on a `float`/`double` and silently stores `0.00`
85
+ * for a `decimal`. SQLite returns both infinities and silently turns `NaN` into NULL, which is
86
+ * real and is filed on its own: a column needs both halves of that answer or none.
87
+ *
88
+ * Absent on every other column, including the string mode of `numeric`, which already carries the
89
+ * same fact as a pattern; see `COLUMN_FORMATS.numeric` in `@drzl/validation-core`.
90
+ */
91
+ allowsNaN?: boolean;
92
+ allowsInfinity?: boolean;
65
93
  /**
66
94
  * A string column whose contents have a shape the database enforces.
67
95
  *
@@ -451,6 +479,24 @@ declare class SchemaAnalyzer {
451
479
  * `number double` on drizzle v1, which is where these pairings come from.
452
480
  */
453
481
  private static readonly INEXACT_RANGES;
482
+ /**
483
+ * The Postgres number columns that hold a non-finite double, and which of the three each holds.
484
+ *
485
+ * The class-name half of what `describeV1Column` reads off the codec, and the two must agree: a
486
+ * fact stated on one path and not the other is a schema that changes when the user upgrades
487
+ * drizzle, which the cross-major diff in `verify-packed.sh` fails on. These three class names are
488
+ * the same on both majors, read off real `pgTable` columns on 0.45.2 and on 1.0.0-rc.4, so this
489
+ * table also answers for a v1 column and the two answers are identical rather than merely
490
+ * compatible. non-finite-numbers.spec.ts asserts that agreement through the real analyzer.
491
+ *
492
+ * Postgres only. No MySQL, SingleStore or SQLite class belongs here: MySQL refuses all three on a
493
+ * `float`/`double` and stores `0.00` for a `decimal`, and SQLite returns both infinities while
494
+ * silently turning `NaN` into NULL, which is a different answer that has to arrive whole.
495
+ *
496
+ * `PgNumeric` is absent because its value is a string, and its pattern already accepts `NaN` and
497
+ * `Infinity`. `PgNumericNumber` states `infinity: false` on purpose; see `Column.allowsNaN`.
498
+ */
499
+ private static readonly PG_NON_FINITE;
454
500
  /**
455
501
  * Constraints the column definition already carries, which the analysis used to throw away.
456
502
  *
package/dist/index.js CHANGED
@@ -100,6 +100,10 @@ function describeV1Column(column) {
100
100
  out.integer = false;
101
101
  out.tsType = "number";
102
102
  out.dbType = semantic === "float" ? "REAL" : "DOUBLE";
103
+ if (codec === "float4" || codec === "float8") {
104
+ out.allowsNaN = true;
105
+ out.allowsInfinity = true;
106
+ }
103
107
  break;
104
108
  }
105
109
  case "uuid":
@@ -209,6 +213,10 @@ function describeV1Column(column) {
209
213
  out.dbType = "NUMERIC";
210
214
  out.integer = false;
211
215
  [out.min, out.max] = JS_SAFE_INTEGER_BOUNDS;
216
+ if (codec === "numeric:number") {
217
+ out.allowsNaN = true;
218
+ out.allowsInfinity = false;
219
+ }
212
220
  } else if (js === "string") {
213
221
  out.tsType = "string";
214
222
  out.dbType = codec === "varchar" ? "VARCHAR" : codec === "char" ? "CHAR" : "TEXT";
@@ -528,6 +536,11 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
528
536
  if (inexact) [out.min, out.max] = inexact;
529
537
  out.integer = false;
530
538
  }
539
+ const nonFinite = _SchemaAnalyzer.PG_NON_FINITE[ctor];
540
+ if (nonFinite) {
541
+ out.allowsNaN = nonFinite.nan;
542
+ out.allowsInfinity = nonFinite.infinity;
543
+ }
531
544
  if (/^(Pg)?UUID$/i.test(ctor) || /Uuid$/i.test(ctor)) out.format = "uuid";
532
545
  return out;
533
546
  }
@@ -1194,6 +1207,28 @@ _SchemaAnalyzer.INEXACT_RANGES = {
1194
1207
  // column, which Postgres caps far lower: it refuses 2147483648 into a `numeric(10,2)`.
1195
1208
  PgNumericNumber: JS_SAFE_INTEGER_BOUNDS
1196
1209
  };
1210
+ /**
1211
+ * The Postgres number columns that hold a non-finite double, and which of the three each holds.
1212
+ *
1213
+ * The class-name half of what `describeV1Column` reads off the codec, and the two must agree: a
1214
+ * fact stated on one path and not the other is a schema that changes when the user upgrades
1215
+ * drizzle, which the cross-major diff in `verify-packed.sh` fails on. These three class names are
1216
+ * the same on both majors, read off real `pgTable` columns on 0.45.2 and on 1.0.0-rc.4, so this
1217
+ * table also answers for a v1 column and the two answers are identical rather than merely
1218
+ * compatible. non-finite-numbers.spec.ts asserts that agreement through the real analyzer.
1219
+ *
1220
+ * Postgres only. No MySQL, SingleStore or SQLite class belongs here: MySQL refuses all three on a
1221
+ * `float`/`double` and stores `0.00` for a `decimal`, and SQLite returns both infinities while
1222
+ * silently turning `NaN` into NULL, which is a different answer that has to arrive whole.
1223
+ *
1224
+ * `PgNumeric` is absent because its value is a string, and its pattern already accepts `NaN` and
1225
+ * `Infinity`. `PgNumericNumber` states `infinity: false` on purpose; see `Column.allowsNaN`.
1226
+ */
1227
+ _SchemaAnalyzer.PG_NON_FINITE = {
1228
+ PgReal: { nan: true, infinity: true },
1229
+ PgDoublePrecision: { nan: true, infinity: true },
1230
+ PgNumericNumber: { nan: true, infinity: false }
1231
+ };
1197
1232
  var SchemaAnalyzer = _SchemaAnalyzer;
1198
1233
  var index_default = SchemaAnalyzer;
1199
1234
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drzl/analyzer",
3
- "version": "1.17.3",
3
+ "version": "1.17.4",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",