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.
Files changed (57) hide show
  1. package/lib/apiv2.js +8 -1
  2. package/lib/auth.js +14 -2
  3. package/lib/commands/dataconnect-sdk-generate.js +5 -2
  4. package/lib/commands/emulators-start.js +3 -0
  5. package/lib/commands/init.js +20 -16
  6. package/lib/commands/setup-emulators-dataconnect.js +0 -14
  7. package/lib/dataconnect/dataplaneClient.js +12 -9
  8. package/lib/dataconnect/fileUtils.js +16 -4
  9. package/lib/dataconnect/freeTrial.js +8 -6
  10. package/lib/dataconnect/provisionCloudSql.js +4 -4
  11. package/lib/dataconnect/types.js +1 -0
  12. package/lib/dataconnect/webhook.js +31 -0
  13. package/lib/deploy/dataconnect/deploy.js +2 -0
  14. package/lib/deploy/dataconnect/prepare.js +2 -0
  15. package/lib/deploy/dataconnect/release.js +10 -5
  16. package/lib/deploy/functions/runtimes/node/index.js +6 -1
  17. package/lib/emulator/commandUtils.js +6 -1
  18. package/lib/emulator/constants.js +1 -1
  19. package/lib/emulator/controller.js +17 -3
  20. package/lib/emulator/dataconnect/pg-gateway/auth/base-auth-flow.js +11 -0
  21. package/lib/emulator/dataconnect/pg-gateway/auth/cert.js +69 -0
  22. package/lib/emulator/dataconnect/pg-gateway/auth/index.js +22 -0
  23. package/lib/emulator/dataconnect/pg-gateway/auth/md5.js +135 -0
  24. package/lib/emulator/dataconnect/pg-gateway/auth/password.js +65 -0
  25. package/lib/emulator/dataconnect/pg-gateway/auth/sasl/sasl-mechanism.js +34 -0
  26. package/lib/emulator/dataconnect/pg-gateway/auth/sasl/scram-sha-256.js +298 -0
  27. package/lib/emulator/dataconnect/pg-gateway/auth/trust.js +2 -0
  28. package/lib/emulator/dataconnect/pg-gateway/backend-error.js +75 -0
  29. package/lib/emulator/dataconnect/pg-gateway/buffer-reader.js +55 -0
  30. package/lib/emulator/dataconnect/pg-gateway/buffer-writer.js +79 -0
  31. package/lib/emulator/dataconnect/pg-gateway/connection.js +419 -0
  32. package/lib/emulator/dataconnect/pg-gateway/connection.types.js +8 -0
  33. package/lib/emulator/dataconnect/pg-gateway/crypto.js +40 -0
  34. package/lib/emulator/dataconnect/pg-gateway/duplex.js +53 -0
  35. package/lib/emulator/dataconnect/pg-gateway/index.js +27 -0
  36. package/lib/emulator/dataconnect/pg-gateway/message-buffer.js +96 -0
  37. package/lib/emulator/dataconnect/pg-gateway/message-codes.js +54 -0
  38. package/lib/emulator/dataconnect/pg-gateway/platforms/node/index.js +13 -0
  39. package/lib/emulator/dataconnect/pg-gateway/polyfills/readable-stream-async-iterator.js +36 -0
  40. package/lib/emulator/dataconnect/pg-gateway/utils.js +40 -0
  41. package/lib/emulator/dataconnect/pgliteServer.js +134 -0
  42. package/lib/emulator/dataconnectEmulator.js +55 -73
  43. package/lib/emulator/dataconnectToolkitController.js +44 -0
  44. package/lib/emulator/downloadableEmulators.js +22 -11
  45. package/lib/emulator/hub.js +2 -1
  46. package/lib/emulator/portUtils.js +9 -11
  47. package/lib/emulator/storage/rules/runtime.js +1 -1
  48. package/lib/experiments.js +1 -0
  49. package/lib/init/features/dataconnect/index.js +148 -111
  50. package/lib/init/features/dataconnect/sdk.js +40 -27
  51. package/lib/init/features/emulators.js +2 -14
  52. package/lib/prompt.js +1 -1
  53. package/lib/rc.js +1 -9
  54. package/package.json +3 -1
  55. package/schema/connector-yaml.json +14 -0
  56. package/schema/firebase-config.json +6 -0
  57. 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.checkIfDataConnectEmulatorRunningOnAddress = exports.DataConnectEmulatorClient = exports.DataConnectEmulator = exports.dataConnectEmulatorEvents = void 0;
3
+ exports.DataConnectEmulatorClient = exports.DataConnectEmulator = exports.dataConnectEmulatorEvents = void 0;
4
4
  const childProcess = require("child_process");
5
- const clc = require("colorette");
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 alreadyRunning = await this.discoverRunningInstance();
46
- if (alreadyRunning) {
47
- this.logger.logLabeled("INFO", "Data Connect", "Detected an instance of the emulator already running with your service, reusing it. This emulator will not be shut down at the end of this command.");
48
- this.usingExistingEmulator = true;
49
- this.watchUnmanagedInstance();
50
- }
51
- else {
52
- await (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, {
53
- auto_download: this.args.auto_download,
54
- listen: (0, portUtils_1.listenSpecsToString)(this.args.listen),
55
- config_dir: resolvedConfigDir,
56
- enable_output_schema_extensions: true,
57
- enable_output_generated_sdk: true,
58
- });
59
- this.usingExistingEmulator = false;
60
- }
61
- if (!(0, utils_1.isVSCodeExtension)()) {
62
- await this.connectToPostgres();
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
- getLocalConectionString() {
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 string found in '.firebaserc'. The Data Connect emulator will not be able to execute operations.
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
- await this.emulatorClient.configureEmulator({ connectionString, database, serviceId });
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, 800));
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");