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
@@ -0,0 +1,249 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveExpression = exports.ExprParseError = exports.isCelExpression = void 0;
4
+ const error_1 = require("../../error");
5
+ const functional_1 = require("../../functional");
6
+ const identityRegexp = /{{ params\.(\S+) }}/;
7
+ const dualEqualityRegexp = /{{ params\.(\S+) == params\.(\S+) }}/;
8
+ const equalityRegexp = /{{ params\.(\S+) == (.+) }}/;
9
+ const dualTernaryRegexp = /{{ params\.(\S+) == params\.(\S+) \? (.+) : (.+) }/;
10
+ const ternaryRegexp = /{{ params\.(\S+) == (.+) \? (.+) : (.+) }/;
11
+ const literalTernaryRegexp = /{{ params\.(\S+) \? (.+) : (.+) }/;
12
+ const paramRegexp = /params\.(\S+)/;
13
+ function isCelExpression(value) {
14
+ return typeof value === "string" && value.includes("{{") && value.includes("}}");
15
+ }
16
+ exports.isCelExpression = isCelExpression;
17
+ function isIdentityExpression(value) {
18
+ return identityRegexp.test(value);
19
+ }
20
+ function isEqualityExpression(value) {
21
+ return equalityRegexp.test(value);
22
+ }
23
+ function isDualEqualityExpression(value) {
24
+ return dualEqualityRegexp.test(value);
25
+ }
26
+ function isTernaryExpression(value) {
27
+ return ternaryRegexp.test(value);
28
+ }
29
+ function isLiteralTernaryExpression(value) {
30
+ return literalTernaryRegexp.test(value);
31
+ }
32
+ function isDualTernaryExpression(value) {
33
+ return dualTernaryRegexp.test(value);
34
+ }
35
+ class ExprParseError extends error_1.FirebaseError {
36
+ }
37
+ exports.ExprParseError = ExprParseError;
38
+ function resolveExpression(wantType, expr, params) {
39
+ if (isIdentityExpression(expr)) {
40
+ return resolveIdentity(wantType, expr, params);
41
+ }
42
+ else if (isDualTernaryExpression(expr)) {
43
+ return resolveDualTernary(wantType, expr, params);
44
+ }
45
+ else if (isLiteralTernaryExpression(expr)) {
46
+ return resolveLiteralTernary(wantType, expr, params);
47
+ }
48
+ else if (isTernaryExpression(expr)) {
49
+ return resolveTernary(wantType, expr, params);
50
+ }
51
+ else if (isDualEqualityExpression(expr)) {
52
+ return resolveDualEquality(expr, params);
53
+ }
54
+ else if (isEqualityExpression(expr)) {
55
+ return resolveEquality(expr, params);
56
+ }
57
+ else {
58
+ throw new ExprParseError("CEL expression '" + expr + "' is of an unsupported form");
59
+ }
60
+ }
61
+ exports.resolveExpression = resolveExpression;
62
+ function assertType(wantType, paramName, paramValue) {
63
+ if ((wantType === "string" && !paramValue.legalString) ||
64
+ (wantType === "number" && !paramValue.legalNumber) ||
65
+ (wantType === "boolean" && !paramValue.legalBoolean)) {
66
+ throw new ExprParseError(`Illegal type coercion of param ${paramName} to type ${wantType}`);
67
+ }
68
+ }
69
+ function readParamValue(wantType, paramName, paramValue) {
70
+ assertType(wantType, paramName, paramValue);
71
+ if (wantType === "string") {
72
+ return paramValue.asString();
73
+ }
74
+ else if (wantType === "number") {
75
+ return paramValue.asNumber();
76
+ }
77
+ else if (wantType === "boolean") {
78
+ return paramValue.asBoolean();
79
+ }
80
+ else {
81
+ (0, functional_1.assertExhaustive)(wantType);
82
+ }
83
+ }
84
+ function resolveIdentity(wantType, expr, params) {
85
+ const match = identityRegexp.exec(expr);
86
+ if (!match) {
87
+ throw new ExprParseError("Malformed CEL identity expression '" + expr + "'");
88
+ }
89
+ const name = match[1];
90
+ const value = params[name];
91
+ if (!value) {
92
+ throw new ExprParseError("CEL identity expression '" + expr + "' was not resolvable to a param");
93
+ }
94
+ return readParamValue(wantType, name, value);
95
+ }
96
+ function resolveEquality(expr, params) {
97
+ const match = equalityRegexp.exec(expr);
98
+ if (!match) {
99
+ throw new ExprParseError("Malformed CEL equality expression '" + expr + "'");
100
+ }
101
+ const lhsName = match[1];
102
+ const lhsVal = params[lhsName];
103
+ if (!lhsVal) {
104
+ throw new ExprParseError("CEL equality expression '" + expr + "' references missing param " + lhsName);
105
+ }
106
+ let rhs;
107
+ if (lhsVal.legalString) {
108
+ rhs = resolveLiteral("string", match[2]);
109
+ return lhsVal.asString() === rhs;
110
+ }
111
+ else if (lhsVal.legalNumber) {
112
+ rhs = resolveLiteral("number", match[2]);
113
+ return lhsVal.asNumber() === rhs;
114
+ }
115
+ else if (lhsVal.legalBoolean) {
116
+ rhs = resolveLiteral("boolean", match[2]);
117
+ return lhsVal.asBoolean() === rhs;
118
+ }
119
+ else {
120
+ throw new ExprParseError(`Could not infer type of param ${lhsName} used in equality operation`);
121
+ }
122
+ }
123
+ function resolveDualEquality(expr, params) {
124
+ const match = dualEqualityRegexp.exec(expr);
125
+ if (!match) {
126
+ throw new ExprParseError("Malformed CEL equality expression '" + expr + "'");
127
+ }
128
+ const lhsName = match[1];
129
+ const lhsVal = params[lhsName];
130
+ if (!lhsVal) {
131
+ throw new ExprParseError("CEL equality expression '" + expr + "' references missing param " + lhsName);
132
+ }
133
+ const rhsName = match[2];
134
+ const rhsVal = params[rhsName];
135
+ if (!rhsVal) {
136
+ throw new ExprParseError("CEL equality expression '" + expr + "' references missing param " + lhsName);
137
+ }
138
+ if (lhsVal.legalString) {
139
+ if (!rhsVal.legalString) {
140
+ throw new ExprParseError(`CEL equality expression ${expr} has type mismatch between the operands`);
141
+ }
142
+ return lhsVal.asString() === rhsVal.asString();
143
+ }
144
+ else if (lhsVal.legalNumber) {
145
+ if (!rhsVal.legalNumber) {
146
+ throw new ExprParseError(`CEL equality expression ${expr} has type mismatch between the operands`);
147
+ }
148
+ return lhsVal.asNumber() === rhsVal.asNumber();
149
+ }
150
+ else if (lhsVal.legalBoolean) {
151
+ if (!rhsVal.legalBoolean) {
152
+ throw new ExprParseError(`CEL equality expression ${expr} has type mismatch between the operands`);
153
+ }
154
+ return lhsVal.asBoolean() === rhsVal.asBoolean();
155
+ }
156
+ else {
157
+ throw new ExprParseError(`could not infer type of param ${lhsName} used in equality operation`);
158
+ }
159
+ }
160
+ function resolveTernary(wantType, expr, params) {
161
+ const match = ternaryRegexp.exec(expr);
162
+ if (!match) {
163
+ throw new ExprParseError("malformed CEL ternary expression '" + expr + "'");
164
+ }
165
+ const equalityExpr = `{{ params.${match[1]} == ${match[2]} }}`;
166
+ const isTrue = resolveEquality(equalityExpr, params);
167
+ if (isTrue) {
168
+ return resolveParamOrLiteral(wantType, match[3], params);
169
+ }
170
+ else {
171
+ return resolveParamOrLiteral(wantType, match[4], params);
172
+ }
173
+ }
174
+ function resolveDualTernary(wantType, expr, params) {
175
+ const match = dualTernaryRegexp.exec(expr);
176
+ if (!match) {
177
+ throw new ExprParseError("Malformed CEL ternary expression '" + expr + "'");
178
+ }
179
+ const equalityExpr = `{{ params.${match[1]} == params.${match[2]} }}`;
180
+ const isTrue = resolveDualEquality(equalityExpr, params);
181
+ if (isTrue) {
182
+ return resolveParamOrLiteral(wantType, match[3], params);
183
+ }
184
+ else {
185
+ return resolveParamOrLiteral(wantType, match[4], params);
186
+ }
187
+ }
188
+ function resolveLiteralTernary(wantType, expr, params) {
189
+ const match = literalTernaryRegexp.exec(expr);
190
+ if (!match) {
191
+ throw new ExprParseError("Malformed CEL ternary expression '" + expr + "'");
192
+ }
193
+ const paramName = match[1];
194
+ const paramValue = params[match[1]];
195
+ if (!paramValue) {
196
+ throw new ExprParseError("CEL ternary expression '" + expr + "' references missing param " + paramName);
197
+ }
198
+ if (!paramValue.legalBoolean) {
199
+ throw new ExprParseError("CEL ternary expression '" + expr + "' is conditional on non-boolean param " + paramName);
200
+ }
201
+ if (paramValue.asBoolean()) {
202
+ return resolveParamOrLiteral(wantType, match[2], params);
203
+ }
204
+ else {
205
+ return resolveParamOrLiteral(wantType, match[3], params);
206
+ }
207
+ }
208
+ function resolveParamOrLiteral(wantType, field, params) {
209
+ const match = paramRegexp.exec(field);
210
+ if (!match) {
211
+ return resolveLiteral(wantType, field);
212
+ }
213
+ const paramValue = params[match[1]];
214
+ if (!paramValue) {
215
+ throw new ExprParseError("CEL expression resolved to the value of a missing param " + match[1]);
216
+ }
217
+ return readParamValue(wantType, match[1], paramValue);
218
+ }
219
+ function resolveLiteral(wantType, value) {
220
+ if (paramRegexp.exec(value)) {
221
+ throw new ExprParseError("CEL tried to evaluate param." + value + " in a context which only permits literal values");
222
+ }
223
+ if (wantType === "number") {
224
+ if (isNaN(+value)) {
225
+ throw new ExprParseError("CEL literal " + value + " does not seem to be a number");
226
+ }
227
+ return +value;
228
+ }
229
+ else if (wantType === "string") {
230
+ if (!value.startsWith('"') || !value.endsWith('"')) {
231
+ throw new ExprParseError("CEL literal " + value + ' does not seem to be a "-delimited string');
232
+ }
233
+ return value.slice(1, -1);
234
+ }
235
+ else if (wantType === "boolean") {
236
+ if (value === "true") {
237
+ return true;
238
+ }
239
+ else if (value === "false") {
240
+ return false;
241
+ }
242
+ else {
243
+ throw new ExprParseError("CEL literal " + value + "does not seem to be a true/false boolean");
244
+ }
245
+ }
246
+ else {
247
+ throw new ExprParseError("CEL literal '" + value + "' somehow was resolved with a non-string/number/boolean type");
248
+ }
249
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ensureServiceAgentRoles = exports.mergeBindings = exports.obtainDefaultComputeServiceAgentBindings = exports.obtainPubSubServiceAgentBindings = exports.checkHttpIam = exports.checkServiceAccountIam = exports.EVENTARC_EVENT_RECEIVER_ROLE = exports.RUN_INVOKER_ROLE = exports.SERVICE_ACCOUNT_TOKEN_CREATOR_ROLE = void 0;
3
+ exports.ensureServiceAgentRoles = exports.mergeBindings = exports.obtainDefaultComputeServiceAgentBindings = exports.obtainPubSubServiceAgentBindings = exports.getDefaultComputeServiceAgent = exports.checkHttpIam = exports.checkServiceAccountIam = exports.EVENTARC_EVENT_RECEIVER_ROLE = exports.RUN_INVOKER_ROLE = exports.SERVICE_ACCOUNT_TOKEN_CREATOR_ROLE = void 0;
4
4
  const colorette_1 = require("colorette");
5
5
  const logger_1 = require("../../logger");
6
6
  const functionsDeployHelper_1 = require("./functionsDeployHelper");
@@ -68,11 +68,12 @@ async function checkHttpIam(context, options, payload) {
68
68
  }
69
69
  exports.checkHttpIam = checkHttpIam;
70
70
  function getPubsubServiceAgent(projectNumber) {
71
- return `serviceAccount:service-${projectNumber}@gcp-sa-pubsub.iam.gserviceaccount.com`;
71
+ return `service-${projectNumber}@gcp-sa-pubsub.iam.gserviceaccount.com`;
72
72
  }
73
73
  function getDefaultComputeServiceAgent(projectNumber) {
74
- return `serviceAccount:${projectNumber}-compute@developer.gserviceaccount.com`;
74
+ return `${projectNumber}-compute@developer.gserviceaccount.com`;
75
75
  }
76
+ exports.getDefaultComputeServiceAgent = getDefaultComputeServiceAgent;
76
77
  function reduceEventsToServices(services, endpoint) {
77
78
  const service = (0, services_1.serviceForEndpoint)(endpoint);
78
79
  if (service.requiredProjectBindings && !services.find((s) => s.name === service.name)) {
@@ -83,13 +84,13 @@ function reduceEventsToServices(services, endpoint) {
83
84
  function obtainPubSubServiceAgentBindings(projectNumber) {
84
85
  const serviceAccountTokenCreatorBinding = {
85
86
  role: exports.SERVICE_ACCOUNT_TOKEN_CREATOR_ROLE,
86
- members: [getPubsubServiceAgent(projectNumber)],
87
+ members: [`serviceAccount:${getPubsubServiceAgent(projectNumber)}`],
87
88
  };
88
89
  return [serviceAccountTokenCreatorBinding];
89
90
  }
90
91
  exports.obtainPubSubServiceAgentBindings = obtainPubSubServiceAgentBindings;
91
92
  function obtainDefaultComputeServiceAgentBindings(projectNumber) {
92
- const defaultComputeServiceAgent = getDefaultComputeServiceAgent(projectNumber);
93
+ const defaultComputeServiceAgent = `serviceAccount:${getDefaultComputeServiceAgent(projectNumber)}`;
93
94
  const runInvokerBinding = {
94
95
  role: exports.RUN_INVOKER_ROLE,
95
96
  members: [defaultComputeServiceAgent],
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.groupEndpointsByCodebase = exports.targetCodebases = exports.getFunctionLabel = exports.getEndpointFilters = exports.parseFunctionSelector = exports.endpointMatchesFilter = exports.endpointMatchesAnyFilter = void 0;
3
+ exports.isEndpointFiltered = exports.isCodebaseFiltered = exports.groupEndpointsByCodebase = exports.targetCodebases = exports.getFunctionLabel = exports.getEndpointFilters = exports.parseFunctionSelector = exports.endpointMatchesFilter = exports.endpointMatchesAnyFilter = void 0;
4
4
  const backend = require("./backend");
5
5
  const projectConfig_1 = require("../../functions/projectConfig");
6
6
  function endpointMatchesAnyFilter(endpoint, filters) {
@@ -114,3 +114,14 @@ function groupEndpointsByCodebase(wantBackends, haveEndpoints) {
114
114
  return grouped;
115
115
  }
116
116
  exports.groupEndpointsByCodebase = groupEndpointsByCodebase;
117
+ function isCodebaseFiltered(codebase, filters) {
118
+ return filters.some((filter) => {
119
+ const noIdChunks = (filter.idChunks || []).length === 0;
120
+ return noIdChunks && filter.codebase === codebase;
121
+ });
122
+ }
123
+ exports.isCodebaseFiltered = isCodebaseFiltered;
124
+ function isEndpointFiltered(endpoint, filters) {
125
+ return filters.some((filter) => endpointMatchesFilter(endpoint, filter));
126
+ }
127
+ exports.isEndpointFiltered = isEndpointFiltered;