firebase-tools 13.8.1 → 13.8.3

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 (36) hide show
  1. package/lib/apphosting/app.js +9 -7
  2. package/lib/apphosting/githubConnections.js +6 -8
  3. package/lib/apphosting/index.js +20 -19
  4. package/lib/apphosting/repo.js +2 -2
  5. package/lib/commands/apphosting-backends-create.js +3 -3
  6. package/lib/commands/{dataconnect-list.js → dataconnect-services-list.js} +23 -6
  7. package/lib/commands/dataconnect-sql-migrate.js +3 -3
  8. package/lib/commands/index.js +2 -1
  9. package/lib/commands/init.js +3 -3
  10. package/lib/dataconnect/client.js +2 -2
  11. package/lib/dataconnect/errors.js +31 -0
  12. package/lib/dataconnect/fileUtils.js +10 -7
  13. package/lib/dataconnect/freeTrial.js +1 -1
  14. package/lib/dataconnect/graphqlError.js +2 -2
  15. package/lib/dataconnect/provisionCloudSql.js +4 -3
  16. package/lib/dataconnect/schemaMigration.js +119 -46
  17. package/lib/deploy/dataconnect/deploy.js +4 -14
  18. package/lib/deploy/dataconnect/prepare.js +3 -0
  19. package/lib/emulator/dataconnectEmulator.js +2 -1
  20. package/lib/emulator/downloadableEmulators.js +9 -9
  21. package/lib/experiments.js +5 -0
  22. package/lib/gcp/cloudsql/cloudsqladmin.js +39 -19
  23. package/lib/gcp/firedata.js +3 -2
  24. package/lib/init/features/dataconnect/index.js +39 -33
  25. package/lib/init/features/emulators.js +9 -10
  26. package/lib/init/features/functions/index.js +4 -0
  27. package/lib/init/features/functions/npm-dependencies.js +12 -23
  28. package/lib/init/features/genkit.js +54 -0
  29. package/lib/init/features/index.js +3 -1
  30. package/lib/init/index.js +1 -0
  31. package/lib/init/spawn.js +23 -0
  32. package/lib/requireTosAcceptance.js +1 -0
  33. package/package.json +1 -1
  34. package/templates/init/dataconnect/mutations.gql +29 -3
  35. package/templates/init/dataconnect/queries.gql +49 -4
  36. package/templates/init/dataconnect/schema.gql +23 -10
@@ -12,21 +12,23 @@ exports.webApps = {
12
12
  getOrCreateWebApp,
13
13
  generateWebAppName,
14
14
  };
15
- async function getOrCreateWebApp(projectId, firebaseWebAppName, backendId) {
15
+ async function getOrCreateWebApp(projectId, firebaseWebAppId, backendId) {
16
+ var _a;
16
17
  const webAppsInProject = await (0, apps_1.listFirebaseApps)(projectId, apps_1.AppPlatform.WEB);
17
- const existingUserProjectWebApps = firebaseAppsToMap(webAppsInProject);
18
- if (firebaseWebAppName) {
19
- if (existingUserProjectWebApps.get(firebaseWebAppName) === undefined) {
20
- throw new error_1.FirebaseError(`The web app '${firebaseWebAppName}' does not exist in project ${projectId}`);
18
+ if (firebaseWebAppId) {
19
+ const webApp = webAppsInProject.find((app) => app.appId === firebaseWebAppId);
20
+ if (webApp === undefined) {
21
+ throw new error_1.FirebaseError(`The web app '${firebaseWebAppId}' does not exist in project ${projectId}`);
21
22
  }
22
23
  return {
23
- name: firebaseWebAppName,
24
- id: existingUserProjectWebApps.get(firebaseWebAppName),
24
+ name: (_a = webApp.displayName) !== null && _a !== void 0 ? _a : webApp.appId,
25
+ id: webApp.appId,
25
26
  };
26
27
  }
27
28
  const webAppName = await generateWebAppName(projectId, backendId);
28
29
  try {
29
30
  const app = await (0, apps_1.createWebApp)(projectId, { displayName: webAppName });
31
+ (0, utils_1.logSuccess)(`Created a new Firebase web app named "${webAppName}"`);
30
32
  return { name: app.displayName, id: app.appId };
31
33
  }
32
34
  catch (e) {
@@ -54,7 +54,7 @@ function generateConnectionId() {
54
54
  const ADD_CONN_CHOICE = "@ADD_CONN";
55
55
  async function linkGitHubRepository(projectId, location) {
56
56
  var _a, _b;
57
- utils.logBullet(clc.bold(`${clc.yellow("===")} Set up a GitHub connection`));
57
+ utils.logBullet(clc.bold(`${clc.yellow("===")} Import a GitHub repository`));
58
58
  const oauthConn = await getOrCreateOauthConnection(projectId, location);
59
59
  const existingConns = await listAppHostingConnections(projectId);
60
60
  if (existingConns.length === 0) {
@@ -76,8 +76,6 @@ async function linkGitHubRepository(projectId, location) {
76
76
  appInstallationId: (_b = connection.githubConfig) === null || _b === void 0 ? void 0 : _b.appInstallationId,
77
77
  });
78
78
  const repo = await getOrCreateRepository(projectId, location, connectionId, repoCloneUri);
79
- utils.logSuccess(`Successfully linked GitHub repository at remote URI`);
80
- utils.logSuccess(`\t${repo.cloneUri}\n`);
81
79
  return repo;
82
80
  }
83
81
  exports.linkGitHubRepository = linkGitHubRepository;
@@ -115,18 +113,18 @@ async function getOrCreateOauthConnection(projectId, location) {
115
113
  }
116
114
  }
117
115
  while (conn.installationState.stage === "PENDING_USER_OAUTH") {
118
- utils.logBullet("You must authorize the Firebase GitHub app.");
119
- utils.logBullet("Sign in to GitHub and authorize Firebase GitHub app:");
116
+ utils.logBullet("Please authorize the Firebase GitHub app by visiting this url:");
120
117
  const { url, cleanup } = await utils.openInBrowserPopup(conn.installationState.actionUri, "Authorize the GitHub app");
121
118
  utils.logBullet(`\t${url}`);
122
119
  await (0, prompt_1.promptOnce)({
123
120
  type: "input",
124
- message: "Press Enter once you have authorized the app",
121
+ message: "Press Enter once you have authorized the GitHub App.",
125
122
  });
126
123
  cleanup();
127
124
  const { projectId, location, id } = parseConnectionName(conn.name);
128
125
  conn = await devConnect.getConnection(projectId, location, id);
129
126
  }
127
+ utils.logSuccess("Connected with GitHub successfully\n");
130
128
  return conn;
131
129
  }
132
130
  exports.getOrCreateOauthConnection = getOrCreateOauthConnection;
@@ -135,7 +133,7 @@ async function promptCloneUri(projectId, connections) {
135
133
  const cloneUri = await (0, prompt_1.promptOnce)({
136
134
  type: "autocomplete",
137
135
  name: "cloneUri",
138
- message: "Which repository would you like to deploy?",
136
+ message: "Which GitHub repo do you want to deploy?",
139
137
  source: (_, input = "") => {
140
138
  return new Promise((resolve) => resolve([
141
139
  new inquirer.Separator(),
@@ -192,7 +190,7 @@ async function ensureSecretManagerAdminGrant(projectId) {
192
190
  throw e;
193
191
  }
194
192
  }
195
- utils.logSuccess("Successfully granted the required role to the Developer Connect Service Agent!");
193
+ utils.logSuccess("Successfully granted the required role to the Developer Connect Service Agent!\n");
196
194
  }
197
195
  exports.ensureSecretManagerAdminGrant = ensureSecretManagerAdminGrant;
198
196
  async function createConnection(projectId, location, connectionId, githubConfig) {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getBackendForAmbiguousLocation = exports.promptLocation = exports.deleteBackendAndPoll = exports.orchestrateRollout = exports.setDefaultTrafficPolicy = exports.createBackend = exports.ensureAppHostingComputeServiceAccount = exports.doSetup = void 0;
4
+ const clc = require("colorette");
4
5
  const poller = require("../operation-poller");
5
6
  const apphosting = require("../gcp/apphosting");
6
7
  const githubConnections = require("./githubConnections");
@@ -56,7 +57,6 @@ async function doSetup(projectId, webAppName, location, serviceAccount) {
56
57
  (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.artifactRegistryDomain)(), "apphosting", true),
57
58
  (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.iamOrigin)(), "apphosting", true),
58
59
  ]);
59
- (0, utils_1.logBullet)("First we need a few details to create your backend.\n");
60
60
  await ensureAppHostingComputeServiceAccount(projectId, serviceAccount);
61
61
  const allowedLocations = (await apphosting.listLocations(projectId)).map((loc) => loc.locationId);
62
62
  if (location) {
@@ -66,20 +66,6 @@ async function doSetup(projectId, webAppName, location, serviceAccount) {
66
66
  }
67
67
  location =
68
68
  location || (await promptLocation(projectId, "Select a location to host your backend:\n"));
69
- (0, utils_1.logSuccess)(`Location set to ${location}.\n`);
70
- const backendId = await promptNewBackendId(projectId, location, {
71
- name: "backendId",
72
- type: "input",
73
- default: "my-web-app",
74
- message: "Create a name for your backend [1-30 characters]",
75
- });
76
- const webApp = await app_1.webApps.getOrCreateWebApp(projectId, webAppName, backendId);
77
- if (webApp) {
78
- (0, utils_1.logSuccess)(`Created a new Firebase web app named "${webApp.name}"`);
79
- }
80
- else {
81
- (0, utils_1.logWarning)(`Firebase web app not set`);
82
- }
83
69
  const gitRepositoryConnection = await githubConnections.linkGitHubRepository(projectId, location);
84
70
  const rootDir = await (0, prompt_1.promptOnce)({
85
71
  name: "rootDir",
@@ -87,15 +73,28 @@ async function doSetup(projectId, webAppName, location, serviceAccount) {
87
73
  default: "/",
88
74
  message: "Specify your app's root directory relative to your repository",
89
75
  });
90
- const createBackendSpinner = ora("Creating your new backend...").start();
91
- const backend = await createBackend(projectId, location, backendId, gitRepositoryConnection, serviceAccount, webApp === null || webApp === void 0 ? void 0 : webApp.id, rootDir);
92
- createBackendSpinner.succeed(`Successfully created backend:\n\t${backend.name}\n`);
93
76
  const branch = await (0, prompt_1.promptOnce)({
94
77
  name: "branch",
95
78
  type: "input",
96
79
  default: "main",
97
80
  message: "Pick a branch for continuous deployment",
98
81
  });
82
+ (0, utils_1.logSuccess)(`Repo linked successfully!\n`);
83
+ (0, utils_1.logBullet)(`${clc.yellow("===")} Set up your backend`);
84
+ const backendId = await promptNewBackendId(projectId, location, {
85
+ name: "backendId",
86
+ type: "input",
87
+ default: "my-web-app",
88
+ message: "Provide a name for your backend [1-30 characters]",
89
+ });
90
+ (0, utils_1.logSuccess)(`Name set to ${backendId}\n`);
91
+ const webApp = await app_1.webApps.getOrCreateWebApp(projectId, webAppName, backendId);
92
+ if (!webApp) {
93
+ (0, utils_1.logWarning)(`Firebase web app not set`);
94
+ }
95
+ const createBackendSpinner = ora("Creating your new backend...").start();
96
+ const backend = await createBackend(projectId, location, backendId, gitRepositoryConnection, serviceAccount, webApp === null || webApp === void 0 ? void 0 : webApp.id, rootDir);
97
+ createBackendSpinner.succeed(`Successfully created backend!\n\t${backend.name}\n`);
99
98
  await setDefaultTrafficPolicy(projectId, location, backendId, branch);
100
99
  const confirmRollout = await (0, prompt_1.promptOnce)({
101
100
  type: "confirm",
@@ -264,13 +263,15 @@ async function promptLocation(projectId, prompt = "Please select a location:") {
264
263
  if (allowedLocations.length === 1) {
265
264
  return allowedLocations[0];
266
265
  }
267
- return (await (0, prompt_1.promptOnce)({
266
+ const location = (await (0, prompt_1.promptOnce)({
268
267
  name: "location",
269
268
  type: "list",
270
269
  default: constants_1.DEFAULT_LOCATION,
271
270
  message: prompt,
272
271
  choices: allowedLocations,
273
272
  }));
273
+ (0, utils_1.logSuccess)(`Location set to ${location}.\n`);
274
+ return location;
274
275
  }
275
276
  exports.promptLocation = promptLocation;
276
277
  async function getBackendForAmbiguousLocation(projectId, backendId, locationDisambugationPrompt) {
@@ -52,7 +52,7 @@ function generateConnectionId() {
52
52
  const ADD_CONN_CHOICE = "@ADD_CONN";
53
53
  async function linkGitHubRepository(projectId, location) {
54
54
  var _a, _b;
55
- utils.logBullet(clc.bold(`${clc.yellow("===")} Set up a GitHub connection`));
55
+ utils.logBullet(clc.bold(`${clc.yellow("===")} Import a GitHub repository`));
56
56
  const oauthConn = await getOrCreateOauthConnection(projectId, location);
57
57
  const existingConns = await listAppHostingConnections(projectId);
58
58
  if (existingConns.length === 0) {
@@ -132,7 +132,7 @@ async function promptRepositoryUri(projectId, connections) {
132
132
  const remoteUri = await (0, prompt_1.promptOnce)({
133
133
  type: "autocomplete",
134
134
  name: "remoteUri",
135
- message: "Which repository would you like to deploy?",
135
+ message: "Which GitHub repo do you want to deploy?",
136
136
  source: (_, input = "") => {
137
137
  return new Promise((resolve) => resolve([
138
138
  new inquirer.Separator(),
@@ -10,7 +10,7 @@ const firedata_1 = require("../gcp/firedata");
10
10
  const requireTosAcceptance_1 = require("../requireTosAcceptance");
11
11
  exports.command = new command_1.Command("apphosting:backends:create")
12
12
  .description("create a Firebase App Hosting backend")
13
- .option("-a, --app <webApp>", "specify an existing Firebase web app to associate your App Hosting backend with")
13
+ .option("-a, --app <webAppId>", "specify an existing Firebase web app's ID to associate your App Hosting backend with")
14
14
  .option("-l, --location <location>", "specify the location of the backend", "")
15
15
  .option("-s, --service-account <serviceAccount>", "specify the service account used to run the server", "")
16
16
  .before(apphosting_2.ensureApiEnabled)
@@ -18,8 +18,8 @@ exports.command = new command_1.Command("apphosting:backends:create")
18
18
  .before((0, requireTosAcceptance_1.requireTosAcceptance)(firedata_1.APPHOSTING_TOS_ID))
19
19
  .action(async (options) => {
20
20
  const projectId = (0, projectUtils_1.needProjectId)(options);
21
- const webApp = options.app;
21
+ const webAppId = options.app;
22
22
  const location = options.location;
23
23
  const serviceAccount = options.serviceAccount;
24
- await (0, apphosting_1.doSetup)(projectId, webApp, location, serviceAccount);
24
+ await (0, apphosting_1.doSetup)(projectId, webAppId, location, serviceAccount);
25
25
  });
@@ -9,7 +9,7 @@ const logger_1 = require("../logger");
9
9
  const requirePermissions_1 = require("../requirePermissions");
10
10
  const ensureApis_1 = require("../dataconnect/ensureApis");
11
11
  const Table = require("cli-table");
12
- exports.command = new command_1.Command("dataconnect:list")
12
+ exports.command = new command_1.Command("dataconnect:services:list")
13
13
  .description("list all deployed services in your Firebase project")
14
14
  .before(requirePermissions_1.requirePermissions, [
15
15
  "dataconnect.services.list",
@@ -17,7 +17,7 @@ exports.command = new command_1.Command("dataconnect:list")
17
17
  "dataconnect.connectors.list",
18
18
  ])
19
19
  .action(async (options) => {
20
- var _a, _b, _c, _d, _e;
20
+ var _a, _b, _c, _d, _e, _f;
21
21
  const projectId = (0, projectUtils_1.needProjectId)(options);
22
22
  await (0, ensureApis_1.ensureApis)(projectId);
23
23
  const services = await client.listAllServices(projectId);
@@ -34,14 +34,31 @@ exports.command = new command_1.Command("dataconnect:list")
34
34
  });
35
35
  const jsonOutput = { services: [] };
36
36
  for (const service of services) {
37
- const schema = await client.getSchema(service.name);
37
+ let schema = {
38
+ name: "",
39
+ primaryDatasource: {},
40
+ source: { files: [] },
41
+ };
42
+ try {
43
+ schema = await client.getSchema(service.name);
44
+ }
45
+ catch (err) {
46
+ logger_1.logger.debug(`Error fetching schema: ${err}`);
47
+ }
38
48
  const connectors = await client.listConnectors(service.name);
39
49
  const serviceName = names.parseServiceName(service.name);
40
50
  const instanceName = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.primaryDatasource.postgresql) === null || _a === void 0 ? void 0 : _a.cloudSql.instance) !== null && _b !== void 0 ? _b : "";
41
51
  const instanceId = instanceName.split("/").pop();
42
52
  const dbId = (_d = (_c = schema === null || schema === void 0 ? void 0 : schema.primaryDatasource.postgresql) === null || _c === void 0 ? void 0 : _c.database) !== null && _d !== void 0 ? _d : "";
43
- const dbName = `CloudSQL Instance: ${instanceId} Database:${dbId}`;
44
- table.push([serviceName.serviceId, serviceName.location, dbName, schema === null || schema === void 0 ? void 0 : schema.updateTime, "", ""]);
53
+ const dbName = `CloudSQL Instance: ${instanceId}\nDatabase:${dbId}`;
54
+ table.push([
55
+ serviceName.serviceId,
56
+ serviceName.location,
57
+ dbName,
58
+ (_e = schema === null || schema === void 0 ? void 0 : schema.updateTime) !== null && _e !== void 0 ? _e : "",
59
+ "",
60
+ "",
61
+ ]);
45
62
  const serviceJson = {
46
63
  serviceId: serviceName.serviceId,
47
64
  location: serviceName.location,
@@ -54,7 +71,7 @@ exports.command = new command_1.Command("dataconnect:list")
54
71
  table.push(["", "", "", "", connectorName.connectorId, conn.updateTime]);
55
72
  serviceJson.connectors.push({
56
73
  connectorId: connectorName.connectorId,
57
- connectorLastUpdated: (_e = conn.updateTime) !== null && _e !== void 0 ? _e : "",
74
+ connectorLastUpdated: (_f = conn.updateTime) !== null && _f !== void 0 ? _f : "",
58
75
  });
59
76
  }
60
77
  jsonOutput.services.push(serviceJson);
@@ -4,12 +4,12 @@ exports.command = void 0;
4
4
  const command_1 = require("../command");
5
5
  const projectUtils_1 = require("../projectUtils");
6
6
  const fileUtils_1 = require("../dataconnect/fileUtils");
7
- const logger_1 = require("../logger");
8
7
  const error_1 = require("../error");
9
8
  const schemaMigration_1 = require("../dataconnect/schemaMigration");
10
9
  const requireAuth_1 = require("../requireAuth");
11
10
  const requirePermissions_1 = require("../requirePermissions");
12
11
  const ensureApis_1 = require("../dataconnect/ensureApis");
12
+ const utils_1 = require("../utils");
13
13
  exports.command = new command_1.Command("dataconnect:sql:migrate [serviceId]")
14
14
  .description("migrates your CloudSQL database's schema to match your local DataConnect schema")
15
15
  .before(requirePermissions_1.requirePermissions, [
@@ -37,10 +37,10 @@ exports.command = new command_1.Command("dataconnect:sql:migrate [serviceId]")
37
37
  validateOnly: true,
38
38
  });
39
39
  if (diffs.length) {
40
- logger_1.logger.info(`Schema sucessfully migrated! Run 'firebase deploy' to deploy your new schema to your Data Connect service.`);
40
+ (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema sucessfully migrated! Run 'firebase deploy' to deploy your new schema to your Data Connect service.`);
41
41
  }
42
42
  else {
43
- logger_1.logger.info("Schema was already up to date!");
43
+ (0, utils_1.logLabeledSuccess)("dataconnect", "Database schema is already up to date!");
44
44
  }
45
45
  return { projectId, serviceId, diffs };
46
46
  });
@@ -203,7 +203,8 @@ function load(client) {
203
203
  if (experiments.isEnabled("dataconnect")) {
204
204
  client.dataconnect = {};
205
205
  client.setup.emulators.dataconnect = loadCommand("setup-emulators-dataconnect");
206
- client.dataconnect.list = loadCommand("dataconnect-list");
206
+ client.dataconnect.services = {};
207
+ client.dataconnect.services.list = loadCommand("dataconnect-services-list");
207
208
  client.dataconnect.sql = {};
208
209
  client.dataconnect.sql.diff = loadCommand("dataconnect-sql-diff");
209
210
  client.dataconnect.sql.migrate = loadCommand("dataconnect-sql-migrate");
@@ -69,10 +69,10 @@ const choices = [
69
69
  checked: false,
70
70
  },
71
71
  ];
72
- if ((0, experiments_1.isEnabled)("apphosting")) {
72
+ if ((0, experiments_1.isEnabled)("genkit")) {
73
73
  choices.push({
74
- value: "apphosting",
75
- name: "App Hosting: Get started with App Hosting projects.",
74
+ value: "genkit",
75
+ name: "Genkit: Setup a new Genkit project with Firebase",
76
76
  checked: false,
77
77
  });
78
78
  }
@@ -21,7 +21,7 @@ exports.listLocations = listLocations;
21
21
  async function listAllServices(projectId) {
22
22
  const locations = await listLocations(projectId);
23
23
  let services = [];
24
- for (const l of locations) {
24
+ await Promise.all(locations.map(async (l) => {
25
25
  try {
26
26
  const locationServices = await listServices(projectId, l);
27
27
  services = services.concat(locationServices);
@@ -29,7 +29,7 @@ async function listAllServices(projectId) {
29
29
  catch (err) {
30
30
  logger_1.logger.debug(`Unable to listServices in ${l}: ${err}`);
31
31
  }
32
- }
32
+ }));
33
33
  return services;
34
34
  }
35
35
  exports.listAllServices = listAllServices;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getInvalidConnectors = exports.getIncompatibleSchemaError = void 0;
4
+ const INCOMPATIBLE_SCHEMA_ERROR_TYPESTRING = "IncompatibleSqlSchemaError";
5
+ const PRECONDITION_ERROR_TYPESTRING = "type.googleapis.com/google.rpc.PreconditionFailure";
6
+ const INCOMPATIBLE_CONNECTOR_TYPE = "INCOMPATIBLE_CONNECTOR";
7
+ function getIncompatibleSchemaError(err) {
8
+ var _a, _b;
9
+ const original = ((_b = (_a = err.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) || err.orignal;
10
+ if (!original) {
11
+ throw err;
12
+ }
13
+ const details = original.details;
14
+ const incompatibles = details.filter((d) => { var _a; return (_a = d["@type"]) === null || _a === void 0 ? void 0 : _a.includes(INCOMPATIBLE_SCHEMA_ERROR_TYPESTRING); });
15
+ return incompatibles[0];
16
+ }
17
+ exports.getIncompatibleSchemaError = getIncompatibleSchemaError;
18
+ function getInvalidConnectors(err) {
19
+ var _a, _b, _c, _d;
20
+ const invalidConns = [];
21
+ const original = ((_b = (_a = err.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) || (err === null || err === void 0 ? void 0 : err.orignal);
22
+ const details = original === null || original === void 0 ? void 0 : original.details;
23
+ const preconditionErrs = details === null || details === void 0 ? void 0 : details.filter((d) => { var _a; return (_a = d["@type"]) === null || _a === void 0 ? void 0 : _a.includes(PRECONDITION_ERROR_TYPESTRING); });
24
+ for (const preconditionErr of preconditionErrs) {
25
+ const incompatibleConnViolation = (_c = preconditionErr === null || preconditionErr === void 0 ? void 0 : preconditionErr.violations) === null || _c === void 0 ? void 0 : _c.filter((v) => v.type === INCOMPATIBLE_CONNECTOR_TYPE);
26
+ const newConns = (_d = incompatibleConnViolation === null || incompatibleConnViolation === void 0 ? void 0 : incompatibleConnViolation.map((i) => i.subject)) !== null && _d !== void 0 ? _d : [];
27
+ invalidConns.push(...newConns);
28
+ }
29
+ return invalidConns;
30
+ }
31
+ exports.getInvalidConnectors = getInvalidConnectors;
@@ -51,17 +51,20 @@ function validateConnectorYaml(unvalidated) {
51
51
  }
52
52
  async function readGQLFiles(sourceDir) {
53
53
  const files = await fs.readdir(sourceDir);
54
- return files.filter((f) => f.endsWith(".gql")).map((f) => toFile(path.join(sourceDir, f)));
54
+ return files
55
+ .filter((f) => f.endsWith(".gql") || f.endsWith(".graphql"))
56
+ .map((f) => toFile(sourceDir, f));
55
57
  }
56
58
  exports.readGQLFiles = readGQLFiles;
57
- function toFile(path) {
58
- if (!fs.existsSync(path)) {
59
- throw new error_1.FirebaseError(`file ${path} not found`);
59
+ function toFile(sourceDir, relPath) {
60
+ const fullPath = path.join(sourceDir, relPath);
61
+ if (!fs.existsSync(fullPath)) {
62
+ throw new error_1.FirebaseError(`file ${fullPath} not found`);
60
63
  }
61
- const file = fs.readFileSync(path).toString();
64
+ const content = fs.readFileSync(fullPath).toString();
62
65
  return {
63
- path: path,
64
- content: file,
66
+ path: relPath,
67
+ content,
65
68
  };
66
69
  }
67
70
  async function pickService(projectId, config, serviceId) {
@@ -4,7 +4,7 @@ exports.printFreeTrialUnavailable = exports.checkForFreeTrialInstance = exports.
4
4
  const cloudsqladmin_1 = require("../gcp/cloudsql/cloudsqladmin");
5
5
  const utils = require("../utils");
6
6
  function freeTrialTermsLink() {
7
- return "";
7
+ return "https://firebase.google.com/pricing";
8
8
  }
9
9
  exports.freeTrialTermsLink = freeTrialTermsLink;
10
10
  async function checkForFreeTrialInstance(projectId) {
@@ -5,8 +5,8 @@ function prettify(err) {
5
5
  var _a;
6
6
  const message = err.message;
7
7
  let header = (_a = err.extensions.file) !== null && _a !== void 0 ? _a : "";
8
- for (const loc of err.locations) {
9
- header += `(${loc.line}, ${loc.column})`;
8
+ if (err.locations) {
9
+ header += `:${err.locations[0].line}`;
10
10
  }
11
11
  return header.length ? `${header}: ${message}` : message;
12
12
  }
@@ -4,6 +4,7 @@ exports.checkInstanceConfig = exports.provisionCloudSql = void 0;
4
4
  const cloudSqlAdminClient = require("../gcp/cloudsql/cloudsqladmin");
5
5
  const utils = require("../utils");
6
6
  const checkIam_1 = require("./checkIam");
7
+ const utils_1 = require("../utils");
7
8
  const GOOGLE_ML_INTEGRATION_ROLE = "roles/aiplatform.user";
8
9
  const freeTrial_1 = require("./freeTrial");
9
10
  const error_1 = require("../error");
@@ -16,9 +17,9 @@ async function provisionCloudSql(args) {
16
17
  connectionName = (existingInstance === null || existingInstance === void 0 ? void 0 : existingInstance.connectionName) || "";
17
18
  if (!checkInstanceConfig(existingInstance, enableGoogleMlIntegration)) {
18
19
  silent ||
19
- utils.logLabeledBullet("dataconnect", `Instance ${instanceId} settings not compatible with Firebase Data Connect.` +
20
+ utils.logLabeledBullet("dataconnect", `Instance ${instanceId} settings not compatible with Firebase Data Connect. ` +
20
21
  `Updating instance to enable Cloud IAM authentication and public IP. This may take a few minutes...`);
21
- await cloudSqlAdminClient.updateInstanceForDataConnect(existingInstance, enableGoogleMlIntegration);
22
+ await (0, utils_1.promiseWithSpinner)(() => cloudSqlAdminClient.updateInstanceForDataConnect(existingInstance, enableGoogleMlIntegration), "Updating your instance...");
22
23
  silent || utils.logLabeledBullet("dataconnect", "Instance updated");
23
24
  }
24
25
  }
@@ -34,7 +35,7 @@ async function provisionCloudSql(args) {
34
35
  silent ||
35
36
  utils.logLabeledBullet("dataconnect", `CloudSQL instance '${instanceId}' not found, creating it. This instance is provided under the terms of the Data Connect free trial ${(0, freeTrial_1.freeTrialTermsLink)()}`);
36
37
  silent || utils.logLabeledBullet("dataconnect", `This may take while...`);
37
- const newInstance = await cloudSqlAdminClient.createInstance(projectId, locationId, instanceId, enableGoogleMlIntegration);
38
+ const newInstance = await (0, utils_1.promiseWithSpinner)(() => cloudSqlAdminClient.createInstance(projectId, locationId, instanceId, enableGoogleMlIntegration), "Creating your instance...");
38
39
  silent || utils.logLabeledBullet("dataconnect", "Instance created");
39
40
  connectionName = (newInstance === null || newInstance === void 0 ? void 0 : newInstance.connectionName) || "";
40
41
  }