firebase-tools 11.6.0 → 11.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/lib/auth.js +1 -1
  2. package/lib/commands/crashlytics-mappingfile-generateid.js +26 -0
  3. package/lib/commands/crashlytics-mappingfile-upload.js +46 -0
  4. package/lib/commands/crashlytics-symbols-upload.js +18 -87
  5. package/lib/commands/functions-delete.js +2 -0
  6. package/lib/commands/functions-secrets-get.js +2 -0
  7. package/lib/commands/index.js +3 -0
  8. package/lib/crashlytics/buildToolsJarHelper.js +51 -0
  9. package/lib/deploy/functions/backend.js +4 -4
  10. package/lib/deploy/functions/build.js +98 -17
  11. package/lib/deploy/functions/cache/applyHash.js +29 -0
  12. package/lib/deploy/functions/cache/hash.js +30 -0
  13. package/lib/deploy/functions/cel.js +249 -0
  14. package/lib/deploy/functions/checkIam.js +6 -5
  15. package/lib/deploy/functions/functionsDeployHelper.js +12 -1
  16. package/lib/deploy/functions/params.js +262 -105
  17. package/lib/deploy/functions/prepare.js +34 -4
  18. package/lib/deploy/functions/prepareFunctionsUpload.js +12 -4
  19. package/lib/deploy/functions/release/fabricator.js +39 -6
  20. package/lib/deploy/functions/release/index.js +2 -0
  21. package/lib/deploy/functions/release/planner.js +17 -0
  22. package/lib/deploy/functions/runtimes/discovery/index.js +1 -16
  23. package/lib/deploy/functions/runtimes/discovery/parsing.js +16 -0
  24. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +59 -131
  25. package/lib/deploy/functions/runtimes/node/parseTriggers.js +10 -1
  26. package/lib/emulator/constants.js +1 -1
  27. package/lib/emulator/controller.js +6 -11
  28. package/lib/emulator/extensionsEmulator.js +1 -0
  29. package/lib/emulator/functionsEmulator.js +18 -59
  30. package/lib/emulator/functionsEmulatorRuntime.js +12 -23
  31. package/lib/emulator/functionsRuntimeWorker.js +38 -7
  32. package/lib/emulator/storage/apis/firebase.js +145 -129
  33. package/lib/emulator/storage/apis/gcloud.js +102 -42
  34. package/lib/emulator/storage/files.js +25 -15
  35. package/lib/emulator/storage/metadata.js +86 -56
  36. package/lib/emulator/storage/multipart.js +2 -2
  37. package/lib/emulator/storage/rules/runtime.js +10 -2
  38. package/lib/emulator/storage/upload.js +45 -9
  39. package/lib/extensions/extensionsHelper.js +1 -1
  40. package/lib/functions/constants.js +14 -0
  41. package/lib/functions/env.js +9 -9
  42. package/lib/functions/secrets.js +8 -1
  43. package/lib/gcp/cloudfunctions.js +15 -18
  44. package/lib/gcp/cloudfunctionsv2.js +15 -18
  45. package/lib/gcp/cloudscheduler.js +32 -14
  46. package/lib/gcp/secretManager.js +15 -1
  47. package/lib/gcp/storage.js +15 -1
  48. package/lib/previews.js +1 -1
  49. package/lib/track.js +3 -0
  50. package/npm-shrinkwrap.json +563 -30
  51. package/package.json +7 -5
  52. package/templates/init/storage/storage.rules +1 -1
package/lib/auth.js CHANGED
@@ -23,7 +23,7 @@ const uuid_1 = require("uuid");
23
23
  const crypto_1 = require("crypto");
24
24
  const track_1 = require("./track");
25
25
  const api_1 = require("./api");
26
- portfinder.basePort = 9005;
26
+ portfinder.setBasePort(9005);
27
27
  function getGlobalDefaultAccount() {
28
28
  const user = configstore_1.configstore.get("user");
29
29
  const tokens = configstore_1.configstore.get("tokens");
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const utils = require("../utils");
6
+ const buildToolsJarHelper_1 = require("../crashlytics/buildToolsJarHelper");
7
+ const error_1 = require("../error");
8
+ exports.command = new command_1.Command("crashlytics:mappingfile:generateid")
9
+ .description("generate a mapping file id and write it to an Android resource file, which will be built into the app")
10
+ .option("--resource-file <resourceFile>", "path to the Android resource XML file that will be created or updated.")
11
+ .action(async (options) => {
12
+ const debug = !!options.debug;
13
+ const resourceFilePath = options.resourceFile;
14
+ if (!resourceFilePath) {
15
+ throw new error_1.FirebaseError("set --resource-file <resourceFile> to an Android resource file path, e.g. app/src/main/res/values/crashlytics.xml");
16
+ }
17
+ const jarFile = await (0, buildToolsJarHelper_1.fetchBuildtoolsJar)();
18
+ const jarOptions = { resourceFilePath };
19
+ utils.logBullet(`Updating resource file: ${resourceFilePath}`);
20
+ const generateIdArgs = buildArgs(jarOptions);
21
+ (0, buildToolsJarHelper_1.runBuildtoolsCommand)(jarFile, generateIdArgs, debug);
22
+ utils.logBullet("Successfully updated mapping file id");
23
+ });
24
+ function buildArgs(options) {
25
+ return ["-injectMappingFileIdIntoResource", options.resourceFilePath, "-verbose"];
26
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const error_1 = require("../error");
6
+ const utils = require("../utils");
7
+ const buildToolsJarHelper_1 = require("../crashlytics/buildToolsJarHelper");
8
+ exports.command = new command_1.Command("crashlytics:mappingfile:upload <mappingFile>")
9
+ .description("upload a ProGuard/R8-compatible mapping file to deobfuscate stack traces")
10
+ .option("--app <appID>", "the app id of your Firebase app")
11
+ .option("--resource-file <resourceFile>", "path to the Android resource XML file that includes the mapping file id")
12
+ .action(async (mappingFile, options) => {
13
+ const app = getGoogleAppID(options);
14
+ const debug = !!options.debug;
15
+ if (!mappingFile) {
16
+ throw new error_1.FirebaseError("set `--mapping-file <mappingFile>` to a valid mapping file path, e.g. app/build/outputs/mapping.txt");
17
+ }
18
+ const mappingFilePath = mappingFile;
19
+ const resourceFilePath = options.resourceFile;
20
+ if (!resourceFilePath) {
21
+ throw new error_1.FirebaseError("set --resource-file <resourceFile> to a valid Android resource file path, e.g. app/main/res/values/strings.xml");
22
+ }
23
+ const jarFile = await (0, buildToolsJarHelper_1.fetchBuildtoolsJar)();
24
+ const jarOptions = { app, mappingFilePath, resourceFilePath };
25
+ utils.logBullet(`Uploading mapping file: ${mappingFilePath}`);
26
+ const uploadArgs = buildArgs(jarOptions);
27
+ (0, buildToolsJarHelper_1.runBuildtoolsCommand)(jarFile, uploadArgs, debug);
28
+ utils.logBullet("Successfully uploaded mapping file");
29
+ });
30
+ function getGoogleAppID(options) {
31
+ if (!options.app) {
32
+ throw new error_1.FirebaseError("set --app <appId> to a valid Firebase application id, e.g. 1:00000000:android:0000000");
33
+ }
34
+ return options.app;
35
+ }
36
+ function buildArgs(options) {
37
+ return [
38
+ "-uploadMappingFile",
39
+ options.mappingFilePath,
40
+ "-resourceFile",
41
+ options.resourceFilePath,
42
+ "-googleAppId",
43
+ options.app,
44
+ "-verbose",
45
+ ];
46
+ }
@@ -1,44 +1,31 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const fs = require("fs-extra");
5
4
  const os = require("os");
6
5
  const path = require("path");
7
- const spawn = require("cross-spawn");
8
6
  const uuid = require("uuid");
9
7
  const command_1 = require("../command");
10
- const downloadUtils = require("../downloadUtils");
11
8
  const error_1 = require("../error");
12
- const logger_1 = require("../logger");
13
- const rimraf = require("rimraf");
14
9
  const utils = require("../utils");
10
+ const buildToolsJarHelper_1 = require("../crashlytics/buildToolsJarHelper");
15
11
  var SymbolGenerator;
16
12
  (function (SymbolGenerator) {
17
13
  SymbolGenerator["breakpad"] = "breakpad";
18
14
  SymbolGenerator["csym"] = "csym";
19
15
  })(SymbolGenerator || (SymbolGenerator = {}));
20
16
  const SYMBOL_CACHE_ROOT_DIR = process.env.FIREBASE_CRASHLYTICS_CACHE_PATH || os.tmpdir();
21
- const JAR_CACHE_DIR = process.env.FIREBASE_CRASHLYTICS_BUILDTOOLS_PATH ||
22
- path.join(os.homedir(), ".cache", "firebase", "crashlytics", "buildtools");
23
- const JAR_VERSION = "2.8.0";
24
- const JAR_URL = `https://dl.google.com/android/maven2/com/google/firebase/firebase-crashlytics-buildtools/${JAR_VERSION}/firebase-crashlytics-buildtools-${JAR_VERSION}.jar`;
25
17
  exports.command = new command_1.Command("crashlytics:symbols:upload <symbolFiles...>")
26
- .description("Upload symbols for native code, to symbolicate stack traces.")
18
+ .description("upload symbols for native code, to symbolicate stack traces")
27
19
  .option("--app <appID>", "the app id of your Firebase app")
28
- .option("--generator [breakpad|csym]", "the symbol generator being used, defaults to breakpad.")
20
+ .option("--generator [breakpad|csym]", "the symbol generator being used, default is breakpad")
29
21
  .option("--dry-run", "generate symbols without uploading them")
30
- .option("--debug", "print debug output and logging from the underlying uploader tool")
31
22
  .action(async (symbolFiles, options) => {
32
- const app = getGoogleAppID(options) || "";
23
+ const app = getGoogleAppID(options);
33
24
  const generator = getSymbolGenerator(options);
34
25
  const dryRun = !!options.dryRun;
35
26
  const debug = !!options.debug;
36
- let jarFile = await downloadBuiltoolsJar();
37
- if (process.env.LOCAL_JAR) {
38
- jarFile = process.env.LOCAL_JAR;
39
- }
27
+ const jarFile = await (0, buildToolsJarHelper_1.fetchBuildtoolsJar)();
40
28
  const jarOptions = {
41
- jarFile,
42
29
  app,
43
30
  generator,
44
31
  cachePath: path.join(SYMBOL_CACHE_ROOT_DIR, `crashlytics-${uuid.v4()}`, "nativeSymbols", app.replace(/:/g, "-"), generator),
@@ -48,32 +35,22 @@ exports.command = new command_1.Command("crashlytics:symbols:upload <symbolFiles
48
35
  for (const symbolFile of symbolFiles) {
49
36
  utils.logBullet(`Generating symbols for ${symbolFile}`);
50
37
  const generateArgs = buildArgs(Object.assign(Object.assign({}, jarOptions), { symbolFile }));
51
- const output = runJar(generateArgs, debug);
52
- if (output.length > 0) {
53
- utils.logBullet(output);
54
- }
55
- else {
56
- utils.logBullet(`Generated symbols for ${symbolFile}`);
57
- utils.logBullet(`Output Path: ${jarOptions.cachePath}`);
58
- }
38
+ (0, buildToolsJarHelper_1.runBuildtoolsCommand)(jarFile, generateArgs, debug);
39
+ utils.logBullet(`Generated symbols for ${symbolFile}`);
40
+ utils.logBullet(`Output Path: ${jarOptions.cachePath}`);
59
41
  }
60
42
  if (dryRun) {
61
43
  utils.logBullet("Skipping upload because --dry-run was passed");
62
44
  return;
63
45
  }
64
- utils.logBullet(`Uploading all generated symbols`);
46
+ utils.logBullet(`Uploading all generated symbols...`);
65
47
  const uploadArgs = buildArgs(Object.assign(Object.assign({}, jarOptions), { generate: false }));
66
- const output = runJar(uploadArgs, debug);
67
- if (output.length > 0) {
68
- utils.logBullet(output);
69
- }
70
- else {
71
- utils.logBullet("Successfully uploaded all symbols");
72
- }
48
+ (0, buildToolsJarHelper_1.runBuildtoolsCommand)(jarFile, uploadArgs, debug);
49
+ utils.logBullet("Successfully uploaded all symbols");
73
50
  });
74
51
  function getGoogleAppID(options) {
75
52
  if (!options.app) {
76
- throw new error_1.FirebaseError("set the --app option to a valid Firebase app id and try again");
53
+ throw new error_1.FirebaseError("set --app <appId> to a valid Firebase application id, e.g. 1:00000000:android:0000000");
77
54
  }
78
55
  return options.app;
79
56
  }
@@ -86,62 +63,16 @@ function getSymbolGenerator(options) {
86
63
  }
87
64
  return options.generator;
88
65
  }
89
- async function downloadBuiltoolsJar() {
90
- const jarPath = path.join(JAR_CACHE_DIR, `crashlytics-buildtools-${JAR_VERSION}.jar`);
91
- if (fs.existsSync(jarPath)) {
92
- logger_1.logger.debug(`Buildtools Jar already downloaded at ${jarPath}`);
93
- return jarPath;
94
- }
95
- if (fs.existsSync(JAR_CACHE_DIR)) {
96
- logger_1.logger.debug(`Deleting Jar cache at ${JAR_CACHE_DIR} because the CLI was run with a newer Jar version`);
97
- rimraf.sync(JAR_CACHE_DIR);
98
- }
99
- utils.logBullet("Downloading buildtools.jar to " + jarPath);
100
- utils.logBullet("For open source licenses used by this command, look in the META-INF directory in the buildtools.jar file");
101
- const tmpfile = await downloadUtils.downloadToTmp(JAR_URL);
102
- fs.mkdirSync(JAR_CACHE_DIR, { recursive: true });
103
- fs.copySync(tmpfile, jarPath);
104
- return jarPath;
105
- }
106
66
  function buildArgs(options) {
107
67
  const baseArgs = [
108
- "-jar",
109
- options.jarFile,
110
- `-symbolGenerator=${options.generator}`,
111
- `-symbolFileCacheDir=${options.cachePath}`,
68
+ "-symbolGenerator",
69
+ options.generator,
70
+ "-symbolFileCacheDir",
71
+ options.cachePath,
112
72
  "-verbose",
113
73
  ];
114
74
  if (options.generate) {
115
- return baseArgs.concat(["-generateNativeSymbols", `-unstrippedLibrary=${options.symbolFile}`]);
116
- }
117
- return baseArgs.concat([
118
- "-uploadNativeSymbols",
119
- `-googleAppId=${options.app}`,
120
- ]);
121
- }
122
- function runJar(args, debug) {
123
- var _a, _b, _c;
124
- const outputs = spawn.sync("java", args, {
125
- stdio: debug ? "inherit" : "pipe",
126
- });
127
- if (outputs.status || 0 > 0) {
128
- if (!debug) {
129
- utils.logWarning(((_a = outputs.stdout) === null || _a === void 0 ? void 0 : _a.toString()) || "An unknown error occurred");
130
- }
131
- throw new error_1.FirebaseError("Failed to upload symbols");
132
- }
133
- if (!debug) {
134
- let logRegex = /(Generated symbol file.*$)/m;
135
- let matched = (((_b = outputs.stdout) === null || _b === void 0 ? void 0 : _b.toString()) || "").match(logRegex);
136
- if (matched) {
137
- return matched[1];
138
- }
139
- logRegex = /(Crashlytics symbol file uploaded successfully.*$)/m;
140
- matched = (((_c = outputs.stdout) === null || _c === void 0 ? void 0 : _c.toString()) || "").match(logRegex);
141
- if (matched) {
142
- return matched[1];
143
- }
144
- return "";
75
+ return baseArgs.concat(["-generateNativeSymbols", "-unstrippedLibrary", options.symbolFile]);
145
76
  }
146
- return "";
77
+ return baseArgs.concat(["-uploadNativeSymbols", "-googleAppId", options.app]);
147
78
  }
@@ -17,6 +17,7 @@ const fabricator = require("../deploy/functions/release/fabricator");
17
17
  const executor = require("../deploy/functions/release/executor");
18
18
  const reporter = require("../deploy/functions/release/reporter");
19
19
  const containerCleaner = require("../deploy/functions/containerCleaner");
20
+ const getProjectNumber_1 = require("../getProjectNumber");
20
21
  exports.command = new command_1.Command("functions:delete [filters...]")
21
22
  .description("delete one or more Cloud Functions by name or group name.")
22
23
  .option("--region <region>", "Specify region of the function to be deleted. " +
@@ -78,6 +79,7 @@ exports.command = new command_1.Command("functions:delete [filters...]")
78
79
  appEngineLocation,
79
80
  executor: new executor.QueueExecutor({}),
80
81
  sources: {},
82
+ projectNumber: options.projectNumber || (await (0, getProjectNumber_1.getProjectNumber)({ projectId: context.projectId })),
81
83
  });
82
84
  const summary = await fab.applyPlan(plan);
83
85
  await reporter.logAndTrackDeployStats(summary);
@@ -6,8 +6,10 @@ const command_1 = require("../command");
6
6
  const logger_1 = require("../logger");
7
7
  const projectUtils_1 = require("../projectUtils");
8
8
  const secretManager_1 = require("../gcp/secretManager");
9
+ const requirePermissions_1 = require("../requirePermissions");
9
10
  exports.command = new command_1.Command("functions:secrets:get <KEY>")
10
11
  .description("Get metadata for secret and its versions")
12
+ .before(requirePermissions_1.requirePermissions, ["secretmanager.secrets.get"])
11
13
  .action(async (key, options) => {
12
14
  const projectId = (0, projectUtils_1.needProjectId)(options);
13
15
  const versions = await (0, secretManager_1.listSecretVersions)(projectId, key);
@@ -34,6 +34,9 @@ function load(client) {
34
34
  client.crashlytics = {};
35
35
  client.crashlytics.symbols = {};
36
36
  client.crashlytics.symbols.upload = loadCommand("crashlytics-symbols-upload");
37
+ client.crashlytics.mappingfile = {};
38
+ client.crashlytics.mappingfile.generateid = loadCommand("crashlytics-mappingfile-generateid");
39
+ client.crashlytics.mappingfile.upload = loadCommand("crashlytics-mappingfile-upload");
37
40
  client.database = {};
38
41
  client.database.get = loadCommand("database-get");
39
42
  client.database.instances = {};
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runBuildtoolsCommand = exports.fetchBuildtoolsJar = void 0;
4
+ const fs = require("fs-extra");
5
+ const os = require("os");
6
+ const path = require("path");
7
+ const spawn = require("cross-spawn");
8
+ const downloadUtils = require("../downloadUtils");
9
+ const error_1 = require("../error");
10
+ const logger_1 = require("../logger");
11
+ const rimraf = require("rimraf");
12
+ const utils = require("../utils");
13
+ const JAR_CACHE_DIR = process.env.FIREBASE_CRASHLYTICS_BUILDTOOLS_PATH ||
14
+ path.join(os.homedir(), ".cache", "firebase", "crashlytics", "buildtools");
15
+ const JAR_VERSION = "2.9.1";
16
+ const JAR_URL = `https://dl.google.com/android/maven2/com/google/firebase/firebase-crashlytics-buildtools/${JAR_VERSION}/firebase-crashlytics-buildtools-${JAR_VERSION}.jar`;
17
+ async function fetchBuildtoolsJar() {
18
+ if (process.env.CRASHLYTICS_LOCAL_JAR) {
19
+ return process.env.CRASHLYTICS_LOCAL_JAR;
20
+ }
21
+ const jarPath = path.join(JAR_CACHE_DIR, `crashlytics-buildtools-${JAR_VERSION}.jar`);
22
+ if (fs.existsSync(jarPath)) {
23
+ logger_1.logger.debug(`Buildtools Jar already downloaded at ${jarPath}`);
24
+ return jarPath;
25
+ }
26
+ if (fs.existsSync(JAR_CACHE_DIR)) {
27
+ logger_1.logger.debug(`Deleting Jar cache at ${JAR_CACHE_DIR} because the CLI was run with a newer Jar version`);
28
+ rimraf.sync(JAR_CACHE_DIR);
29
+ }
30
+ utils.logBullet("Downloading crashlytics-buildtools.jar to " + jarPath);
31
+ utils.logBullet("For open source licenses used by this command, look in the META-INF directory in the buildtools.jar file");
32
+ const tmpfile = await downloadUtils.downloadToTmp(JAR_URL);
33
+ fs.mkdirSync(JAR_CACHE_DIR, { recursive: true });
34
+ fs.copySync(tmpfile, jarPath);
35
+ return jarPath;
36
+ }
37
+ exports.fetchBuildtoolsJar = fetchBuildtoolsJar;
38
+ function runBuildtoolsCommand(jarFile, args, debug) {
39
+ var _a;
40
+ const fullArgs = ["-jar", jarFile, ...args, "-clientName", "firebase-cli;crashlytics-buildtools"];
41
+ const outputs = spawn.sync("java", fullArgs, {
42
+ stdio: debug ? "inherit" : "pipe",
43
+ });
44
+ if (outputs.status !== 0) {
45
+ if (!debug) {
46
+ utils.logWarning(((_a = outputs.stdout) === null || _a === void 0 ? void 0 : _a.toString()) || "An unknown error occurred");
47
+ }
48
+ throw new error_1.FirebaseError(`java command failed with args: ${fullArgs}`);
49
+ }
50
+ }
51
+ exports.runBuildtoolsCommand = runBuildtoolsCommand;
@@ -65,8 +65,8 @@ function memoryToGen1Cpu(memory) {
65
65
  2048: 1,
66
66
  4096: 2,
67
67
  8192: 2,
68
- 16384: 3,
69
- 32768: 4,
68
+ 16384: 4,
69
+ 32768: 8,
70
70
  }[memory];
71
71
  }
72
72
  exports.memoryToGen1Cpu = memoryToGen1Cpu;
@@ -79,8 +79,8 @@ function memoryToGen2Cpu(memory) {
79
79
  2048: 1,
80
80
  4096: 2,
81
81
  8192: 2,
82
- 16384: 2,
83
- 32768: 4,
82
+ 16384: 4,
83
+ 32768: 8,
84
84
  }[memory];
85
85
  }
86
86
  exports.memoryToGen2Cpu = memoryToGen2Cpu;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toBackend = exports.resolveBackend = exports.of = exports.empty = void 0;
3
+ exports.toBackend = exports.resolveBackend = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.AllFunctionsPlatforms = exports.isValidMemoryOption = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.of = exports.empty = void 0;
4
4
  const backend = require("./backend");
5
5
  const proto = require("../../gcp/proto");
6
6
  const api = require("../../.../../api");
@@ -8,7 +8,7 @@ const params = require("./params");
8
8
  const previews_1 = require("../../previews");
9
9
  const error_1 = require("../../error");
10
10
  const functional_1 = require("../../functional");
11
- const logger_1 = require("../../logger");
11
+ const env_1 = require("../../functions/env");
12
12
  function empty() {
13
13
  return {
14
14
  requiredAPIs: [],
@@ -23,15 +23,98 @@ function of(endpoints) {
23
23
  return build;
24
24
  }
25
25
  exports.of = of;
26
- async function resolveBackend(build, userEnvOpt, userEnvs) {
26
+ function isHttpsTriggered(triggered) {
27
+ return {}.hasOwnProperty.call(triggered, "httpsTrigger");
28
+ }
29
+ exports.isHttpsTriggered = isHttpsTriggered;
30
+ function isCallableTriggered(triggered) {
31
+ return {}.hasOwnProperty.call(triggered, "callableTrigger");
32
+ }
33
+ exports.isCallableTriggered = isCallableTriggered;
34
+ function isEventTriggered(triggered) {
35
+ return {}.hasOwnProperty.call(triggered, "eventTrigger");
36
+ }
37
+ exports.isEventTriggered = isEventTriggered;
38
+ function isScheduleTriggered(triggered) {
39
+ return {}.hasOwnProperty.call(triggered, "scheduleTrigger");
40
+ }
41
+ exports.isScheduleTriggered = isScheduleTriggered;
42
+ function isTaskQueueTriggered(triggered) {
43
+ return {}.hasOwnProperty.call(triggered, "taskQueueTrigger");
44
+ }
45
+ exports.isTaskQueueTriggered = isTaskQueueTriggered;
46
+ function isBlockingTriggered(triggered) {
47
+ return {}.hasOwnProperty.call(triggered, "blockingTrigger");
48
+ }
49
+ exports.isBlockingTriggered = isBlockingTriggered;
50
+ const allMemoryOptions = [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768];
51
+ function isValidMemoryOption(mem) {
52
+ return allMemoryOptions.includes(mem);
53
+ }
54
+ exports.isValidMemoryOption = isValidMemoryOption;
55
+ exports.AllFunctionsPlatforms = ["gcfv1", "gcfv2"];
56
+ exports.AllVpcEgressSettings = ["PRIVATE_RANGES_ONLY", "ALL_TRAFFIC"];
57
+ exports.AllIngressSettings = [
58
+ "ALLOW_ALL",
59
+ "ALLOW_INTERNAL_ONLY",
60
+ "ALLOW_INTERNAL_AND_GCLB",
61
+ ];
62
+ async function resolveBackend(build, userEnvOpt, userEnvs, nonInteractive) {
27
63
  const projectId = userEnvOpt.projectId;
28
64
  let paramValues = {};
29
65
  if (previews_1.previews.functionsparams) {
30
- paramValues = await params.resolveParams(build.params, projectId, userEnvs);
66
+ paramValues = await params.resolveParams(build.params, projectId, envWithTypes(build.params, userEnvs), nonInteractive);
67
+ const toWrite = {};
68
+ for (const paramName of Object.keys(paramValues)) {
69
+ const paramValue = paramValues[paramName];
70
+ if (Object.prototype.hasOwnProperty.call(userEnvs, paramName) || paramValue.secret) {
71
+ continue;
72
+ }
73
+ toWrite[paramName] = paramValue.toString();
74
+ }
75
+ (0, env_1.writeUserEnvs)(toWrite, userEnvOpt);
31
76
  }
32
- return toBackend(build, paramValues);
77
+ return { backend: toBackend(build, paramValues), envs: paramValues };
33
78
  }
34
79
  exports.resolveBackend = resolveBackend;
80
+ function envWithTypes(definedParams, rawEnvs) {
81
+ const out = {};
82
+ for (const envName of Object.keys(rawEnvs)) {
83
+ const value = rawEnvs[envName];
84
+ let providedType = {
85
+ string: true,
86
+ boolean: true,
87
+ number: true,
88
+ };
89
+ for (const param of definedParams) {
90
+ if (param.name === envName) {
91
+ if (param.type === "string") {
92
+ providedType = {
93
+ string: true,
94
+ boolean: false,
95
+ number: false,
96
+ };
97
+ }
98
+ else if (param.type === "int") {
99
+ providedType = {
100
+ string: false,
101
+ boolean: false,
102
+ number: true,
103
+ };
104
+ }
105
+ else if (param.type === "boolean") {
106
+ providedType = {
107
+ string: false,
108
+ boolean: true,
109
+ number: false,
110
+ };
111
+ }
112
+ }
113
+ }
114
+ out[envName] = new params.ParamValue(value, false, providedType);
115
+ }
116
+ return out;
117
+ }
35
118
  class Resolver {
36
119
  constructor(paramValues) {
37
120
  this.paramValues = paramValues;
@@ -87,10 +170,6 @@ function toBackend(build, paramValues) {
87
170
  if (typeof bdEndpoint.platform === "undefined") {
88
171
  throw new error_1.FirebaseError("platform can't be undefined");
89
172
  }
90
- if (bdEndpoint.availableMemoryMb != null &&
91
- !backend.isValidMemoryOption(bdEndpoint.availableMemoryMb)) {
92
- throw new error_1.FirebaseError("available memory must be a supported value, if present");
93
- }
94
173
  const bkEndpoint = Object.assign({ id: endpointId, project: bdEndpoint.project, region: region, entryPoint: bdEndpoint.entryPoint, platform: bdEndpoint.platform, runtime: bdEndpoint.runtime }, trigger);
95
174
  proto.copyIfPresent(bkEndpoint, bdEndpoint, "environmentVariables", "labels", "secretEnvironmentVariables", "serviceAccount");
96
175
  proto.convertIfPresent(bkEndpoint, bdEndpoint, "ingressSettings", (from) => {
@@ -102,9 +181,9 @@ function toBackend(build, paramValues) {
102
181
  proto.convertIfPresent(bkEndpoint, bdEndpoint, "availableMemoryMb", (from) => {
103
182
  const mem = r.resolveInt(from);
104
183
  if (mem !== null && !backend.isValidMemoryOption(mem)) {
105
- logger_1.logger.debug("Warning; setting memory to unexpected value", mem);
184
+ throw new error_1.FirebaseError(`Function memory (${mem}) must resolve to a supported value, if present: ${JSON.stringify(allMemoryOptions)}`);
106
185
  }
107
- return mem;
186
+ return mem || null;
108
187
  });
109
188
  r.resolveInts(bkEndpoint, bdEndpoint, "timeoutSeconds", "maxInstances", "minInstances", "concurrency");
110
189
  proto.convertIfPresent(bkEndpoint, bdEndpoint, "cpu", (0, functional_1.nullsafeVisitor)((cpu) => (cpu === "gcf_gen1" ? cpu : r.resolveInt(cpu))));
@@ -127,7 +206,7 @@ function toBackend(build, paramValues) {
127
206
  }
128
207
  exports.toBackend = toBackend;
129
208
  function discoverTrigger(endpoint, region, r) {
130
- if ("httpsTrigger" in endpoint) {
209
+ if (isHttpsTriggered(endpoint)) {
131
210
  const httpsTrigger = {};
132
211
  if (endpoint.httpsTrigger.invoker === null) {
133
212
  httpsTrigger.invoker = null;
@@ -137,13 +216,13 @@ function discoverTrigger(endpoint, region, r) {
137
216
  }
138
217
  return { httpsTrigger };
139
218
  }
140
- else if ("callableTrigger" in endpoint) {
219
+ else if (isCallableTriggered(endpoint)) {
141
220
  return { callableTrigger: {} };
142
221
  }
143
- else if ("blockingTrigger" in endpoint) {
222
+ else if (isBlockingTriggered(endpoint)) {
144
223
  return { blockingTrigger: endpoint.blockingTrigger };
145
224
  }
146
- else if ("eventTrigger" in endpoint) {
225
+ else if (isEventTriggered(endpoint)) {
147
226
  const eventTrigger = {
148
227
  eventType: endpoint.eventTrigger.eventType,
149
228
  retry: r.resolveBoolean(endpoint.eventTrigger.retry) || false,
@@ -157,11 +236,13 @@ function discoverTrigger(endpoint, region, r) {
157
236
  r.resolveStrings(eventTrigger, endpoint.eventTrigger, "serviceAccount", "region", "channel");
158
237
  return { eventTrigger };
159
238
  }
160
- else if ("scheduleTrigger" in endpoint) {
239
+ else if (isScheduleTriggered(endpoint)) {
161
240
  const bkSchedule = {
162
241
  schedule: r.resolveString(endpoint.scheduleTrigger.schedule),
163
- timeZone: r.resolveString(endpoint.scheduleTrigger.timeZone),
164
242
  };
243
+ if (endpoint.scheduleTrigger.timeZone !== undefined) {
244
+ bkSchedule.timeZone = r.resolveString(endpoint.scheduleTrigger.timeZone);
245
+ }
165
246
  if (endpoint.scheduleTrigger.retryConfig) {
166
247
  const bkRetry = {};
167
248
  r.resolveInts(bkRetry, endpoint.scheduleTrigger.retryConfig, "maxBackoffSeconds", "minBackoffSeconds", "maxRetrySeconds", "retryCount", "maxDoublings");
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyBackendHashToBackends = void 0;
4
+ const backend_1 = require("../backend");
5
+ const hash_1 = require("./hash");
6
+ const functionsDeployHelper_1 = require("../functionsDeployHelper");
7
+ function applyBackendHashToBackends(wantBackends, context) {
8
+ var _a;
9
+ for (const [codebase, wantBackend] of Object.entries(wantBackends)) {
10
+ if ((0, functionsDeployHelper_1.isCodebaseFiltered)(codebase, context.filters || [])) {
11
+ continue;
12
+ }
13
+ const source = (_a = context === null || context === void 0 ? void 0 : context.sources) === null || _a === void 0 ? void 0 : _a[codebase];
14
+ const envHash = (0, hash_1.getEnvironmentVariablesHash)(wantBackend);
15
+ applyBackendHashToEndpoints(wantBackend, envHash, context.filters || [], source === null || source === void 0 ? void 0 : source.functionsSourceV1Hash, source === null || source === void 0 ? void 0 : source.functionsSourceV2Hash);
16
+ }
17
+ }
18
+ exports.applyBackendHashToBackends = applyBackendHashToBackends;
19
+ function applyBackendHashToEndpoints(wantBackend, envHash, endpointFilters, sourceV1Hash, sourceV2Hash) {
20
+ for (const endpoint of (0, backend_1.allEndpoints)(wantBackend)) {
21
+ const secretsHash = (0, hash_1.getSecretsHash)(endpoint);
22
+ const isV2 = endpoint.platform === "gcfv2";
23
+ const sourceHash = isV2 ? sourceV2Hash : sourceV1Hash;
24
+ if ((0, functionsDeployHelper_1.isEndpointFiltered)(endpoint, endpointFilters)) {
25
+ continue;
26
+ }
27
+ endpoint.hash = (0, hash_1.getEndpointHash)(sourceHash, envHash, secretsHash);
28
+ }
29
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEndpointHash = exports.getSecretsHash = exports.getSourceHash = exports.getEnvironmentVariablesHash = void 0;
4
+ const promises_1 = require("node:fs/promises");
5
+ const crypto = require("crypto");
6
+ const secrets_1 = require("../../../functions/secrets");
7
+ function getEnvironmentVariablesHash(backend) {
8
+ return createHash(JSON.stringify(backend.environmentVariables || {}));
9
+ }
10
+ exports.getEnvironmentVariablesHash = getEnvironmentVariablesHash;
11
+ async function getSourceHash(pathToFile) {
12
+ const data = await (0, promises_1.readFile)(pathToFile);
13
+ return createHash(data);
14
+ }
15
+ exports.getSourceHash = getSourceHash;
16
+ function getSecretsHash(endpoint) {
17
+ const secretVersions = (0, secrets_1.getSecretVersions)(endpoint);
18
+ return createHash(JSON.stringify(secretVersions || {}));
19
+ }
20
+ exports.getSecretsHash = getSecretsHash;
21
+ function getEndpointHash(sourceHash, envHash, secretsHash) {
22
+ const combined = [sourceHash, envHash, secretsHash].filter((hash) => !!hash).join("");
23
+ return createHash(combined);
24
+ }
25
+ exports.getEndpointHash = getEndpointHash;
26
+ function createHash(data, algorithm = "sha1") {
27
+ const hash = crypto.createHash(algorithm);
28
+ hash.update(data);
29
+ return hash.digest("hex");
30
+ }