firebase-tools 13.19.0 → 13.20.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/lib/commands/dataconnect-sdk-generate.js +5 -2
- package/lib/commands/emulators-start.js +3 -0
- package/lib/commands/init.js +20 -16
- package/lib/commands/setup-emulators-dataconnect.js +0 -14
- package/lib/dataconnect/fileUtils.js +16 -4
- package/lib/dataconnect/freeTrial.js +8 -6
- package/lib/dataconnect/provisionCloudSql.js +4 -4
- package/lib/dataconnect/types.js +1 -0
- package/lib/dataconnect/webhook.js +31 -0
- package/lib/deploy/dataconnect/deploy.js +2 -0
- package/lib/deploy/dataconnect/prepare.js +2 -0
- package/lib/deploy/dataconnect/release.js +10 -5
- package/lib/deploy/functions/runtimes/node/index.js +6 -1
- package/lib/emulator/commandUtils.js +6 -1
- package/lib/emulator/constants.js +1 -1
- package/lib/emulator/controller.js +17 -3
- package/lib/emulator/dataconnect/pg-gateway/auth/base-auth-flow.js +11 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/cert.js +69 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/index.js +22 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/md5.js +135 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/password.js +65 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/sasl/sasl-mechanism.js +34 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/sasl/scram-sha-256.js +298 -0
- package/lib/emulator/dataconnect/pg-gateway/auth/trust.js +2 -0
- package/lib/emulator/dataconnect/pg-gateway/backend-error.js +75 -0
- package/lib/emulator/dataconnect/pg-gateway/buffer-reader.js +55 -0
- package/lib/emulator/dataconnect/pg-gateway/buffer-writer.js +79 -0
- package/lib/emulator/dataconnect/pg-gateway/connection.js +419 -0
- package/lib/emulator/dataconnect/pg-gateway/connection.types.js +8 -0
- package/lib/emulator/dataconnect/pg-gateway/crypto.js +40 -0
- package/lib/emulator/dataconnect/pg-gateway/duplex.js +53 -0
- package/lib/emulator/dataconnect/pg-gateway/index.js +27 -0
- package/lib/emulator/dataconnect/pg-gateway/message-buffer.js +96 -0
- package/lib/emulator/dataconnect/pg-gateway/message-codes.js +54 -0
- package/lib/emulator/dataconnect/pg-gateway/platforms/node/index.js +13 -0
- package/lib/emulator/dataconnect/pg-gateway/polyfills/readable-stream-async-iterator.js +36 -0
- package/lib/emulator/dataconnect/pg-gateway/utils.js +40 -0
- package/lib/emulator/dataconnect/pgliteServer.js +134 -0
- package/lib/emulator/dataconnectEmulator.js +55 -73
- package/lib/emulator/dataconnectToolkitController.js +44 -0
- package/lib/emulator/downloadableEmulators.js +22 -11
- package/lib/emulator/hub.js +2 -1
- package/lib/emulator/portUtils.js +9 -11
- package/lib/emulator/storage/rules/runtime.js +1 -1
- package/lib/experiments.js +1 -0
- package/lib/init/features/dataconnect/index.js +148 -111
- package/lib/init/features/dataconnect/sdk.js +40 -27
- package/lib/init/features/emulators.js +2 -14
- package/lib/prompt.js +1 -1
- package/lib/rc.js +1 -9
- package/package.json +3 -1
- package/schema/connector-yaml.json +14 -0
- package/schema/firebase-config.json +6 -0
- package/templates/init/dataconnect/queries.gql +1 -2
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BufferWriter = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
class BufferWriter {
|
|
6
|
+
constructor(size = 256) {
|
|
7
|
+
this.size = size;
|
|
8
|
+
this.offset = 5;
|
|
9
|
+
this.headerPosition = 0;
|
|
10
|
+
this.encoder = new TextEncoder();
|
|
11
|
+
this.buffer = new Uint8Array(size);
|
|
12
|
+
}
|
|
13
|
+
ensure(size) {
|
|
14
|
+
const remaining = this.buffer.length - this.offset;
|
|
15
|
+
if (remaining < size) {
|
|
16
|
+
const oldBuffer = this.buffer;
|
|
17
|
+
const newSize = oldBuffer.length + (oldBuffer.length >> 1) + size;
|
|
18
|
+
this.buffer = new Uint8Array(newSize);
|
|
19
|
+
(0, utils_1.copy)(oldBuffer, this.buffer);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
addInt32(num) {
|
|
23
|
+
this.ensure(4);
|
|
24
|
+
this.buffer[this.offset++] = (num >>> 24) & 0xff;
|
|
25
|
+
this.buffer[this.offset++] = (num >>> 16) & 0xff;
|
|
26
|
+
this.buffer[this.offset++] = (num >>> 8) & 0xff;
|
|
27
|
+
this.buffer[this.offset++] = (num >>> 0) & 0xff;
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
addInt16(num) {
|
|
31
|
+
this.ensure(2);
|
|
32
|
+
this.buffer[this.offset++] = (num >>> 8) & 0xff;
|
|
33
|
+
this.buffer[this.offset++] = (num >>> 0) & 0xff;
|
|
34
|
+
return this;
|
|
35
|
+
}
|
|
36
|
+
addCString(string) {
|
|
37
|
+
if (!string) {
|
|
38
|
+
this.ensure(1);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const stringBuffer = this.encoder.encode(string);
|
|
42
|
+
this.ensure(stringBuffer.byteLength + 1);
|
|
43
|
+
this.buffer.set(stringBuffer, this.offset);
|
|
44
|
+
this.offset += stringBuffer.byteLength;
|
|
45
|
+
}
|
|
46
|
+
this.buffer[this.offset++] = 0;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
addString(string = '') {
|
|
50
|
+
const stringBuffer = this.encoder.encode(string);
|
|
51
|
+
this.ensure(stringBuffer.byteLength);
|
|
52
|
+
this.buffer.set(stringBuffer, this.offset);
|
|
53
|
+
this.offset += stringBuffer.byteLength;
|
|
54
|
+
return this;
|
|
55
|
+
}
|
|
56
|
+
add(otherBuffer) {
|
|
57
|
+
this.ensure(otherBuffer.byteLength);
|
|
58
|
+
(0, utils_1.copy)(otherBuffer, this.buffer, this.offset);
|
|
59
|
+
this.offset += otherBuffer.length;
|
|
60
|
+
return this;
|
|
61
|
+
}
|
|
62
|
+
join(code) {
|
|
63
|
+
if (code) {
|
|
64
|
+
this.buffer[this.headerPosition] = code;
|
|
65
|
+
const length = this.offset - (this.headerPosition + 1);
|
|
66
|
+
const dataView = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
|
|
67
|
+
dataView.setInt32(this.headerPosition + 1, length);
|
|
68
|
+
}
|
|
69
|
+
return this.buffer.slice(code ? 0 : 5, this.offset);
|
|
70
|
+
}
|
|
71
|
+
flush(code) {
|
|
72
|
+
const result = this.join(code);
|
|
73
|
+
this.offset = 5;
|
|
74
|
+
this.headerPosition = 0;
|
|
75
|
+
this.buffer = new Uint8Array(this.size);
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.BufferWriter = BufferWriter;
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
3
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
4
|
+
var m = o[Symbol.asyncIterator], i;
|
|
5
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
6
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
7
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
8
|
+
};
|
|
9
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
10
|
+
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
|
|
11
|
+
var i, p;
|
|
12
|
+
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
|
|
13
|
+
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
|
|
14
|
+
};
|
|
15
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
16
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
17
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
18
|
+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
19
|
+
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
|
20
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
21
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
22
|
+
function fulfill(value) { resume("next", value); }
|
|
23
|
+
function reject(value) { resume("throw", value); }
|
|
24
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
25
|
+
};
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.closeSignal = void 0;
|
|
28
|
+
const index_1 = require("./auth/index");
|
|
29
|
+
const backend_error_1 = require("./backend-error");
|
|
30
|
+
const buffer_reader_1 = require("./buffer-reader");
|
|
31
|
+
const buffer_writer_1 = require("./buffer-writer");
|
|
32
|
+
const connection_types_1 = require("./connection.types");
|
|
33
|
+
const utils_1 = require("./utils");
|
|
34
|
+
const message_buffer_1 = require("./message-buffer");
|
|
35
|
+
const message_codes_1 = require("./message-codes");
|
|
36
|
+
const logger_1 = require("../../../logger");
|
|
37
|
+
exports.closeSignal = Symbol('close');
|
|
38
|
+
class PostgresConnection {
|
|
39
|
+
constructor(duplex, options = {}) {
|
|
40
|
+
this.duplex = duplex;
|
|
41
|
+
this.step = connection_types_1.ServerStep.AwaitingInitialMessage;
|
|
42
|
+
this.hasStarted = false;
|
|
43
|
+
this.isAuthenticated = false;
|
|
44
|
+
this.detached = false;
|
|
45
|
+
this.writer = new buffer_writer_1.BufferWriter();
|
|
46
|
+
this.reader = new buffer_reader_1.BufferReader();
|
|
47
|
+
this.messageBuffer = new message_buffer_1.MessageBuffer();
|
|
48
|
+
this.options = Object.assign({ auth: { method: 'trust' } }, options);
|
|
49
|
+
if (this.options.tls && !this.options.upgradeTls) {
|
|
50
|
+
throw new Error('TLS options are only available when upgradeTls() is implemented. Did you mean to use fromNodeSocket()?');
|
|
51
|
+
}
|
|
52
|
+
this.processData();
|
|
53
|
+
}
|
|
54
|
+
get state() {
|
|
55
|
+
return {
|
|
56
|
+
hasStarted: this.hasStarted,
|
|
57
|
+
isAuthenticated: this.isAuthenticated,
|
|
58
|
+
clientInfo: this.clientInfo,
|
|
59
|
+
tlsInfo: this.tlsInfo,
|
|
60
|
+
step: this.step,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
async detach() {
|
|
64
|
+
this.detached = true;
|
|
65
|
+
return this.duplex;
|
|
66
|
+
}
|
|
67
|
+
async processData() {
|
|
68
|
+
var _a, e_1, _b, _c, _d, e_2, _e, _f, _g, e_3, _h, _j, _k, e_4, _l, _m;
|
|
69
|
+
const writer = this.duplex.writable.getWriter();
|
|
70
|
+
try {
|
|
71
|
+
for (var _o = true, _p = __asyncValues(this.duplex.readable), _q; _q = await _p.next(), _a = _q.done, !_a;) {
|
|
72
|
+
_c = _q.value;
|
|
73
|
+
_o = false;
|
|
74
|
+
try {
|
|
75
|
+
const data = _c;
|
|
76
|
+
this.messageBuffer.mergeBuffer(data);
|
|
77
|
+
try {
|
|
78
|
+
for (var _r = true, _s = (e_2 = void 0, __asyncValues(this.messageBuffer.processMessages(this.hasStarted))), _t; _t = await _s.next(), _d = _t.done, !_d;) {
|
|
79
|
+
_f = _t.value;
|
|
80
|
+
_r = false;
|
|
81
|
+
try {
|
|
82
|
+
const clientMessage = _f;
|
|
83
|
+
logger_1.logger.debug('Frontend message', (0, message_codes_1.getFrontendMessageName)(clientMessage[0]));
|
|
84
|
+
try {
|
|
85
|
+
for (var _u = true, _v = (e_3 = void 0, __asyncValues(this.handleClientMessage(clientMessage))), _w; _w = await _v.next(), _g = _w.done, !_g;) {
|
|
86
|
+
_j = _w.value;
|
|
87
|
+
_u = false;
|
|
88
|
+
try {
|
|
89
|
+
const responseMessage = _j;
|
|
90
|
+
if (responseMessage === exports.closeSignal) {
|
|
91
|
+
await writer.close();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
for (var _x = true, _y = (e_4 = void 0, __asyncValues((0, message_buffer_1.getMessages)(responseMessage))), _z; _z = await _y.next(), _k = _z.done, !_k;) {
|
|
96
|
+
_m = _z.value;
|
|
97
|
+
_x = false;
|
|
98
|
+
try {
|
|
99
|
+
const msg = _m;
|
|
100
|
+
if (msg[0] !== message_codes_1.BackendMessageCode.NoticeMessage) {
|
|
101
|
+
logger_1.logger.debug('Backend message', (0, message_codes_1.getBackendMessageName)(msg[0]));
|
|
102
|
+
if (msg[0] === message_codes_1.BackendMessageCode.ErrorMessage) {
|
|
103
|
+
logger_1.logger.debug(new TextDecoder().decode(msg));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
_x = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
113
|
+
finally {
|
|
114
|
+
try {
|
|
115
|
+
if (!_x && !_k && (_l = _y.return)) await _l.call(_y);
|
|
116
|
+
}
|
|
117
|
+
finally { if (e_4) throw e_4.error; }
|
|
118
|
+
}
|
|
119
|
+
await writer.write(responseMessage);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
_u = true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
127
|
+
finally {
|
|
128
|
+
try {
|
|
129
|
+
if (!_u && !_g && (_h = _v.return)) await _h.call(_v);
|
|
130
|
+
}
|
|
131
|
+
finally { if (e_3) throw e_3.error; }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
_r = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
140
|
+
finally {
|
|
141
|
+
try {
|
|
142
|
+
if (!_r && !_d && (_e = _s.return)) await _e.call(_s);
|
|
143
|
+
}
|
|
144
|
+
finally { if (e_2) throw e_2.error; }
|
|
145
|
+
}
|
|
146
|
+
if (this.detached) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
_o = true;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
156
|
+
finally {
|
|
157
|
+
try {
|
|
158
|
+
if (!_o && !_a && (_b = _p.return)) await _b.call(_p);
|
|
159
|
+
}
|
|
160
|
+
finally { if (e_1) throw e_1.error; }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
handleClientMessage(message) {
|
|
164
|
+
var _a, _b;
|
|
165
|
+
return __asyncGenerator(this, arguments, function* handleClientMessage_1() {
|
|
166
|
+
this.reader.setBuffer(message);
|
|
167
|
+
const messageResponse = yield __await(((_b = (_a = this.options).onMessage) === null || _b === void 0 ? void 0 : _b.call(_a, message, this.state)));
|
|
168
|
+
let skipProcessing = messageResponse !== undefined;
|
|
169
|
+
if (messageResponse) {
|
|
170
|
+
const iterableResponse = new utils_1.AsyncIterableWithMetadata(messageResponse instanceof Uint8Array ? [messageResponse] : messageResponse);
|
|
171
|
+
yield __await(yield* __asyncDelegator(__asyncValues(iterableResponse)));
|
|
172
|
+
if (iterableResponse.returnValue instanceof Uint8Array) {
|
|
173
|
+
yield yield __await(iterableResponse.returnValue);
|
|
174
|
+
}
|
|
175
|
+
skipProcessing =
|
|
176
|
+
iterableResponse.iterations > 0 || iterableResponse.returnValue !== undefined;
|
|
177
|
+
}
|
|
178
|
+
if (this.detached) {
|
|
179
|
+
return yield __await(void 0);
|
|
180
|
+
}
|
|
181
|
+
if (skipProcessing) {
|
|
182
|
+
if (this.isStartupMessage(message)) {
|
|
183
|
+
this.hasStarted = true;
|
|
184
|
+
}
|
|
185
|
+
return yield __await(void 0);
|
|
186
|
+
}
|
|
187
|
+
switch (this.step) {
|
|
188
|
+
case connection_types_1.ServerStep.AwaitingInitialMessage:
|
|
189
|
+
if (this.isSslRequest(message)) {
|
|
190
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.handleSslRequest())));
|
|
191
|
+
}
|
|
192
|
+
else if (this.isStartupMessage(message)) {
|
|
193
|
+
if (this.options.tls && !this.tlsInfo) {
|
|
194
|
+
yield yield __await((0, backend_error_1.createBackendErrorMessage)({
|
|
195
|
+
severity: 'FATAL',
|
|
196
|
+
code: '08P01',
|
|
197
|
+
message: 'SSL connection is required',
|
|
198
|
+
}));
|
|
199
|
+
yield yield __await(exports.closeSignal);
|
|
200
|
+
return yield __await(void 0);
|
|
201
|
+
}
|
|
202
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.handleStartupMessage(message))));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
throw new Error('Unexpected initial message');
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
208
|
+
case connection_types_1.ServerStep.PerformingAuthentication: {
|
|
209
|
+
const authenticationComplete = yield __await(yield* __asyncDelegator(__asyncValues(this.handleAuthenticationMessage(message))));
|
|
210
|
+
if (authenticationComplete) {
|
|
211
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.completeAuthentication())));
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
case connection_types_1.ServerStep.ReadyForQuery:
|
|
216
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.handleRegularMessage(message))));
|
|
217
|
+
break;
|
|
218
|
+
default:
|
|
219
|
+
throw new Error(`Unexpected step: ${this.step}`);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
handleSslRequest() {
|
|
224
|
+
var _a, _b;
|
|
225
|
+
return __asyncGenerator(this, arguments, function* handleSslRequest_1() {
|
|
226
|
+
if (!this.options.tls || !this.options.upgradeTls) {
|
|
227
|
+
this.writer.addString('N');
|
|
228
|
+
yield yield __await(this.writer.flush());
|
|
229
|
+
return yield __await(void 0);
|
|
230
|
+
}
|
|
231
|
+
this.writer.addString('S');
|
|
232
|
+
yield yield __await(this.writer.flush());
|
|
233
|
+
const requestCert = this.options.auth.method === 'cert';
|
|
234
|
+
const { duplex, tlsInfo } = yield __await(this.options.upgradeTls(this.duplex, this.options.tls, this.tlsInfo, requestCert));
|
|
235
|
+
this.duplex = duplex;
|
|
236
|
+
this.tlsInfo = tlsInfo;
|
|
237
|
+
yield __await(((_b = (_a = this.options).onTlsUpgrade) === null || _b === void 0 ? void 0 : _b.call(_a, this.state)));
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
handleStartupMessage(message) {
|
|
241
|
+
var _a, _b;
|
|
242
|
+
return __asyncGenerator(this, arguments, function* handleStartupMessage_1() {
|
|
243
|
+
const { majorVersion, minorVersion, parameters } = this.readStartupMessage();
|
|
244
|
+
if (!parameters.user) {
|
|
245
|
+
yield yield __await((0, backend_error_1.createBackendErrorMessage)({
|
|
246
|
+
severity: 'FATAL',
|
|
247
|
+
code: '08000',
|
|
248
|
+
message: 'user is required',
|
|
249
|
+
}));
|
|
250
|
+
yield yield __await(exports.closeSignal);
|
|
251
|
+
return yield __await(void 0);
|
|
252
|
+
}
|
|
253
|
+
if (majorVersion !== 3 || minorVersion !== 0) {
|
|
254
|
+
yield yield __await((0, backend_error_1.createBackendErrorMessage)({
|
|
255
|
+
severity: 'FATAL',
|
|
256
|
+
code: '08000',
|
|
257
|
+
message: `Unsupported protocol version ${majorVersion.toString()}.${minorVersion.toString()}`,
|
|
258
|
+
}));
|
|
259
|
+
yield yield __await(exports.closeSignal);
|
|
260
|
+
return yield __await(void 0);
|
|
261
|
+
}
|
|
262
|
+
this.clientInfo = {
|
|
263
|
+
majorVersion,
|
|
264
|
+
minorVersion,
|
|
265
|
+
parameters: Object.assign({ user: parameters.user }, parameters),
|
|
266
|
+
};
|
|
267
|
+
this.hasStarted = true;
|
|
268
|
+
yield __await(((_b = (_a = this.options).onStartup) === null || _b === void 0 ? void 0 : _b.call(_a, this.state)));
|
|
269
|
+
if (this.detached) {
|
|
270
|
+
return yield __await(void 0);
|
|
271
|
+
}
|
|
272
|
+
if (this.options.auth.method === 'trust') {
|
|
273
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.completeAuthentication())));
|
|
274
|
+
return yield __await(void 0);
|
|
275
|
+
}
|
|
276
|
+
this.authFlow = (0, index_1.createAuthFlow)({
|
|
277
|
+
reader: this.reader,
|
|
278
|
+
writer: this.writer,
|
|
279
|
+
username: this.clientInfo.parameters.user,
|
|
280
|
+
auth: this.options.auth,
|
|
281
|
+
connectionState: this.state,
|
|
282
|
+
});
|
|
283
|
+
this.step = connection_types_1.ServerStep.PerformingAuthentication;
|
|
284
|
+
const initialAuthMessage = this.authFlow.createInitialAuthMessage();
|
|
285
|
+
if (initialAuthMessage) {
|
|
286
|
+
yield yield __await(initialAuthMessage);
|
|
287
|
+
}
|
|
288
|
+
if (this.options.auth.method === 'cert') {
|
|
289
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.authFlow.handleClientMessage(message))));
|
|
290
|
+
if (this.authFlow.isCompleted) {
|
|
291
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.completeAuthentication())));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
handleAuthenticationMessage(message) {
|
|
297
|
+
return __asyncGenerator(this, arguments, function* handleAuthenticationMessage_1() {
|
|
298
|
+
const code = this.reader.byte();
|
|
299
|
+
if (code !== message_codes_1.FrontendMessageCode.Password) {
|
|
300
|
+
throw new Error(`Unexpected authentication message code: ${code}`);
|
|
301
|
+
}
|
|
302
|
+
if (!this.authFlow) {
|
|
303
|
+
throw new Error('AuthFlow not initialized');
|
|
304
|
+
}
|
|
305
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this.authFlow.handleClientMessage(message))));
|
|
306
|
+
return yield __await(this.authFlow.isCompleted);
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
handleRegularMessage(message) {
|
|
310
|
+
return __asyncGenerator(this, arguments, function* handleRegularMessage_1() {
|
|
311
|
+
const code = this.reader.byte();
|
|
312
|
+
switch (code) {
|
|
313
|
+
case message_codes_1.FrontendMessageCode.Terminate:
|
|
314
|
+
yield yield __await(exports.closeSignal);
|
|
315
|
+
return yield __await(void 0);
|
|
316
|
+
default:
|
|
317
|
+
yield yield __await((0, backend_error_1.createBackendErrorMessage)({
|
|
318
|
+
severity: 'ERROR',
|
|
319
|
+
code: '123',
|
|
320
|
+
message: 'Message code not yet implemented',
|
|
321
|
+
}));
|
|
322
|
+
yield yield __await(this.createReadyForQuery());
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
isSslRequest(message) {
|
|
327
|
+
if (message.byteLength !== 8)
|
|
328
|
+
return false;
|
|
329
|
+
const dataView = new DataView(message.buffer, message.byteOffset, message.byteLength);
|
|
330
|
+
const mostSignificantPart = dataView.getInt16(4);
|
|
331
|
+
const leastSignificantPart = dataView.getInt16(6);
|
|
332
|
+
return mostSignificantPart === 1234 && leastSignificantPart === 5679;
|
|
333
|
+
}
|
|
334
|
+
isStartupMessage(message) {
|
|
335
|
+
if (message.byteLength < 8)
|
|
336
|
+
return false;
|
|
337
|
+
const dataView = new DataView(message.buffer, message.byteOffset, message.byteLength);
|
|
338
|
+
const length = dataView.getInt32(0);
|
|
339
|
+
const majorVersion = dataView.getInt16(4);
|
|
340
|
+
const minorVersion = dataView.getInt16(6);
|
|
341
|
+
return message.byteLength === length && majorVersion === 3 && minorVersion === 0;
|
|
342
|
+
}
|
|
343
|
+
completeAuthentication() {
|
|
344
|
+
var _a, _b;
|
|
345
|
+
return __asyncGenerator(this, arguments, function* completeAuthentication_1() {
|
|
346
|
+
this.isAuthenticated = true;
|
|
347
|
+
yield yield __await(this.createAuthenticationOk());
|
|
348
|
+
yield __await(((_b = (_a = this.options).onAuthenticated) === null || _b === void 0 ? void 0 : _b.call(_a, this.state)));
|
|
349
|
+
if (this.options.serverVersion) {
|
|
350
|
+
let serverVersion;
|
|
351
|
+
if (typeof this.options.serverVersion === 'function') {
|
|
352
|
+
serverVersion = yield __await(this.options.serverVersion(this.state));
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
serverVersion = this.options.serverVersion;
|
|
356
|
+
}
|
|
357
|
+
yield yield __await(this.createParameterStatus('server_version', serverVersion));
|
|
358
|
+
}
|
|
359
|
+
this.step = connection_types_1.ServerStep.ReadyForQuery;
|
|
360
|
+
yield yield __await(this.createReadyForQuery());
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
readStartupMessage() {
|
|
364
|
+
const length = this.reader.int32();
|
|
365
|
+
const majorVersion = this.reader.int16();
|
|
366
|
+
const minorVersion = this.reader.int16();
|
|
367
|
+
const parameters = {};
|
|
368
|
+
for (let key; (key = this.reader.cstring()) !== '';) {
|
|
369
|
+
parameters[key] = this.reader.cstring();
|
|
370
|
+
}
|
|
371
|
+
return {
|
|
372
|
+
majorVersion,
|
|
373
|
+
minorVersion,
|
|
374
|
+
parameters,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
readQuery() {
|
|
378
|
+
const query = this.reader.cstring();
|
|
379
|
+
return {
|
|
380
|
+
query,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
createAuthenticationOk() {
|
|
384
|
+
this.writer.addInt32(0);
|
|
385
|
+
return this.writer.flush(message_codes_1.BackendMessageCode.AuthenticationResponse);
|
|
386
|
+
}
|
|
387
|
+
createParameterStatus(name, value) {
|
|
388
|
+
this.writer.addCString(name);
|
|
389
|
+
this.writer.addCString(value);
|
|
390
|
+
return this.writer.flush(message_codes_1.BackendMessageCode.ParameterStatus);
|
|
391
|
+
}
|
|
392
|
+
createReadyForQuery(transactionStatus = 'idle') {
|
|
393
|
+
switch (transactionStatus) {
|
|
394
|
+
case 'idle':
|
|
395
|
+
this.writer.addString('I');
|
|
396
|
+
break;
|
|
397
|
+
case 'transaction':
|
|
398
|
+
this.writer.addString('T');
|
|
399
|
+
break;
|
|
400
|
+
case 'error':
|
|
401
|
+
this.writer.addString('E');
|
|
402
|
+
break;
|
|
403
|
+
default:
|
|
404
|
+
throw new Error(`Unknown transaction status '${transactionStatus}'`);
|
|
405
|
+
}
|
|
406
|
+
return this.writer.flush(message_codes_1.BackendMessageCode.ReadyForQuery);
|
|
407
|
+
}
|
|
408
|
+
createAuthenticationFailedError() {
|
|
409
|
+
var _a;
|
|
410
|
+
return (0, backend_error_1.createBackendErrorMessage)({
|
|
411
|
+
severity: 'FATAL',
|
|
412
|
+
code: '28P01',
|
|
413
|
+
message: ((_a = this.clientInfo) === null || _a === void 0 ? void 0 : _a.parameters.user)
|
|
414
|
+
? `password authentication failed for user "${this.clientInfo.parameters.user}"`
|
|
415
|
+
: 'password authentication failed',
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
exports.default = PostgresConnection;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServerStep = void 0;
|
|
4
|
+
exports.ServerStep = {
|
|
5
|
+
AwaitingInitialMessage: 'AwaitingInitialMessage',
|
|
6
|
+
PerformingAuthentication: 'PerformingAuthentication',
|
|
7
|
+
ReadyForQuery: 'ReadyForQuery',
|
|
8
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.timingSafeEqual = exports.createHashKey = exports.createHmacKey = exports.pbkdf2 = void 0;
|
|
4
|
+
async function pbkdf2(password, salt, iterations, length, hashAlgorithm) {
|
|
5
|
+
const encoder = new TextEncoder();
|
|
6
|
+
const keyMaterial = await crypto.subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, ['deriveBits']);
|
|
7
|
+
const derivedBits = await crypto.subtle.deriveBits({
|
|
8
|
+
name: 'PBKDF2',
|
|
9
|
+
salt,
|
|
10
|
+
iterations: iterations,
|
|
11
|
+
hash: hashAlgorithm,
|
|
12
|
+
}, keyMaterial, length * 8);
|
|
13
|
+
return derivedBits;
|
|
14
|
+
}
|
|
15
|
+
exports.pbkdf2 = pbkdf2;
|
|
16
|
+
async function createHmacKey(key, message, algorithm) {
|
|
17
|
+
const encoder = new TextEncoder();
|
|
18
|
+
const keyMaterial = await crypto.subtle.importKey('raw', key, {
|
|
19
|
+
name: 'HMAC',
|
|
20
|
+
hash: { name: algorithm },
|
|
21
|
+
}, false, ['sign']);
|
|
22
|
+
const hmacKey = await crypto.subtle.sign('HMAC', keyMaterial, encoder.encode(message));
|
|
23
|
+
return hmacKey;
|
|
24
|
+
}
|
|
25
|
+
exports.createHmacKey = createHmacKey;
|
|
26
|
+
async function createHashKey(key, algorithm) {
|
|
27
|
+
const hashKey = await crypto.subtle.digest({
|
|
28
|
+
name: algorithm,
|
|
29
|
+
}, key);
|
|
30
|
+
return hashKey;
|
|
31
|
+
}
|
|
32
|
+
exports.createHashKey = createHashKey;
|
|
33
|
+
async function timingSafeEqual(bufferA, bufferB) {
|
|
34
|
+
const algorithm = { name: 'HMAC', hash: 'SHA-256' };
|
|
35
|
+
const key = (await crypto.subtle.generateKey(algorithm, false, ['sign', 'verify']));
|
|
36
|
+
const hmac = await crypto.subtle.sign(algorithm, key, bufferA);
|
|
37
|
+
const equal = await crypto.subtle.verify(algorithm, key, hmac, bufferB);
|
|
38
|
+
return equal;
|
|
39
|
+
}
|
|
40
|
+
exports.timingSafeEqual = timingSafeEqual;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createVirtualServer = exports.createDuplexPair = exports.BufferedStream = void 0;
|
|
4
|
+
const web_1 = require("node:stream/web");
|
|
5
|
+
class BufferedStream {
|
|
6
|
+
constructor() {
|
|
7
|
+
const buffer = [];
|
|
8
|
+
this.readable = new web_1.ReadableStream({
|
|
9
|
+
async pull(controller) {
|
|
10
|
+
while (buffer.length === 0) {
|
|
11
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
12
|
+
}
|
|
13
|
+
const chunk = buffer.shift();
|
|
14
|
+
controller.enqueue(chunk);
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
this.writable = new WritableStream({
|
|
18
|
+
async write(chunk) {
|
|
19
|
+
buffer.push(chunk);
|
|
20
|
+
await new Promise((resolve) => setTimeout(resolve));
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.BufferedStream = BufferedStream;
|
|
26
|
+
function createDuplexPair() {
|
|
27
|
+
const aToB = new BufferedStream();
|
|
28
|
+
const bToA = new BufferedStream();
|
|
29
|
+
const duplexA = {
|
|
30
|
+
readable: bToA.readable,
|
|
31
|
+
writable: aToB.writable,
|
|
32
|
+
};
|
|
33
|
+
const duplexB = {
|
|
34
|
+
readable: aToB.readable,
|
|
35
|
+
writable: bToA.writable,
|
|
36
|
+
};
|
|
37
|
+
return [duplexA, duplexB];
|
|
38
|
+
}
|
|
39
|
+
exports.createDuplexPair = createDuplexPair;
|
|
40
|
+
function createVirtualServer() {
|
|
41
|
+
const listener = new BufferedStream();
|
|
42
|
+
const connWriter = listener.writable.getWriter();
|
|
43
|
+
function listen() {
|
|
44
|
+
return listener.readable;
|
|
45
|
+
}
|
|
46
|
+
async function connect() {
|
|
47
|
+
const [clientConn, serverConn] = createDuplexPair();
|
|
48
|
+
await connWriter.write(serverConn);
|
|
49
|
+
return clientConn;
|
|
50
|
+
}
|
|
51
|
+
return { listen, connect };
|
|
52
|
+
}
|
|
53
|
+
exports.createVirtualServer = createVirtualServer;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.PostgresConnection = void 0;
|
|
18
|
+
require("./polyfills/readable-stream-async-iterator");
|
|
19
|
+
var connection_1 = require("./connection");
|
|
20
|
+
Object.defineProperty(exports, "PostgresConnection", { enumerable: true, get: function () { return connection_1.default; } });
|
|
21
|
+
__exportStar(require("./connection"), exports);
|
|
22
|
+
__exportStar(require("./auth/sasl/scram-sha-256"), exports);
|
|
23
|
+
__exportStar(require("./auth/md5"), exports);
|
|
24
|
+
__exportStar(require("./backend-error"), exports);
|
|
25
|
+
__exportStar(require("./duplex"), exports);
|
|
26
|
+
__exportStar(require("./message-codes"), exports);
|
|
27
|
+
__exportStar(require("./message-buffer"), exports);
|