@juit/pgproxy-types 1.0.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 +14 -0
- package/dist/index.cjs +48 -0
- package/dist/index.cjs.map +6 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.mjs +15 -0
- package/dist/index.mjs.map +6 -0
- package/dist/oids.cjs +163 -0
- package/dist/oids.cjs.map +6 -0
- package/dist/oids.d.ts +74 -0
- package/dist/oids.mjs +138 -0
- package/dist/oids.mjs.map +6 -0
- package/dist/parsers/array.cjs +140 -0
- package/dist/parsers/array.cjs.map +6 -0
- package/dist/parsers/array.d.ts +31 -0
- package/dist/parsers/array.mjs +111 -0
- package/dist/parsers/array.mjs.map +6 -0
- package/dist/parsers/basic.cjs +69 -0
- package/dist/parsers/basic.cjs.map +6 -0
- package/dist/parsers/basic.d.ts +15 -0
- package/dist/parsers/basic.mjs +28 -0
- package/dist/parsers/basic.mjs.map +6 -0
- package/dist/parsers/bytea.cjs +68 -0
- package/dist/parsers/bytea.cjs.map +6 -0
- package/dist/parsers/bytea.d.ts +7 -0
- package/dist/parsers/bytea.mjs +43 -0
- package/dist/parsers/bytea.mjs.map +6 -0
- package/dist/parsers/geometric.cjs +86 -0
- package/dist/parsers/geometric.cjs.map +6 -0
- package/dist/parsers/geometric.d.ts +27 -0
- package/dist/parsers/geometric.mjs +58 -0
- package/dist/parsers/geometric.mjs.map +6 -0
- package/dist/parsers/interval.cjs +50 -0
- package/dist/parsers/interval.cjs.map +6 -0
- package/dist/parsers/interval.d.ts +23 -0
- package/dist/parsers/interval.mjs +14 -0
- package/dist/parsers/interval.mjs.map +6 -0
- package/dist/parsers/range.cjs +97 -0
- package/dist/parsers/range.cjs.map +6 -0
- package/dist/parsers/range.d.ts +54 -0
- package/dist/parsers/range.mjs +50 -0
- package/dist/parsers/range.mjs.map +6 -0
- package/dist/parsers.cjs +104 -0
- package/dist/parsers.cjs.map +6 -0
- package/dist/parsers.d.ts +8 -0
- package/dist/parsers.mjs +86 -0
- package/dist/parsers.mjs.map +6 -0
- package/dist/registry.cjs +189 -0
- package/dist/registry.cjs.map +6 -0
- package/dist/registry.d.ts +81 -0
- package/dist/registry.mjs +200 -0
- package/dist/registry.mjs.map +6 -0
- package/dist/serializers/bytea.cjs +52 -0
- package/dist/serializers/bytea.cjs.map +6 -0
- package/dist/serializers/bytea.d.ts +13 -0
- package/dist/serializers/bytea.mjs +27 -0
- package/dist/serializers/bytea.mjs.map +6 -0
- package/dist/serializers/date.cjs +46 -0
- package/dist/serializers/date.cjs.map +6 -0
- package/dist/serializers/date.d.ts +2 -0
- package/dist/serializers/date.mjs +21 -0
- package/dist/serializers/date.mjs.map +6 -0
- package/dist/serializers.cjs +119 -0
- package/dist/serializers.cjs.map +6 -0
- package/dist/serializers.d.ts +20 -0
- package/dist/serializers.mjs +92 -0
- package/dist/serializers.mjs.map +6 -0
- package/package.json +49 -0
- package/src/index.ts +13 -0
- package/src/oids.ts +90 -0
- package/src/parsers/array.ts +176 -0
- package/src/parsers/basic.ts +55 -0
- package/src/parsers/bytea.ts +77 -0
- package/src/parsers/geometric.ts +96 -0
- package/src/parsers/interval.ts +40 -0
- package/src/parsers/range.ts +128 -0
- package/src/parsers.ts +57 -0
- package/src/registry.ts +168 -0
- package/src/serializers/bytea.ts +67 -0
- package/src/serializers/date.ts +63 -0
- package/src/serializers.ts +165 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Pad a number with zeroes to the specified number of digits */
|
|
2
|
+
function pad(number: number, digits: number): string {
|
|
3
|
+
return number.toString().padStart(digits, '0')
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// /* THIS IS UNTESTABLE: We can't set the timezone offset in a JavaScript date,
|
|
7
|
+
// * it's always the _local_ one (which basically means, depends on where the
|
|
8
|
+
// * tester actually _is_)... So until we get some inspiration, let's keep the
|
|
9
|
+
// * code here but don't develop it further... */
|
|
10
|
+
//
|
|
11
|
+
// /** Serialize a {@link Date} as a timestamp preserving its time zone */
|
|
12
|
+
// export function serializeDateWithTimezone(date: Date): string {
|
|
13
|
+
// if (isNaN(date.getTime())) throw new TypeError('Attempted to serialize invalid date')
|
|
14
|
+
//
|
|
15
|
+
// let offset = -date.getTimezoneOffset()
|
|
16
|
+
//
|
|
17
|
+
// let year = date.getFullYear()
|
|
18
|
+
// const isBCYear = year < 1
|
|
19
|
+
// if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation
|
|
20
|
+
//
|
|
21
|
+
// let result =
|
|
22
|
+
// pad(year, 4) + '-' +
|
|
23
|
+
// pad(date.getMonth() + 1, 2) + '-' +
|
|
24
|
+
// pad(date.getDate(), 2) + 'T' +
|
|
25
|
+
// pad(date.getHours(), 2) + ':' +
|
|
26
|
+
// pad(date.getMinutes(), 2) + ':' +
|
|
27
|
+
// pad(date.getSeconds(), 2) + '.' +
|
|
28
|
+
// pad(date.getMilliseconds(), 3)
|
|
29
|
+
//
|
|
30
|
+
// if (offset < 0) {
|
|
31
|
+
// result += '-'
|
|
32
|
+
// offset *= -1
|
|
33
|
+
// } else {
|
|
34
|
+
// result += '+'
|
|
35
|
+
// }
|
|
36
|
+
//
|
|
37
|
+
// result += pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2)
|
|
38
|
+
// if (isBCYear) result += ' BC'
|
|
39
|
+
//
|
|
40
|
+
// return result
|
|
41
|
+
// }
|
|
42
|
+
|
|
43
|
+
/** Serialize a {@link Date} as a timestamp always in the UTC time zone */
|
|
44
|
+
export function serializeDateUTC(date: Date): string {
|
|
45
|
+
if (isNaN(date.getTime())) throw new TypeError('Attempted to serialize invalid date')
|
|
46
|
+
|
|
47
|
+
let year = date.getUTCFullYear()
|
|
48
|
+
const isBCYear = year < 1
|
|
49
|
+
if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation
|
|
50
|
+
|
|
51
|
+
let ret =
|
|
52
|
+
pad(year, 4) + '-' +
|
|
53
|
+
pad(date.getUTCMonth() + 1, 2) + '-' +
|
|
54
|
+
pad(date.getUTCDate(), 2) + 'T' +
|
|
55
|
+
pad(date.getUTCHours(), 2) + ':' +
|
|
56
|
+
pad(date.getUTCMinutes(), 2) + ':' +
|
|
57
|
+
pad(date.getUTCSeconds(), 2) + '.' +
|
|
58
|
+
pad(date.getUTCMilliseconds(), 3)
|
|
59
|
+
|
|
60
|
+
ret += '+00:00'
|
|
61
|
+
if (isBCYear) ret += ' BC'
|
|
62
|
+
return ret
|
|
63
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { serializeByteA } from './serializers/bytea'
|
|
2
|
+
import { serializeDateUTC } from './serializers/date'
|
|
3
|
+
|
|
4
|
+
/** A cache storing serialized versions of objects */
|
|
5
|
+
const serializationCache = new WeakMap<object, string>()
|
|
6
|
+
|
|
7
|
+
/** Quote (escape with "quotes") a string */
|
|
8
|
+
function quote(string: string): string {
|
|
9
|
+
return `"${string.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** Serialize an {@link Array} as a PosgreSQL `ARRAY` */
|
|
13
|
+
function serializeArray(value: any[], stack: WeakSet<object>): string {
|
|
14
|
+
const result = new Array<string>(value.length)
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < value.length; i ++) {
|
|
17
|
+
const member = value[i]
|
|
18
|
+
const type = typeof member
|
|
19
|
+
|
|
20
|
+
/* Nulls (or undefined, we consider them same) are the unquoted "NULL" */
|
|
21
|
+
if ((member === null) || (member === undefined)) {
|
|
22
|
+
result[i] = 'NULL'
|
|
23
|
+
|
|
24
|
+
/* Booleans are simply "t" or "f" */
|
|
25
|
+
} else if (type === 'boolean') {
|
|
26
|
+
result[i] = member ? 't' : 'f'
|
|
27
|
+
|
|
28
|
+
/* Numbers and booleans can be left unquoted */
|
|
29
|
+
} else if ((type === 'bigint') || (type === 'number')) {
|
|
30
|
+
result[i] = `${member}`
|
|
31
|
+
|
|
32
|
+
/* Arrays are a beast on their own: we leave them unquoted, and we can
|
|
33
|
+
* short-circuit on "serializeArray" directly, but in this case we have
|
|
34
|
+
* to manually manage our cache and our stack... */
|
|
35
|
+
} else if (Array.isArray(member)) {
|
|
36
|
+
const cached = serializationCache.get(member)
|
|
37
|
+
if (cached) {
|
|
38
|
+
result[i] = cached
|
|
39
|
+
} else {
|
|
40
|
+
if (stack.has(member)) throw new TypeError('Circularity detected serializing')
|
|
41
|
+
stack.add(member) // we bypass "valueSerializer", so add to the stack
|
|
42
|
+
result[i] = serializeArray(member, stack) // invoke ourselves
|
|
43
|
+
serializationCache.set(member, result[i]!) // cache the result
|
|
44
|
+
stack.delete(member) // then remove the member from the stack
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* BYTEA representations must be quoted as well in arrays, but as we know
|
|
48
|
+
* their representation is always '\x0123456789abcdef', we can avoid the
|
|
49
|
+
* expensive regex in 'quote' and wrap the result manually */
|
|
50
|
+
} else if (ArrayBuffer.isView(member)) {
|
|
51
|
+
result[i] = `"\\${serializeByteA(member)}"`
|
|
52
|
+
|
|
53
|
+
/* Everything else gets serialized *and* properly quoted */
|
|
54
|
+
} else {
|
|
55
|
+
result[i] = quote(serializeValue(member, stack))
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return `{${result.join(',')}}`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Serialize any value into its PostgreSQL string equivalent */
|
|
63
|
+
function serializeValue(value: any, stack: WeakSet<object>): string {
|
|
64
|
+
/* Never "null" */
|
|
65
|
+
if (value === null) throw new TypeError('Can not serialize "null"')
|
|
66
|
+
|
|
67
|
+
/* Basic primitives */
|
|
68
|
+
switch (typeof value) {
|
|
69
|
+
case 'string':
|
|
70
|
+
return value
|
|
71
|
+
|
|
72
|
+
case 'boolean':
|
|
73
|
+
return value ? 't' : 'f'
|
|
74
|
+
|
|
75
|
+
case 'bigint':
|
|
76
|
+
case 'number':
|
|
77
|
+
return value.toString()
|
|
78
|
+
|
|
79
|
+
case 'object':
|
|
80
|
+
break
|
|
81
|
+
|
|
82
|
+
case 'function':
|
|
83
|
+
case 'symbol':
|
|
84
|
+
case 'undefined':
|
|
85
|
+
default:
|
|
86
|
+
throw new TypeError(`Can not serialize "${typeof value}"`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* All primitives, "null" or "undefined" are resolved, value is "object" */
|
|
90
|
+
|
|
91
|
+
/* Check caches */
|
|
92
|
+
const cached = serializationCache.get(value)
|
|
93
|
+
if (cached !== undefined) return cached
|
|
94
|
+
|
|
95
|
+
/* Check for loops */
|
|
96
|
+
if (stack.has(value)) throw new TypeError('Circularity detected serializing')
|
|
97
|
+
stack.add(value)
|
|
98
|
+
|
|
99
|
+
/* Create a sub-serializer to serialize values (it carries our stack) */
|
|
100
|
+
const subserialize = ((v: any) => serializeValue(v, stack)) as PGSerialize
|
|
101
|
+
|
|
102
|
+
/* The string we serialized */
|
|
103
|
+
let string: string
|
|
104
|
+
|
|
105
|
+
/* PGSerializable objects */
|
|
106
|
+
if (isPGSerializable(value)) {
|
|
107
|
+
string = value.toPostgres(subserialize)
|
|
108
|
+
|
|
109
|
+
/* Buffers, Uint8Arrays, and all other ArrayBufferViews */
|
|
110
|
+
} else if (ArrayBuffer.isView(value)) {
|
|
111
|
+
string = serializeByteA(value)
|
|
112
|
+
|
|
113
|
+
/* Arrays */
|
|
114
|
+
} else if (Array.isArray(value)) {
|
|
115
|
+
string = serializeArray(value, stack)
|
|
116
|
+
|
|
117
|
+
/* Dates: for now always UTC, but we have the code for including TZ */
|
|
118
|
+
} else if (value instanceof Date) {
|
|
119
|
+
string = serializeDateUTC(value)
|
|
120
|
+
|
|
121
|
+
/* Any other object gets serialized as JSON */
|
|
122
|
+
} else {
|
|
123
|
+
string = JSON.stringify(value)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Cache the resulting string, pop value out of the stack and return */
|
|
127
|
+
serializationCache.set(value, string)
|
|
128
|
+
stack.delete(value)
|
|
129
|
+
return string
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Type guard identifying {@link PGSerializable} instances */
|
|
133
|
+
function isPGSerializable(value: any): value is PGSerializable {
|
|
134
|
+
return value && (typeof value['toPostgres'] === 'function')
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* ========================================================================== *
|
|
138
|
+
* EXPORTED SERIALIZATION INTERFACE *
|
|
139
|
+
* ========================================================================== */
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Defines an object that can be serialized to a _string_ comprehensible by
|
|
143
|
+
* PostgreSQL.
|
|
144
|
+
*
|
|
145
|
+
* The `serialize` parameter is a serialization function which can be used
|
|
146
|
+
* to serialize _members_ of the {@link PGSerializable} itself (e.g. boundaries
|
|
147
|
+
* of a {@link PGRange}, members of an _array_, ...).
|
|
148
|
+
*/
|
|
149
|
+
export interface PGSerializable {
|
|
150
|
+
toPostgres(serialize: PGSerialize): string
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** An interface describing our {@link serialize} function. */
|
|
154
|
+
export interface PGSerialize {
|
|
155
|
+
(value?: null | undefined): never
|
|
156
|
+
(value: any): string
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Serialize a value to _string_ comprehensible by PostgreSQL. */
|
|
160
|
+
export const serialize: PGSerialize =
|
|
161
|
+
((value: any) => serializeValue(value, new WeakSet())) as PGSerialize
|
|
162
|
+
|
|
163
|
+
/* All other exported serializers */
|
|
164
|
+
export { serializeByteA } from './serializers/bytea'
|
|
165
|
+
export { serializeDateUTC } from './serializers/date'
|