firebase-tools 13.7.5 → 13.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/lib/api.js +9 -1
  2. package/lib/apiv2.js +19 -13
  3. package/lib/apphosting/app.js +4 -3
  4. package/lib/apphosting/githubConnections.js +1 -1
  5. package/lib/apphosting/index.js +42 -18
  6. package/lib/checkValidTargetFilters.js +8 -1
  7. package/lib/commands/apphosting-backends-create.js +3 -3
  8. package/lib/commands/apphosting-backends-delete.js +24 -17
  9. package/lib/commands/apphosting-backends-list.js +3 -3
  10. package/lib/commands/apphosting-secrets-grantaccess.js +9 -5
  11. package/lib/commands/dataconnect-list.js +64 -0
  12. package/lib/commands/dataconnect-sdk-generate.js +36 -0
  13. package/lib/commands/dataconnect-sql-diff.js +25 -0
  14. package/lib/commands/dataconnect-sql-migrate.js +41 -0
  15. package/lib/commands/deploy.js +27 -1
  16. package/lib/commands/index.js +10 -0
  17. package/lib/commands/init.js +7 -0
  18. package/lib/commands/setup-emulators-dataconnect.js +12 -0
  19. package/lib/config.js +1 -0
  20. package/lib/dataconnect/build.js +23 -0
  21. package/lib/dataconnect/checkIam.js +30 -0
  22. package/lib/dataconnect/client.js +115 -0
  23. package/lib/dataconnect/dataplaneClient.js +16 -0
  24. package/lib/dataconnect/ensureApis.js +12 -0
  25. package/lib/dataconnect/fileUtils.js +89 -0
  26. package/lib/dataconnect/filters.js +45 -0
  27. package/lib/dataconnect/freeTrial.js +23 -0
  28. package/lib/dataconnect/graphqlError.js +13 -0
  29. package/lib/dataconnect/load.js +40 -0
  30. package/lib/dataconnect/names.js +48 -0
  31. package/lib/dataconnect/prompts.js +20 -0
  32. package/lib/dataconnect/provisionCloudSql.js +91 -0
  33. package/lib/dataconnect/schemaMigration.js +137 -0
  34. package/lib/dataconnect/types.js +23 -0
  35. package/lib/deploy/dataconnect/deploy.js +84 -0
  36. package/lib/deploy/dataconnect/index.js +9 -0
  37. package/lib/deploy/dataconnect/prepare.js +30 -0
  38. package/lib/deploy/dataconnect/release.js +67 -0
  39. package/lib/deploy/functions/checkIam.js +4 -34
  40. package/lib/deploy/index.js +2 -0
  41. package/lib/downloadUtils.js +2 -2
  42. package/lib/emulator/constants.js +3 -0
  43. package/lib/emulator/controller.js +38 -12
  44. package/lib/emulator/dataconnectEmulator.js +86 -0
  45. package/lib/emulator/download.js +1 -1
  46. package/lib/emulator/downloadableEmulators.js +42 -3
  47. package/lib/emulator/portUtils.js +3 -2
  48. package/lib/emulator/registry.js +5 -0
  49. package/lib/emulator/types.js +3 -0
  50. package/lib/experiments.js +5 -0
  51. package/lib/extensions/emulator/specHelper.js +5 -39
  52. package/lib/gcp/apphosting.js +6 -1
  53. package/lib/gcp/cloudsql/cloudsqladmin.js +155 -0
  54. package/lib/gcp/cloudsql/connect.js +127 -0
  55. package/lib/gcp/cloudsql/fbToolsAuthClient.js +42 -0
  56. package/lib/gcp/cloudsql/types.js +2 -0
  57. package/lib/gcp/iam.js +33 -1
  58. package/lib/gcp/secretManager.js +1 -1
  59. package/lib/init/features/dataconnect/index.js +124 -0
  60. package/lib/init/features/emulators.js +13 -0
  61. package/lib/init/features/functions/index.js +15 -3
  62. package/lib/init/features/index.js +3 -1
  63. package/lib/init/index.js +1 -0
  64. package/lib/logger.js +22 -2
  65. package/lib/operation-poller.js +7 -1
  66. package/lib/rc.js +10 -1
  67. package/lib/requireAuth.js +1 -0
  68. package/lib/utils.js +51 -4
  69. package/package.json +6 -2
  70. package/schema/connector-yaml.json +54 -0
  71. package/schema/dataconnect-yaml.json +72 -0
  72. package/schema/firebase-config.json +103 -0
  73. package/templates/extensions/javascript/package.lint.json +2 -2
  74. package/templates/extensions/javascript/package.nolint.json +2 -2
  75. package/templates/extensions/typescript/package.lint.json +2 -2
  76. package/templates/extensions/typescript/package.nolint.json +2 -2
  77. package/templates/init/dataconnect/connector.yaml +2 -0
  78. package/templates/init/dataconnect/dataconnect.yaml +10 -0
  79. package/templates/init/dataconnect/mutations.gql +5 -0
  80. package/templates/init/dataconnect/queries.gql +7 -0
  81. package/templates/init/dataconnect/schema.gql +16 -0
  82. package/templates/init/functions/javascript/_gitignore +2 -1
  83. package/templates/init/functions/javascript/package.lint.json +2 -2
  84. package/templates/init/functions/javascript/package.nolint.json +2 -2
  85. package/templates/init/functions/python/_gitignore +1 -0
  86. package/templates/init/functions/typescript/_gitignore +1 -0
  87. package/templates/init/functions/typescript/package.lint.json +2 -2
  88. package/templates/init/functions/typescript/package.nolint.json +2 -2
@@ -12,14 +12,8 @@ const registry_1 = require("./registry");
12
12
  const types_1 = require("./types");
13
13
  const constants_1 = require("./constants");
14
14
  const functionsEmulator_1 = require("./functionsEmulator");
15
- const auth_1 = require("./auth");
16
- const databaseEmulator_1 = require("./databaseEmulator");
17
- const firestoreEmulator_1 = require("./firestoreEmulator");
18
- const hostingEmulator_1 = require("./hostingEmulator");
19
- const eventarcEmulator_1 = require("./eventarcEmulator");
20
15
  const error_1 = require("../error");
21
16
  const projectUtils_1 = require("../projectUtils");
22
- const pubsubEmulator_1 = require("./pubsubEmulator");
23
17
  const commandUtils = require("./commandUtils");
24
18
  const hub_1 = require("./hub");
25
19
  const hubExport_1 = require("./hubExport");
@@ -31,10 +25,9 @@ const hubClient_1 = require("./hubClient");
31
25
  const prompt_1 = require("../prompt");
32
26
  const commandUtils_1 = require("./commandUtils");
33
27
  const fsutils_1 = require("../fsutils");
34
- const storage_1 = require("./storage");
35
28
  const config_1 = require("./storage/rules/config");
36
29
  const getDefaultDatabaseInstance_1 = require("../getDefaultDatabaseInstance");
37
- const auth_2 = require("../auth");
30
+ const auth_1 = require("../auth");
38
31
  const extensionsEmulator_1 = require("./extensionsEmulator");
39
32
  const projectConfig_1 = require("../functions/projectConfig");
40
33
  const downloadableEmulators_1 = require("./downloadableEmulators");
@@ -42,6 +35,15 @@ const frameworks_1 = require("../frameworks");
42
35
  const experiments = require("../experiments");
43
36
  const portUtils_1 = require("./portUtils");
44
37
  const supported_1 = require("../deploy/functions/runtimes/supported");
38
+ const auth_2 = require("./auth");
39
+ const databaseEmulator_1 = require("./databaseEmulator");
40
+ const eventarcEmulator_1 = require("./eventarcEmulator");
41
+ const dataconnectEmulator_1 = require("./dataconnectEmulator");
42
+ const firestoreEmulator_1 = require("./firestoreEmulator");
43
+ const hostingEmulator_1 = require("./hostingEmulator");
44
+ const pubsubEmulator_1 = require("./pubsubEmulator");
45
+ const storage_1 = require("./storage");
46
+ const fileUtils_1 = require("../dataconnect/fileUtils");
45
47
  const START_LOGGING_EMULATOR = utils.envOverride("START_LOGGING_EMULATOR", "false", (val) => val === "true");
46
48
  async function exportOnExit(options) {
47
49
  const exportOnExitDir = options.exportOnExit;
@@ -346,7 +348,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
346
348
  if (emulatorsNotRunning.length > 0 && !constants_1.Constants.isDemoProject(projectId)) {
347
349
  functionsLogger.logLabeled("WARN", "functions", `The following emulators are not running, calls to these services from the Functions emulator will affect production: ${clc.bold(emulatorsNotRunning.join(", "))}`);
348
350
  }
349
- const account = (0, auth_2.getProjectDefaultAccount)(options.projectRoot);
351
+ const account = (0, auth_1.getProjectDefaultAccount)(options.projectRoot);
350
352
  const functionsEmulator = new functionsEmulator_1.FunctionsEmulator({
351
353
  projectId,
352
354
  projectDir,
@@ -486,13 +488,13 @@ async function startAll(options, showUI = true, runningTestScript = false) {
486
488
  throw new error_1.FirebaseError(`Cannot start the ${constants_1.Constants.description(types_1.Emulators.AUTH)} without a project: run 'firebase init' or provide the --project flag`);
487
489
  }
488
490
  const authAddr = legacyGetFirstAddr(types_1.Emulators.AUTH);
489
- const authEmulator = new auth_1.AuthEmulator({
491
+ const authEmulator = new auth_2.AuthEmulator({
490
492
  host: authAddr.host,
491
493
  port: authAddr.port,
492
494
  projectId,
493
495
  singleProjectMode: singleProjectModeEnabled
494
- ? auth_1.SingleProjectMode.WARNING
495
- : auth_1.SingleProjectMode.NO_WARNING,
496
+ ? auth_2.SingleProjectMode.WARNING
497
+ : auth_2.SingleProjectMode.NO_WARNING,
496
498
  });
497
499
  await startEmulator(authEmulator);
498
500
  if (exportMetadata.auth) {
@@ -515,6 +517,30 @@ async function startAll(options, showUI = true, runningTestScript = false) {
515
517
  });
516
518
  await startEmulator(pubsubEmulator);
517
519
  }
520
+ if (listenForEmulator.dataconnect) {
521
+ const dataConnectAddr = legacyGetFirstAddr(types_1.Emulators.DATACONNECT);
522
+ const config = (0, fileUtils_1.readFirebaseJson)(options.config);
523
+ if (!config.length) {
524
+ throw new error_1.FirebaseError("No Data Connect service found in firebase.json");
525
+ }
526
+ else if (config.length > 1) {
527
+ logger_1.logger.warn(`TODO: Add support for multiple services in the Data Connect emulator. Currently emulating first service ${config[0].source}`);
528
+ }
529
+ let configDir = config[0].source;
530
+ if (!path.isAbsolute(configDir)) {
531
+ const cwd = options.cwd || process.cwd();
532
+ configDir = path.resolve(path.join(cwd), configDir);
533
+ }
534
+ const dataConnectEmulator = new dataconnectEmulator_1.DataConnectEmulator({
535
+ host: dataConnectAddr.host,
536
+ port: dataConnectAddr.port,
537
+ projectId,
538
+ auto_download: true,
539
+ configDir,
540
+ rc: options.rc,
541
+ });
542
+ await startEmulator(dataConnectEmulator);
543
+ }
518
544
  if (listenForEmulator.storage) {
519
545
  const storageAddr = legacyGetFirstAddr(types_1.Emulators.STORAGE);
520
546
  const storageEmulator = new storage_1.StorageEmulator({
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataConnectEmulator = void 0;
4
+ const childProcess = require("child_process");
5
+ const api_1 = require("../api");
6
+ const constants_1 = require("./constants");
7
+ const downloadableEmulators_1 = require("./downloadableEmulators");
8
+ const types_1 = require("./types");
9
+ const error_1 = require("../error");
10
+ const emulatorLogger_1 = require("./emulatorLogger");
11
+ const types_2 = require("../dataconnect/types");
12
+ class DataConnectEmulator {
13
+ constructor(args) {
14
+ this.args = args;
15
+ this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT);
16
+ }
17
+ async start() {
18
+ const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATACONNECT);
19
+ this.logger.log("DEBUG", `Using Postgres connection string: ${this.getLocalConectionString()}`);
20
+ const info = await this.build();
21
+ if ((0, types_2.requiresVector)(info.metadata)) {
22
+ if (constants_1.Constants.isDemoProject(this.args.projectId)) {
23
+ this.logger.logLabeled("WARN", "Data Connect", "Detected a 'demo-' project, but vector embeddings require a real project. Operations that use vector_embed will fail.");
24
+ }
25
+ else {
26
+ this.logger.logLabeled("WARN", "Data Connect", "Operations that use vector_embed will make calls to production Vertex AI");
27
+ }
28
+ }
29
+ return (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, Object.assign(Object.assign({}, this.args), { http_port: port, grpc_port: port + 1, config_dir: this.args.configDir, local_connection_string: this.getLocalConectionString(), project_id: this.args.projectId }));
30
+ }
31
+ connect() {
32
+ return Promise.resolve();
33
+ }
34
+ stop() {
35
+ return (0, downloadableEmulators_1.stop)(types_1.Emulators.DATACONNECT);
36
+ }
37
+ getInfo() {
38
+ const host = this.args.host || constants_1.Constants.getDefaultHost();
39
+ const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATACONNECT);
40
+ return {
41
+ name: this.getName(),
42
+ host,
43
+ port,
44
+ pid: (0, downloadableEmulators_1.getPID)(types_1.Emulators.DATACONNECT),
45
+ };
46
+ }
47
+ getName() {
48
+ return types_1.Emulators.DATACONNECT;
49
+ }
50
+ async generate(connectorId) {
51
+ const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
52
+ const cmd = [
53
+ "generate",
54
+ `--config_dir=${this.args.configDir}`,
55
+ `--connector_id=${connectorId}`,
56
+ ];
57
+ const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
58
+ if (res.error) {
59
+ throw new error_1.FirebaseError(`Error starting up Data Connect emulator: ${res.error}`);
60
+ }
61
+ return res.stdout;
62
+ }
63
+ async build() {
64
+ var _a;
65
+ const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
66
+ const cmd = ["build", `--config_dir=${this.args.configDir}`];
67
+ const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
68
+ if (res.stderr) {
69
+ throw new error_1.FirebaseError(`Unable to build your Data Connect schema and connectors: ${res.stderr}`);
70
+ }
71
+ try {
72
+ return JSON.parse(res.stdout);
73
+ }
74
+ catch (err) {
75
+ throw new error_1.FirebaseError(`Unable to parse 'fdc build' output: ${(_a = res.stdout) !== null && _a !== void 0 ? _a : res.stderr}`);
76
+ }
77
+ }
78
+ getLocalConectionString() {
79
+ var _a, _b;
80
+ if ((0, api_1.dataConnectLocalConnString)()) {
81
+ return (0, api_1.dataConnectLocalConnString)();
82
+ }
83
+ return (_b = (_a = this.args.rc.getDataconnect()) === null || _a === void 0 ? void 0 : _a.postgres) === null || _b === void 0 ? void 0 : _b.localConnectionString;
84
+ }
85
+ }
86
+ exports.DataConnectEmulator = DataConnectEmulator;
@@ -15,7 +15,7 @@ async function downloadEmulator(name) {
15
15
  const emulator = downloadableEmulators.getDownloadDetails(name);
16
16
  emulatorLogger_1.EmulatorLogger.forEmulator(name).logLabeled("BULLET", name, `downloading ${path.basename(emulator.downloadPath)}...`);
17
17
  fs.ensureDirSync(emulator.opts.cacheDir);
18
- const tmpfile = await downloadUtils.downloadToTmp(emulator.opts.remoteUrl);
18
+ const tmpfile = await downloadUtils.downloadToTmp(emulator.opts.remoteUrl, !!emulator.opts.auth);
19
19
  if (!emulator.opts.skipChecksumAndSize) {
20
20
  await validateSize(tmpfile, emulator.opts.expectedSize);
21
21
  await validateChecksum(tmpfile, emulator.opts.expectedChecksum);
@@ -44,6 +44,17 @@ const EMULATOR_UPDATE_DETAILS = {
44
44
  expectedSize: 65611398,
45
45
  expectedChecksum: "70bb840321423e6ae621a3ae2f314903",
46
46
  },
47
+ dataconnect: process.platform === "darwin"
48
+ ? {
49
+ version: "1.1.12",
50
+ expectedSize: 25542352,
51
+ expectedChecksum: "b523fe9d5506cc07480d1a571c72de9a",
52
+ }
53
+ : {
54
+ version: "1.1.12",
55
+ expectedSize: 23004624,
56
+ expectedChecksum: "e69f79755263b7cd77ec7cd15ef0d825",
57
+ },
47
58
  };
48
59
  exports.DownloadDetails = {
49
60
  database: {
@@ -107,6 +118,22 @@ exports.DownloadDetails = {
107
118
  namePrefix: "pubsub-emulator",
108
119
  },
109
120
  },
121
+ dataconnect: {
122
+ downloadPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}`),
123
+ version: EMULATOR_UPDATE_DETAILS.dataconnect.version,
124
+ binaryPath: path.join(CACHE_DIR, `dataconnect-emulator-${EMULATOR_UPDATE_DETAILS.dataconnect.version}`),
125
+ opts: {
126
+ cacheDir: CACHE_DIR,
127
+ remoteUrl: process.platform === "darwin"
128
+ ? `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`
129
+ : `https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v${EMULATOR_UPDATE_DETAILS.dataconnect.version}`,
130
+ expectedSize: EMULATOR_UPDATE_DETAILS.dataconnect.expectedSize,
131
+ expectedChecksum: EMULATOR_UPDATE_DETAILS.dataconnect.expectedChecksum,
132
+ skipChecksumAndSize: false,
133
+ namePrefix: "dataconnect-emulator",
134
+ auth: true,
135
+ },
136
+ },
110
137
  };
111
138
  const EmulatorDetails = {
112
139
  database: {
@@ -134,6 +161,11 @@ const EmulatorDetails = {
134
161
  instance: null,
135
162
  stdout: null,
136
163
  },
164
+ dataconnect: {
165
+ name: types_1.Emulators.DATACONNECT,
166
+ instance: null,
167
+ stdout: null,
168
+ },
137
169
  };
138
170
  const Commands = {
139
171
  database: {
@@ -197,6 +229,13 @@ const Commands = {
197
229
  joinArgs: false,
198
230
  shell: false,
199
231
  },
232
+ dataconnect: {
233
+ binary: getExecPath(types_1.Emulators.DATACONNECT),
234
+ args: ["dev"],
235
+ optionalArgs: ["http_port", "grpc_port", "config_dir", "local_connection_string", "project_id"],
236
+ joinArgs: true,
237
+ shell: true,
238
+ },
200
239
  };
201
240
  function getExecPath(name) {
202
241
  const details = getDownloadDetails(name);
@@ -364,10 +403,10 @@ async function stop(targetName) {
364
403
  exports.stop = stop;
365
404
  async function downloadIfNecessary(targetName) {
366
405
  const hasEmulator = fs.existsSync(getExecPath(targetName));
367
- if (hasEmulator) {
368
- return;
406
+ if (!hasEmulator) {
407
+ await (0, download_1.downloadEmulator)(targetName);
369
408
  }
370
- await (0, download_1.downloadEmulator)(targetName);
409
+ return Commands[targetName];
371
410
  }
372
411
  exports.downloadIfNecessary = downloadIfNecessary;
373
412
  async function start(targetName, args, extraEnv = {}) {
@@ -132,8 +132,8 @@ async function checkListenable(arg1, port) {
132
132
  }
133
133
  exports.checkListenable = checkListenable;
134
134
  async function waitForPortUsed(port, host) {
135
- const interval = 250;
136
- const timeout = 60000;
135
+ const interval = 200;
136
+ const timeout = 5000;
137
137
  try {
138
138
  await tcpport.waitUntilUsedOnHost(port, host, interval, timeout);
139
139
  }
@@ -147,6 +147,7 @@ const EMULATOR_CAN_LISTEN_ON_PRIMARY_ONLY = {
147
147
  firestore: true,
148
148
  "firestore.websocket": true,
149
149
  pubsub: true,
150
+ dataconnect: true,
150
151
  hub: false,
151
152
  ui: false,
152
153
  auth: true,
@@ -8,6 +8,7 @@ const constants_1 = require("./constants");
8
8
  const emulatorLogger_1 = require("./emulatorLogger");
9
9
  const utils_1 = require("../utils");
10
10
  const apiv2_1 = require("../apiv2");
11
+ const downloadableEmulators_1 = require("./downloadableEmulators");
11
12
  class EmulatorRegistry {
12
13
  static async start(instance) {
13
14
  const description = constants_1.Constants.description(instance.getName());
@@ -47,6 +48,7 @@ class EmulatorRegistry {
47
48
  auth: 3.3,
48
49
  storage: 3.5,
49
50
  eventarc: 3.6,
51
+ dataconnect: 3.7,
50
52
  hub: 4,
51
53
  logging: 5,
52
54
  };
@@ -83,6 +85,9 @@ class EmulatorRegistry {
83
85
  }
84
86
  return Object.assign(Object.assign({}, info), { host: (0, utils_1.connectableHostname)(info.host) });
85
87
  }
88
+ static getDetails(emulator) {
89
+ return (0, downloadableEmulators_1.get)(emulator);
90
+ }
86
91
  static url(emulator, req) {
87
92
  const url = new URL("http://unknown/");
88
93
  if (req) {
@@ -15,6 +15,7 @@ var Emulators;
15
15
  Emulators["STORAGE"] = "storage";
16
16
  Emulators["EXTENSIONS"] = "extensions";
17
17
  Emulators["EVENTARC"] = "eventarc";
18
+ Emulators["DATACONNECT"] = "dataconnect";
18
19
  })(Emulators = exports.Emulators || (exports.Emulators = {}));
19
20
  exports.DOWNLOADABLE_EMULATORS = [
20
21
  Emulators.FIRESTORE,
@@ -22,6 +23,7 @@ exports.DOWNLOADABLE_EMULATORS = [
22
23
  Emulators.PUBSUB,
23
24
  Emulators.UI,
24
25
  Emulators.STORAGE,
26
+ Emulators.DATACONNECT,
25
27
  ];
26
28
  exports.IMPORT_EXPORT_EMULATORS = [
27
29
  Emulators.FIRESTORE,
@@ -38,6 +40,7 @@ exports.ALL_SERVICE_EMULATORS = [
38
40
  Emulators.PUBSUB,
39
41
  Emulators.STORAGE,
40
42
  Emulators.EVENTARC,
43
+ Emulators.DATACONNECT,
41
44
  ].filter((v) => v);
42
45
  exports.EMULATORS_SUPPORTED_BY_FUNCTIONS = [
43
46
  Emulators.FIRESTORE,
@@ -89,6 +89,11 @@ exports.ALL_EXPERIMENTS = experiments({
89
89
  default: false,
90
90
  public: false,
91
91
  },
92
+ dataconnect: {
93
+ shortDescription: "Enable Data Connect related features.",
94
+ fullDescription: "Enable Data Connect related features.",
95
+ public: false,
96
+ },
92
97
  });
93
98
  function isValidExperiment(name) {
94
99
  return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
@@ -1,13 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getRuntime = exports.DEFAULT_RUNTIME = exports.getFunctionProperties = exports.getFunctionResourcesWithParamSubstitution = exports.readFileFromDirectory = exports.readPostinstall = exports.readExtensionYaml = void 0;
4
- const yaml = require("yaml");
5
- const path = require("path");
6
- const fs = require("fs-extra");
3
+ exports.getRuntime = exports.DEFAULT_RUNTIME = exports.getFunctionProperties = exports.getFunctionResourcesWithParamSubstitution = exports.readPostinstall = exports.readExtensionYaml = void 0;
7
4
  const supported = require("../../deploy/functions/runtimes/supported");
8
5
  const error_1 = require("../../error");
9
6
  const extensionsHelper_1 = require("../extensionsHelper");
10
7
  const utils_1 = require("../utils");
8
+ const utils_2 = require("../../utils");
11
9
  const SPEC_FILE = "extension.yaml";
12
10
  const POSTINSTALL_FILE = "POSTINSTALL.md";
13
11
  const validFunctionTypes = [
@@ -15,22 +13,11 @@ const validFunctionTypes = [
15
13
  "firebaseextensions.v1beta.v2function",
16
14
  "firebaseextensions.v1beta.scheduledFunction",
17
15
  ];
18
- function wrappedSafeLoad(source) {
19
- try {
20
- return yaml.parse(source);
21
- }
22
- catch (err) {
23
- if (err instanceof yaml.YAMLParseError) {
24
- throw new error_1.FirebaseError(`YAML Error: ${err.message}`, { original: err });
25
- }
26
- throw err;
27
- }
28
- }
29
16
  async function readExtensionYaml(directory) {
30
17
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
31
- const extensionYaml = await readFileFromDirectory(directory, SPEC_FILE);
18
+ const extensionYaml = await (0, utils_2.readFileFromDirectory)(directory, SPEC_FILE);
32
19
  const source = extensionYaml.source;
33
- const spec = wrappedSafeLoad(source);
20
+ const spec = (0, utils_2.wrappedSafeLoad)(source);
34
21
  spec.params = (_a = spec.params) !== null && _a !== void 0 ? _a : [];
35
22
  spec.systemParams = (_b = spec.systemParams) !== null && _b !== void 0 ? _b : [];
36
23
  spec.resources = (_c = spec.resources) !== null && _c !== void 0 ? _c : [];
@@ -44,31 +31,10 @@ async function readExtensionYaml(directory) {
44
31
  }
45
32
  exports.readExtensionYaml = readExtensionYaml;
46
33
  async function readPostinstall(directory) {
47
- const content = await readFileFromDirectory(directory, POSTINSTALL_FILE);
34
+ const content = await (0, utils_2.readFileFromDirectory)(directory, POSTINSTALL_FILE);
48
35
  return content.source;
49
36
  }
50
37
  exports.readPostinstall = readPostinstall;
51
- function readFileFromDirectory(directory, file) {
52
- return new Promise((resolve, reject) => {
53
- fs.readFile(path.resolve(directory, file), "utf8", (err, data) => {
54
- if (err) {
55
- if (err.code === "ENOENT") {
56
- return reject(new error_1.FirebaseError(`Could not find "${file}" in "${directory}"`, { original: err }));
57
- }
58
- reject(new error_1.FirebaseError(`Failed to read file "${file}" in "${directory}"`, { original: err }));
59
- }
60
- else {
61
- resolve(data);
62
- }
63
- });
64
- }).then((source) => {
65
- return {
66
- source,
67
- sourceDirectory: directory,
68
- };
69
- });
70
- }
71
- exports.readFileFromDirectory = readFileFromDirectory;
72
38
  function getFunctionResourcesWithParamSubstitution(extensionSpec, params) {
73
39
  const rawResources = extensionSpec.resources.filter((resource) => validFunctionTypes.includes(resource.type));
74
40
  return (0, extensionsHelper_1.substituteParams)(rawResources, params);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getNextRolloutId = exports.ensureApiEnabled = exports.listLocations = exports.updateTraffic = exports.listRollouts = exports.createRollout = exports.createBuild = exports.listBuilds = exports.getBuild = exports.deleteBackend = exports.listBackends = exports.getBackend = exports.createBackend = exports.serviceAgentEmail = exports.client = exports.API_VERSION = void 0;
3
+ exports.getNextRolloutId = exports.ensureApiEnabled = exports.listLocations = exports.updateTraffic = exports.listRollouts = exports.createRollout = exports.createBuild = exports.listBuilds = exports.getBuild = exports.deleteBackend = exports.listBackends = exports.getBackend = exports.createBackend = exports.parseBackendName = exports.serviceAgentEmail = exports.client = exports.API_VERSION = void 0;
4
4
  const proto = require("../gcp/proto");
5
5
  const apiv2_1 = require("../apiv2");
6
6
  const projectUtils_1 = require("../projectUtils");
@@ -24,6 +24,11 @@ function serviceAgentEmail(projectNumber) {
24
24
  return `service-${projectNumber}@${P4SA_DOMAIN}`;
25
25
  }
26
26
  exports.serviceAgentEmail = serviceAgentEmail;
27
+ function parseBackendName(backendName) {
28
+ const [, projectName, , location, , id] = backendName.split("/");
29
+ return { projectName, location, id };
30
+ }
31
+ exports.parseBackendName = parseBackendName;
27
32
  async function createBackend(projectId, location, backendReqBoby, backendId) {
28
33
  const res = await exports.client.post(`projects/${projectId}/locations/${location}/backends`, Object.assign(Object.assign({}, backendReqBoby), { labels: Object.assign(Object.assign({}, backendReqBoby.labels), deploymentTool.labels()) }), { queryParams: { backendId } });
29
34
  return res.body;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listUsers = exports.deleteUser = exports.getUser = exports.createUser = exports.createDatabase = exports.getDatabase = exports.listDatabases = exports.updateInstanceForDataConnect = exports.createInstance = exports.getInstance = exports.listInstances = void 0;
4
+ const apiv2_1 = require("../../apiv2");
5
+ const api_1 = require("../../api");
6
+ const operationPoller = require("../../operation-poller");
7
+ const API_VERSION = "v1";
8
+ const client = new apiv2_1.Client({
9
+ urlPrefix: (0, api_1.cloudSQLAdminOrigin)(),
10
+ auth: true,
11
+ apiVersion: API_VERSION,
12
+ });
13
+ async function listInstances(projectId) {
14
+ var _a;
15
+ const res = await client.get(`projects/${projectId}/instances`);
16
+ return (_a = res.body.items) !== null && _a !== void 0 ? _a : [];
17
+ }
18
+ exports.listInstances = listInstances;
19
+ async function getInstance(projectId, instanceId) {
20
+ const res = await client.get(`projects/${projectId}/instances/${instanceId}`);
21
+ return res.body;
22
+ }
23
+ exports.getInstance = getInstance;
24
+ async function createInstance(projectId, location, instanceId, enableGoogleMlIntegration) {
25
+ const databaseFlags = [{ name: "cloudsql.iam_authentication", value: "on" }];
26
+ if (enableGoogleMlIntegration) {
27
+ databaseFlags.push({ name: "cloudsql.enable_google_ml_integration", value: "on" });
28
+ }
29
+ const op = await client.post(`projects/${projectId}/instances`, {
30
+ name: instanceId,
31
+ region: location,
32
+ databaseVersion: "POSTGRES_15",
33
+ settings: {
34
+ tier: "db-f1-micro",
35
+ edition: "ENTERPRISE",
36
+ ipConfiguration: {
37
+ authorizedNetworks: [],
38
+ },
39
+ enableGoogleMlIntegration,
40
+ databaseFlags,
41
+ storageAutoResize: false,
42
+ userLabels: { "firebase-data-connect": "ft" },
43
+ insightsConfig: {
44
+ queryInsightsEnabled: true,
45
+ },
46
+ },
47
+ });
48
+ const opName = `projects/${projectId}/operations/${op.body.name}`;
49
+ const pollRes = await operationPoller.pollOperation({
50
+ apiOrigin: (0, api_1.cloudSQLAdminOrigin)(),
51
+ apiVersion: API_VERSION,
52
+ operationResourceName: opName,
53
+ doneFn: (op) => op.status === "DONE",
54
+ masterTimeout: 1200000,
55
+ });
56
+ return pollRes;
57
+ }
58
+ exports.createInstance = createInstance;
59
+ async function updateInstanceForDataConnect(instance, enableGoogleMlIntegration) {
60
+ let dbFlags = setDatabaseFlag({ name: "cloudsql.iam_authentication", value: "on" }, instance.settings.databaseFlags);
61
+ if (enableGoogleMlIntegration) {
62
+ dbFlags = setDatabaseFlag({ name: "cloudsql.enable_google_ml_integration", value: "on" }, dbFlags);
63
+ }
64
+ const op = await client.patch(`projects/${instance.project}/instances/${instance.name}`, {
65
+ settings: {
66
+ ipConfiguration: {
67
+ ipv4Enabled: true,
68
+ },
69
+ databaseFlags: dbFlags,
70
+ enableGoogleMlIntegration,
71
+ },
72
+ });
73
+ const opName = `projects/${instance.project}/operations/${op.body.name}`;
74
+ const pollRes = await operationPoller.pollOperation({
75
+ apiOrigin: (0, api_1.cloudSQLAdminOrigin)(),
76
+ apiVersion: API_VERSION,
77
+ operationResourceName: opName,
78
+ doneFn: (op) => op.status === "DONE",
79
+ masterTimeout: 1200000,
80
+ });
81
+ return pollRes;
82
+ }
83
+ exports.updateInstanceForDataConnect = updateInstanceForDataConnect;
84
+ function setDatabaseFlag(flag, flags = []) {
85
+ const temp = flags.filter((f) => f.name !== flag.name);
86
+ temp.push(flag);
87
+ return temp;
88
+ }
89
+ async function listDatabases(projectId, instanceId) {
90
+ const res = await client.get(`projects/${projectId}/instances/${instanceId}/databases`);
91
+ return res.body.items;
92
+ }
93
+ exports.listDatabases = listDatabases;
94
+ async function getDatabase(projectId, instanceId, databaseId) {
95
+ const res = await client.get(`projects/${projectId}/instances/${instanceId}/databases/${databaseId}`);
96
+ return res.body;
97
+ }
98
+ exports.getDatabase = getDatabase;
99
+ async function createDatabase(projectId, instanceId, databaseId) {
100
+ const op = await client.post(`projects/${projectId}/instances/${instanceId}/databases`, {
101
+ project: projectId,
102
+ instance: instanceId,
103
+ name: databaseId,
104
+ });
105
+ const opName = `projects/${projectId}/operations/${op.body.name}`;
106
+ const pollRes = await operationPoller.pollOperation({
107
+ apiOrigin: (0, api_1.cloudSQLAdminOrigin)(),
108
+ apiVersion: API_VERSION,
109
+ operationResourceName: opName,
110
+ doneFn: (op) => op.status === "DONE",
111
+ });
112
+ return pollRes;
113
+ }
114
+ exports.createDatabase = createDatabase;
115
+ async function createUser(projectId, instanceId, type, username, password) {
116
+ const op = await client.post(`projects/${projectId}/instances/${instanceId}/users`, {
117
+ name: username,
118
+ instance: instanceId,
119
+ project: projectId,
120
+ password: password,
121
+ sqlserverUserDetails: {
122
+ disabled: false,
123
+ serverRoles: ["cloudsqlsuperuser"],
124
+ },
125
+ type,
126
+ });
127
+ const opName = `projects/${projectId}/operations/${op.body.name}`;
128
+ const pollRes = await operationPoller.pollOperation({
129
+ apiOrigin: (0, api_1.cloudSQLAdminOrigin)(),
130
+ apiVersion: API_VERSION,
131
+ operationResourceName: opName,
132
+ doneFn: (op) => op.status === "DONE",
133
+ });
134
+ return pollRes;
135
+ }
136
+ exports.createUser = createUser;
137
+ async function getUser(projectId, instanceId, username) {
138
+ const res = await client.get(`projects/${projectId}/instances/${instanceId}/users/${username}`);
139
+ return res.body;
140
+ }
141
+ exports.getUser = getUser;
142
+ async function deleteUser(projectId, instanceId, username) {
143
+ const res = await client.delete(`projects/${projectId}/instances/${instanceId}/users`, {
144
+ queryParams: {
145
+ name: username,
146
+ },
147
+ });
148
+ return res.body;
149
+ }
150
+ exports.deleteUser = deleteUser;
151
+ async function listUsers(projectId, instanceId) {
152
+ const res = await client.get(`projects/${projectId}/instances/${instanceId}/users`);
153
+ return res.body.items;
154
+ }
155
+ exports.listUsers = listUsers;