firebase-tools 13.27.0 → 13.29.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 (47) hide show
  1. package/lib/appdistribution/client.js +2 -1
  2. package/lib/appdistribution/options-parser-util.js +5 -5
  3. package/lib/auth.js +13 -3
  4. package/lib/bin/firebase.js +4 -3
  5. package/lib/commands/appdistribution-distribute.js +55 -31
  6. package/lib/commands/firestore-indexes-list.js +4 -2
  7. package/lib/commands/index.js +2 -2
  8. package/lib/dataconnect/fileUtils.js +3 -0
  9. package/lib/dataconnect/schemaMigration.js +8 -15
  10. package/lib/dataconnect/types.js +1 -1
  11. package/lib/deploy/extensions/tasks.js +2 -2
  12. package/lib/deploy/functions/backend.js +1 -3
  13. package/lib/deploy/functions/build.js +3 -1
  14. package/lib/deploy/functions/release/planner.js +4 -4
  15. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +4 -0
  16. package/lib/deploy/functions/runtimes/supported/types.js +1 -1
  17. package/lib/emulator/apphosting/developmentServer.js +1 -1
  18. package/lib/emulator/apphosting/index.js +1 -1
  19. package/lib/emulator/auth/operations.js +8 -5
  20. package/lib/emulator/controller.js +19 -1
  21. package/lib/emulator/dataconnect/pgliteServer.js +34 -7
  22. package/lib/emulator/dataconnectEmulator.js +20 -1
  23. package/lib/emulator/downloadableEmulators.js +22 -10
  24. package/lib/emulator/eventarcEmulator.js +1 -0
  25. package/lib/emulator/initEmulators.js +17 -2
  26. package/lib/error.js +11 -1
  27. package/lib/experiments.js +0 -6
  28. package/lib/extensions/localHelper.js +2 -2
  29. package/lib/extensions/runtimes/node.js +16 -15
  30. package/lib/extensions/types.js +6 -9
  31. package/lib/functions/events/v2.js +7 -3
  32. package/lib/gcp/cloudfunctionsv2.js +6 -0
  33. package/lib/init/features/dataconnect/index.js +8 -5
  34. package/lib/init/features/emulators.js +1 -1
  35. package/lib/init/features/genkit/index.js +13 -5
  36. package/lib/init/spawn.js +38 -7
  37. package/lib/management/projects.js +23 -1
  38. package/lib/requireAuth.js +2 -1
  39. package/package.json +3 -2
  40. package/schema/firebase-config.json +3 -0
  41. package/templates/init/dataconnect/dataconnect.yaml +1 -0
  42. package/templates/init/functions/javascript/package.lint.json +1 -1
  43. package/templates/init/functions/javascript/package.nolint.json +1 -1
  44. package/templates/init/functions/typescript/package.lint.json +1 -1
  45. package/templates/init/functions/typescript/package.nolint.json +1 -1
  46. package/templates/init/functions/typescript/tsconfig.json +3 -1
  47. package/templates/init/dataconnect/dataconnect-fdccompatiblemode.yaml +0 -12
@@ -69,7 +69,13 @@ class DataConnectEmulator {
69
69
  const postgresDumpPath = this.args.importPath
70
70
  ? path.join(this.args.importPath, "postgres.tar.gz")
71
71
  : undefined;
72
- this.postgresServer = new pgliteServer_1.PostgresServer(dbId, "postgres", dataDirectory, postgresDumpPath);
72
+ this.postgresServer = new pgliteServer_1.PostgresServer({
73
+ database: dbId,
74
+ username: "fdc",
75
+ dataDirectory,
76
+ importPath: postgresDumpPath,
77
+ debug: this.args.debug,
78
+ });
73
79
  const server = await this.postgresServer.createPGServer(pgHost, pgPort);
74
80
  const connectableHost = (0, utils_1.connectableHostname)(pgHost);
75
81
  connStr = `postgres://${connectableHost}:${pgPort}/${dbId}?sslmode=disable`;
@@ -101,6 +107,9 @@ class DataConnectEmulator {
101
107
  this.logger.logLabeled("INFO", "dataconnect", "Skipping cleanup of Data Connect emulator, as it was not started by this process.");
102
108
  return;
103
109
  }
110
+ if (this.postgresServer) {
111
+ await this.postgresServer.stop();
112
+ }
104
113
  return (0, downloadableEmulators_1.stop)(types_1.Emulators.DATACONNECT);
105
114
  }
106
115
  getInfo() {
@@ -147,6 +156,11 @@ class DataConnectEmulator {
147
156
  cmd.push("--watch");
148
157
  }
149
158
  const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
159
+ if ((0, downloadableEmulators_1.isIncomaptibleArchError)(res.error)) {
160
+ throw new error_1.FirebaseError(`Unknown system error when running the Data Connect toolkit. ` +
161
+ `You may be able to fix this by installing Rosetta: ` +
162
+ `softwareupdate --install-rosetta`);
163
+ }
150
164
  logger_1.logger.info(res.stderr);
151
165
  if (res.error) {
152
166
  throw new error_1.FirebaseError(`Error starting up Data Connect generate: ${res.error.message}`, {
@@ -163,6 +177,11 @@ class DataConnectEmulator {
163
177
  const commandInfo = await (0, downloadableEmulators_1.downloadIfNecessary)(types_1.Emulators.DATACONNECT);
164
178
  const cmd = ["--logtostderr", "-v=2", "build", `--config_dir=${args.configDir}`];
165
179
  const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8" });
180
+ if ((0, downloadableEmulators_1.isIncomaptibleArchError)(res.error)) {
181
+ throw new error_1.FirebaseError(`Unkown system error when running the Data Connect toolkit. ` +
182
+ `You may be able to fix this by installing Rosetta: ` +
183
+ `softwareupdate --install-rosetta`);
184
+ }
166
185
  if (res.error) {
167
186
  throw new error_1.FirebaseError(`Error starting up Data Connect build: ${res.error.message}`, {
168
187
  original: res.error,
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName = exports.DownloadDetails = void 0;
3
+ exports.isIncomaptibleArchError = exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName = exports.DownloadDetails = void 0;
4
4
  const lsofi = require("lsofi");
5
5
  const types_1 = require("./types");
6
6
  const constants_1 = require("./constants");
@@ -48,20 +48,20 @@ const EMULATOR_UPDATE_DETAILS = {
48
48
  },
49
49
  dataconnect: process.platform === "darwin"
50
50
  ? {
51
- version: "1.7.3",
52
- expectedSize: 25211648,
53
- expectedChecksum: "8410794304b2ae340c3facf07d7edc16",
51
+ version: "1.7.5",
52
+ expectedSize: 25281280,
53
+ expectedChecksum: "85d0de96b5c08b553fd8506a2bc381bb",
54
54
  }
55
55
  : process.platform === "win32"
56
56
  ? {
57
- version: "1.7.3",
58
- expectedSize: 25641984,
59
- expectedChecksum: "a4bd0f9d9d884528fa4494e4d7918c08",
57
+ version: "1.7.5",
58
+ expectedSize: 25711616,
59
+ expectedChecksum: "c99d67fa8e74d41760b96122b055b8e2",
60
60
  }
61
61
  : {
62
- version: "1.7.3",
63
- expectedSize: 25125016,
64
- expectedChecksum: "48660e6370aeed973f33c3420c3255fb",
62
+ version: "1.7.5",
63
+ expectedSize: 25190552,
64
+ expectedChecksum: "61d966b781e6f2887f8b38ec271b54e2",
65
65
  },
66
66
  };
67
67
  exports.DownloadDetails = {
@@ -355,6 +355,11 @@ async function _runBinary(emulator, command, extraEnv) {
355
355
  if (e.code === "EACCES") {
356
356
  logger.logLabeled("WARN", emulator.name, `Could not spawn child process for emulator, check that java is installed and on your $PATH.`);
357
357
  }
358
+ else if (isIncomaptibleArchError(e)) {
359
+ logger.logLabeled("WARN", emulator.name, `Unknown system error when starting emulator binary. ` +
360
+ `You may be able to fix this by installing Rosetta: ` +
361
+ `softwareupdate --install-rosetta`);
362
+ }
358
363
  _fatal(emulator.name, e);
359
364
  }
360
365
  const description = constants_1.Constants.description(emulator.name);
@@ -468,3 +473,10 @@ async function start(targetName, args, extraEnv = {}) {
468
473
  return _runBinary(emulator, command, extraEnv);
469
474
  }
470
475
  exports.start = start;
476
+ function isIncomaptibleArchError(err) {
477
+ var _a;
478
+ return ((0, error_1.hasMessage)(err) &&
479
+ /Unknown system error/.test((_a = err.message) !== null && _a !== void 0 ? _a : "") &&
480
+ process.platform === "darwin");
481
+ }
482
+ exports.isIncomaptibleArchError = isIncomaptibleArchError;
@@ -140,6 +140,7 @@ class EventarcEmulator {
140
140
  .request({
141
141
  method: "POST",
142
142
  path: `/functions/projects/${trigger.projectId}/triggers/${trigger.triggerName}`,
143
+ headers: { "Content-Type": "application/json" },
143
144
  body: JSON.stringify(event),
144
145
  responseType: "stream",
145
146
  resolveOnHTTPError: true,
@@ -25,10 +25,10 @@ exports.AdditionalInitFns = {
25
25
  const backendRoot = (0, path_1.join)(cwd, backendRelativeDir);
26
26
  try {
27
27
  const startCommand = await (0, developmentServer_1.detectStartCommand)(backendRoot);
28
- additionalConfigs.set("startCommandOverride", startCommand);
28
+ additionalConfigs.set("startCommand", startCommand);
29
29
  }
30
30
  catch (e) {
31
- logger.log("WARN", "Failed to auto-detect your project's start command. Consider manually setting the start command by setting `firebase.json#emulators.apphosting.startCommandOverride`");
31
+ logger.log("WARN", "Failed to auto-detect your project's start command. Consider manually setting the start command by setting `firebase.json#emulators.apphosting.startCommand`");
32
32
  }
33
33
  try {
34
34
  const projectRoot = (_a = (0, detectProjectRoot_1.detectProjectRoot)({})) !== null && _a !== void 0 ? _a : backendRoot;
@@ -39,6 +39,21 @@ exports.AdditionalInitFns = {
39
39
  }
40
40
  return mapToObject(additionalConfigs);
41
41
  },
42
+ [types_1.Emulators.DATACONNECT]: async (config) => {
43
+ const additionalConfig = {};
44
+ const defaultDataConnectDir = config.get("dataconnect.source", "dataconnect");
45
+ const defaultDataDir = config.get("emulators.dataconnect.dataDir", `${defaultDataConnectDir}/.dataconnect/pgliteData`);
46
+ if (await (0, prompt_1.promptOnce)({
47
+ name: "dataDir",
48
+ type: "confirm",
49
+ message: "Do you want to persist Postgres data from the Data Connect emulator between runs? " +
50
+ `Data will be saved to ${defaultDataDir}. ` +
51
+ `You can change this directory by editing 'firebase.json#emulators.dataconnect.dataDir'.`,
52
+ })) {
53
+ additionalConfig["dataDir"] = defaultDataDir;
54
+ }
55
+ return additionalConfig;
56
+ },
42
57
  };
43
58
  function mapToObject(map) {
44
59
  const newObject = {};
package/lib/error.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isBillingError = exports.getError = exports.getErrStatus = exports.getErrMsg = exports.FirebaseError = void 0;
3
+ exports.hasMessage = exports.isBillingError = exports.getError = exports.getErrStatus = exports.isObject = exports.getErrStack = exports.getErrMsg = exports.FirebaseError = void 0;
4
4
  const lodash_1 = require("lodash");
5
5
  const DEFAULT_CHILDREN = [];
6
6
  const DEFAULT_EXIT = 1;
@@ -31,9 +31,17 @@ function getErrMsg(err, defaultMsg) {
31
31
  return JSON.stringify(err);
32
32
  }
33
33
  exports.getErrMsg = getErrMsg;
34
+ function getErrStack(err) {
35
+ if (err instanceof Error) {
36
+ return err.stack || err.message;
37
+ }
38
+ return getErrMsg(err);
39
+ }
40
+ exports.getErrStack = getErrStack;
34
41
  function isObject(value) {
35
42
  return typeof value === "object" && value !== null;
36
43
  }
44
+ exports.isObject = isObject;
37
45
  function getErrStatus(err, defaultStatus) {
38
46
  if (isObject(err) && err.status && typeof err.status === "number") {
39
47
  return err.status;
@@ -57,3 +65,5 @@ function isBillingError(e) {
57
65
  }));
58
66
  }
59
67
  exports.isBillingError = isBillingError;
68
+ const hasMessage = (e) => !!(e === null || e === void 0 ? void 0 : e.message);
69
+ exports.hasMessage = hasMessage;
@@ -106,12 +106,6 @@ exports.ALL_EXPERIMENTS = experiments({
106
106
  default: true,
107
107
  public: false,
108
108
  },
109
- fdccompatiblemode: {
110
- shortDescription: "Enable Data Connect schema migrations in Compatible Mode",
111
- fullDescription: "Enable Data Connect schema migrations in Compatible Mode",
112
- default: true,
113
- public: false,
114
- },
115
109
  });
116
110
  function isValidExperiment(name) {
117
111
  return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
@@ -38,9 +38,9 @@ function fixLifecycleEvents(lifecycleEvents) {
38
38
  stageUnspecified: "STAGE_UNSPECIFIED",
39
39
  };
40
40
  const arrayLifecycle = [];
41
- if ((0, types_1.isObject)(lifecycleEvents)) {
41
+ if ((0, error_1.isObject)(lifecycleEvents)) {
42
42
  for (const [key, val] of Object.entries(lifecycleEvents)) {
43
- if ((0, types_1.isObject)(val) &&
43
+ if ((0, error_1.isObject)(val) &&
44
44
  typeof val.function === "string" &&
45
45
  typeof val.processingMessage === "string") {
46
46
  arrayLifecycle.push({
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.writeSDK = exports.TYPESCRIPT_VERSION = exports.FIREBASE_FUNCTIONS_VERSION = exports.SDK_GENERATION_VERSION = void 0;
4
4
  const path = require("path");
5
- const child_process_1 = require("child_process");
6
5
  const marked_terminal_1 = require("marked-terminal");
7
6
  const marked_1 = require("marked");
7
+ const error_1 = require("../../error");
8
8
  const types_1 = require("../types");
9
9
  const prompt_1 = require("../../prompt");
10
10
  const secretsUtils = require("../secretsUtils");
@@ -12,7 +12,8 @@ const utils_1 = require("../../utils");
12
12
  const common_1 = require("./common");
13
13
  const askUserForEventsConfig_1 = require("../askUserForEventsConfig");
14
14
  const extensionsHelper_1 = require("../extensionsHelper");
15
- const error_1 = require("../../error");
15
+ const error_2 = require("../../error");
16
+ const spawn_1 = require("../../init/spawn");
16
17
  marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
17
18
  exports.SDK_GENERATION_VERSION = "1.0.0";
18
19
  exports.FIREBASE_FUNCTIONS_VERSION = ">=5.1.0";
@@ -91,8 +92,8 @@ function addPeerDependency(pkgJson, dependency, version) {
91
92
  if (!pkgJson.peerDependencies) {
92
93
  pkgJson.peerDependencies = {};
93
94
  }
94
- if (!(0, types_1.isObject)(pkgJson.peerDependencies)) {
95
- throw new error_1.FirebaseError("Internal error generating peer dependencies.");
95
+ if (!(0, error_1.isObject)(pkgJson.peerDependencies)) {
96
+ throw new error_2.FirebaseError("Internal error generating peer dependencies.");
96
97
  }
97
98
  pkgJson.peerDependencies[dependency] = version;
98
99
  }
@@ -118,7 +119,7 @@ async function writeSDK(extensionRef, localPath, spec, options) {
118
119
  }
119
120
  }
120
121
  if (!dirPath) {
121
- throw new error_1.FirebaseError("Invalid extension definition. Must have either extensionRef or localPath");
122
+ throw new error_2.FirebaseError("Invalid extension definition. Must have either extensionRef or localPath");
122
123
  }
123
124
  const packageName = makePackageName(extensionRef, spec.name);
124
125
  const pkgJson = {
@@ -292,7 +293,7 @@ async function writeSDK(extensionRef, localPath, spec, options) {
292
293
  sdkLines.push(` ${sysParam.param}${opt}: string;`);
293
294
  break;
294
295
  default:
295
- throw new error_1.FirebaseError(`Error: Unknown systemParam type: ${sysParam.type || "undefined"}.`);
296
+ throw new error_2.FirebaseError(`Error: Unknown systemParam type: ${sysParam.type || "undefined"}.`);
296
297
  }
297
298
  sdkLines.push("");
298
299
  }
@@ -347,19 +348,19 @@ async function writeSDK(extensionRef, localPath, spec, options) {
347
348
  await (0, common_1.writeFile)(`${dirPath}/tsconfig.json`, JSON.stringify(tsconfigJson, null, 2), options);
348
349
  (0, utils_1.logLabeledBullet)("extensions", `running 'npm --prefix ${shortDirPath} install'`);
349
350
  try {
350
- (0, child_process_1.execFileSync)("npm", ["--prefix", dirPath, "install"]);
351
+ await (0, spawn_1.spawnWithOutput)("npm", ["--prefix", dirPath, "install"]);
351
352
  }
352
353
  catch (err) {
353
- const errMsg = (0, error_1.getErrMsg)(err, "unknown error");
354
- throw new error_1.FirebaseError(`Error during npm install in ${shortDirPath}: ${errMsg}`);
354
+ const errMsg = (0, error_2.getErrMsg)(err, "unknown error");
355
+ throw new error_2.FirebaseError(`Error during npm install in ${shortDirPath}: ${errMsg}`);
355
356
  }
356
357
  (0, utils_1.logLabeledBullet)("extensions", `running 'npm --prefix ${shortDirPath} run build'`);
357
358
  try {
358
- (0, child_process_1.execFileSync)("npm", ["--prefix", dirPath, "run", "build"]);
359
+ await (0, spawn_1.spawnWithOutput)("npm", ["--prefix", dirPath, "run", "build"]);
359
360
  }
360
361
  catch (err) {
361
- const errMsg = (0, error_1.getErrMsg)(err, "unknown error");
362
- throw new error_1.FirebaseError(`Error during npm run build in ${shortDirPath}: ${errMsg}`);
362
+ const errMsg = (0, error_2.getErrMsg)(err, "unknown error");
363
+ throw new error_2.FirebaseError(`Error during npm run build in ${shortDirPath}: ${errMsg}`);
363
364
  }
364
365
  const codebaseDir = (0, common_1.getCodebaseDir)(options);
365
366
  const shortCodebaseDir = codebaseDir.replace(process.cwd(), ".");
@@ -372,11 +373,11 @@ async function writeSDK(extensionRef, localPath, spec, options) {
372
373
  })) {
373
374
  (0, utils_1.logLabeledBullet)("extensions", `running 'npm --prefix ${shortCodebaseDir} install --save ${shortDirPath}'`);
374
375
  try {
375
- (0, child_process_1.execFileSync)("npm", ["--prefix", codebaseDir, "install", "--save", dirPath]);
376
+ await (0, spawn_1.spawnWithOutput)("npm", ["--prefix", codebaseDir, "install", "--save", dirPath]);
376
377
  }
377
378
  catch (err) {
378
- const errMsg = (0, error_1.getErrMsg)(err, "unknown error");
379
- throw new error_1.FirebaseError(`Error during npm install in ${codebaseDir}: ${errMsg}`);
379
+ const errMsg = (0, error_2.getErrMsg)(err, "unknown error");
380
+ throw new error_2.FirebaseError(`Error during npm install in ${codebaseDir}: ${errMsg}`);
380
381
  }
381
382
  }
382
383
  else {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isExtensionSpec = exports.isResource = exports.isParam = exports.isObject = exports.ParamType = exports.FUNCTIONS_V2_RESOURCE_TYPE = exports.FUNCTIONS_RESOURCE_TYPE = exports.isExtensionInstance = exports.Visibility = exports.RegistryLaunchStage = void 0;
3
+ exports.isExtensionSpec = exports.isResource = exports.isParam = exports.ParamType = exports.FUNCTIONS_V2_RESOURCE_TYPE = exports.FUNCTIONS_RESOURCE_TYPE = exports.isExtensionInstance = exports.Visibility = exports.RegistryLaunchStage = void 0;
4
+ const error_1 = require("../error");
4
5
  var RegistryLaunchStage;
5
6
  (function (RegistryLaunchStage) {
6
7
  RegistryLaunchStage["EXPERIMENTAL"] = "EXPERIMENTAL";
@@ -23,7 +24,7 @@ const extensionInstanceState = [
23
24
  "PAUSED",
24
25
  ];
25
26
  const isExtensionInstance = (value) => {
26
- if (!isObject(value) || typeof value.name !== "string") {
27
+ if (!(0, error_1.isObject)(value) || typeof value.name !== "string") {
27
28
  return false;
28
29
  }
29
30
  return true;
@@ -40,20 +41,16 @@ var ParamType;
40
41
  ParamType["SELECT_RESOURCE"] = "SELECT_RESOURCE";
41
42
  ParamType["SECRET"] = "SECRET";
42
43
  })(ParamType = exports.ParamType || (exports.ParamType = {}));
43
- function isObject(value) {
44
- return typeof value === "object" && value !== null;
45
- }
46
- exports.isObject = isObject;
47
44
  const isParam = (param) => {
48
- return (isObject(param) && typeof param["param"] === "string" && typeof param["label"] === "string");
45
+ return ((0, error_1.isObject)(param) && typeof param["param"] === "string" && typeof param["label"] === "string");
49
46
  };
50
47
  exports.isParam = isParam;
51
48
  const isResource = (res) => {
52
- return isObject(res) && typeof res["name"] === "string";
49
+ return (0, error_1.isObject)(res) && typeof res["name"] === "string";
53
50
  };
54
51
  exports.isResource = isResource;
55
52
  const isExtensionSpec = (spec) => {
56
- if (!isObject(spec) || typeof spec.name !== "string" || typeof spec.version !== "string") {
53
+ if (!(0, error_1.isObject)(spec) || typeof spec.name !== "string" || typeof spec.version !== "string") {
57
54
  return false;
58
55
  }
59
56
  if (spec.resources && Array.isArray(spec.resources)) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FIRESTORE_EVENT_WITH_AUTH_CONTEXT_REGEX = exports.FIRESTORE_EVENT_REGEX = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
3
+ exports.CONVERTABLE_EVENTS = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
4
4
  exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
5
5
  exports.STORAGE_EVENTS = [
6
6
  "google.cloud.storage.object.v1.finalized",
@@ -28,5 +28,9 @@ exports.FIRESTORE_EVENTS = [
28
28
  "google.cloud.firestore.document.v1.deleted.withAuthContext",
29
29
  ];
30
30
  exports.FIREALERTS_EVENT = "google.firebase.firebasealerts.alerts.v1.published";
31
- exports.FIRESTORE_EVENT_REGEX = /^google\.cloud\.firestore\.document\.v1\.[^\.]*$/;
32
- exports.FIRESTORE_EVENT_WITH_AUTH_CONTEXT_REGEX = /^google\.cloud\.firestore\.document\.v1\..*\.withAuthContext$/;
31
+ exports.CONVERTABLE_EVENTS = {
32
+ "google.cloud.firestore.document.v1.created": "google.cloud.firestore.document.v1.created.withAuthContext",
33
+ "google.cloud.firestore.document.v1.updated": "google.cloud.firestore.document.v1.updated.withAuthContext",
34
+ "google.cloud.firestore.document.v1.deleted": "google.cloud.firestore.document.v1.deleted.withAuthContext",
35
+ "google.cloud.firestore.document.v1.written": "google.cloud.firestore.document.v1.written.withAuthContext",
36
+ };
@@ -259,6 +259,9 @@ function functionFromEndpoint(endpoint) {
259
259
  }
260
260
  else if (backend.isCallableTriggered(endpoint)) {
261
261
  gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-callable": "true" });
262
+ if (endpoint.callableTrigger.genkitAction) {
263
+ gcfFunction.labels["genkit-action"] = endpoint.callableTrigger.genkitAction;
264
+ }
262
265
  }
263
266
  else if (backend.isBlockingTriggered(endpoint)) {
264
267
  gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.BLOCKING_LABEL]: constants_1.BLOCKING_EVENT_TO_LABEL_KEY[endpoint.blockingTrigger.eventType] });
@@ -294,6 +297,9 @@ function endpointFromFunction(gcfFunction) {
294
297
  trigger = {
295
298
  callableTrigger: {},
296
299
  };
300
+ if (gcfFunction.labels["genkit-action"]) {
301
+ trigger.callableTrigger.genkitAction = gcfFunction.labels["genkit-action"];
302
+ }
297
303
  }
298
304
  else if ((_d = gcfFunction.labels) === null || _d === void 0 ? void 0 : _d[constants_1.BLOCKING_LABEL]) {
299
305
  trigger = {
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.actuate = exports.doSetup = void 0;
4
4
  const path_1 = require("path");
5
5
  const clc = require("colorette");
6
+ const fs = require("fs-extra");
6
7
  const prompt_1 = require("../../../prompt");
7
8
  const provisionCloudSql_1 = require("../../../dataconnect/provisionCloudSql");
8
9
  const freeTrial_1 = require("../../../dataconnect/freeTrial");
9
10
  const cloudsql = require("../../../gcp/cloudsql/cloudsqladmin");
10
11
  const ensureApis_1 = require("../../../dataconnect/ensureApis");
11
- const experiments = require("../../../experiments");
12
12
  const client_1 = require("../../../dataconnect/client");
13
13
  const types_1 = require("../../../dataconnect/types");
14
14
  const names_1 = require("../../../dataconnect/names");
@@ -19,7 +19,6 @@ const cloudbilling_1 = require("../../../gcp/cloudbilling");
19
19
  const sdk = require("./sdk");
20
20
  const fileUtils_1 = require("../../../dataconnect/fileUtils");
21
21
  const DATACONNECT_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/dataconnect.yaml");
22
- const DATACONNECT_YAML_COMPAT_EXPERIMENT_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/dataconnect-fdccompatiblemode.yaml");
23
22
  const CONNECTOR_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/connector.yaml");
24
23
  const SCHEMA_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/schema.gql");
25
24
  const QUERIES_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/queries.gql");
@@ -50,6 +49,9 @@ async function doSetup(setup, config) {
50
49
  isBillingEnabled ? await (0, ensureApis_1.ensureApis)(setup.projectId) : await (0, ensureApis_1.ensureSparkApis)(setup.projectId);
51
50
  }
52
51
  const info = await askQuestions(setup, isBillingEnabled);
52
+ const dir = config.get("dataconnect.source", "dataconnect");
53
+ const dataDir = config.get("emulators.dataconnect.dataDir", `${dir}/.dataconnect/pgliteData`);
54
+ config.set("emulators.dataconnect.dataDir", dataDir);
53
55
  await actuate(setup, config, info);
54
56
  const cwdPlatformGuess = await (0, fileUtils_1.getPlatformFromFolder)(process.cwd());
55
57
  if (cwdPlatformGuess !== types_1.Platform.NONE) {
@@ -136,6 +138,9 @@ async function writeFiles(config, info) {
136
138
  await config.askWriteProjectFile((0, path_1.join)(dir, "schema", f.path), f.content);
137
139
  }
138
140
  }
141
+ else {
142
+ fs.ensureFileSync((0, path_1.join)(dir, "schema", "schema.gql"));
143
+ }
139
144
  for (const c of info.connectors) {
140
145
  await writeConnectorFiles(config, c);
141
146
  }
@@ -156,9 +161,7 @@ function subDataconnectYamlValues(replacementValues) {
156
161
  connectorDirs: "__connectorDirs__",
157
162
  locationId: "__location__",
158
163
  };
159
- let replaced = experiments.isEnabled("fdccompatiblemode")
160
- ? DATACONNECT_YAML_COMPAT_EXPERIMENT_TEMPLATE
161
- : DATACONNECT_YAML_TEMPLATE;
164
+ let replaced = DATACONNECT_YAML_TEMPLATE;
162
165
  for (const [k, v] of Object.entries(replacementValues)) {
163
166
  replaced = replaced.replace(replacements[k], JSON.stringify(v));
164
167
  }
@@ -49,7 +49,7 @@ async function doSetup(setup, config) {
49
49
  }
50
50
  const additionalInitFn = initEmulators_1.AdditionalInitFns[selected];
51
51
  if (additionalInitFn) {
52
- const additionalOptions = await additionalInitFn();
52
+ const additionalOptions = await additionalInitFn(config);
53
53
  if (additionalOptions) {
54
54
  setup.config.emulators[selected] = Object.assign(Object.assign({}, setup.config.emulators[selected]), additionalOptions);
55
55
  }
@@ -6,7 +6,6 @@ const inquirer = require("inquirer");
6
6
  const path = require("path");
7
7
  const semver = require("semver");
8
8
  const clc = require("colorette");
9
- const child_process_1 = require("child_process");
10
9
  const functions_1 = require("../functions");
11
10
  const prompt_1 = require("../../../prompt");
12
11
  const spawn_1 = require("../../spawn");
@@ -15,7 +14,6 @@ const ensureApiEnabled_1 = require("../../../ensureApiEnabled");
15
14
  const logger_1 = require("../../../logger");
16
15
  const error_1 = require("../../../error");
17
16
  const utils_1 = require("../../../utils");
18
- const types_1 = require("../../../extensions/types");
19
17
  async function getGenkitVersion() {
20
18
  let genkitVersion;
21
19
  let templateVersion = "0.9.0";
@@ -26,7 +24,17 @@ async function getGenkitVersion() {
26
24
  genkitVersion = process.env.GENKIT_DEV_VERSION;
27
25
  }
28
26
  else {
29
- genkitVersion = (0, child_process_1.execFileSync)("npm", ["view", "genkit", "version"]).toString();
27
+ try {
28
+ genkitVersion = await (0, spawn_1.spawnWithOutput)("npm", ["view", "genkit", "version"]);
29
+ }
30
+ catch (err) {
31
+ throw new error_1.FirebaseError("Unable to determine which genkit version to install.\n" +
32
+ `npm Error: ${(0, error_1.getErrMsg)(err)}\n\n` +
33
+ "For a possible workaround run\n npm view genkit version\n" +
34
+ "and then set an environment variable:\n" +
35
+ " export GENKIT_DEV_VERSION=<output from previous command>\n" +
36
+ "and run `firebase init genkit` again");
37
+ }
30
38
  }
31
39
  if (!genkitVersion) {
32
40
  throw new error_1.FirebaseError("Unable to determine genkit version to install");
@@ -236,7 +244,7 @@ async function genkitSetup(options, genkitInfo, projectDir) {
236
244
  }
237
245
  exports.genkitSetup = genkitSetup;
238
246
  const isTsConfig = (value) => {
239
- if (!(0, types_1.isObject)(value) || (value.compilerOptions && !(0, types_1.isObject)(value.compilerOptions))) {
247
+ if (!(0, error_1.isObject)(value) || (value.compilerOptions && !(0, error_1.isObject)(value.compilerOptions))) {
240
248
  return false;
241
249
  }
242
250
  return true;
@@ -339,7 +347,7 @@ function generateSampleFile(modelPlugin, configPlugins, projectDir, templateVers
339
347
  }
340
348
  }
341
349
  const isPackageJson = (value) => {
342
- if (!(0, types_1.isObject)(value) || (value.scripts && !(0, types_1.isObject)(value.scripts))) {
350
+ if (!(0, error_1.isObject)(value) || (value.scripts && !(0, error_1.isObject)(value.scripts))) {
343
351
  return false;
344
352
  }
345
353
  return true;
package/lib/init/spawn.js CHANGED
@@ -1,27 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.spawnWithCommandString = exports.wrapSpawn = void 0;
3
+ exports.spawnWithCommandString = exports.spawnWithOutput = exports.wrapSpawn = void 0;
4
4
  const spawn = require("cross-spawn");
5
5
  const logger_1 = require("../logger");
6
- function wrapSpawn(cmd, args, projectDir, environmentVariables) {
6
+ const error_1 = require("../error");
7
+ function wrapSpawn(cmd, args, projectDir) {
7
8
  return new Promise((resolve, reject) => {
8
9
  const installer = spawn(cmd, args, {
9
10
  cwd: projectDir,
10
11
  stdio: "inherit",
11
- env: Object.assign(Object.assign({}, process.env), environmentVariables),
12
+ env: Object.assign({}, process.env),
12
13
  });
13
14
  installer.on("error", (err) => {
14
- logger_1.logger.debug(err.stack);
15
+ logger_1.logger.debug((0, error_1.getErrStack)(err));
15
16
  });
16
17
  installer.on("close", (code) => {
17
18
  if (code === 0) {
18
19
  return resolve();
19
20
  }
20
- return reject();
21
+ return reject(new Error(`Error: spawn(${cmd}, [${args.join(", ")}]) \n exited with code: ${code || "null"}`));
21
22
  });
22
23
  });
23
24
  }
24
25
  exports.wrapSpawn = wrapSpawn;
26
+ function spawnWithOutput(cmd, args) {
27
+ return new Promise((resolve, reject) => {
28
+ var _a, _b;
29
+ const child = spawn(cmd, args);
30
+ let output = "";
31
+ (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (data) => {
32
+ if ((0, error_1.isObject)(data) && data.toString) {
33
+ output += data.toString();
34
+ }
35
+ else {
36
+ output += JSON.stringify(data);
37
+ }
38
+ });
39
+ (_b = child.stderr) === null || _b === void 0 ? void 0 : _b.on("data", (data) => {
40
+ logger_1.logger.debug(`Error: spawn(${cmd}, ${args.join(", ")})\n Stderr:\n${JSON.stringify(data)}\n`);
41
+ });
42
+ child.on("error", (err) => {
43
+ logger_1.logger.debug((0, error_1.getErrStack)(err));
44
+ });
45
+ child.on("close", (code) => {
46
+ if (code === 0) {
47
+ resolve(output);
48
+ }
49
+ else {
50
+ reject(new Error(`Error: spawn(${cmd}, [${args.join(", ")}]) \n exited with code: ${code || "null"}`));
51
+ }
52
+ });
53
+ });
54
+ }
55
+ exports.spawnWithOutput = spawnWithOutput;
25
56
  function spawnWithCommandString(cmd, projectDir, environmentVariables) {
26
57
  return new Promise((resolve, reject) => {
27
58
  const installer = spawn(cmd, {
@@ -31,13 +62,13 @@ function spawnWithCommandString(cmd, projectDir, environmentVariables) {
31
62
  env: Object.assign(Object.assign({}, process.env), environmentVariables),
32
63
  });
33
64
  installer.on("error", (err) => {
34
- logger_1.logger.log("DEBUG", err.stack);
65
+ logger_1.logger.log("DEBUG", (0, error_1.getErrStack)(err));
35
66
  });
36
67
  installer.on("close", (code) => {
37
68
  if (code === 0) {
38
69
  return resolve();
39
70
  }
40
- return reject();
71
+ return reject(new Error(`Error: spawn(${cmd}) \n exited with code: ${code || "null"}`));
41
72
  });
42
73
  });
43
74
  }
@@ -26,12 +26,34 @@ exports.PROJECTS_CREATE_QUESTIONS = [
26
26
  default: "",
27
27
  message: "Please specify a unique project id " +
28
28
  `(${clc.yellow("warning")}: cannot be modified afterward) [6-30 characters]:\n`,
29
+ validate: (projectId) => {
30
+ if (projectId.length < 6) {
31
+ return "Project ID must be at least 6 characters long";
32
+ }
33
+ else if (projectId.length > 30) {
34
+ return "Project ID cannot be longer than 30 characters";
35
+ }
36
+ else {
37
+ return true;
38
+ }
39
+ },
29
40
  },
30
41
  {
31
42
  type: "input",
32
43
  name: "displayName",
33
- default: "",
44
+ default: (answers) => answers.projectId,
34
45
  message: "What would you like to call your project? (defaults to your project ID)",
46
+ validate: (displayName) => {
47
+ if (displayName.length < 4) {
48
+ return "Project name must be at least 4 characters long";
49
+ }
50
+ else if (displayName.length > 30) {
51
+ return "Project name cannot be longer than 30 characters";
52
+ }
53
+ else {
54
+ return true;
55
+ }
56
+ },
35
57
  },
36
58
  ];
37
59
  const firebaseAPIClient = new apiv2_1.Client({
@@ -25,6 +25,7 @@ async function autoAuth(options, authScopes) {
25
25
  const client = getAuthClient({ scopes: authScopes, projectId: options.project });
26
26
  const token = await client.getAccessToken();
27
27
  token !== null ? apiv2.setAccessToken(token) : false;
28
+ logger_1.logger.debug(`Running auto auth`);
28
29
  let clientEmail;
29
30
  try {
30
31
  const credentials = await client.getCredentials();
@@ -72,7 +73,7 @@ async function requireAuth(options) {
72
73
  utils.logWarning("Authenticating with `FIREBASE_TOKEN` is deprecated and will be removed in a future major version of `firebase-tools`. " +
73
74
  "Instead, use a service account key with `GOOGLE_APPLICATION_CREDENTIALS`: https://cloud.google.com/docs/authentication/getting-started");
74
75
  }
75
- else if (user) {
76
+ else if (user && (!(0, auth_1.isExpired)(tokens) || (tokens === null || tokens === void 0 ? void 0 : tokens.refresh_token))) {
76
77
  logger_1.logger.debug(`> authorizing via signed-in user (${user.email})`);
77
78
  }
78
79
  else {