@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.
Files changed (80) hide show
  1. package/README.md +14 -0
  2. package/dist/index.cjs +48 -0
  3. package/dist/index.cjs.map +6 -0
  4. package/dist/index.d.ts +9 -0
  5. package/dist/index.mjs +15 -0
  6. package/dist/index.mjs.map +6 -0
  7. package/dist/oids.cjs +163 -0
  8. package/dist/oids.cjs.map +6 -0
  9. package/dist/oids.d.ts +74 -0
  10. package/dist/oids.mjs +138 -0
  11. package/dist/oids.mjs.map +6 -0
  12. package/dist/parsers/array.cjs +140 -0
  13. package/dist/parsers/array.cjs.map +6 -0
  14. package/dist/parsers/array.d.ts +31 -0
  15. package/dist/parsers/array.mjs +111 -0
  16. package/dist/parsers/array.mjs.map +6 -0
  17. package/dist/parsers/basic.cjs +69 -0
  18. package/dist/parsers/basic.cjs.map +6 -0
  19. package/dist/parsers/basic.d.ts +15 -0
  20. package/dist/parsers/basic.mjs +28 -0
  21. package/dist/parsers/basic.mjs.map +6 -0
  22. package/dist/parsers/bytea.cjs +68 -0
  23. package/dist/parsers/bytea.cjs.map +6 -0
  24. package/dist/parsers/bytea.d.ts +7 -0
  25. package/dist/parsers/bytea.mjs +43 -0
  26. package/dist/parsers/bytea.mjs.map +6 -0
  27. package/dist/parsers/geometric.cjs +86 -0
  28. package/dist/parsers/geometric.cjs.map +6 -0
  29. package/dist/parsers/geometric.d.ts +27 -0
  30. package/dist/parsers/geometric.mjs +58 -0
  31. package/dist/parsers/geometric.mjs.map +6 -0
  32. package/dist/parsers/interval.cjs +50 -0
  33. package/dist/parsers/interval.cjs.map +6 -0
  34. package/dist/parsers/interval.d.ts +23 -0
  35. package/dist/parsers/interval.mjs +14 -0
  36. package/dist/parsers/interval.mjs.map +6 -0
  37. package/dist/parsers/range.cjs +97 -0
  38. package/dist/parsers/range.cjs.map +6 -0
  39. package/dist/parsers/range.d.ts +54 -0
  40. package/dist/parsers/range.mjs +50 -0
  41. package/dist/parsers/range.mjs.map +6 -0
  42. package/dist/parsers.cjs +104 -0
  43. package/dist/parsers.cjs.map +6 -0
  44. package/dist/parsers.d.ts +8 -0
  45. package/dist/parsers.mjs +86 -0
  46. package/dist/parsers.mjs.map +6 -0
  47. package/dist/registry.cjs +189 -0
  48. package/dist/registry.cjs.map +6 -0
  49. package/dist/registry.d.ts +81 -0
  50. package/dist/registry.mjs +200 -0
  51. package/dist/registry.mjs.map +6 -0
  52. package/dist/serializers/bytea.cjs +52 -0
  53. package/dist/serializers/bytea.cjs.map +6 -0
  54. package/dist/serializers/bytea.d.ts +13 -0
  55. package/dist/serializers/bytea.mjs +27 -0
  56. package/dist/serializers/bytea.mjs.map +6 -0
  57. package/dist/serializers/date.cjs +46 -0
  58. package/dist/serializers/date.cjs.map +6 -0
  59. package/dist/serializers/date.d.ts +2 -0
  60. package/dist/serializers/date.mjs +21 -0
  61. package/dist/serializers/date.mjs.map +6 -0
  62. package/dist/serializers.cjs +119 -0
  63. package/dist/serializers.cjs.map +6 -0
  64. package/dist/serializers.d.ts +20 -0
  65. package/dist/serializers.mjs +92 -0
  66. package/dist/serializers.mjs.map +6 -0
  67. package/package.json +49 -0
  68. package/src/index.ts +13 -0
  69. package/src/oids.ts +90 -0
  70. package/src/parsers/array.ts +176 -0
  71. package/src/parsers/basic.ts +55 -0
  72. package/src/parsers/bytea.ts +77 -0
  73. package/src/parsers/geometric.ts +96 -0
  74. package/src/parsers/interval.ts +40 -0
  75. package/src/parsers/range.ts +128 -0
  76. package/src/parsers.ts +57 -0
  77. package/src/registry.ts +168 -0
  78. package/src/serializers/bytea.ts +67 -0
  79. package/src/serializers/date.ts +63 -0
  80. 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'