@drzl/analyzer 1.17.1 → 1.17.3

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/README.md CHANGED
@@ -51,7 +51,7 @@ Per column, beyond the type: `nullable`, `hasDefault`, `defaultValue` (literal d
51
51
  `isGenerated`, `enumValues`, `maxLength` (characters), `maxBytes` (MySQL's TEXT family is a byte
52
52
  budget, which is a different measurement on the same kind of column), `min`/`max`,
53
53
  `arrayDimensions`, `format`, and `shape` for values that are not scalars (json, buffer, tuple,
54
- vector, bitstring, customType).
54
+ numberObject, vector, bitstring, customType).
55
55
 
56
56
  `DRZL_ANL_UNKNOWN_COLUMN` is reported for any column whose validator would accept anything, which
57
57
  is the shape a missing type mapping takes: nothing throws, and every row passes.
package/dist/index.cjs CHANGED
@@ -63,13 +63,24 @@ var PG_FLOAT4_INPUT_MAX = "340282356779733661637539395458142568448";
63
63
  var PG_FLOAT4_RANGE = [`-${PG_FLOAT4_INPUT_MAX}`, PG_FLOAT4_INPUT_MAX];
64
64
  var MYSQL_FLOAT_RANGE = [`-${FLOAT32_MAX}`, FLOAT32_MAX];
65
65
  var JS_SAFE_INTEGER_BOUNDS = ["-9007199254740991", "9007199254740991"];
66
- var TUPLE_CLASS_SHAPES = {
66
+ var GEOMETRIC_CLASS_SHAPES = {
67
67
  // `line()` is the trap here: its `drizzle:entityKind` is `PgLine` while its constructor is
68
68
  // `PgLineTuple`, and this path matches on the constructor.
69
69
  PgPointTuple: { kind: "tuple", length: 2 },
70
- PgLineTuple: { kind: "tuple", length: 3 }
70
+ PgLineTuple: { kind: "tuple", length: 3 },
71
+ // The object modes. `line({ mode: 'abc' })` is a `PgLineABC` and not a `PgLineObject`, and any
72
+ // mode but `'tuple'` builds the object class: `point({ mode: 'abc' })` is a `PgPointObject` too.
73
+ PgPointObject: { kind: "numberObject", fields: ["x", "y"] },
74
+ PgLineABC: { kind: "numberObject", fields: ["a", "b", "c"] },
75
+ // `geometry()` and `geometry({ mode: 'xy' })` are two classes, not one class with a flag, and
76
+ // the fuzzer found both unnamed on this path. Their driver mappers disagree the same way the
77
+ // point ones do: the default hands back `[1, 2]` and the xy mode hands back `{ x: 1, y: 2 }`.
78
+ PgGeometry: { kind: "tuple", length: 2 },
79
+ PgGeometryObject: { kind: "numberObject", fields: ["x", "y"] }
71
80
  };
72
81
  var V1_ONLY_ENTITY_KINDS = /^(?:MsSql|Cockroach)/;
82
+ var NUMBER_VECTOR_CLASSES = /* @__PURE__ */ new Set(["PgVector", "PgHalfVector", "SingleStoreVector"]);
83
+ var BIT_STRING_CLASSES = /* @__PURE__ */ new Set(["PgBinaryVector"]);
73
84
  var BYTE_STRING_CLASSES = /* @__PURE__ */ new Set([
74
85
  "MySqlBinary",
75
86
  "MySqlVarBinary",
@@ -190,18 +201,38 @@ function describeV1Column(column) {
190
201
  };
191
202
  break;
192
203
  }
204
+ // Two modes per builder, and v1 states which in the JS half of the dataType it already
205
+ // carries: the tuple modes say `array point` / `array line` / `array geometry` and the object
206
+ // modes say `object point` / `object line` / `object geometry`. Read off real 1.0.0-rc.4
207
+ // columns rather than assumed. Both used to reach these arms and be called tuples, so a select
208
+ // schema for `point({ mode: 'xy' })` rejected every row the driver returned, on the major that
209
+ // describes the column outright.
210
+ //
211
+ // `js` rather than the codec, which also distinguishes them here (`point:tuple` against
212
+ // `point`): three dialects state a semantic with no codec at all on this release, so the codec
213
+ // is the weaker of the two signals and this file already prefers `js` elsewhere for the same
214
+ // reason.
193
215
  case "point":
194
216
  case "geometry":
195
- out.tsType = "[number, number]";
217
+ out.tsType = js === "object" ? "{ x: number; y: number }" : "[number, number]";
196
218
  out.dbType = semantic.toUpperCase();
197
- out.shape = { kind: "tuple", length: 2 };
219
+ out.shape = js === "object" ? { kind: "numberObject", fields: ["x", "y"] } : { kind: "tuple", length: 2 };
198
220
  break;
199
221
  case "line":
200
- out.tsType = "[number, number, number]";
222
+ out.tsType = js === "object" ? "{ a: number; b: number; c: number }" : "[number, number, number]";
201
223
  out.dbType = "LINE";
202
- out.shape = { kind: "tuple", length: 3 };
224
+ out.shape = js === "object" ? { kind: "numberObject", fields: ["a", "b", "c"] } : { kind: "tuple", length: 3 };
203
225
  break;
226
+ // `halfvec` beside `vector`, because they differ in storage width and in nothing a validator
227
+ // can see: `mapFromDriverValue` on both hands back `[1, 2, 3]`. It had no arm and came back
228
+ // `unknown` on this path too, which the fuzzer found.
229
+ //
230
+ // `sparsevec` is deliberately not here. Its name says vector and its value is the string
231
+ // `{1:1.5,3:2}/3`, so typing it `number[]` for symmetry would reject every row the database
232
+ // returns. Its codec already answers `string` on its own, which is the same conclusion reached
233
+ // without this arm.
204
234
  case "vector":
235
+ case "halfvec":
205
236
  out.tsType = "number[]";
206
237
  out.dbType = "VECTOR";
207
238
  out.shape = { kind: "numberVector", length: declaredLength(column) };
@@ -593,6 +624,34 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
593
624
  case "MySqlEnumColumn":
594
625
  case "SingleStoreEnumColumn":
595
626
  return { tsType: "string", dbType: "TEXT" };
627
+ // The pgvector family, found by the analyzer fuzzer: all three came back `unknown` on this
628
+ // path, so their validators accepted anything. The answers are drizzle's own mappers rather
629
+ // than the type names, and the three do not agree with each other:
630
+ //
631
+ // vector(3) SELECT gives [1,2,3] INSERT sends "[1,2,3]"
632
+ // halfvec(3) SELECT gives [1,2,3] INSERT sends "[1,2,3]"
633
+ // sparsevec(3) SELECT gives "{1:1.5,3:2}/3" INSERT sends "{1:1.5,3:2}/3"
634
+ //
635
+ // So the two dense ones are number arrays and the sparse one is a string. Typing `sparsevec`
636
+ // as a vector for symmetry would reject every row the database returns, which is the defect
637
+ // this family was filed under to begin with. The `shape` carries the dimension count where
638
+ // one is declared, as the codec path already did for `vector`.
639
+ case "PgVector":
640
+ case "PgHalfVector":
641
+ case "SingleStoreVector":
642
+ return { tsType: "number[]", dbType: "VECTOR" };
643
+ // `BIT` rather than `TEXT`, which a first version of this arm returned. v1's codec says `BIT`
644
+ // for the same column, and the cross-major diff said so: naming the class made ten of its
645
+ // twelve entries go stale and left `c_bit.dbType` and its nullable twin standing, which is
646
+ // that check distinguishing a fix from a half fix.
647
+ case "PgBinaryVector":
648
+ return { tsType: "string", dbType: "BIT" };
649
+ case "PgGeometry":
650
+ return { tsType: "[number, number]", dbType: "GEOMETRY" };
651
+ case "PgGeometryObject":
652
+ return { tsType: "{ x: number; y: number }", dbType: "GEOMETRY" };
653
+ case "PgSparseVector":
654
+ return { tsType: "string", dbType: "TEXT" };
596
655
  case "PgInteger":
597
656
  case "PgSmallInt":
598
657
  return { tsType: "number", dbType: "INTEGER" };
@@ -658,6 +717,15 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
658
717
  return { tsType: "[number, number]", dbType: "POINT" };
659
718
  case "PgLineTuple":
660
719
  return { tsType: "[number, number, number]", dbType: "LINE" };
720
+ // The object modes, which the same regex answered `string` for and which are not tuples
721
+ // either. `point({ mode: 'xy' })` returns `{ x, y }` and `line({ mode: 'abc' })` returns
722
+ // `{ a, b, c }`, read back from PGlite through drizzle 0.45.2; the same column refuses
723
+ // `[1, 2]` and `'1,2'`, both of which `mapToDriverValue` renders `(undefined,undefined)`.
724
+ // v1 says the same thing about the same two columns through `dataType: 'object point'`.
725
+ case "PgPointObject":
726
+ return { tsType: "{ x: number; y: number }", dbType: "POINT" };
727
+ case "PgLineABC":
728
+ return { tsType: "{ a: number; b: number; c: number }", dbType: "LINE" };
661
729
  case "PgJson":
662
730
  case "PgJsonb":
663
731
  return { tsType: "any", dbType: ctor === "PgJsonb" ? "JSONB" : "JSON" };
@@ -678,7 +746,6 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
678
746
  if (/^Pg/.test(ctor)) {
679
747
  if (/Text|Varchar|Char|Uuid/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
680
748
  if (/Inet|Cidr|Macaddr8?|Uuid/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
681
- if (/Point|Line/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
682
749
  if (/TimestampString|DateString/i.test(ctor))
683
750
  return { tsType: "string", dbType: "TIMESTAMP" };
684
751
  if (/Timestamptz/i.test(ctor)) return { tsType: "Date", dbType: "TIMESTAMPTZ" };
@@ -800,7 +867,7 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
800
867
  const sqlType = sqlKind.startsWith("MySql") && typeof col?.getSQLType === "function" ? String(col.getSQLType()).toLowerCase() : void 0;
801
868
  const byteCap = sqlType ? MYSQL_TEXT_CAPS[sqlType] : void 0;
802
869
  const ctorName = String(col?.constructor?.name ?? "");
803
- const fallbackShape = dbType === "JSON" || dbType === "JSONB" || col?.config?.mode === "json" ? { kind: "json" } : BYTE_STRING_CLASSES.has(ctorName) ? { kind: "byteString", length: declaredLength(col) } : TUPLE_CLASS_SHAPES[ctorName];
870
+ const fallbackShape = dbType === "JSON" || dbType === "JSONB" || col?.config?.mode === "json" ? { kind: "json" } : BYTE_STRING_CLASSES.has(ctorName) ? { kind: "byteString", length: declaredLength(col) } : NUMBER_VECTOR_CLASSES.has(ctorName) ? { kind: "numberVector", length: declaredLength(col) } : BIT_STRING_CLASSES.has(ctorName) ? { kind: "bitstring", length: declaredLength(col), exact: true } : GEOMETRIC_CLASS_SHAPES[ctorName];
804
871
  if (fallbackShape?.kind === "byteString") delete constraints.maxLength;
805
872
  const shape = (v1?.shape ?? fallbackShape)?.kind;
806
873
  const finalTs = v1?.tsType ?? tsType;
package/dist/index.d.cts CHANGED
@@ -121,11 +121,33 @@ type ColumnShape =
121
121
  | {
122
122
  kind: 'json';
123
123
  }
124
- /** `point`, `line`, `geometry`: a fixed-length tuple of numbers. */
124
+ /** `point`, `line`, `geometry` in their tuple modes: a fixed-length tuple of numbers. */
125
125
  | {
126
126
  kind: 'tuple';
127
127
  length: number;
128
128
  }
129
+ /**
130
+ * The same three columns in their object modes: an object of named number fields.
131
+ *
132
+ * `point({ mode: 'xy' })` hands back `{ x, y }`, `line({ mode: 'abc' })` hands back
133
+ * `{ a, b, c }`, and `geometry({ type: 'point', mode: 'xy' })` hands back `{ x, y }`. The names
134
+ * are carried rather than derived from a length, because the two arities have different keys and
135
+ * nothing else on the column states them.
136
+ *
137
+ * Not a tuple, on either major, and the difference is a value the database refuses. Asked of
138
+ * PGlite through drizzle 0.45.2 and again through 1.0.0-rc.4: `mapToDriverValue` reads `.x`/`.y`
139
+ * off whatever it is handed, so `[1, 2]` and `'1,2'` both become the literal
140
+ * `(undefined,undefined)` and Postgres answers `invalid input syntax for type point`, while
141
+ * `{ x: 1.5, y: -2.25 }` is stored as `(1.5,-2.25)` and read back unchanged.
142
+ *
143
+ * Every field is required and unlisted keys are ignored, both measured on the same server:
144
+ * `{ x: 1 }` renders `(1,undefined)` and is refused, and `{ x: 1, y: 2, z: 3 }` is accepted and
145
+ * stored as `(1,2)`.
146
+ */
147
+ | {
148
+ kind: 'numberObject';
149
+ fields: string[];
150
+ }
129
151
  /** `vector`, `halfvec`: a numeric vector, with a fixed length where one is declared. */
130
152
  | {
131
153
  kind: 'numberVector';
package/dist/index.d.ts CHANGED
@@ -121,11 +121,33 @@ type ColumnShape =
121
121
  | {
122
122
  kind: 'json';
123
123
  }
124
- /** `point`, `line`, `geometry`: a fixed-length tuple of numbers. */
124
+ /** `point`, `line`, `geometry` in their tuple modes: a fixed-length tuple of numbers. */
125
125
  | {
126
126
  kind: 'tuple';
127
127
  length: number;
128
128
  }
129
+ /**
130
+ * The same three columns in their object modes: an object of named number fields.
131
+ *
132
+ * `point({ mode: 'xy' })` hands back `{ x, y }`, `line({ mode: 'abc' })` hands back
133
+ * `{ a, b, c }`, and `geometry({ type: 'point', mode: 'xy' })` hands back `{ x, y }`. The names
134
+ * are carried rather than derived from a length, because the two arities have different keys and
135
+ * nothing else on the column states them.
136
+ *
137
+ * Not a tuple, on either major, and the difference is a value the database refuses. Asked of
138
+ * PGlite through drizzle 0.45.2 and again through 1.0.0-rc.4: `mapToDriverValue` reads `.x`/`.y`
139
+ * off whatever it is handed, so `[1, 2]` and `'1,2'` both become the literal
140
+ * `(undefined,undefined)` and Postgres answers `invalid input syntax for type point`, while
141
+ * `{ x: 1.5, y: -2.25 }` is stored as `(1.5,-2.25)` and read back unchanged.
142
+ *
143
+ * Every field is required and unlisted keys are ignored, both measured on the same server:
144
+ * `{ x: 1 }` renders `(1,undefined)` and is refused, and `{ x: 1, y: 2, z: 3 }` is accepted and
145
+ * stored as `(1,2)`.
146
+ */
147
+ | {
148
+ kind: 'numberObject';
149
+ fields: string[];
150
+ }
129
151
  /** `vector`, `halfvec`: a numeric vector, with a fixed length where one is declared. */
130
152
  | {
131
153
  kind: 'numberVector';
package/dist/index.js CHANGED
@@ -22,13 +22,24 @@ var PG_FLOAT4_INPUT_MAX = "340282356779733661637539395458142568448";
22
22
  var PG_FLOAT4_RANGE = [`-${PG_FLOAT4_INPUT_MAX}`, PG_FLOAT4_INPUT_MAX];
23
23
  var MYSQL_FLOAT_RANGE = [`-${FLOAT32_MAX}`, FLOAT32_MAX];
24
24
  var JS_SAFE_INTEGER_BOUNDS = ["-9007199254740991", "9007199254740991"];
25
- var TUPLE_CLASS_SHAPES = {
25
+ var GEOMETRIC_CLASS_SHAPES = {
26
26
  // `line()` is the trap here: its `drizzle:entityKind` is `PgLine` while its constructor is
27
27
  // `PgLineTuple`, and this path matches on the constructor.
28
28
  PgPointTuple: { kind: "tuple", length: 2 },
29
- PgLineTuple: { kind: "tuple", length: 3 }
29
+ PgLineTuple: { kind: "tuple", length: 3 },
30
+ // The object modes. `line({ mode: 'abc' })` is a `PgLineABC` and not a `PgLineObject`, and any
31
+ // mode but `'tuple'` builds the object class: `point({ mode: 'abc' })` is a `PgPointObject` too.
32
+ PgPointObject: { kind: "numberObject", fields: ["x", "y"] },
33
+ PgLineABC: { kind: "numberObject", fields: ["a", "b", "c"] },
34
+ // `geometry()` and `geometry({ mode: 'xy' })` are two classes, not one class with a flag, and
35
+ // the fuzzer found both unnamed on this path. Their driver mappers disagree the same way the
36
+ // point ones do: the default hands back `[1, 2]` and the xy mode hands back `{ x: 1, y: 2 }`.
37
+ PgGeometry: { kind: "tuple", length: 2 },
38
+ PgGeometryObject: { kind: "numberObject", fields: ["x", "y"] }
30
39
  };
31
40
  var V1_ONLY_ENTITY_KINDS = /^(?:MsSql|Cockroach)/;
41
+ var NUMBER_VECTOR_CLASSES = /* @__PURE__ */ new Set(["PgVector", "PgHalfVector", "SingleStoreVector"]);
42
+ var BIT_STRING_CLASSES = /* @__PURE__ */ new Set(["PgBinaryVector"]);
32
43
  var BYTE_STRING_CLASSES = /* @__PURE__ */ new Set([
33
44
  "MySqlBinary",
34
45
  "MySqlVarBinary",
@@ -149,18 +160,38 @@ function describeV1Column(column) {
149
160
  };
150
161
  break;
151
162
  }
163
+ // Two modes per builder, and v1 states which in the JS half of the dataType it already
164
+ // carries: the tuple modes say `array point` / `array line` / `array geometry` and the object
165
+ // modes say `object point` / `object line` / `object geometry`. Read off real 1.0.0-rc.4
166
+ // columns rather than assumed. Both used to reach these arms and be called tuples, so a select
167
+ // schema for `point({ mode: 'xy' })` rejected every row the driver returned, on the major that
168
+ // describes the column outright.
169
+ //
170
+ // `js` rather than the codec, which also distinguishes them here (`point:tuple` against
171
+ // `point`): three dialects state a semantic with no codec at all on this release, so the codec
172
+ // is the weaker of the two signals and this file already prefers `js` elsewhere for the same
173
+ // reason.
152
174
  case "point":
153
175
  case "geometry":
154
- out.tsType = "[number, number]";
176
+ out.tsType = js === "object" ? "{ x: number; y: number }" : "[number, number]";
155
177
  out.dbType = semantic.toUpperCase();
156
- out.shape = { kind: "tuple", length: 2 };
178
+ out.shape = js === "object" ? { kind: "numberObject", fields: ["x", "y"] } : { kind: "tuple", length: 2 };
157
179
  break;
158
180
  case "line":
159
- out.tsType = "[number, number, number]";
181
+ out.tsType = js === "object" ? "{ a: number; b: number; c: number }" : "[number, number, number]";
160
182
  out.dbType = "LINE";
161
- out.shape = { kind: "tuple", length: 3 };
183
+ out.shape = js === "object" ? { kind: "numberObject", fields: ["a", "b", "c"] } : { kind: "tuple", length: 3 };
162
184
  break;
185
+ // `halfvec` beside `vector`, because they differ in storage width and in nothing a validator
186
+ // can see: `mapFromDriverValue` on both hands back `[1, 2, 3]`. It had no arm and came back
187
+ // `unknown` on this path too, which the fuzzer found.
188
+ //
189
+ // `sparsevec` is deliberately not here. Its name says vector and its value is the string
190
+ // `{1:1.5,3:2}/3`, so typing it `number[]` for symmetry would reject every row the database
191
+ // returns. Its codec already answers `string` on its own, which is the same conclusion reached
192
+ // without this arm.
163
193
  case "vector":
194
+ case "halfvec":
164
195
  out.tsType = "number[]";
165
196
  out.dbType = "VECTOR";
166
197
  out.shape = { kind: "numberVector", length: declaredLength(column) };
@@ -552,6 +583,34 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
552
583
  case "MySqlEnumColumn":
553
584
  case "SingleStoreEnumColumn":
554
585
  return { tsType: "string", dbType: "TEXT" };
586
+ // The pgvector family, found by the analyzer fuzzer: all three came back `unknown` on this
587
+ // path, so their validators accepted anything. The answers are drizzle's own mappers rather
588
+ // than the type names, and the three do not agree with each other:
589
+ //
590
+ // vector(3) SELECT gives [1,2,3] INSERT sends "[1,2,3]"
591
+ // halfvec(3) SELECT gives [1,2,3] INSERT sends "[1,2,3]"
592
+ // sparsevec(3) SELECT gives "{1:1.5,3:2}/3" INSERT sends "{1:1.5,3:2}/3"
593
+ //
594
+ // So the two dense ones are number arrays and the sparse one is a string. Typing `sparsevec`
595
+ // as a vector for symmetry would reject every row the database returns, which is the defect
596
+ // this family was filed under to begin with. The `shape` carries the dimension count where
597
+ // one is declared, as the codec path already did for `vector`.
598
+ case "PgVector":
599
+ case "PgHalfVector":
600
+ case "SingleStoreVector":
601
+ return { tsType: "number[]", dbType: "VECTOR" };
602
+ // `BIT` rather than `TEXT`, which a first version of this arm returned. v1's codec says `BIT`
603
+ // for the same column, and the cross-major diff said so: naming the class made ten of its
604
+ // twelve entries go stale and left `c_bit.dbType` and its nullable twin standing, which is
605
+ // that check distinguishing a fix from a half fix.
606
+ case "PgBinaryVector":
607
+ return { tsType: "string", dbType: "BIT" };
608
+ case "PgGeometry":
609
+ return { tsType: "[number, number]", dbType: "GEOMETRY" };
610
+ case "PgGeometryObject":
611
+ return { tsType: "{ x: number; y: number }", dbType: "GEOMETRY" };
612
+ case "PgSparseVector":
613
+ return { tsType: "string", dbType: "TEXT" };
555
614
  case "PgInteger":
556
615
  case "PgSmallInt":
557
616
  return { tsType: "number", dbType: "INTEGER" };
@@ -617,6 +676,15 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
617
676
  return { tsType: "[number, number]", dbType: "POINT" };
618
677
  case "PgLineTuple":
619
678
  return { tsType: "[number, number, number]", dbType: "LINE" };
679
+ // The object modes, which the same regex answered `string` for and which are not tuples
680
+ // either. `point({ mode: 'xy' })` returns `{ x, y }` and `line({ mode: 'abc' })` returns
681
+ // `{ a, b, c }`, read back from PGlite through drizzle 0.45.2; the same column refuses
682
+ // `[1, 2]` and `'1,2'`, both of which `mapToDriverValue` renders `(undefined,undefined)`.
683
+ // v1 says the same thing about the same two columns through `dataType: 'object point'`.
684
+ case "PgPointObject":
685
+ return { tsType: "{ x: number; y: number }", dbType: "POINT" };
686
+ case "PgLineABC":
687
+ return { tsType: "{ a: number; b: number; c: number }", dbType: "LINE" };
620
688
  case "PgJson":
621
689
  case "PgJsonb":
622
690
  return { tsType: "any", dbType: ctor === "PgJsonb" ? "JSONB" : "JSON" };
@@ -637,7 +705,6 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
637
705
  if (/^Pg/.test(ctor)) {
638
706
  if (/Text|Varchar|Char|Uuid/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
639
707
  if (/Inet|Cidr|Macaddr8?|Uuid/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
640
- if (/Point|Line/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
641
708
  if (/TimestampString|DateString/i.test(ctor))
642
709
  return { tsType: "string", dbType: "TIMESTAMP" };
643
710
  if (/Timestamptz/i.test(ctor)) return { tsType: "Date", dbType: "TIMESTAMPTZ" };
@@ -759,7 +826,7 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
759
826
  const sqlType = sqlKind.startsWith("MySql") && typeof col?.getSQLType === "function" ? String(col.getSQLType()).toLowerCase() : void 0;
760
827
  const byteCap = sqlType ? MYSQL_TEXT_CAPS[sqlType] : void 0;
761
828
  const ctorName = String(col?.constructor?.name ?? "");
762
- const fallbackShape = dbType === "JSON" || dbType === "JSONB" || col?.config?.mode === "json" ? { kind: "json" } : BYTE_STRING_CLASSES.has(ctorName) ? { kind: "byteString", length: declaredLength(col) } : TUPLE_CLASS_SHAPES[ctorName];
829
+ const fallbackShape = dbType === "JSON" || dbType === "JSONB" || col?.config?.mode === "json" ? { kind: "json" } : BYTE_STRING_CLASSES.has(ctorName) ? { kind: "byteString", length: declaredLength(col) } : NUMBER_VECTOR_CLASSES.has(ctorName) ? { kind: "numberVector", length: declaredLength(col) } : BIT_STRING_CLASSES.has(ctorName) ? { kind: "bitstring", length: declaredLength(col), exact: true } : GEOMETRIC_CLASS_SHAPES[ctorName];
763
830
  if (fallbackShape?.kind === "byteString") delete constraints.maxLength;
764
831
  const shape = (v1?.shape ?? fallbackShape)?.kind;
765
832
  const finalTs = v1?.tsType ?? tsType;
package/package.json CHANGED
@@ -1,16 +1,22 @@
1
1
  {
2
2
  "name": "@drzl/analyzer",
3
- "version": "1.17.1",
3
+ "version": "1.17.3",
4
4
  "private": false,
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
- "main": "dist/index.js",
8
- "types": "dist/index.d.ts",
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
9
10
  "exports": {
10
11
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js",
13
- "require": "./dist/index.cjs"
12
+ "import": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./dist/index.d.cts",
18
+ "default": "./dist/index.cjs"
19
+ }
14
20
  }
15
21
  },
16
22
  "files": [
@@ -22,6 +28,7 @@
22
28
  },
23
29
  "devDependencies": {
24
30
  "drizzle-orm": "^0.45.2",
31
+ "drizzle-orm-v1": "npm:drizzle-orm@1.0.0-rc.4",
25
32
  "tsup": "^8.5.1",
26
33
  "typescript": "^5.9.3"
27
34
  },
@@ -45,6 +52,8 @@
45
52
  "scripts": {
46
53
  "build": "tsup src/index.ts --dts --format esm,cjs --clean",
47
54
  "lint": "eslint . --ext .ts",
48
- "test": "vitest run --testTimeout=20000"
55
+ "test": "vitest run --testTimeout=20000",
56
+ "fuzz": "node test/fuzz/run.mjs",
57
+ "fuzz:gate": "node test/fuzz/run.mjs --gate"
49
58
  }
50
59
  }