firebase-tools 13.20.1 → 13.21.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 (36) hide show
  1. package/lib/apphosting/githubConnections.js +19 -1
  2. package/lib/apphosting/index.js +12 -46
  3. package/lib/apphosting/rollout.js +127 -0
  4. package/lib/command.js +10 -3
  5. package/lib/commands/apphosting-rollouts-create.js +13 -13
  6. package/lib/commands/emulators-start.js +1 -1
  7. package/lib/config.js +14 -4
  8. package/lib/dataconnect/fileUtils.js +7 -43
  9. package/lib/dataconnect/freeTrial.js +44 -10
  10. package/lib/dataconnect/provisionCloudSql.js +4 -4
  11. package/lib/dataconnect/types.js +3 -2
  12. package/lib/dataconnect/webhook.js +2 -1
  13. package/lib/deploy/dataconnect/prepare.js +5 -0
  14. package/lib/emulator/apphosting/config.js +45 -0
  15. package/lib/emulator/apphosting/index.js +9 -11
  16. package/lib/emulator/apphosting/serve.js +16 -10
  17. package/lib/emulator/apphosting/utils.js +18 -0
  18. package/lib/emulator/controller.js +6 -1
  19. package/lib/emulator/downloadableEmulators.js +12 -12
  20. package/lib/emulator/eventarcEmulator.js +1 -1
  21. package/lib/emulator/extensionsEmulator.js +38 -6
  22. package/lib/emulator/functionsEmulator.js +85 -41
  23. package/lib/emulator/functionsEmulatorShared.js +2 -1
  24. package/lib/error.js +24 -1
  25. package/lib/extensions/emulator/triggerHelper.js +1 -1
  26. package/lib/extensions/extensionsApi.js +11 -8
  27. package/lib/extensions/runtimes/common.js +11 -19
  28. package/lib/extensions/runtimes/node.js +25 -22
  29. package/lib/extensions/types.js +16 -1
  30. package/lib/gcp/cloudmonitoring.js +3 -3
  31. package/lib/gcp/cloudsql/cloudsqladmin.js +32 -20
  32. package/lib/gcp/devConnect.js +38 -1
  33. package/lib/init/features/dataconnect/index.js +69 -85
  34. package/lib/init/features/dataconnect/sdk.js +69 -86
  35. package/lib/init/spawn.js +2 -1
  36. package/package.json +1 -1
@@ -24,6 +24,11 @@ const CONNECTOR_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconn
24
24
  const SCHEMA_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/schema.gql");
25
25
  const QUERIES_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/queries.gql");
26
26
  const MUTATIONS_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/mutations.gql");
27
+ const emptyConnector = {
28
+ id: "default",
29
+ path: "./connector",
30
+ files: [],
31
+ };
27
32
  const defaultConnector = {
28
33
  id: "default",
29
34
  path: "./connector",
@@ -38,29 +43,27 @@ const defaultConnector = {
38
43
  },
39
44
  ],
40
45
  };
46
+ const defaultSchema = { path: "schema.gql", content: SCHEMA_TEMPLATE };
41
47
  async function doSetup(setup, config) {
42
- const info = await askQuestions(setup);
48
+ const isBillingEnabled = setup.projectId ? await (0, cloudbilling_1.checkBillingEnabled)(setup.projectId) : false;
49
+ if (setup.projectId) {
50
+ isBillingEnabled ? await (0, ensureApis_1.ensureApis)(setup.projectId) : await (0, ensureApis_1.ensureSparkApis)(setup.projectId);
51
+ }
52
+ const info = await askQuestions(setup, isBillingEnabled);
43
53
  await actuate(setup, config, info);
44
54
  const cwdPlatformGuess = await (0, fileUtils_1.getPlatformFromFolder)(process.cwd());
45
- if (cwdPlatformGuess !== types_1.Platform.UNDETERMINED) {
55
+ if (cwdPlatformGuess !== types_1.Platform.NONE) {
46
56
  await sdk.doSetup(setup, config);
47
57
  }
48
58
  else {
49
- const promptForSDKGeneration = await (0, prompt_1.confirm)({
50
- message: `Would you like to configure generated SDKs now?`,
51
- default: false,
52
- });
53
- if (promptForSDKGeneration) {
54
- await sdk.doSetup(setup, config);
55
- }
56
- else {
57
- (0, utils_1.logBullet)(`If you'd like to generate an SDK for your new connector later, run ${clc.bold("firebase init dataconnect:sdk")}`);
58
- }
59
+ (0, utils_1.logBullet)(`If you'd like to add the generated SDK to your app your, run ${clc.bold("firebase init dataconnect:sdk")}`);
60
+ }
61
+ if (setup.projectId && !isBillingEnabled) {
62
+ (0, utils_1.logBullet)((0, freeTrial_1.upgradeInstructions)(setup.projectId));
59
63
  }
60
- logger_1.logger.info("");
61
64
  }
62
65
  exports.doSetup = doSetup;
63
- async function askQuestions(setup) {
66
+ async function askQuestions(setup, isBillingEnabled) {
64
67
  let info = {
65
68
  serviceId: "",
66
69
  locationId: "",
@@ -69,14 +72,10 @@ async function askQuestions(setup) {
69
72
  cloudSqlDatabase: "",
70
73
  isNewDatabase: false,
71
74
  connectors: [defaultConnector],
72
- schemaGql: [],
75
+ schemaGql: [defaultSchema],
73
76
  shouldProvisionCSQL: false,
74
77
  };
75
- const isBillingEnabled = setup.projectId ? await (0, cloudbilling_1.checkBillingEnabled)(setup.projectId) : false;
76
- if (setup.projectId) {
77
- isBillingEnabled ? await (0, ensureApis_1.ensureApis)(setup.projectId) : await (0, ensureApis_1.ensureSparkApis)(setup.projectId);
78
- }
79
- info = await checkExistingInstances(setup, info, isBillingEnabled);
78
+ info = await promptForExistingServices(setup, info, isBillingEnabled);
80
79
  const requiredConfigUnset = info.serviceId === "" ||
81
80
  info.cloudSqlInstanceId === "" ||
82
81
  info.locationId === "" ||
@@ -84,13 +83,12 @@ async function askQuestions(setup) {
84
83
  const shouldConfigureBackend = isBillingEnabled && requiredConfigUnset
85
84
  ? await (0, prompt_1.confirm)({
86
85
  message: `Would you like to configure your backend resources now?`,
87
- default: false,
86
+ default: true,
88
87
  })
89
88
  : false;
90
89
  if (shouldConfigureBackend) {
91
90
  info = await promptForService(info);
92
- info = await promptForCloudSQLInstance(setup, info);
93
- info = await promptForDatabase(info);
91
+ info = await promptForCloudSQL(setup, info);
94
92
  info.shouldProvisionCSQL = !!(setup.projectId &&
95
93
  (info.isNewInstance || info.isNewDatabase) &&
96
94
  isBillingEnabled &&
@@ -100,14 +98,10 @@ async function askQuestions(setup) {
100
98
  })));
101
99
  }
102
100
  else {
103
- if (requiredConfigUnset) {
104
- (0, utils_1.logBullet)(`Setting placeholder values in dataconnect.yaml. You can edit these before you deploy to specify different IDs or regions.`);
105
- }
106
- info.serviceId = info.serviceId !== "" ? info.serviceId : (0, path_1.basename)(process.cwd());
107
- info.cloudSqlInstanceId =
108
- info.cloudSqlInstanceId !== "" ? info.cloudSqlInstanceId : `${info.serviceId || "app"}-fdc`;
109
- info.locationId = info.locationId !== "" ? info.locationId : `us-central1`;
110
- info.cloudSqlDatabase = info.cloudSqlDatabase !== "" ? info.cloudSqlDatabase : `fdcdb`;
101
+ info.serviceId = info.serviceId || (0, path_1.basename)(process.cwd());
102
+ info.cloudSqlInstanceId = info.cloudSqlInstanceId || `${info.serviceId || "app"}-fdc`;
103
+ info.locationId = info.locationId || `us-central1`;
104
+ info.cloudSqlDatabase = info.cloudSqlDatabase || `fdcdb`;
111
105
  }
112
106
  return info;
113
107
  }
@@ -130,16 +124,12 @@ async function writeFiles(config, info) {
130
124
  const dir = config.get("dataconnect.source") || "dataconnect";
131
125
  const subbedDataconnectYaml = subDataconnectYamlValues(Object.assign(Object.assign({}, info), { connectorDirs: info.connectors.map((c) => c.path) }));
132
126
  config.set("dataconnect", { source: dir });
133
- await config.askWriteProjectFile((0, path_1.join)(dir, "dataconnect.yaml"), subbedDataconnectYaml);
127
+ await config.askWriteProjectFile((0, path_1.join)(dir, "dataconnect.yaml"), subbedDataconnectYaml, false, true);
134
128
  if (info.schemaGql.length) {
135
- (0, utils_1.logSuccess)("The service you chose already has GQL files deployed. We'll use those instead of the default templates.");
136
129
  for (const f of info.schemaGql) {
137
130
  await config.askWriteProjectFile((0, path_1.join)(dir, "schema", f.path), f.content);
138
131
  }
139
132
  }
140
- else {
141
- await config.askWriteProjectFile((0, path_1.join)(dir, "schema", "schema.gql"), SCHEMA_TEMPLATE);
142
- }
143
133
  for (const c of info.connectors) {
144
134
  await writeConnectorFiles(config, c);
145
135
  }
@@ -178,8 +168,8 @@ function subConnectorYamlValues(replacementValues) {
178
168
  }
179
169
  return replaced;
180
170
  }
181
- async function checkExistingInstances(setup, info, isBillingEnabled) {
182
- var _a, _b, _c;
171
+ async function promptForExistingServices(setup, info, isBillingEnabled) {
172
+ var _a, _b, _c, _d;
183
173
  if (!setup.projectId || !isBillingEnabled) {
184
174
  return info;
185
175
  }
@@ -208,16 +198,18 @@ async function checkExistingInstances(setup, info, isBillingEnabled) {
208
198
  const serviceName = (0, names_1.parseServiceName)(choice.service.name);
209
199
  info.serviceId = serviceName.serviceId;
210
200
  info.locationId = serviceName.location;
201
+ info.schemaGql = [];
202
+ info.connectors = [emptyConnector];
211
203
  if (choice.schema) {
212
204
  const primaryDatasource = choice.schema.datasources.find((d) => d.postgresql);
213
205
  if ((_a = primaryDatasource === null || primaryDatasource === void 0 ? void 0 : primaryDatasource.postgresql) === null || _a === void 0 ? void 0 : _a.cloudSql.instance) {
214
206
  const instanceName = (0, names_1.parseCloudSQLInstanceName)(primaryDatasource.postgresql.cloudSql.instance);
215
207
  info.cloudSqlInstanceId = instanceName.instanceId;
216
208
  }
217
- if (choice.schema.source.files) {
209
+ if ((_b = choice.schema.source.files) === null || _b === void 0 ? void 0 : _b.length) {
218
210
  info.schemaGql = choice.schema.source.files;
219
211
  }
220
- info.cloudSqlDatabase = (_c = (_b = primaryDatasource === null || primaryDatasource === void 0 ? void 0 : primaryDatasource.postgresql) === null || _b === void 0 ? void 0 : _b.database) !== null && _c !== void 0 ? _c : "";
212
+ info.cloudSqlDatabase = (_d = (_c = primaryDatasource === null || primaryDatasource === void 0 ? void 0 : primaryDatasource.postgresql) === null || _c === void 0 ? void 0 : _c.database) !== null && _d !== void 0 ? _d : "";
221
213
  const connectors = await (0, client_1.listConnectors)(choice.service.name, [
222
214
  "connectors.name",
223
215
  "connectors.source.files",
@@ -234,20 +226,24 @@ async function checkExistingInstances(setup, info, isBillingEnabled) {
234
226
  }
235
227
  }
236
228
  }
237
- else {
238
- info = await promptForService(info);
239
- }
240
229
  }
241
- if (info.cloudSqlInstanceId === "") {
230
+ return info;
231
+ }
232
+ async function promptForCloudSQL(setup, info) {
233
+ if (info.cloudSqlInstanceId === "" && setup.projectId) {
242
234
  const instances = await cloudsql.listInstances(setup.projectId);
243
235
  let choices = instances.map((i) => {
244
- return { name: i.name, value: i.name, location: i.region };
236
+ var _a;
237
+ let display = `${i.name} (${i.region})`;
238
+ if (((_a = i.settings.userLabels) === null || _a === void 0 ? void 0 : _a["firebase-data-connect"]) === "ft") {
239
+ display += " (no cost trial)";
240
+ }
241
+ return { name: display, value: i.name, location: i.region };
245
242
  });
246
243
  choices = choices.filter((c) => info.locationId === "" || info.locationId === c.location);
247
244
  if (choices.length) {
248
- const freeTrialInstanceId = await (0, freeTrial_1.checkForFreeTrialInstance)(setup.projectId);
249
- if (!freeTrialInstanceId) {
250
- choices.push({ name: "Create a new instance", value: "", location: "" });
245
+ if (!(await (0, freeTrial_1.checkFreeTrialInstanceUsed)(setup.projectId))) {
246
+ choices.push({ name: "Create a new free trial instance", value: "", location: "" });
251
247
  }
252
248
  info.cloudSqlInstanceId = await (0, prompt_1.promptOnce)({
253
249
  message: `Which CloudSQL instance would you like to use?`,
@@ -257,12 +253,25 @@ async function checkExistingInstances(setup, info, isBillingEnabled) {
257
253
  if (info.cloudSqlInstanceId !== "") {
258
254
  info.locationId = choices.find((c) => c.value === info.cloudSqlInstanceId).location;
259
255
  }
260
- else {
261
- info = await promptForCloudSQLInstance(setup, info);
262
- }
263
256
  }
264
257
  }
265
- if (info.cloudSqlDatabase === "" && info.cloudSqlInstanceId !== "") {
258
+ if (info.cloudSqlInstanceId === "") {
259
+ info.isNewInstance = true;
260
+ info.cloudSqlInstanceId = await (0, prompt_1.promptOnce)({
261
+ message: `What ID would you like to use for your new CloudSQL instance?`,
262
+ type: "input",
263
+ default: `${info.serviceId || "app"}-fdc`,
264
+ });
265
+ }
266
+ if (info.locationId === "") {
267
+ const choices = await locationChoices(setup);
268
+ info.locationId = await (0, prompt_1.promptOnce)({
269
+ message: "What location would like to use?",
270
+ type: "list",
271
+ choices,
272
+ });
273
+ }
274
+ if (info.cloudSqlDatabase === "" && setup.projectId) {
266
275
  try {
267
276
  const dbs = await cloudsql.listDatabases(setup.projectId, info.cloudSqlInstanceId);
268
277
  const choices = dbs.map((d) => {
@@ -275,15 +284,20 @@ async function checkExistingInstances(setup, info, isBillingEnabled) {
275
284
  type: "list",
276
285
  choices,
277
286
  });
278
- if (info.cloudSqlDatabase === "") {
279
- info = await promptForDatabase(info);
280
- }
281
287
  }
282
288
  }
283
289
  catch (err) {
284
290
  logger_1.logger.debug(`[dataconnect] Cannot list databases during init: ${err}`);
285
291
  }
286
292
  }
293
+ if (info.cloudSqlDatabase === "") {
294
+ info.isNewDatabase = true;
295
+ info.cloudSqlDatabase = await (0, prompt_1.promptOnce)({
296
+ message: `What ID would you like to use for your new database in ${info.cloudSqlInstanceId}?`,
297
+ type: "input",
298
+ default: `fdcdb`,
299
+ });
300
+ }
287
301
  return info;
288
302
  }
289
303
  async function promptForService(info) {
@@ -296,25 +310,6 @@ async function promptForService(info) {
296
310
  }
297
311
  return info;
298
312
  }
299
- async function promptForCloudSQLInstance(setup, info) {
300
- if (info.cloudSqlInstanceId === "") {
301
- info.isNewInstance = true;
302
- info.cloudSqlInstanceId = await (0, prompt_1.promptOnce)({
303
- message: `What ID would you like to use for your new CloudSQL instance?`,
304
- type: "input",
305
- default: `${info.serviceId || "app"}-fdc`,
306
- });
307
- }
308
- if (info.locationId === "") {
309
- const choices = await locationChoices(setup);
310
- info.locationId = await (0, prompt_1.promptOnce)({
311
- message: "What location would like to use?",
312
- type: "list",
313
- choices,
314
- });
315
- }
316
- return info;
317
- }
318
313
  async function locationChoices(setup) {
319
314
  if (setup.projectId) {
320
315
  const locations = await (0, client_1.listLocations)(setup.projectId);
@@ -335,14 +330,3 @@ async function locationChoices(setup) {
335
330
  ];
336
331
  }
337
332
  }
338
- async function promptForDatabase(info) {
339
- if (info.cloudSqlDatabase === "") {
340
- info.isNewDatabase = true;
341
- info.cloudSqlDatabase = await (0, prompt_1.promptOnce)({
342
- message: `What ID would you like to use for your new database in ${info.cloudSqlInstanceId}?`,
343
- type: "input",
344
- default: `fdcdb`,
345
- });
346
- }
347
- return info;
348
- }
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.actuate = exports.doSetup = exports.FDC_APP_FOLDER = void 0;
3
+ exports.actuate = exports.generateSdkYaml = exports.doSetup = exports.FDC_APP_FOLDER = void 0;
4
4
  const yaml = require("yaml");
5
5
  const fs = require("fs");
6
6
  const clc = require("colorette");
7
7
  const path = require("path");
8
+ const fsutils_1 = require("../../../fsutils");
8
9
  const prompt_1 = require("../../../prompt");
9
10
  const fileUtils_1 = require("../../../dataconnect/fileUtils");
10
11
  const load_1 = require("../../../dataconnect/load");
@@ -16,12 +17,12 @@ const utils_1 = require("../../../utils");
16
17
  exports.FDC_APP_FOLDER = "_FDC_APP_FOLDER";
17
18
  async function doSetup(setup, config) {
18
19
  const sdkInfo = await askQuestions(setup, config);
19
- await actuate(sdkInfo, setup.projectId);
20
- (0, utils_1.logSuccess)(`If you'd like to generate additional SDKs later, run ${clc.bold("firebase init dataconnect:sdk")}`);
20
+ await actuate(sdkInfo);
21
+ (0, utils_1.logSuccess)(`If you'd like to add more generated SDKs to your app your later, run ${clc.bold("firebase init dataconnect:sdk")} again`);
21
22
  }
22
23
  exports.doSetup = doSetup;
23
24
  async function askQuestions(setup, config) {
24
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
25
+ var _a;
25
26
  const serviceCfgs = (0, fileUtils_1.readFirebaseJson)(config);
26
27
  const serviceInfos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(setup.projectId || "", config, c.source)));
27
28
  const connectorChoices = serviceInfos
@@ -37,121 +38,103 @@ async function askQuestions(setup, config) {
37
38
  if (!connectorChoices.length) {
38
39
  throw new error_1.FirebaseError(`Your config has no connectors to set up SDKs for. Run ${clc.bold("firebase init dataconnect")} to set up a service and connectors.`);
39
40
  }
40
- let targetPlatform = types_1.Platform.UNDETERMINED;
41
41
  let appDir = process.env[exports.FDC_APP_FOLDER] || process.cwd();
42
- const cwdPlatformGuess = await (0, fileUtils_1.getPlatformFromFolder)(appDir);
43
- if (cwdPlatformGuess !== types_1.Platform.UNDETERMINED) {
44
- (0, utils_1.logSuccess)(`Detected ${cwdPlatformGuess} app in directory ${appDir}`);
45
- targetPlatform = cwdPlatformGuess;
42
+ let targetPlatform = await (0, fileUtils_1.getPlatformFromFolder)(appDir);
43
+ if (targetPlatform === types_1.Platform.NONE && !((_a = process.env[exports.FDC_APP_FOLDER]) === null || _a === void 0 ? void 0 : _a.length)) {
44
+ appDir = await (0, prompt_1.promptForDirectory)({
45
+ config,
46
+ message: "Where is your app directory? Leave blank to set up a generated SDK in your current directory.",
47
+ });
48
+ targetPlatform = await (0, fileUtils_1.getPlatformFromFolder)(appDir);
46
49
  }
47
- else {
48
- (0, utils_1.logBullet)(`Couldn't automatically detect your app directory.`);
49
- appDir =
50
- (_a = process.env[exports.FDC_APP_FOLDER]) !== null && _a !== void 0 ? _a : (await (0, prompt_1.promptForDirectory)({
51
- config,
52
- message: "Where is your app directory? Leave blank to set up a generated SDK in your current directory.",
53
- }));
54
- const platformGuess = await (0, fileUtils_1.getPlatformFromFolder)(appDir);
55
- if (platformGuess !== types_1.Platform.UNDETERMINED) {
56
- (0, utils_1.logSuccess)(`Detected ${platformGuess} app in directory ${appDir}`);
57
- targetPlatform = platformGuess;
50
+ if (targetPlatform === types_1.Platform.NONE || targetPlatform === types_1.Platform.MULTIPLE) {
51
+ if (targetPlatform === types_1.Platform.NONE) {
52
+ (0, utils_1.logBullet)(`Couldn't automatically detect app your in directory ${appDir}.`);
58
53
  }
59
54
  else {
60
- (0, utils_1.logBullet)("Couldn't automatically detect your app's platform.");
61
- const platforms = [
62
- { name: "iOS (Swift)", value: types_1.Platform.IOS },
63
- { name: "Web (JavaScript)", value: types_1.Platform.WEB },
64
- { name: "Android (Kotlin)", value: types_1.Platform.ANDROID },
65
- ];
66
- targetPlatform = await (0, prompt_1.promptOnce)({
67
- message: "Which platform do you want to set up a generated SDK for?",
68
- type: "list",
69
- choices: platforms,
70
- });
55
+ (0, utils_1.logSuccess)(`Detected multiple app platforms in directory ${appDir}`);
71
56
  }
57
+ const platforms = [
58
+ { name: "iOS (Swift)", value: types_1.Platform.IOS },
59
+ { name: "Web (JavaScript)", value: types_1.Platform.WEB },
60
+ { name: "Android (Kotlin)", value: types_1.Platform.ANDROID },
61
+ { name: "Flutter (Dart)", value: types_1.Platform.FLUTTER },
62
+ ];
63
+ targetPlatform = await (0, prompt_1.promptOnce)({
64
+ message: "Which platform do you want to set up a generated SDK for?",
65
+ type: "list",
66
+ choices: platforms,
67
+ });
68
+ }
69
+ else {
70
+ (0, utils_1.logSuccess)(`Detected ${targetPlatform} app in directory ${appDir}`);
72
71
  }
73
72
  const connectorInfo = await (0, prompt_1.promptOnce)({
74
73
  message: "Which connector do you want set up a generated SDK for?",
75
74
  type: "list",
76
75
  choices: connectorChoices,
77
76
  });
78
- const newConnectorYaml = JSON.parse(JSON.stringify(connectorInfo.connectorYaml));
79
- if (!newConnectorYaml.generate) {
80
- newConnectorYaml.generate = {};
77
+ const connectorYaml = JSON.parse(JSON.stringify(connectorInfo.connectorYaml));
78
+ const newConnectorYaml = generateSdkYaml(targetPlatform, connectorYaml, connectorInfo.directory, appDir);
79
+ const connectorYamlContents = yaml.stringify(newConnectorYaml);
80
+ connectorInfo.connectorYaml = newConnectorYaml;
81
+ const displayIOSWarning = targetPlatform === types_1.Platform.IOS;
82
+ return { connectorYamlContents, connectorInfo, displayIOSWarning };
83
+ }
84
+ function generateSdkYaml(targetPlatform, connectorYaml, connectorDir, appDir) {
85
+ if (!connectorYaml.generate) {
86
+ connectorYaml.generate = {};
81
87
  }
82
- let displayIOSWarning = false;
83
88
  if (targetPlatform === types_1.Platform.IOS) {
84
- const outputDir = ((_b = newConnectorYaml.generate.swiftSdk) === null || _b === void 0 ? void 0 : _b.outputDir) ||
85
- path.relative(connectorInfo.directory, path.join(appDir, `generated/swift`));
86
- const pkg = (_d = (_c = newConnectorYaml.generate.swiftSdk) === null || _c === void 0 ? void 0 : _c.package) !== null && _d !== void 0 ? _d : (0, lodash_1.upperFirst)((0, lodash_1.camelCase)(newConnectorYaml.connectorId));
87
- const swiftSdk = { outputDir, package: pkg };
88
- newConnectorYaml.generate.swiftSdk = swiftSdk;
89
- displayIOSWarning = true;
89
+ const swiftSdk = {
90
+ outputDir: path.relative(connectorDir, path.join(appDir, `dataconnect-generated/swift`)),
91
+ package: (0, lodash_1.upperFirst)((0, lodash_1.camelCase)(connectorYaml.connectorId)) + "Connector",
92
+ };
93
+ connectorYaml.generate.swiftSdk = swiftSdk;
90
94
  }
91
95
  if (targetPlatform === types_1.Platform.WEB) {
92
- const outputDir = ((_e = newConnectorYaml.generate.javascriptSdk) === null || _e === void 0 ? void 0 : _e.outputDir) ||
93
- path.relative(connectorInfo.directory, path.join(appDir, `generated/javascript/${newConnectorYaml.connectorId}`));
94
- const pkg = (_g = (_f = newConnectorYaml.generate.javascriptSdk) === null || _f === void 0 ? void 0 : _f.package) !== null && _g !== void 0 ? _g : `@firebasegen/${connectorInfo.connectorYaml.connectorId}`;
96
+ const pkg = `${connectorYaml.connectorId}-connector`;
95
97
  const javascriptSdk = {
96
- outputDir,
97
- package: pkg,
98
+ outputDir: path.relative(connectorDir, path.join(appDir, `dataconnect-generated/js/${pkg}`)),
99
+ package: `@firebasegen/${pkg}`,
100
+ packageJsonDir: path.relative(connectorDir, appDir),
98
101
  };
99
- if ((await (0, fileUtils_1.directoryHasPackageJson)(appDir)) &&
100
- (await (0, prompt_1.confirm)({
101
- message: "Would you like to add a dependency on the generated SDK to your package.json?",
102
- }))) {
103
- javascriptSdk.packageJsonDir = path.relative(connectorInfo.directory, appDir);
104
- }
105
- newConnectorYaml.generate.javascriptSdk = javascriptSdk;
102
+ connectorYaml.generate.javascriptSdk = javascriptSdk;
106
103
  }
107
- if (targetPlatform === types_1.Platform.DART) {
108
- const outputDir = ((_h = newConnectorYaml.generate.dartSdk) === null || _h === void 0 ? void 0 : _h.outputDir) ||
109
- path.relative(connectorInfo.directory, path.join(appDir, `generated/dart/${newConnectorYaml.connectorId}`));
110
- const pkg = (_k = (_j = newConnectorYaml.generate.dartSdk) === null || _j === void 0 ? void 0 : _j.package) !== null && _k !== void 0 ? _k : newConnectorYaml.connectorId;
104
+ if (targetPlatform === types_1.Platform.FLUTTER) {
105
+ const pkg = `${(0, lodash_1.snakeCase)(connectorYaml.connectorId)}_connector`;
111
106
  const dartSdk = {
112
- outputDir,
107
+ outputDir: path.relative(connectorDir, path.join(appDir, `dataconnect-generated/dart/${pkg}`)),
113
108
  package: pkg,
114
109
  };
115
- newConnectorYaml.generate.dartSdk = dartSdk;
110
+ connectorYaml.generate.dartSdk = dartSdk;
116
111
  }
117
112
  if (targetPlatform === types_1.Platform.ANDROID) {
118
- let baseDir = path.join(appDir, `generated/kotlin`);
113
+ const kotlinSdk = {
114
+ outputDir: path.relative(connectorDir, path.join(appDir, `dataconnect-generated/kotlin`)),
115
+ package: `connectors.${(0, lodash_1.snakeCase)(connectorYaml.connectorId)}`,
116
+ };
119
117
  for (const candidateSubdir of ["app/src/main/java", "app/src/main/kotlin"]) {
120
118
  const candidateDir = path.join(appDir, candidateSubdir);
121
- if (fs.existsSync(candidateDir)) {
122
- baseDir = candidateDir;
119
+ if ((0, fsutils_1.dirExistsSync)(candidateDir)) {
120
+ kotlinSdk.outputDir = path.relative(connectorDir, candidateDir);
123
121
  }
124
122
  }
125
- const outputDir = ((_l = newConnectorYaml.generate.kotlinSdk) === null || _l === void 0 ? void 0 : _l.outputDir) ||
126
- path.relative(connectorInfo.directory, baseDir);
127
- const pkg = (_o = (_m = newConnectorYaml.generate.kotlinSdk) === null || _m === void 0 ? void 0 : _m.package) !== null && _o !== void 0 ? _o : `connectors.${(0, lodash_1.snakeCase)(connectorInfo.connectorYaml.connectorId)}`;
128
- const kotlinSdk = {
129
- outputDir,
130
- package: pkg,
131
- };
132
- newConnectorYaml.generate.kotlinSdk = kotlinSdk;
123
+ connectorYaml.generate.kotlinSdk = kotlinSdk;
133
124
  }
134
- const shouldGenerate = !!(setup.projectId &&
135
- (await (0, prompt_1.confirm)({
136
- message: "Would you like to generate SDK code now?",
137
- default: true,
138
- })));
139
- const connectorYamlContents = yaml.stringify(newConnectorYaml);
140
- connectorInfo.connectorYaml = newConnectorYaml;
141
- return { connectorYamlContents, connectorInfo, shouldGenerate, displayIOSWarning };
125
+ return connectorYaml;
142
126
  }
143
- async function actuate(sdkInfo, projectId) {
127
+ exports.generateSdkYaml = generateSdkYaml;
128
+ async function actuate(sdkInfo) {
144
129
  var _a;
145
130
  const connectorYamlPath = `${sdkInfo.connectorInfo.directory}/connector.yaml`;
146
131
  fs.writeFileSync(connectorYamlPath, sdkInfo.connectorYamlContents, "utf8");
147
132
  (0, utils_1.logBullet)(`Wrote new config to ${connectorYamlPath}`);
148
- if (projectId && sdkInfo.shouldGenerate) {
149
- await dataconnectEmulator_1.DataConnectEmulator.generate({
150
- configDir: sdkInfo.connectorInfo.directory,
151
- connectorId: sdkInfo.connectorInfo.connectorYaml.connectorId,
152
- });
153
- (0, utils_1.logBullet)(`Generated SDK code for ${sdkInfo.connectorInfo.connectorYaml.connectorId}`);
154
- }
133
+ await dataconnectEmulator_1.DataConnectEmulator.generate({
134
+ configDir: sdkInfo.connectorInfo.directory,
135
+ connectorId: sdkInfo.connectorInfo.connectorYaml.connectorId,
136
+ });
137
+ (0, utils_1.logBullet)(`Generated SDK code for ${sdkInfo.connectorInfo.connectorYaml.connectorId}`);
155
138
  if (((_a = sdkInfo.connectorInfo.connectorYaml.generate) === null || _a === void 0 ? void 0 : _a.swiftSdk) && sdkInfo.displayIOSWarning) {
156
139
  (0, utils_1.logBullet)(clc.bold("Please follow the instructions here to add your generated sdk to your XCode project:\n\thttps://firebase.google.com/docs/data-connect/gp/ios-sdk#set-client"));
157
140
  }
package/lib/init/spawn.js CHANGED
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.wrapSpawn = void 0;
4
4
  const spawn = require("cross-spawn");
5
5
  const logger_1 = require("../logger");
6
- function wrapSpawn(cmd, args, projectDir) {
6
+ function wrapSpawn(cmd, args, projectDir, environmentVariables) {
7
7
  return new Promise((resolve, reject) => {
8
8
  const installer = spawn(cmd, args, {
9
9
  cwd: projectDir,
10
10
  stdio: "inherit",
11
+ env: Object.assign(Object.assign({}, process.env), environmentVariables),
11
12
  });
12
13
  installer.on("error", (err) => {
13
14
  logger_1.logger.debug(err.stack);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "13.20.1",
3
+ "version": "13.21.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {