@drzl/analyzer 1.17.1 → 1.18.0
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 +1 -1
- package/dist/index.cjs +31 -8
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +31 -8
- package/package.json +12 -6
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,11 +63,15 @@ 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
|
|
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"] }
|
|
71
75
|
};
|
|
72
76
|
var V1_ONLY_ENTITY_KINDS = /^(?:MsSql|Cockroach)/;
|
|
73
77
|
var BYTE_STRING_CLASSES = /* @__PURE__ */ new Set([
|
|
@@ -190,16 +194,27 @@ function describeV1Column(column) {
|
|
|
190
194
|
};
|
|
191
195
|
break;
|
|
192
196
|
}
|
|
197
|
+
// Two modes per builder, and v1 states which in the JS half of the dataType it already
|
|
198
|
+
// carries: the tuple modes say `array point` / `array line` / `array geometry` and the object
|
|
199
|
+
// modes say `object point` / `object line` / `object geometry`. Read off real 1.0.0-rc.4
|
|
200
|
+
// columns rather than assumed. Both used to reach these arms and be called tuples, so a select
|
|
201
|
+
// schema for `point({ mode: 'xy' })` rejected every row the driver returned, on the major that
|
|
202
|
+
// describes the column outright.
|
|
203
|
+
//
|
|
204
|
+
// `js` rather than the codec, which also distinguishes them here (`point:tuple` against
|
|
205
|
+
// `point`): three dialects state a semantic with no codec at all on this release, so the codec
|
|
206
|
+
// is the weaker of the two signals and this file already prefers `js` elsewhere for the same
|
|
207
|
+
// reason.
|
|
193
208
|
case "point":
|
|
194
209
|
case "geometry":
|
|
195
|
-
out.tsType = "[number, number]";
|
|
210
|
+
out.tsType = js === "object" ? "{ x: number; y: number }" : "[number, number]";
|
|
196
211
|
out.dbType = semantic.toUpperCase();
|
|
197
|
-
out.shape = { kind: "tuple", length: 2 };
|
|
212
|
+
out.shape = js === "object" ? { kind: "numberObject", fields: ["x", "y"] } : { kind: "tuple", length: 2 };
|
|
198
213
|
break;
|
|
199
214
|
case "line":
|
|
200
|
-
out.tsType = "[number, number, number]";
|
|
215
|
+
out.tsType = js === "object" ? "{ a: number; b: number; c: number }" : "[number, number, number]";
|
|
201
216
|
out.dbType = "LINE";
|
|
202
|
-
out.shape = { kind: "tuple", length: 3 };
|
|
217
|
+
out.shape = js === "object" ? { kind: "numberObject", fields: ["a", "b", "c"] } : { kind: "tuple", length: 3 };
|
|
203
218
|
break;
|
|
204
219
|
case "vector":
|
|
205
220
|
out.tsType = "number[]";
|
|
@@ -658,6 +673,15 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
658
673
|
return { tsType: "[number, number]", dbType: "POINT" };
|
|
659
674
|
case "PgLineTuple":
|
|
660
675
|
return { tsType: "[number, number, number]", dbType: "LINE" };
|
|
676
|
+
// The object modes, which the same regex answered `string` for and which are not tuples
|
|
677
|
+
// either. `point({ mode: 'xy' })` returns `{ x, y }` and `line({ mode: 'abc' })` returns
|
|
678
|
+
// `{ a, b, c }`, read back from PGlite through drizzle 0.45.2; the same column refuses
|
|
679
|
+
// `[1, 2]` and `'1,2'`, both of which `mapToDriverValue` renders `(undefined,undefined)`.
|
|
680
|
+
// v1 says the same thing about the same two columns through `dataType: 'object point'`.
|
|
681
|
+
case "PgPointObject":
|
|
682
|
+
return { tsType: "{ x: number; y: number }", dbType: "POINT" };
|
|
683
|
+
case "PgLineABC":
|
|
684
|
+
return { tsType: "{ a: number; b: number; c: number }", dbType: "LINE" };
|
|
661
685
|
case "PgJson":
|
|
662
686
|
case "PgJsonb":
|
|
663
687
|
return { tsType: "any", dbType: ctor === "PgJsonb" ? "JSONB" : "JSON" };
|
|
@@ -678,7 +702,6 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
678
702
|
if (/^Pg/.test(ctor)) {
|
|
679
703
|
if (/Text|Varchar|Char|Uuid/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
|
|
680
704
|
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
705
|
if (/TimestampString|DateString/i.test(ctor))
|
|
683
706
|
return { tsType: "string", dbType: "TIMESTAMP" };
|
|
684
707
|
if (/Timestamptz/i.test(ctor)) return { tsType: "Date", dbType: "TIMESTAMPTZ" };
|
|
@@ -800,7 +823,7 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
800
823
|
const sqlType = sqlKind.startsWith("MySql") && typeof col?.getSQLType === "function" ? String(col.getSQLType()).toLowerCase() : void 0;
|
|
801
824
|
const byteCap = sqlType ? MYSQL_TEXT_CAPS[sqlType] : void 0;
|
|
802
825
|
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) } :
|
|
826
|
+
const fallbackShape = dbType === "JSON" || dbType === "JSONB" || col?.config?.mode === "json" ? { kind: "json" } : BYTE_STRING_CLASSES.has(ctorName) ? { kind: "byteString", length: declaredLength(col) } : GEOMETRIC_CLASS_SHAPES[ctorName];
|
|
804
827
|
if (fallbackShape?.kind === "byteString") delete constraints.maxLength;
|
|
805
828
|
const shape = (v1?.shape ?? fallbackShape)?.kind;
|
|
806
829
|
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
|
|
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
|
|
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,11 +22,15 @@ 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
|
|
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"] }
|
|
30
34
|
};
|
|
31
35
|
var V1_ONLY_ENTITY_KINDS = /^(?:MsSql|Cockroach)/;
|
|
32
36
|
var BYTE_STRING_CLASSES = /* @__PURE__ */ new Set([
|
|
@@ -149,16 +153,27 @@ function describeV1Column(column) {
|
|
|
149
153
|
};
|
|
150
154
|
break;
|
|
151
155
|
}
|
|
156
|
+
// Two modes per builder, and v1 states which in the JS half of the dataType it already
|
|
157
|
+
// carries: the tuple modes say `array point` / `array line` / `array geometry` and the object
|
|
158
|
+
// modes say `object point` / `object line` / `object geometry`. Read off real 1.0.0-rc.4
|
|
159
|
+
// columns rather than assumed. Both used to reach these arms and be called tuples, so a select
|
|
160
|
+
// schema for `point({ mode: 'xy' })` rejected every row the driver returned, on the major that
|
|
161
|
+
// describes the column outright.
|
|
162
|
+
//
|
|
163
|
+
// `js` rather than the codec, which also distinguishes them here (`point:tuple` against
|
|
164
|
+
// `point`): three dialects state a semantic with no codec at all on this release, so the codec
|
|
165
|
+
// is the weaker of the two signals and this file already prefers `js` elsewhere for the same
|
|
166
|
+
// reason.
|
|
152
167
|
case "point":
|
|
153
168
|
case "geometry":
|
|
154
|
-
out.tsType = "[number, number]";
|
|
169
|
+
out.tsType = js === "object" ? "{ x: number; y: number }" : "[number, number]";
|
|
155
170
|
out.dbType = semantic.toUpperCase();
|
|
156
|
-
out.shape = { kind: "tuple", length: 2 };
|
|
171
|
+
out.shape = js === "object" ? { kind: "numberObject", fields: ["x", "y"] } : { kind: "tuple", length: 2 };
|
|
157
172
|
break;
|
|
158
173
|
case "line":
|
|
159
|
-
out.tsType = "[number, number, number]";
|
|
174
|
+
out.tsType = js === "object" ? "{ a: number; b: number; c: number }" : "[number, number, number]";
|
|
160
175
|
out.dbType = "LINE";
|
|
161
|
-
out.shape = { kind: "tuple", length: 3 };
|
|
176
|
+
out.shape = js === "object" ? { kind: "numberObject", fields: ["a", "b", "c"] } : { kind: "tuple", length: 3 };
|
|
162
177
|
break;
|
|
163
178
|
case "vector":
|
|
164
179
|
out.tsType = "number[]";
|
|
@@ -617,6 +632,15 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
617
632
|
return { tsType: "[number, number]", dbType: "POINT" };
|
|
618
633
|
case "PgLineTuple":
|
|
619
634
|
return { tsType: "[number, number, number]", dbType: "LINE" };
|
|
635
|
+
// The object modes, which the same regex answered `string` for and which are not tuples
|
|
636
|
+
// either. `point({ mode: 'xy' })` returns `{ x, y }` and `line({ mode: 'abc' })` returns
|
|
637
|
+
// `{ a, b, c }`, read back from PGlite through drizzle 0.45.2; the same column refuses
|
|
638
|
+
// `[1, 2]` and `'1,2'`, both of which `mapToDriverValue` renders `(undefined,undefined)`.
|
|
639
|
+
// v1 says the same thing about the same two columns through `dataType: 'object point'`.
|
|
640
|
+
case "PgPointObject":
|
|
641
|
+
return { tsType: "{ x: number; y: number }", dbType: "POINT" };
|
|
642
|
+
case "PgLineABC":
|
|
643
|
+
return { tsType: "{ a: number; b: number; c: number }", dbType: "LINE" };
|
|
620
644
|
case "PgJson":
|
|
621
645
|
case "PgJsonb":
|
|
622
646
|
return { tsType: "any", dbType: ctor === "PgJsonb" ? "JSONB" : "JSON" };
|
|
@@ -637,7 +661,6 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
637
661
|
if (/^Pg/.test(ctor)) {
|
|
638
662
|
if (/Text|Varchar|Char|Uuid/i.test(ctor)) return { tsType: "string", dbType: "TEXT" };
|
|
639
663
|
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
664
|
if (/TimestampString|DateString/i.test(ctor))
|
|
642
665
|
return { tsType: "string", dbType: "TIMESTAMP" };
|
|
643
666
|
if (/Timestamptz/i.test(ctor)) return { tsType: "Date", dbType: "TIMESTAMPTZ" };
|
|
@@ -759,7 +782,7 @@ var _SchemaAnalyzer = class _SchemaAnalyzer {
|
|
|
759
782
|
const sqlType = sqlKind.startsWith("MySql") && typeof col?.getSQLType === "function" ? String(col.getSQLType()).toLowerCase() : void 0;
|
|
760
783
|
const byteCap = sqlType ? MYSQL_TEXT_CAPS[sqlType] : void 0;
|
|
761
784
|
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) } :
|
|
785
|
+
const fallbackShape = dbType === "JSON" || dbType === "JSONB" || col?.config?.mode === "json" ? { kind: "json" } : BYTE_STRING_CLASSES.has(ctorName) ? { kind: "byteString", length: declaredLength(col) } : GEOMETRIC_CLASS_SHAPES[ctorName];
|
|
763
786
|
if (fallbackShape?.kind === "byteString") delete constraints.maxLength;
|
|
764
787
|
const shape = (v1?.shape ?? fallbackShape)?.kind;
|
|
765
788
|
const finalTs = v1?.tsType ?? tsType;
|
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drzl/analyzer",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.18.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "dist/index.
|
|
8
|
-
"
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
9
10
|
"exports": {
|
|
10
11
|
".": {
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
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": [
|