firebase-tools 13.19.0 → 13.20.1
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/apiv2.js +8 -1
- package/lib/auth.js +14 -2
- 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/dataplaneClient.js +12 -9
- 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,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);
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
3
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
4
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
5
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
6
|
+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
7
|
+
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); }); }; }
|
|
8
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
9
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
10
|
+
function fulfill(value) { resume("next", value); }
|
|
11
|
+
function reject(value) { resume("throw", value); }
|
|
12
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.getMessages = exports.MessageBuffer = void 0;
|
|
16
|
+
const utils_1 = require("./utils");
|
|
17
|
+
class MessageBuffer {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.buffer = new Uint8Array();
|
|
20
|
+
this.bufferLength = 0;
|
|
21
|
+
this.bufferOffset = 0;
|
|
22
|
+
}
|
|
23
|
+
mergeBuffer(newData) {
|
|
24
|
+
if (this.bufferLength > 0) {
|
|
25
|
+
const newLength = this.bufferLength + newData.byteLength;
|
|
26
|
+
const newFullLength = newLength + this.bufferOffset;
|
|
27
|
+
if (newFullLength > this.buffer.byteLength) {
|
|
28
|
+
let newBuffer;
|
|
29
|
+
if (newLength <= this.buffer.byteLength && this.bufferOffset >= this.bufferLength) {
|
|
30
|
+
newBuffer = this.buffer;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
let newBufferLength = this.buffer.byteLength * 2;
|
|
34
|
+
while (newLength >= newBufferLength) {
|
|
35
|
+
newBufferLength *= 2;
|
|
36
|
+
}
|
|
37
|
+
newBuffer = new Uint8Array(newBufferLength);
|
|
38
|
+
}
|
|
39
|
+
const bufferView = this.buffer.subarray(this.bufferOffset, this.bufferOffset + this.bufferLength);
|
|
40
|
+
(0, utils_1.copy)(bufferView, newBuffer, 0);
|
|
41
|
+
this.buffer = newBuffer;
|
|
42
|
+
this.bufferOffset = 0;
|
|
43
|
+
}
|
|
44
|
+
(0, utils_1.copy)(newData, this.buffer, this.bufferOffset + this.bufferLength);
|
|
45
|
+
this.bufferLength = newLength;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
this.buffer = newData;
|
|
49
|
+
this.bufferOffset = 0;
|
|
50
|
+
this.bufferLength = newData.byteLength;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
processMessages(hasStarted) {
|
|
54
|
+
return __asyncGenerator(this, arguments, function* processMessages_1() {
|
|
55
|
+
const bufferFullLength = this.bufferOffset + this.bufferLength;
|
|
56
|
+
let offset = this.bufferOffset;
|
|
57
|
+
const codeLength = !hasStarted ? 0 : 1;
|
|
58
|
+
const headerLength = 4 + codeLength;
|
|
59
|
+
while (offset + headerLength <= bufferFullLength) {
|
|
60
|
+
const dataView = new DataView(this.buffer.buffer);
|
|
61
|
+
const length = dataView.getUint32(offset + codeLength);
|
|
62
|
+
const fullMessageLength = codeLength + length;
|
|
63
|
+
if (offset + fullMessageLength <= bufferFullLength) {
|
|
64
|
+
yield yield __await(this.buffer.subarray(offset, offset + fullMessageLength));
|
|
65
|
+
offset += fullMessageLength;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (offset === bufferFullLength) {
|
|
72
|
+
this.buffer = new Uint8Array();
|
|
73
|
+
this.bufferLength = 0;
|
|
74
|
+
this.bufferOffset = 0;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
this.bufferLength = bufferFullLength - offset;
|
|
78
|
+
this.bufferOffset = offset;
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.MessageBuffer = MessageBuffer;
|
|
84
|
+
function* getMessages(data) {
|
|
85
|
+
const dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
86
|
+
let offset = 0;
|
|
87
|
+
if (dataView.byteLength === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
while (offset < dataView.byteLength) {
|
|
91
|
+
const length = dataView.getUint32(offset + 1);
|
|
92
|
+
yield data.subarray(offset, offset + length + 1);
|
|
93
|
+
offset += length + 1;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.getMessages = getMessages;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getBackendMessageName = exports.getFrontendMessageName = exports.BackendMessageCode = exports.FrontendMessageCode = void 0;
|
|
4
|
+
exports.FrontendMessageCode = {
|
|
5
|
+
Query: 0x51,
|
|
6
|
+
Parse: 0x50,
|
|
7
|
+
Bind: 0x42,
|
|
8
|
+
Execute: 0x45,
|
|
9
|
+
FunctionCall: 0x46,
|
|
10
|
+
Flush: 0x48,
|
|
11
|
+
Close: 0x43,
|
|
12
|
+
Describe: 0x44,
|
|
13
|
+
CopyFromChunk: 0x64,
|
|
14
|
+
CopyDone: 0x63,
|
|
15
|
+
CopyData: 0x64,
|
|
16
|
+
CopyFail: 0x66,
|
|
17
|
+
Password: 0x70,
|
|
18
|
+
Sync: 0x53,
|
|
19
|
+
Terminate: 0x58,
|
|
20
|
+
};
|
|
21
|
+
exports.BackendMessageCode = {
|
|
22
|
+
DataRow: 0x44,
|
|
23
|
+
ParseComplete: 0x31,
|
|
24
|
+
BindComplete: 0x32,
|
|
25
|
+
CloseComplete: 0x33,
|
|
26
|
+
CommandComplete: 0x43,
|
|
27
|
+
ReadyForQuery: 0x5a,
|
|
28
|
+
NoData: 0x6e,
|
|
29
|
+
NotificationResponse: 0x41,
|
|
30
|
+
AuthenticationResponse: 0x52,
|
|
31
|
+
ParameterStatus: 0x53,
|
|
32
|
+
BackendKeyData: 0x4b,
|
|
33
|
+
ErrorMessage: 0x45,
|
|
34
|
+
NoticeMessage: 0x4e,
|
|
35
|
+
RowDescriptionMessage: 0x54,
|
|
36
|
+
ParameterDescriptionMessage: 0x74,
|
|
37
|
+
PortalSuspended: 0x73,
|
|
38
|
+
ReplicationStart: 0x57,
|
|
39
|
+
EmptyQuery: 0x49,
|
|
40
|
+
CopyIn: 0x47,
|
|
41
|
+
CopyOut: 0x48,
|
|
42
|
+
CopyDone: 0x63,
|
|
43
|
+
CopyData: 0x64,
|
|
44
|
+
};
|
|
45
|
+
function getFrontendMessageName(code) {
|
|
46
|
+
var _a;
|
|
47
|
+
return (_a = Object.entries(exports.FrontendMessageCode).find(([_, value]) => value === code)) === null || _a === void 0 ? void 0 : _a[0];
|
|
48
|
+
}
|
|
49
|
+
exports.getFrontendMessageName = getFrontendMessageName;
|
|
50
|
+
function getBackendMessageName(code) {
|
|
51
|
+
var _a;
|
|
52
|
+
return (_a = Object.entries(exports.BackendMessageCode).find(([_, value]) => value === code)) === null || _a === void 0 ? void 0 : _a[0];
|
|
53
|
+
}
|
|
54
|
+
exports.getBackendMessageName = getBackendMessageName;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fromNodeSocket = void 0;
|
|
4
|
+
const node_stream_1 = require("node:stream");
|
|
5
|
+
const connection_1 = require("../../connection");
|
|
6
|
+
async function fromNodeSocket(socket, options) {
|
|
7
|
+
const rs = node_stream_1.Readable.toWeb(socket);
|
|
8
|
+
const ws = node_stream_1.Writable.toWeb(socket);
|
|
9
|
+
const opts = options
|
|
10
|
+
? Object.assign({}, options) : undefined;
|
|
11
|
+
return new connection_1.default({ readable: rs, writable: ws }, opts);
|
|
12
|
+
}
|
|
13
|
+
exports.fromNodeSocket = fromNodeSocket;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b;
|
|
3
|
+
var _c;
|
|
4
|
+
(_a = (_c = ReadableStream.prototype).values) !== null && _a !== void 0 ? _a : (_c.values = function ({ preventCancel = false } = {}) {
|
|
5
|
+
const reader = this.getReader();
|
|
6
|
+
return {
|
|
7
|
+
async next() {
|
|
8
|
+
try {
|
|
9
|
+
const result = await reader.read();
|
|
10
|
+
if (result.done) {
|
|
11
|
+
reader.releaseLock();
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
reader.releaseLock();
|
|
17
|
+
throw e;
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
async return(value) {
|
|
21
|
+
if (!preventCancel) {
|
|
22
|
+
const cancelPromise = reader.cancel(value);
|
|
23
|
+
reader.releaseLock();
|
|
24
|
+
await cancelPromise;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
reader.releaseLock();
|
|
28
|
+
}
|
|
29
|
+
return { done: true, value };
|
|
30
|
+
},
|
|
31
|
+
[Symbol.asyncIterator]() {
|
|
32
|
+
return this;
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
|
+
(_b = ReadableStream.prototype) !== null && _b !== void 0 ? _b : (ReadableStream.prototype = ReadableStream.prototype.values);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copy = exports.AsyncIterableWithMetadata = void 0;
|
|
4
|
+
class AsyncIterableWithMetadata {
|
|
5
|
+
constructor(iterable) {
|
|
6
|
+
this.iterable = iterable;
|
|
7
|
+
this.returnValue = undefined;
|
|
8
|
+
this.iterations = 0;
|
|
9
|
+
}
|
|
10
|
+
[Symbol.asyncIterator]() {
|
|
11
|
+
const asyncIterator = Symbol.asyncIterator in this.iterable
|
|
12
|
+
? this.iterable[Symbol.asyncIterator]()
|
|
13
|
+
: this.iterable[Symbol.iterator]();
|
|
14
|
+
this.returnValue = undefined;
|
|
15
|
+
this.iterations = 0;
|
|
16
|
+
return {
|
|
17
|
+
next: async () => {
|
|
18
|
+
const result = await asyncIterator.next();
|
|
19
|
+
if (result.done) {
|
|
20
|
+
this.returnValue = result.value;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
this.iterations++;
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.AsyncIterableWithMetadata = AsyncIterableWithMetadata;
|
|
31
|
+
function copy(src, dst, offset = 0) {
|
|
32
|
+
offset = Math.max(0, Math.min(offset, dst.byteLength));
|
|
33
|
+
const dstBytesAvailable = dst.byteLength - offset;
|
|
34
|
+
if (src.byteLength > dstBytesAvailable) {
|
|
35
|
+
src = src.subarray(0, dstBytesAvailable);
|
|
36
|
+
}
|
|
37
|
+
dst.set(src, offset);
|
|
38
|
+
return src.byteLength;
|
|
39
|
+
}
|
|
40
|
+
exports.copy = copy;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
|
|
3
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
4
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
5
|
+
var m = o[Symbol.asyncIterator], i;
|
|
6
|
+
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);
|
|
7
|
+
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); }); }; }
|
|
8
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
9
|
+
};
|
|
10
|
+
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
11
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
12
|
+
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
13
|
+
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
|
14
|
+
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); }); }; }
|
|
15
|
+
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
|
|
16
|
+
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
|
17
|
+
function fulfill(value) { resume("next", value); }
|
|
18
|
+
function reject(value) { resume("throw", value); }
|
|
19
|
+
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.PGliteExtendedQueryPatch = exports.PostgresServer = void 0;
|
|
23
|
+
const pglite_1 = require("@electric-sql/pglite");
|
|
24
|
+
const { dynamicImport } = require(true && "../../dynamicImport");
|
|
25
|
+
const net = require("node:net");
|
|
26
|
+
const index_1 = require("./pg-gateway/index");
|
|
27
|
+
const node_1 = require("./pg-gateway/platforms/node");
|
|
28
|
+
const logger_1 = require("../../logger");
|
|
29
|
+
class PostgresServer {
|
|
30
|
+
async createPGServer(host = "127.0.0.1", port) {
|
|
31
|
+
const db = await this.getDb();
|
|
32
|
+
await db.waitReady;
|
|
33
|
+
const server = net.createServer(async (socket) => {
|
|
34
|
+
const connection = await (0, node_1.fromNodeSocket)(socket, {
|
|
35
|
+
serverVersion: "16.3 (PGlite 0.2.0)",
|
|
36
|
+
auth: { method: "trust" },
|
|
37
|
+
async onMessage(data, { isAuthenticated }) {
|
|
38
|
+
if (!isAuthenticated) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const result = await db.execProtocolRaw(data);
|
|
42
|
+
return extendedQueryPatch.filterResponse(data, result);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
const extendedQueryPatch = new PGliteExtendedQueryPatch(connection);
|
|
46
|
+
socket.on("end", () => {
|
|
47
|
+
logger_1.logger.debug("Postgres client disconnected");
|
|
48
|
+
});
|
|
49
|
+
socket.on("error", (err) => {
|
|
50
|
+
server.emit("error", err);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
const listeningPromise = new Promise((resolve) => {
|
|
54
|
+
server.listen(port, host, () => {
|
|
55
|
+
resolve();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
await db.waitReady;
|
|
59
|
+
await listeningPromise;
|
|
60
|
+
return server;
|
|
61
|
+
}
|
|
62
|
+
async getDb() {
|
|
63
|
+
if (this.db) {
|
|
64
|
+
return this.db;
|
|
65
|
+
}
|
|
66
|
+
const vector = (await dynamicImport("@electric-sql/pglite/vector")).vector;
|
|
67
|
+
const uuidOssp = (await dynamicImport("@electric-sql/pglite/contrib/uuid_ossp")).uuid_ossp;
|
|
68
|
+
return pglite_1.PGlite.create({
|
|
69
|
+
username: this.username,
|
|
70
|
+
database: this.database,
|
|
71
|
+
debug: 0,
|
|
72
|
+
extensions: {
|
|
73
|
+
vector,
|
|
74
|
+
uuidOssp,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
constructor(database, username) {
|
|
79
|
+
this.username = username;
|
|
80
|
+
this.database = database;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
exports.PostgresServer = PostgresServer;
|
|
84
|
+
class PGliteExtendedQueryPatch {
|
|
85
|
+
constructor(connection) {
|
|
86
|
+
this.connection = connection;
|
|
87
|
+
this.isExtendedQuery = false;
|
|
88
|
+
}
|
|
89
|
+
filterResponse(message, response) {
|
|
90
|
+
return __asyncGenerator(this, arguments, function* filterResponse_1() {
|
|
91
|
+
var _a, e_1, _b, _c;
|
|
92
|
+
const pipelineStartMessages = [
|
|
93
|
+
index_1.FrontendMessageCode.Parse,
|
|
94
|
+
index_1.FrontendMessageCode.Bind,
|
|
95
|
+
index_1.FrontendMessageCode.Close,
|
|
96
|
+
];
|
|
97
|
+
if (pipelineStartMessages.includes(message[0])) {
|
|
98
|
+
this.isExtendedQuery = true;
|
|
99
|
+
}
|
|
100
|
+
if (message[0] === index_1.FrontendMessageCode.Sync) {
|
|
101
|
+
this.isExtendedQuery = false;
|
|
102
|
+
return yield __await(this.connection.createReadyForQuery());
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
for (var _d = true, _e = __asyncValues((0, index_1.getMessages)(response)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a;) {
|
|
106
|
+
_c = _f.value;
|
|
107
|
+
_d = false;
|
|
108
|
+
try {
|
|
109
|
+
const message = _c;
|
|
110
|
+
if (message[0] === index_1.BackendMessageCode.ErrorMessage) {
|
|
111
|
+
this.isExtendedQuery = false;
|
|
112
|
+
}
|
|
113
|
+
if (this.isExtendedQuery && message[0] === index_1.BackendMessageCode.ReadyForQuery) {
|
|
114
|
+
logger_1.logger.debug("Filtered out a ReadyForQuery.");
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
yield yield __await(message);
|
|
118
|
+
}
|
|
119
|
+
finally {
|
|
120
|
+
_d = true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
125
|
+
finally {
|
|
126
|
+
try {
|
|
127
|
+
if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
|
|
128
|
+
}
|
|
129
|
+
finally { if (e_1) throw e_1.error; }
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.PGliteExtendedQueryPatch = PGliteExtendedQueryPatch;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DataConnectEmulatorClient = exports.DataConnectEmulator = exports.dataConnectEmulatorEvents = void 0;
|
|
4
4
|
const childProcess = require("child_process");
|
|
5
|
-
const
|
|
5
|
+
const events_1 = require("events");
|
|
6
6
|
const api_1 = require("../api");
|
|
7
7
|
const constants_1 = require("./constants");
|
|
8
8
|
const downloadableEmulators_1 = require("./downloadableEmulators");
|
|
@@ -11,12 +11,12 @@ const error_1 = require("../error");
|
|
|
11
11
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
12
12
|
const types_2 = require("../dataconnect/types");
|
|
13
13
|
const portUtils_1 = require("./portUtils");
|
|
14
|
-
const apiv2_1 = require("../apiv2");
|
|
15
14
|
const registry_1 = require("./registry");
|
|
16
15
|
const logger_1 = require("../logger");
|
|
17
16
|
const load_1 = require("../dataconnect/load");
|
|
17
|
+
const pgliteServer_1 = require("./dataconnect/pgliteServer");
|
|
18
|
+
const controller_1 = require("./controller");
|
|
18
19
|
const utils_1 = require("../utils");
|
|
19
|
-
const events_1 = require("events");
|
|
20
20
|
exports.dataConnectEmulatorEvents = new events_1.EventEmitter();
|
|
21
21
|
class DataConnectEmulator {
|
|
22
22
|
constructor(args) {
|
|
@@ -26,6 +26,7 @@ class DataConnectEmulator {
|
|
|
26
26
|
this.emulatorClient = new DataConnectEmulatorClient();
|
|
27
27
|
}
|
|
28
28
|
async start() {
|
|
29
|
+
var _a, _b, _c, _d;
|
|
29
30
|
let resolvedConfigDir;
|
|
30
31
|
try {
|
|
31
32
|
resolvedConfigDir = this.args.config.path(this.args.configDir);
|
|
@@ -42,24 +43,41 @@ class DataConnectEmulator {
|
|
|
42
43
|
catch (err) {
|
|
43
44
|
this.logger.log("DEBUG", `'fdc build' failed with error: ${err.message}`);
|
|
44
45
|
}
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
46
|
+
const info = await (0, load_1.load)(this.args.projectId, this.args.config, this.args.configDir);
|
|
47
|
+
const dbId = ((_a = info.dataConnectYaml.schema.datasource.postgresql) === null || _a === void 0 ? void 0 : _a.database) || "postgres";
|
|
48
|
+
const serviceId = info.dataConnectYaml.serviceId;
|
|
49
|
+
await (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, {
|
|
50
|
+
auto_download: this.args.auto_download,
|
|
51
|
+
listen: (0, portUtils_1.listenSpecsToString)(this.args.listen),
|
|
52
|
+
config_dir: resolvedConfigDir,
|
|
53
|
+
enable_output_schema_extensions: this.args.enable_output_schema_extensions,
|
|
54
|
+
enable_output_generated_sdk: this.args.enable_output_generated_sdk,
|
|
55
|
+
});
|
|
56
|
+
this.usingExistingEmulator = false;
|
|
57
|
+
if (this.args.autoconnectToPostgres) {
|
|
58
|
+
const pgPort = (_b = this.args.postgresListen) === null || _b === void 0 ? void 0 : _b[0].port;
|
|
59
|
+
const pgHost = (_c = this.args.postgresListen) === null || _c === void 0 ? void 0 : _c[0].address;
|
|
60
|
+
let connStr = (0, api_1.dataConnectLocalConnString)();
|
|
61
|
+
if ((0, api_1.dataConnectLocalConnString)()) {
|
|
62
|
+
this.logger.logLabeled("INFO", "Data Connect", `FIREBASE_DATACONNECT_POSTGRESQL_STRING is set to ${(0, api_1.dataConnectLocalConnString)()} - using that instead of starting a new database`);
|
|
63
|
+
}
|
|
64
|
+
else if (pgHost && pgPort) {
|
|
65
|
+
const pgServer = new pgliteServer_1.PostgresServer(dbId, "postgres");
|
|
66
|
+
const server = await pgServer.createPGServer(pgHost, pgPort);
|
|
67
|
+
const connectableHost = (0, utils_1.connectableHostname)(pgHost);
|
|
68
|
+
connStr = `postgres://${connectableHost}:${pgPort}/${dbId}?sslmode=disable`;
|
|
69
|
+
server.on("error", (err) => {
|
|
70
|
+
if (err instanceof error_1.FirebaseError) {
|
|
71
|
+
this.logger.logLabeled("ERROR", "Data Connect", `${err}`);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
this.logger.logLabeled("ERROR", "Data Connect", `Postgres threw an unexpected error, shutting down the Data Connect emulator: ${err}`);
|
|
75
|
+
}
|
|
76
|
+
void (0, controller_1.cleanShutdown)();
|
|
77
|
+
});
|
|
78
|
+
this.logger.logLabeled("INFO", "Data Connect", `Started up Postgres server, listening on ${(_d = server.address()) === null || _d === void 0 ? void 0 : _d.toString()}`);
|
|
79
|
+
}
|
|
80
|
+
await this.connectToPostgres(new URL(connStr), dbId, serviceId);
|
|
63
81
|
}
|
|
64
82
|
return;
|
|
65
83
|
}
|
|
@@ -100,6 +118,9 @@ class DataConnectEmulator {
|
|
|
100
118
|
`--config_dir=${args.configDir}`,
|
|
101
119
|
`--connector_id=${args.connectorId}`,
|
|
102
120
|
];
|
|
121
|
+
if (args.watch) {
|
|
122
|
+
cmd.push("--watch");
|
|
123
|
+
}
|
|
103
124
|
const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
|
|
104
125
|
logger_1.logger.info(res.stderr);
|
|
105
126
|
if (res.error) {
|
|
@@ -135,54 +156,23 @@ class DataConnectEmulator {
|
|
|
135
156
|
throw new error_1.FirebaseError(`Unable to parse 'fdc build' output: ${(_a = res.stdout) !== null && _a !== void 0 ? _a : res.stderr}`);
|
|
136
157
|
}
|
|
137
158
|
}
|
|
138
|
-
|
|
139
|
-
var _a, _b;
|
|
140
|
-
if ((0, api_1.dataConnectLocalConnString)()) {
|
|
141
|
-
return (0, api_1.dataConnectLocalConnString)();
|
|
142
|
-
}
|
|
143
|
-
return (_b = (_a = this.args.rc.getDataconnect()) === null || _a === void 0 ? void 0 : _a.postgres) === null || _b === void 0 ? void 0 : _b.localConnectionString;
|
|
144
|
-
}
|
|
145
|
-
async discoverRunningInstance() {
|
|
146
|
-
const emuInfo = await this.emulatorClient.getInfo();
|
|
147
|
-
if (!emuInfo) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
const serviceInfo = await (0, load_1.load)(this.args.projectId, this.args.config, this.args.configDir);
|
|
151
|
-
const sameService = emuInfo.services.find((s) => serviceInfo.dataConnectYaml.serviceId === s.serviceId);
|
|
152
|
-
if (!sameService) {
|
|
153
|
-
throw new error_1.FirebaseError(`There is a Data Connect emulator already running on ${this.args.listen[0].address}:${this.args.listen[0].port}, but it is emulating a different service. Please stop that instance of the Data Connect emulator, or specify a different port in 'firebase.json'`);
|
|
154
|
-
}
|
|
155
|
-
if (sameService.connectionString &&
|
|
156
|
-
sameService.connectionString !== this.getLocalConectionString()) {
|
|
157
|
-
throw new error_1.FirebaseError(`There is a Data Connect emulator already running, but it is using a different Postgres connection string. Please stop that instance of the Data Connect emulator, or specify a different port in 'firebase.json'`);
|
|
158
|
-
}
|
|
159
|
-
return true;
|
|
160
|
-
}
|
|
161
|
-
watchUnmanagedInstance() {
|
|
162
|
-
return setInterval(async () => {
|
|
163
|
-
if (!this.usingExistingEmulator) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const emuInfo = await this.emulatorClient.getInfo();
|
|
167
|
-
if (!emuInfo) {
|
|
168
|
-
this.logger.logLabeled("INFO", "Data Connect", "The already running emulator seems to have shut down. Starting a new instance of the Data Connect emulator...");
|
|
169
|
-
await this.start();
|
|
170
|
-
exports.dataConnectEmulatorEvents.emit("restart");
|
|
171
|
-
}
|
|
172
|
-
}, 5000);
|
|
173
|
-
}
|
|
174
|
-
async connectToPostgres(localConnectionString, database, serviceId) {
|
|
175
|
-
const connectionString = localConnectionString !== null && localConnectionString !== void 0 ? localConnectionString : this.getLocalConectionString();
|
|
159
|
+
async connectToPostgres(connectionString, database, serviceId) {
|
|
176
160
|
if (!connectionString) {
|
|
177
|
-
const msg = `No Postgres connection
|
|
178
|
-
Run ${clc.bold("firebase setup:emulators:dataconnect")} to set up a Postgres connection.`;
|
|
161
|
+
const msg = `No Postgres connection found. The Data Connect emulator will not be able to execute operations.`;
|
|
179
162
|
throw new error_1.FirebaseError(msg);
|
|
180
163
|
}
|
|
181
164
|
const MAX_RETRIES = 3;
|
|
182
165
|
for (let i = 1; i <= MAX_RETRIES; i++) {
|
|
183
166
|
try {
|
|
184
|
-
this.logger.logLabeled("DEBUG", "Data Connect", `Connecting to ${connectionString}}
|
|
185
|
-
|
|
167
|
+
this.logger.logLabeled("DEBUG", "Data Connect", `Connecting to ${connectionString}}...`);
|
|
168
|
+
connectionString.toString();
|
|
169
|
+
await this.emulatorClient.configureEmulator({
|
|
170
|
+
connectionString: connectionString.toString(),
|
|
171
|
+
database,
|
|
172
|
+
serviceId,
|
|
173
|
+
maxOpenConnections: 1,
|
|
174
|
+
});
|
|
175
|
+
this.logger.logLabeled("DEBUG", "Data Connect", `Successfully connected to ${connectionString}}`);
|
|
186
176
|
return true;
|
|
187
177
|
}
|
|
188
178
|
catch (err) {
|
|
@@ -190,7 +180,7 @@ Run ${clc.bold("firebase setup:emulators:dataconnect")} to set up a Postgres con
|
|
|
190
180
|
throw err;
|
|
191
181
|
}
|
|
192
182
|
this.logger.logLabeled("DEBUG", "Data Connect", `Retrying connectToPostgress call (${i} of ${MAX_RETRIES} attempts): ${err}`);
|
|
193
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
183
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
194
184
|
}
|
|
195
185
|
}
|
|
196
186
|
return false;
|
|
@@ -225,14 +215,6 @@ class DataConnectEmulatorClient {
|
|
|
225
215
|
}
|
|
226
216
|
}
|
|
227
217
|
exports.DataConnectEmulatorClient = DataConnectEmulatorClient;
|
|
228
|
-
async function checkIfDataConnectEmulatorRunningOnAddress(l) {
|
|
229
|
-
const client = new apiv2_1.Client({
|
|
230
|
-
urlPrefix: `http:/${l.family === "IPv6" ? `[${l.address}]` : l.address}:${l.port}`,
|
|
231
|
-
auth: false,
|
|
232
|
-
});
|
|
233
|
-
return getInfo(client);
|
|
234
|
-
}
|
|
235
|
-
exports.checkIfDataConnectEmulatorRunningOnAddress = checkIfDataConnectEmulatorRunningOnAddress;
|
|
236
218
|
async function getInfo(client) {
|
|
237
219
|
try {
|
|
238
220
|
const res = await client.get("emulator/info");
|