postgrejs 3.6.1 → 3.7.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +50 -6
  2. package/README.md +9 -83
  3. package/connection/intl-connection.d.ts +5 -3
  4. package/connection/intl-connection.js +43 -15
  5. package/connection/prepared-statement.js +2 -2
  6. package/constants.d.ts +60 -0
  7. package/constants.js +119 -1
  8. package/data-type-map.js +82 -0
  9. package/data-types/bit-type.d.ts +5 -0
  10. package/data-types/bit-type.js +91 -0
  11. package/data-types/box-type.js +9 -19
  12. package/data-types/circle-type.js +6 -16
  13. package/data-types/classes/geometric.d.ts +105 -0
  14. package/data-types/classes/geometric.js +197 -0
  15. package/data-types/classes/interval.d.ts +73 -0
  16. package/data-types/classes/interval.js +181 -0
  17. package/data-types/classes/numeric.d.ts +37 -0
  18. package/data-types/classes/numeric.js +47 -0
  19. package/data-types/classes/range.d.ts +74 -0
  20. package/data-types/classes/range.js +111 -0
  21. package/data-types/classes/type-oid.d.ts +34 -0
  22. package/data-types/classes/type-oid.js +45 -0
  23. package/data-types/inet-type.d.ts +5 -0
  24. package/data-types/inet-type.js +286 -0
  25. package/data-types/interval-type.d.ts +5 -0
  26. package/data-types/interval-type.js +79 -0
  27. package/data-types/jsonpath-type.d.ts +3 -0
  28. package/data-types/jsonpath-type.js +53 -0
  29. package/data-types/line-type.d.ts +3 -0
  30. package/data-types/line-type.js +41 -0
  31. package/data-types/lseg-type.js +9 -19
  32. package/data-types/macaddr-type.d.ts +5 -0
  33. package/data-types/macaddr-type.js +86 -0
  34. package/data-types/numeric-type.js +98 -69
  35. package/data-types/path-type.d.ts +5 -0
  36. package/data-types/path-type.js +139 -0
  37. package/data-types/pg-lsn-type.d.ts +3 -0
  38. package/data-types/pg-lsn-type.js +58 -0
  39. package/data-types/point-type.js +8 -13
  40. package/data-types/range-type.d.ts +23 -0
  41. package/data-types/range-type.js +342 -0
  42. package/data-types/snapshot-type.d.ts +5 -0
  43. package/data-types/snapshot-type.js +96 -0
  44. package/data-types/tid-type.d.ts +3 -0
  45. package/data-types/tid-type.js +50 -0
  46. package/data-types/timetz-type.d.ts +3 -0
  47. package/data-types/timetz-type.js +184 -0
  48. package/data-types/tsvector-type.d.ts +5 -0
  49. package/data-types/tsvector-type.js +216 -0
  50. package/data-types/xid-type.d.ts +7 -0
  51. package/data-types/xid-type.js +110 -0
  52. package/index.d.ts +4 -0
  53. package/index.js +4 -0
  54. package/interfaces/data-mapping-options.d.ts +26 -0
  55. package/interfaces/data-type.d.ts +8 -9
  56. package/package.json +1 -1
  57. package/protocol/connection-lost-error.d.ts +5 -3
  58. package/protocol/connection-lost-error.js +5 -3
  59. package/protocol/pg-socket.js +16 -2
  60. package/util/parse-array.js +17 -2
  61. package/util/resolve-column-formats.d.ts +2 -1
  62. package/util/resolve-column-formats.js +35 -8
  63. package/util/stringify-for-sql.js +37 -1
package/data-type-map.js CHANGED
@@ -1,28 +1,43 @@
1
1
  import { DataTypeOIDs } from './constants.js';
2
+ import { ArrayBitType, ArrayVarbitType, BitType, VarbitType, } from './data-types/bit-type.js';
2
3
  import { ArrayBoolType, BoolType } from './data-types/bool-type.js';
3
4
  import { ArrayBoxType, BoxType } from './data-types/box-type.js';
4
5
  import { ArrayByteaType, ByteaType } from './data-types/bytea-type.js';
5
6
  import { ArrayCharType, CharType } from './data-types/char-type.js';
6
7
  import { ArrayCircleType, CircleType } from './data-types/circle-type.js';
8
+ import { getTypeOid, REQUIRES_TYPE_OID, } from './data-types/classes/type-oid.js';
7
9
  import { ArrayDateType, DateType } from './data-types/date-type.js';
8
10
  import { ArrayFloat4Type, Float4Type } from './data-types/float4-type.js';
9
11
  import { ArrayFloat8Type, Float8Type } from './data-types/float8-type.js';
12
+ import { ArrayCidrType, ArrayInetType, CidrType, InetType, } from './data-types/inet-type.js';
10
13
  import { ArrayInt2Type, Int2Type } from './data-types/int2-type.js';
11
14
  import { ArrayInt2VectorType, Int2VectorType, } from './data-types/int2-vector-type.js';
12
15
  import { ArrayInt4Type, Int4Type } from './data-types/int4-type.js';
13
16
  import { ArrayInt8Type, Int8Type } from './data-types/int8-type.js';
17
+ import { ArrayIntervalType, IntervalType } from './data-types/interval-type.js';
14
18
  import { ArrayJsonType, JsonType } from './data-types/json-type.js';
15
19
  import { ArrayJsonbType, JsonbType } from './data-types/jsonb-type.js';
20
+ import { ArrayJsonPathType, JsonPathType } from './data-types/jsonpath-type.js';
21
+ import { ArrayLineType, LineType } from './data-types/line-type.js';
16
22
  import { ArrayLsegType, LsegType } from './data-types/lseg-type.js';
23
+ import { ArrayMacaddr8Type, ArrayMacaddrType, Macaddr8Type, MacaddrType, } from './data-types/macaddr-type.js';
17
24
  import { ArrayNumericType, NumericType } from './data-types/numeric-type.js';
18
25
  import { ArrayOidType, OidType } from './data-types/oid-type.js';
19
26
  import { ArrayOidVectorType, OidVectorType, } from './data-types/oid-vector-type.js';
27
+ import { ArrayPathType, ArrayPolygonType, PathType, PolygonType, } from './data-types/path-type.js';
28
+ import { ArrayPgLsnType, PgLsnType } from './data-types/pg-lsn-type.js';
20
29
  import { ArrayPointType, PointType } from './data-types/point-type.js';
30
+ import { RangeTypes } from './data-types/range-type.js';
31
+ import { ArrayPgSnapshotType, ArrayTxidSnapshotType, PgSnapshotType, TxidSnapshotType, } from './data-types/snapshot-type.js';
32
+ import { ArrayTidType, TidType } from './data-types/tid-type.js';
21
33
  import { ArrayTimeType, TimeType } from './data-types/time-type.js';
22
34
  import { ArrayTimestampType, TimestampType, } from './data-types/timestamp-type.js';
23
35
  import { ArrayTimestamptzType, TimestamptzType, } from './data-types/timestamptz-type.js';
36
+ import { ArrayTimeTzType, TimeTzType } from './data-types/timetz-type.js';
37
+ import { ArrayTsQueryType, ArrayTsVectorType, TsQueryType, TsVectorType, } from './data-types/tsvector-type.js';
24
38
  import { ArrayUuidType, UuidType } from './data-types/uuid-type.js';
25
39
  import { ArrayVarcharType, VarcharType } from './data-types/varchar-type.js';
40
+ import { ArrayCidType, ArrayXid8Type, ArrayXidType, CidType, Xid8Type, XidType, } from './data-types/xid-type.js';
26
41
  export class DataTypeMap {
27
42
  _itemsByOID = {};
28
43
  _items = [];
@@ -60,6 +75,25 @@ export class DataTypeMap {
60
75
  determine(value) {
61
76
  if (value == null)
62
77
  return DataTypeOIDs.unknown;
78
+ if (typeof value === 'object') {
79
+ // A value that already knows which type it came from says so,
80
+ // rather than being matched by shape - which is the only thing
81
+ // that can work when several types share one JavaScript class.
82
+ const carried = getTypeOid(value);
83
+ if (carried !== undefined)
84
+ return carried;
85
+ const ctor = value
86
+ .constructor;
87
+ if (ctor && ctor[REQUIRES_TYPE_OID]) {
88
+ // Checked before the walk below rather than after it: JsonType
89
+ // takes any object, so left to the walk this value would quietly
90
+ // go out declared `json` and come back looking right.
91
+ throw new TypeError(`A ${ctor.name} carries no type OID, and ` +
92
+ 'which PostgreSQL type it is cannot be told from the value - ' +
93
+ 'give it one (`new Range(lower, upper, bounds, oid)`) or name ' +
94
+ 'it at the call site (`new BindParam(oid, value)`)');
95
+ }
96
+ }
63
97
  const valueIsArray = Array.isArray(value);
64
98
  let i;
65
99
  let t;
@@ -97,6 +131,9 @@ GlobalTypeMap.register([CircleType, ArrayCircleType]);
97
131
  GlobalTypeMap.register([PointType, ArrayPointType]);
98
132
  GlobalTypeMap.register([LsegType, ArrayLsegType]);
99
133
  GlobalTypeMap.register([BoxType, ArrayBoxType]);
134
+ GlobalTypeMap.register([LineType, ArrayLineType]);
135
+ GlobalTypeMap.register([PathType, ArrayPathType]);
136
+ GlobalTypeMap.register([PolygonType, ArrayPolygonType]);
100
137
  GlobalTypeMap.register([Int2VectorType, ArrayInt2VectorType]);
101
138
  GlobalTypeMap.register({
102
139
  ...VarcharType,
@@ -138,10 +175,55 @@ GlobalTypeMap.register({
138
175
  oid: DataTypeOIDs._xml,
139
176
  elementsOID: DataTypeOIDs.xml,
140
177
  });
178
+ // `refcursor` is a cursor's name and `pg_node_tree` a catalog blob, and
179
+ // both are literally text on the wire - `refcursor`'s own typsend is
180
+ // textsend. Registered before varchar the way bpchar and the rest are,
181
+ // and marked uninferrable on top of that: a plain string is not evidence
182
+ // of either, and sending one declared `refcursor` where `text` was meant
183
+ // would be refused by the server.
184
+ GlobalTypeMap.register({
185
+ ...VarcharType,
186
+ name: 'refcursor',
187
+ oid: DataTypeOIDs.refcursor,
188
+ inferrable: false,
189
+ });
190
+ GlobalTypeMap.register({
191
+ ...ArrayVarcharType,
192
+ name: '_refcursor',
193
+ oid: DataTypeOIDs._refcursor,
194
+ elementsOID: DataTypeOIDs.refcursor,
195
+ inferrable: false,
196
+ });
197
+ // pg_node_tree has no array type of its own.
198
+ GlobalTypeMap.register({
199
+ ...VarcharType,
200
+ name: 'pg_node_tree',
201
+ oid: DataTypeOIDs.pg_node_tree,
202
+ inferrable: false,
203
+ });
141
204
  GlobalTypeMap.register([VarcharType, ArrayVarcharType]);
142
205
  GlobalTypeMap.register([UuidType, ArrayUuidType]);
143
206
  GlobalTypeMap.register([CharType, ArrayCharType]);
144
207
  GlobalTypeMap.register([TimestamptzType, ArrayTimestamptzType]);
145
208
  GlobalTypeMap.register([TimeType, ArrayTimeType]);
209
+ GlobalTypeMap.register([TimeTzType, ArrayTimeTzType]);
146
210
  GlobalTypeMap.register([DateType, ArrayDateType]);
147
211
  GlobalTypeMap.register([TimestampType, ArrayTimestampType]);
212
+ GlobalTypeMap.register([IntervalType, ArrayIntervalType]);
213
+ GlobalTypeMap.register(RangeTypes);
214
+ GlobalTypeMap.register([InetType, ArrayInetType]);
215
+ GlobalTypeMap.register([CidrType, ArrayCidrType]);
216
+ GlobalTypeMap.register([BitType, ArrayBitType]);
217
+ GlobalTypeMap.register([VarbitType, ArrayVarbitType]);
218
+ GlobalTypeMap.register([JsonPathType, ArrayJsonPathType]);
219
+ GlobalTypeMap.register([TsVectorType, ArrayTsVectorType]);
220
+ GlobalTypeMap.register([TsQueryType, ArrayTsQueryType]);
221
+ GlobalTypeMap.register([XidType, ArrayXidType]);
222
+ GlobalTypeMap.register([Xid8Type, ArrayXid8Type]);
223
+ GlobalTypeMap.register([CidType, ArrayCidType]);
224
+ GlobalTypeMap.register([TidType, ArrayTidType]);
225
+ GlobalTypeMap.register([PgLsnType, ArrayPgLsnType]);
226
+ GlobalTypeMap.register([PgSnapshotType, ArrayPgSnapshotType]);
227
+ GlobalTypeMap.register([TxidSnapshotType, ArrayTxidSnapshotType]);
228
+ GlobalTypeMap.register([MacaddrType, ArrayMacaddrType]);
229
+ GlobalTypeMap.register([Macaddr8Type, ArrayMacaddr8Type]);
@@ -0,0 +1,5 @@
1
+ import type { DataType } from '../interfaces/data-type.js';
2
+ export declare const BitType: DataType;
3
+ export declare const ArrayBitType: DataType;
4
+ export declare const VarbitType: DataType;
5
+ export declare const ArrayVarbitType: DataType;
@@ -0,0 +1,91 @@
1
+ import { DataTypeOIDs } from '../constants.js';
2
+ /**
3
+ * `bit` and `varbit` are one type on the wire - the length is a property
4
+ * of the column, not of the value - so they share a codec and differ
5
+ * only in which OID they register under.
6
+ *
7
+ * Both decode to a string of `0` and `1`, which is what the type is:
8
+ * PostgreSQL prints it that way, accepts it back that way, and the
9
+ * alternatives are all worse. A number loses leading zeroes and anything
10
+ * past 53 bits; a Buffer loses the bit count, so `1` and `10000000`
11
+ * become the same eight padded bits. `pg` leaves it a string too.
12
+ */
13
+ /** Every byte's eight bits, so decoding is one lookup per byte. */
14
+ const BYTE_BITS = new Array(256);
15
+ for (let i = 0; i < 256; i++)
16
+ BYTE_BITS[i] = i.toString(2).padStart(8, '0');
17
+ const BIT_PATTERN = /^[01]*$/;
18
+ /**
19
+ * An int32 bit count, then the bits themselves packed most-significant
20
+ * first and the last byte zero-padded. A zero-length value is the count
21
+ * and nothing else.
22
+ */
23
+ function decode(v, offset) {
24
+ const bits = v.readInt32BE(offset);
25
+ const whole = bits >> 3;
26
+ const start = offset + 4;
27
+ let out = '';
28
+ let i;
29
+ for (i = 0; i < whole; i++)
30
+ out += BYTE_BITS[v[start + i]];
31
+ const rest = bits & 7;
32
+ if (rest)
33
+ out += BYTE_BITS[v[start + whole]].slice(0, rest);
34
+ return out;
35
+ }
36
+ function encode(buf, v, name) {
37
+ if (typeof v !== 'string' || !BIT_PATTERN.test(v))
38
+ throw new Error(`"${v}" is not a valid ${name} value - a string of 0 and 1 is`);
39
+ const bits = v.length;
40
+ buf.writeInt32BE(bits);
41
+ const bytes = Buffer.alloc((bits + 7) >> 3);
42
+ let i;
43
+ for (i = 0; i < bits; i++)
44
+ if (v.charCodeAt(i) === 49)
45
+ bytes[i >> 3] |= 128 >> (i & 7);
46
+ buf.writeBytes(bytes);
47
+ }
48
+ function createType(name, oid) {
49
+ return {
50
+ name,
51
+ oid,
52
+ jsType: 'string',
53
+ // `0` and `1` are ordinary characters, and a string of them is far
54
+ // more often text than a bit string - inferring this type would send
55
+ // `bit` where `text` was meant. See inet-type.ts.
56
+ inferrable: false,
57
+ encodeText(v) {
58
+ return '' + v;
59
+ },
60
+ encodeBinary(buf, v) {
61
+ encode(buf, v, name);
62
+ },
63
+ decodeBinary(v, offset = 0) {
64
+ return decode(v, offset);
65
+ },
66
+ decodeText(v) {
67
+ return v;
68
+ },
69
+ // Two characters, both ASCII - see inet-type.ts for why 'latin1'.
70
+ decodeTextBuffer(buf, offset, len) {
71
+ return buf.toString('latin1', offset, offset + len);
72
+ },
73
+ isType(v) {
74
+ return typeof v === 'string' && BIT_PATTERN.test(v);
75
+ },
76
+ };
77
+ }
78
+ export const BitType = createType('bit', DataTypeOIDs.bit);
79
+ export const ArrayBitType = {
80
+ ...BitType,
81
+ name: '_bit',
82
+ oid: DataTypeOIDs._bit,
83
+ elementsOID: DataTypeOIDs.bit,
84
+ };
85
+ export const VarbitType = createType('varbit', DataTypeOIDs.varbit);
86
+ export const ArrayVarbitType = {
87
+ ...VarbitType,
88
+ name: '_varbit',
89
+ oid: DataTypeOIDs._varbit,
90
+ elementsOID: DataTypeOIDs.varbit,
91
+ };
@@ -1,11 +1,12 @@
1
1
  import { DataTypeOIDs } from '../constants.js';
2
+ import { Box, TwoPoints } from './classes/geometric.js';
2
3
  const BOX_PATTERN1 = /^\( *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *\)$/;
3
4
  const BOX_PATTERN2 = /^\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\)$/;
4
5
  const BOX_PATTERN3 = /^(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-?\d+\.?\d*)$/;
5
6
  export const BoxType = {
6
7
  name: 'box',
7
8
  oid: DataTypeOIDs.box,
8
- jsType: 'object',
9
+ jsType: 'Box',
9
10
  arraySeparator: ';',
10
11
  encodeText(v) {
11
12
  return `(${v.x1},${v.y1}),(${v.x2},${v.y2})`;
@@ -17,34 +18,23 @@ export const BoxType = {
17
18
  buf.writeDoubleBE(v.y2);
18
19
  },
19
20
  decodeBinary(v, offset = 0) {
20
- return {
21
- x1: v.readDoubleBE(offset),
22
- y1: v.readDoubleBE(offset + 8),
23
- x2: v.readDoubleBE(offset + 16),
24
- y2: v.readDoubleBE(offset + 24),
25
- };
21
+ return new Box(v.readDoubleBE(offset), v.readDoubleBE(offset + 8), v.readDoubleBE(offset + 16), v.readDoubleBE(offset + 24));
26
22
  },
27
23
  decodeText(v) {
28
24
  const m = v.match(BOX_PATTERN1) || v.match(BOX_PATTERN2) || v.match(BOX_PATTERN3);
29
25
  if (!m)
30
26
  return undefined;
31
- return {
32
- x1: parseFloat(m[1]),
33
- y1: parseFloat(m[2]),
34
- x2: parseFloat(m[3]),
35
- y2: parseFloat(m[4]),
36
- };
27
+ return new Box(parseFloat(m[1]), parseFloat(m[2]), parseFloat(m[3]), parseFloat(m[4]));
37
28
  },
38
29
  decodeTextBuffer(buf, offset, len, options) {
39
30
  return BoxType.decodeText(buf.toString('latin1', offset, offset + len), options);
40
31
  },
32
+ // A plain object of the four numbers is still accepted - it is what
33
+ // this type returned before these classes existed - but only a plain
34
+ // one: box and lseg carry the same four, so an instance of the other
35
+ // must not be claimed here.
41
36
  isType(v) {
42
- return (typeof v === 'object' &&
43
- Object.keys(v).length === 4 &&
44
- typeof v.x1 === 'number' &&
45
- typeof v.y1 === 'number' &&
46
- typeof v.x2 === 'number' &&
47
- typeof v.y2 === 'number');
37
+ return v instanceof Box || TwoPoints.isTwoPointsLike(v);
48
38
  },
49
39
  };
50
40
  export const ArrayBoxType = {
@@ -1,4 +1,5 @@
1
1
  import { DataTypeOIDs } from '../constants.js';
2
+ import { Circle } from './classes/geometric.js';
2
3
  const CIRCLE_PATTERN1 = /^< *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *(-?\d+\.?\d*) *>$/;
3
4
  const CIRCLE_PATTERN2 = /^\( *\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *(-?\d+\.?\d*) *\)$/;
4
5
  const CIRCLE_PATTERN3 = /^\( *(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *\) *, *(-?\d+\.?\d*)$/;
@@ -6,7 +7,7 @@ const CIRCLE_PATTERN4 = /^(-?\d+\.?\d*) *, *(-?\d+\.?\d*) *, *(-?\d+\.?\d*)$/;
6
7
  export const CircleType = {
7
8
  name: 'circle',
8
9
  oid: DataTypeOIDs.circle,
9
- jsType: 'object',
10
+ jsType: 'Circle',
10
11
  encodeText(v) {
11
12
  return `<(${v.x},${v.y}),${v.r}>`;
12
13
  },
@@ -16,11 +17,7 @@ export const CircleType = {
16
17
  buf.writeDoubleBE(v.r);
17
18
  },
18
19
  decodeBinary(v, offset = 0) {
19
- return {
20
- x: v.readDoubleBE(offset),
21
- y: v.readDoubleBE(offset + 8),
22
- r: v.readDoubleBE(offset + 16),
23
- };
20
+ return new Circle(v.readDoubleBE(offset), v.readDoubleBE(offset + 8), v.readDoubleBE(offset + 16));
24
21
  },
25
22
  decodeText(v) {
26
23
  const m = v.match(CIRCLE_PATTERN1) ||
@@ -29,22 +26,15 @@ export const CircleType = {
29
26
  v.match(CIRCLE_PATTERN4);
30
27
  if (!m)
31
28
  return undefined;
32
- return {
33
- x: parseFloat(m[1]),
34
- y: parseFloat(m[2]),
35
- r: parseFloat(m[3]),
36
- };
29
+ return new Circle(parseFloat(m[1]), parseFloat(m[2]), parseFloat(m[3]));
37
30
  },
38
31
  // See box-type.ts's decodeTextBuffer comment - same rationale.
39
32
  decodeTextBuffer(buf, offset, len, options) {
40
33
  return CircleType.decodeText(buf.toString('latin1', offset, offset + len), options);
41
34
  },
35
+ // See point-type.ts: the plain object shape is still accepted.
42
36
  isType(v) {
43
- return (typeof v === 'object' &&
44
- Object.keys(v).length === 3 &&
45
- typeof v.x === 'number' &&
46
- typeof v.y === 'number' &&
47
- typeof v.r === 'number');
37
+ return v instanceof Circle || Circle.isCircleLike(v);
48
38
  },
49
39
  };
50
40
  export const ArrayCircleType = {
@@ -0,0 +1,105 @@
1
+ /** A `point`: one position. */
2
+ export declare class Point {
3
+ x: number;
4
+ y: number;
5
+ constructor(x?: number, y?: number);
6
+ /** As PostgreSQL prints it, so it casts back through `::point`. */
7
+ toString(): string;
8
+ toJSON(): string;
9
+ static isPointLike(v: any): boolean;
10
+ }
11
+ /** A `circle`: a centre and a radius. */
12
+ export declare class Circle {
13
+ x: number;
14
+ y: number;
15
+ r: number;
16
+ constructor(x?: number, y?: number, r?: number);
17
+ /** As PostgreSQL prints it, so it casts back through `::circle`. */
18
+ toString(): string;
19
+ toJSON(): string;
20
+ static isCircleLike(v: any): boolean;
21
+ }
22
+ /**
23
+ * Two corners, which is how both `box` and `lseg` are carried - and why
24
+ * they are two classes rather than one shared shape. They were
25
+ * indistinguishable as plain objects: both types' isType() accepted
26
+ * `{x1, y1, x2, y2}`, so `determine()` answered `box` for every one of
27
+ * them and an lseg parameter could not be expressed at all.
28
+ */
29
+ declare abstract class TwoPoints {
30
+ x1: number;
31
+ y1: number;
32
+ x2: number;
33
+ y2: number;
34
+ constructor(x1?: number, y1?: number, x2?: number, y2?: number);
35
+ toJSON(): string;
36
+ static isTwoPointsLike(v: any): boolean;
37
+ }
38
+ /** A `box`: a rectangle given by two opposite corners. */
39
+ export declare class Box extends TwoPoints {
40
+ /** As PostgreSQL prints it, so it casts back through `::box`. */
41
+ toString(): string;
42
+ }
43
+ /** An `lseg`: the straight line between two points. */
44
+ export declare class LineSegment extends TwoPoints {
45
+ /** As PostgreSQL prints it, so it casts back through `::lseg`. */
46
+ toString(): string;
47
+ }
48
+ /**
49
+ * A `line`: the infinite line Ax + By + C = 0.
50
+ *
51
+ * PostgreSQL stores and prints the three coefficients whatever form the
52
+ * literal took - `line '((0,0),(1,1))'` comes back as `{1,-1,0}` - so
53
+ * that is what this carries. A pair of points would be a second, lossy
54
+ * spelling of the same thing, since a line through them is not the
55
+ * points.
56
+ */
57
+ export declare class Line {
58
+ a: number;
59
+ b: number;
60
+ c: number;
61
+ constructor(a?: number, b?: number, c?: number);
62
+ /** As PostgreSQL prints it, so it casts back through `::line`. */
63
+ toString(): string;
64
+ toJSON(): string;
65
+ static isLineLike(v: any): boolean;
66
+ }
67
+ /**
68
+ * The list of points `path` and `polygon` share. They are two classes
69
+ * rather than one for the same reason `Box` and `LineSegment` are: the
70
+ * values are indistinguishable by shape, so only the class can say which
71
+ * type a parameter is meant for.
72
+ */
73
+ declare abstract class PointList {
74
+ points: Point[];
75
+ /** Plain `{x, y}` objects are accepted and kept as Points. */
76
+ constructor(points?: (Point | {
77
+ x: number;
78
+ y: number;
79
+ })[]);
80
+ toJSON(): string;
81
+ protected join(): string;
82
+ }
83
+ /**
84
+ * A `path`: a series of points, open or closed.
85
+ *
86
+ * Closed is the default because it is PostgreSQL's - a literal written
87
+ * without brackets, `path '1,2,3,4'`, comes back closed. The flag is
88
+ * part of the value and not a formatting choice: the server stores it
89
+ * and prints `[...]` for an open path against `(...)` for a closed one.
90
+ */
91
+ export declare class Path extends PointList {
92
+ isClosed: boolean;
93
+ constructor(points?: (Point | {
94
+ x: number;
95
+ y: number;
96
+ })[], isClosed?: boolean);
97
+ /** As PostgreSQL prints it, so it casts back through `::path`. */
98
+ toString(): string;
99
+ }
100
+ /** A `polygon`: a closed series of points. */
101
+ export declare class Polygon extends PointList {
102
+ /** As PostgreSQL prints it, so it casts back through `::polygon`. */
103
+ toString(): string;
104
+ }
105
+ export { PointList, TwoPoints };
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Whether a value is a bare object literal rather than an instance of
3
+ * some class.
4
+ *
5
+ * The geometric types accept both - a Point, and the `{x, y}` that was
6
+ * the only thing they returned before these classes existed - but a
7
+ * BoxType must not claim a LineSegment just because it carries the same
8
+ * four numbers, so the shape check is limited to plain objects.
9
+ */
10
+ function isPlainObject(v) {
11
+ return (v !== null &&
12
+ typeof v === 'object' &&
13
+ Object.getPrototypeOf(v) === Object.prototype);
14
+ }
15
+ function isNum(v) {
16
+ return typeof v === 'number';
17
+ }
18
+ /** A `point`: one position. */
19
+ export class Point {
20
+ x;
21
+ y;
22
+ constructor(x = 0, y = 0) {
23
+ this.x = x;
24
+ this.y = y;
25
+ }
26
+ /** As PostgreSQL prints it, so it casts back through `::point`. */
27
+ toString() {
28
+ return `(${this.x},${this.y})`;
29
+ }
30
+ toJSON() {
31
+ return this.toString();
32
+ }
33
+ /* c8 ignore next 3 */
34
+ static isPointLike(v) {
35
+ return (isPlainObject(v) &&
36
+ Object.keys(v).length === 2 &&
37
+ isNum(v.x) &&
38
+ isNum(v.y));
39
+ }
40
+ }
41
+ /** A `circle`: a centre and a radius. */
42
+ export class Circle {
43
+ x;
44
+ y;
45
+ r;
46
+ constructor(x = 0, y = 0, r = 0) {
47
+ this.x = x;
48
+ this.y = y;
49
+ this.r = r;
50
+ }
51
+ /** As PostgreSQL prints it, so it casts back through `::circle`. */
52
+ toString() {
53
+ return `<(${this.x},${this.y}),${this.r}>`;
54
+ }
55
+ toJSON() {
56
+ return this.toString();
57
+ }
58
+ static isCircleLike(v) {
59
+ return (isPlainObject(v) &&
60
+ Object.keys(v).length === 3 &&
61
+ isNum(v.x) &&
62
+ isNum(v.y) &&
63
+ isNum(v.r));
64
+ }
65
+ }
66
+ /**
67
+ * Two corners, which is how both `box` and `lseg` are carried - and why
68
+ * they are two classes rather than one shared shape. They were
69
+ * indistinguishable as plain objects: both types' isType() accepted
70
+ * `{x1, y1, x2, y2}`, so `determine()` answered `box` for every one of
71
+ * them and an lseg parameter could not be expressed at all.
72
+ */
73
+ class TwoPoints {
74
+ x1;
75
+ y1;
76
+ x2;
77
+ y2;
78
+ constructor(x1 = 0, y1 = 0, x2 = 0, y2 = 0) {
79
+ this.x1 = x1;
80
+ this.y1 = y1;
81
+ this.x2 = x2;
82
+ this.y2 = y2;
83
+ }
84
+ toJSON() {
85
+ return this.toString();
86
+ }
87
+ static isTwoPointsLike(v) {
88
+ return (isPlainObject(v) &&
89
+ Object.keys(v).length === 4 &&
90
+ isNum(v.x1) &&
91
+ isNum(v.y1) &&
92
+ isNum(v.x2) &&
93
+ isNum(v.y2));
94
+ }
95
+ }
96
+ /** A `box`: a rectangle given by two opposite corners. */
97
+ export class Box extends TwoPoints {
98
+ /** As PostgreSQL prints it, so it casts back through `::box`. */
99
+ toString() {
100
+ return `(${this.x1},${this.y1}),(${this.x2},${this.y2})`;
101
+ }
102
+ }
103
+ /** An `lseg`: the straight line between two points. */
104
+ export class LineSegment extends TwoPoints {
105
+ /** As PostgreSQL prints it, so it casts back through `::lseg`. */
106
+ toString() {
107
+ return `[(${this.x1},${this.y1}),(${this.x2},${this.y2})]`;
108
+ }
109
+ }
110
+ /**
111
+ * A `line`: the infinite line Ax + By + C = 0.
112
+ *
113
+ * PostgreSQL stores and prints the three coefficients whatever form the
114
+ * literal took - `line '((0,0),(1,1))'` comes back as `{1,-1,0}` - so
115
+ * that is what this carries. A pair of points would be a second, lossy
116
+ * spelling of the same thing, since a line through them is not the
117
+ * points.
118
+ */
119
+ export class Line {
120
+ a;
121
+ b;
122
+ c;
123
+ constructor(a = 0, b = 0, c = 0) {
124
+ this.a = a;
125
+ this.b = b;
126
+ this.c = c;
127
+ }
128
+ /** As PostgreSQL prints it, so it casts back through `::line`. */
129
+ toString() {
130
+ return `{${this.a},${this.b},${this.c}}`;
131
+ }
132
+ toJSON() {
133
+ return this.toString();
134
+ }
135
+ static isLineLike(v) {
136
+ return (isPlainObject(v) &&
137
+ Object.keys(v).length === 3 &&
138
+ isNum(v.a) &&
139
+ isNum(v.b) &&
140
+ isNum(v.c));
141
+ }
142
+ }
143
+ /**
144
+ * The list of points `path` and `polygon` share. They are two classes
145
+ * rather than one for the same reason `Box` and `LineSegment` are: the
146
+ * values are indistinguishable by shape, so only the class can say which
147
+ * type a parameter is meant for.
148
+ */
149
+ class PointList {
150
+ points;
151
+ /** Plain `{x, y}` objects are accepted and kept as Points. */
152
+ constructor(points = []) {
153
+ this.points = points.map(p => p instanceof Point ? p : new Point(p.x, p.y));
154
+ }
155
+ toJSON() {
156
+ return this.toString();
157
+ }
158
+ join() {
159
+ let out = '';
160
+ const l = this.points.length;
161
+ let i;
162
+ for (i = 0; i < l; i++) {
163
+ if (i)
164
+ out += ',';
165
+ out += this.points[i].toString();
166
+ }
167
+ return out;
168
+ }
169
+ }
170
+ /**
171
+ * A `path`: a series of points, open or closed.
172
+ *
173
+ * Closed is the default because it is PostgreSQL's - a literal written
174
+ * without brackets, `path '1,2,3,4'`, comes back closed. The flag is
175
+ * part of the value and not a formatting choice: the server stores it
176
+ * and prints `[...]` for an open path against `(...)` for a closed one.
177
+ */
178
+ export class Path extends PointList {
179
+ isClosed;
180
+ constructor(points = [], isClosed = true) {
181
+ super(points);
182
+ this.isClosed = isClosed;
183
+ }
184
+ /** As PostgreSQL prints it, so it casts back through `::path`. */
185
+ toString() {
186
+ const inner = this.join();
187
+ return this.isClosed ? `(${inner})` : `[${inner}]`;
188
+ }
189
+ }
190
+ /** A `polygon`: a closed series of points. */
191
+ export class Polygon extends PointList {
192
+ /** As PostgreSQL prints it, so it casts back through `::polygon`. */
193
+ toString() {
194
+ return `(${this.join()})`;
195
+ }
196
+ }
197
+ export { PointList, TwoPoints };