firebase-tools 9.17.0 → 9.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 (95) hide show
  1. package/CHANGELOG.md +3 -7
  2. package/lib/api.js +1 -0
  3. package/lib/apiv2.js +5 -3
  4. package/lib/appdistribution/client.js +84 -72
  5. package/lib/appdistribution/distribution.js +8 -26
  6. package/lib/appdistribution/options-parser-util.js +51 -0
  7. package/lib/command.js +1 -1
  8. package/lib/commands/appdistribution-distribute.js +74 -91
  9. package/lib/commands/appdistribution-testers-add.js +18 -0
  10. package/lib/commands/appdistribution-testers-remove.js +32 -0
  11. package/lib/commands/crashlytics-symbols-upload.js +146 -0
  12. package/lib/commands/ext-configure.js +9 -1
  13. package/lib/commands/ext-dev-extension-delete.js +2 -1
  14. package/lib/commands/ext-dev-publish.js +11 -4
  15. package/lib/commands/ext-dev-unpublish.js +12 -4
  16. package/lib/commands/ext-install.js +115 -48
  17. package/lib/commands/ext-uninstall.js +6 -0
  18. package/lib/commands/ext-update.js +61 -18
  19. package/lib/commands/functions-config-export.js +115 -0
  20. package/lib/commands/functions-delete.js +45 -25
  21. package/lib/commands/functions-list.js +54 -0
  22. package/lib/commands/functions-log.js +5 -22
  23. package/lib/commands/hosting-channel-deploy.js +6 -4
  24. package/lib/commands/index.js +12 -0
  25. package/lib/deploy/functions/backend.js +118 -121
  26. package/lib/deploy/functions/checkIam.js +8 -8
  27. package/lib/deploy/functions/containerCleaner.js +5 -1
  28. package/lib/deploy/functions/deploy.js +11 -15
  29. package/lib/deploy/functions/functionsDeployHelper.js +3 -68
  30. package/lib/deploy/functions/prepare.js +67 -33
  31. package/lib/deploy/functions/pricing.js +17 -17
  32. package/lib/deploy/functions/prompts.js +24 -41
  33. package/lib/deploy/functions/release/executor.js +39 -0
  34. package/lib/deploy/functions/release/fabricator.js +362 -0
  35. package/lib/deploy/functions/release/index.js +69 -0
  36. package/lib/deploy/functions/release/planner.js +159 -0
  37. package/lib/deploy/functions/release/reporter.js +162 -0
  38. package/lib/deploy/functions/release/sourceTokenScraper.js +28 -0
  39. package/lib/deploy/functions/release/timer.js +14 -0
  40. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +102 -126
  41. package/lib/deploy/functions/runtimes/node/parseTriggers.js +34 -50
  42. package/lib/deploy/functions/triggerRegionHelper.js +40 -0
  43. package/lib/deploy/functions/validate.js +1 -24
  44. package/lib/downloadUtils.js +37 -0
  45. package/lib/emulator/auth/apiSpec.js +1788 -403
  46. package/lib/emulator/auth/handlers.js +6 -5
  47. package/lib/emulator/auth/operations.js +439 -40
  48. package/lib/emulator/auth/server.js +32 -11
  49. package/lib/emulator/auth/state.js +205 -5
  50. package/lib/emulator/auth/widget_ui.js +2 -2
  51. package/lib/emulator/download.js +2 -31
  52. package/lib/emulator/downloadableEmulators.js +7 -7
  53. package/lib/emulator/emulatorLogger.js +0 -3
  54. package/lib/emulator/events/types.js +16 -0
  55. package/lib/emulator/functionsEmulator.js +117 -20
  56. package/lib/emulator/functionsEmulatorRuntime.js +46 -121
  57. package/lib/emulator/functionsEmulatorShared.js +51 -7
  58. package/lib/emulator/functionsEmulatorShell.js +1 -1
  59. package/lib/emulator/pubsubEmulator.js +61 -40
  60. package/lib/emulator/storage/cloudFunctions.js +37 -7
  61. package/lib/extensions/askUserForConsent.js +16 -13
  62. package/lib/extensions/askUserForParam.js +72 -3
  63. package/lib/extensions/billingMigrationHelper.js +1 -11
  64. package/lib/extensions/changelog.js +2 -1
  65. package/lib/extensions/displayExtensionInfo.js +35 -33
  66. package/lib/extensions/emulator/optionsHelper.js +3 -3
  67. package/lib/extensions/emulator/triggerHelper.js +2 -32
  68. package/lib/extensions/extensionsApi.js +67 -94
  69. package/lib/extensions/extensionsHelper.js +49 -35
  70. package/lib/extensions/paramHelper.js +79 -36
  71. package/lib/extensions/refs.js +59 -0
  72. package/lib/extensions/secretsUtils.js +58 -0
  73. package/lib/extensions/updateHelper.js +21 -45
  74. package/lib/extensions/warnings.js +1 -7
  75. package/lib/functional.js +64 -0
  76. package/lib/functions/env.js +26 -13
  77. package/lib/functions/functionslog.js +40 -0
  78. package/lib/functions/runtimeConfigExport.js +137 -0
  79. package/lib/gcp/cloudfunctions.js +46 -38
  80. package/lib/gcp/cloudfunctionsv2.js +47 -47
  81. package/lib/gcp/cloudlogging.js +27 -21
  82. package/lib/gcp/cloudscheduler.js +22 -16
  83. package/lib/gcp/pubsub.js +1 -9
  84. package/lib/gcp/secretManager.js +111 -0
  85. package/lib/gcp/storage.js +16 -0
  86. package/lib/previews.js +1 -1
  87. package/lib/requireInteractive.js +12 -0
  88. package/lib/utils.js +30 -1
  89. package/package.json +5 -4
  90. package/lib/deploy/functions/deploymentPlanner.js +0 -113
  91. package/lib/deploy/functions/deploymentTimer.js +0 -23
  92. package/lib/deploy/functions/errorHandler.js +0 -75
  93. package/lib/deploy/functions/release.js +0 -116
  94. package/lib/deploy/functions/tasks.js +0 -324
  95. package/lib/functionsDelete.js +0 -60
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDotenvFilename = exports.toDotenvFormat = exports.hydrateEnvs = exports.configToEnv = exports.convertKey = exports.hydrateConfigs = exports.getProjectInfos = void 0;
4
+ const clc = require("cli-color");
5
+ const env = require("./env");
6
+ const functionsConfig = require("../functionsConfig");
7
+ const error_1 = require("../error");
8
+ const logger_1 = require("../logger");
9
+ const projectUtils_1 = require("../projectUtils");
10
+ const rc_1 = require("../rc");
11
+ const utils_1 = require("../utils");
12
+ const functional_1 = require("../functional");
13
+ function getProjectInfos(options) {
14
+ const result = {};
15
+ const rc = rc_1.loadRC(options);
16
+ if (rc.projects) {
17
+ for (const [alias, projectId] of Object.entries(rc.projects)) {
18
+ if (Object.keys(result).includes(projectId)) {
19
+ utils_1.logWarning(`Multiple aliases found for ${clc.bold(projectId)}. ` +
20
+ `Preferring alias (${clc.bold(result[projectId])}) over (${clc.bold(alias)}).`);
21
+ continue;
22
+ }
23
+ result[projectId] = alias;
24
+ }
25
+ }
26
+ const projectId = projectUtils_1.getProjectId(options);
27
+ if (projectId && !Object.keys(result).includes(projectId)) {
28
+ result[projectId] = projectId;
29
+ }
30
+ return Object.entries(result).map(([k, v]) => {
31
+ const result = { projectId: k };
32
+ if (k !== v) {
33
+ result.alias = v;
34
+ }
35
+ return result;
36
+ });
37
+ }
38
+ exports.getProjectInfos = getProjectInfos;
39
+ async function hydrateConfigs(pInfos) {
40
+ const hydrate = pInfos.map((info) => {
41
+ return functionsConfig
42
+ .materializeAll(info.projectId)
43
+ .then((config) => {
44
+ info.config = config;
45
+ return;
46
+ })
47
+ .catch((err) => {
48
+ logger_1.logger.debug(`Failed to fetch runtime config for project ${info.projectId}: ${err.message}`);
49
+ });
50
+ });
51
+ await Promise.all(hydrate);
52
+ }
53
+ exports.hydrateConfigs = hydrateConfigs;
54
+ function convertKey(configKey, prefix) {
55
+ const baseKey = configKey
56
+ .toUpperCase()
57
+ .replace(/\./g, "_")
58
+ .replace(/-/g, "_");
59
+ let envKey = baseKey;
60
+ try {
61
+ env.validateKey(envKey);
62
+ }
63
+ catch (err) {
64
+ if (err instanceof env.KeyValidationError) {
65
+ envKey = prefix + envKey;
66
+ env.validateKey(envKey);
67
+ }
68
+ }
69
+ return envKey;
70
+ }
71
+ exports.convertKey = convertKey;
72
+ function configToEnv(configs, prefix) {
73
+ const success = [];
74
+ const errors = [];
75
+ for (const [configKey, value] of functional_1.flatten(configs)) {
76
+ try {
77
+ const envKey = convertKey(configKey, prefix);
78
+ success.push({ origKey: configKey, newKey: envKey, value: value });
79
+ }
80
+ catch (err) {
81
+ if (err instanceof env.KeyValidationError) {
82
+ errors.push({
83
+ origKey: configKey,
84
+ newKey: err.key,
85
+ err: err.message,
86
+ value: value,
87
+ });
88
+ }
89
+ else {
90
+ throw new error_1.FirebaseError("Unexpected error while converting config", {
91
+ exit: 2,
92
+ original: err,
93
+ });
94
+ }
95
+ }
96
+ }
97
+ return { success, errors };
98
+ }
99
+ exports.configToEnv = configToEnv;
100
+ function hydrateEnvs(pInfos, prefix) {
101
+ let errMsg = "";
102
+ for (const pInfo of pInfos) {
103
+ const { success, errors } = configToEnv(pInfo.config, prefix);
104
+ if (errors.length > 0) {
105
+ const msg = `${pInfo.projectId} ` +
106
+ `${pInfo.alias ? "(" + pInfo.alias + ")" : ""}:\n` +
107
+ errors.map((err) => `\t${err.origKey} => ${clc.bold(err.newKey)} (${err.err})`).join("\n") +
108
+ "\n";
109
+ errMsg += msg;
110
+ }
111
+ else {
112
+ pInfo.envs = success;
113
+ }
114
+ }
115
+ return errMsg;
116
+ }
117
+ exports.hydrateEnvs = hydrateEnvs;
118
+ function escape(s) {
119
+ const result = s
120
+ .replace("\n", "\\n")
121
+ .replace("\r", "\\r")
122
+ .replace("\t", "\\t")
123
+ .replace("\v", "\\v");
124
+ return result.replace(/(['"])/g, "\\$1");
125
+ }
126
+ function toDotenvFormat(envs, header = "") {
127
+ const lines = envs.map(({ newKey, value }) => `${newKey}="${escape(value)}"`);
128
+ const maxLineLen = Math.max(...lines.map((l) => l.length));
129
+ return (`${header}\n` +
130
+ lines.map((line, idx) => `${line.padEnd(maxLineLen)} # from ${envs[idx].origKey}`).join("\n"));
131
+ }
132
+ exports.toDotenvFormat = toDotenvFormat;
133
+ function generateDotenvFilename(pInfo) {
134
+ var _a;
135
+ return `.env.${(_a = pInfo.alias) !== null && _a !== void 0 ? _a : pInfo.projectId}`;
136
+ }
137
+ exports.generateDotenvFilename = generateDotenvFilename;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.functionFromSpec = exports.specFromFunction = exports.listAllFunctions = exports.listFunctions = exports.deleteFunction = exports.updateFunction = exports.setInvokerUpdate = exports.setInvokerCreate = exports.getIamPolicy = exports.setIamPolicy = exports.createFunction = exports.generateUploadUrl = exports.API_VERSION = void 0;
3
+ exports.functionFromEndpoint = exports.endpointFromFunction = exports.listAllFunctions = exports.listFunctions = exports.deleteFunction = exports.updateFunction = exports.setInvokerUpdate = exports.setInvokerCreate = exports.getIamPolicy = exports.setIamPolicy = exports.createFunction = exports.generateUploadUrl = exports.API_VERSION = void 0;
4
4
  const clc = require("cli-color");
5
5
  const error_1 = require("../error");
6
6
  const logger_1 = require("../logger");
@@ -198,9 +198,11 @@ async function list(projectId, region) {
198
198
  };
199
199
  }
200
200
  catch (err) {
201
- logger_1.logger.debug("[functions] failed to list functions for " + projectId);
201
+ logger_1.logger.debug(`[functions] failed to list functions for ${projectId}`);
202
202
  logger_1.logger.debug(`[functions] ${err === null || err === void 0 ? void 0 : err.message}`);
203
- return Promise.reject(err === null || err === void 0 ? void 0 : err.message);
203
+ throw new error_1.FirebaseError(`Failed to list functions for ${projectId}`, {
204
+ original: err,
205
+ });
204
206
  }
205
207
  }
206
208
  async function listFunctions(projectId, region) {
@@ -212,74 +214,80 @@ async function listAllFunctions(projectId) {
212
214
  return list(projectId, "-");
213
215
  }
214
216
  exports.listAllFunctions = listAllFunctions;
215
- function specFromFunction(gcfFunction) {
216
- var _a;
217
+ function endpointFromFunction(gcfFunction) {
218
+ var _a, _b;
217
219
  const [, project, , region, , id] = gcfFunction.name.split("/");
218
220
  let trigger;
219
221
  let uri;
220
222
  if (gcfFunction.httpsTrigger) {
223
+ trigger = { httpsTrigger: {} };
224
+ uri = gcfFunction.httpsTrigger.url;
225
+ }
226
+ else if ((_a = gcfFunction.labels) === null || _a === void 0 ? void 0 : _a["deployment-scheduled"]) {
221
227
  trigger = {
222
- allowInsecure: gcfFunction.httpsTrigger.securityLevel !== "SECURE_ALWAYS",
228
+ scheduleTrigger: {},
223
229
  };
224
- uri = gcfFunction.httpsTrigger.url;
225
230
  }
226
231
  else {
227
232
  trigger = {
228
- eventType: gcfFunction.eventTrigger.eventType,
229
- eventFilters: {
230
- resource: gcfFunction.eventTrigger.resource,
233
+ eventTrigger: {
234
+ eventType: gcfFunction.eventTrigger.eventType,
235
+ eventFilters: {
236
+ resource: gcfFunction.eventTrigger.resource,
237
+ },
238
+ retry: !!((_b = gcfFunction.eventTrigger.failurePolicy) === null || _b === void 0 ? void 0 : _b.retry),
231
239
  },
232
- retry: !!((_a = gcfFunction.eventTrigger.failurePolicy) === null || _a === void 0 ? void 0 : _a.retry),
233
240
  };
234
241
  }
235
242
  if (!runtimes.isValidRuntime(gcfFunction.runtime)) {
236
243
  logger_1.logger.debug("GCFv1 function has a deprecated runtime:", JSON.stringify(gcfFunction, null, 2));
237
244
  }
238
- const cloudFunction = {
239
- platform: "gcfv1",
240
- id,
245
+ const endpoint = Object.assign(Object.assign({ platform: "gcfv1", id,
241
246
  project,
242
- region,
243
- trigger,
244
- entryPoint: gcfFunction.entryPoint,
245
- runtime: gcfFunction.runtime,
246
- };
247
+ region }, trigger), { entryPoint: gcfFunction.entryPoint, runtime: gcfFunction.runtime });
247
248
  if (uri) {
248
- cloudFunction.uri = uri;
249
+ endpoint.uri = uri;
249
250
  }
250
- proto.copyIfPresent(cloudFunction, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "timeout", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "labels", "environmentVariables", "sourceUploadUrl");
251
- return cloudFunction;
251
+ proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "timeout", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "labels", "environmentVariables", "sourceUploadUrl");
252
+ return endpoint;
252
253
  }
253
- exports.specFromFunction = specFromFunction;
254
- function functionFromSpec(cloudFunction, sourceUploadUrl) {
255
- if (cloudFunction.platform != "gcfv1") {
254
+ exports.endpointFromFunction = endpointFromFunction;
255
+ function functionFromEndpoint(endpoint, sourceUploadUrl) {
256
+ if (endpoint.platform != "gcfv1") {
256
257
  throw new error_1.FirebaseError("Trying to create a v1 CloudFunction with v2 API. This should never happen");
257
258
  }
258
- if (!runtimes.isValidRuntime(cloudFunction.runtime)) {
259
+ if (!runtimes.isValidRuntime(endpoint.runtime)) {
259
260
  throw new error_1.FirebaseError("Failed internal assertion. Trying to deploy a new function with a deprecated runtime." +
260
261
  " This should never happen");
261
262
  }
262
263
  const gcfFunction = {
263
- name: backend.functionName(cloudFunction),
264
+ name: backend.functionName(endpoint),
264
265
  sourceUploadUrl: sourceUploadUrl,
265
- entryPoint: cloudFunction.entryPoint,
266
- runtime: cloudFunction.runtime,
266
+ entryPoint: endpoint.entryPoint,
267
+ runtime: endpoint.runtime,
267
268
  };
268
- if (backend.isEventTrigger(cloudFunction.trigger)) {
269
+ proto.copyIfPresent(gcfFunction, endpoint, "labels");
270
+ if (backend.isEventTriggered(endpoint)) {
269
271
  gcfFunction.eventTrigger = {
270
- eventType: cloudFunction.trigger.eventType,
271
- resource: cloudFunction.trigger.eventFilters.resource,
272
+ eventType: endpoint.eventTrigger.eventType,
273
+ resource: endpoint.eventTrigger.eventFilters.resource,
272
274
  };
273
- gcfFunction.eventTrigger.failurePolicy = cloudFunction.trigger.retry
275
+ gcfFunction.eventTrigger.failurePolicy = endpoint.eventTrigger.retry
274
276
  ? { retry: {} }
275
277
  : undefined;
276
278
  }
277
- else {
278
- gcfFunction.httpsTrigger = {
279
- securityLevel: cloudFunction.trigger.allowInsecure ? "SECURE_OPTIONAL" : "SECURE_ALWAYS",
279
+ else if (backend.isScheduleTriggered(endpoint)) {
280
+ const id = backend.scheduleIdForFunction(endpoint);
281
+ gcfFunction.eventTrigger = {
282
+ eventType: "google.pubsub.topic.publish",
283
+ resource: `projects/${endpoint.project}/topics/${id}`,
280
284
  };
285
+ gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-scheduled": "true" });
286
+ }
287
+ else {
288
+ gcfFunction.httpsTrigger = {};
281
289
  }
282
- proto.copyIfPresent(gcfFunction, cloudFunction, "serviceAccountEmail", "timeout", "availableMemoryMb", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "labels", "environmentVariables");
290
+ proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "timeout", "availableMemoryMb", "minInstances", "maxInstances", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
283
291
  return gcfFunction;
284
292
  }
285
- exports.functionFromSpec = functionFromSpec;
293
+ exports.functionFromEndpoint = functionFromEndpoint;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.specFromFunction = exports.functionFromSpec = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.PUBSUB_PUBLISH_EVENT = exports.API_VERSION = void 0;
3
+ exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.PUBSUB_PUBLISH_EVENT = exports.API_VERSION = void 0;
4
4
  const clc = require("cli-color");
5
5
  const apiv2_1 = require("../apiv2");
6
6
  const error_1 = require("../error");
@@ -115,19 +115,19 @@ async function deleteFunction(cloudFunction) {
115
115
  }
116
116
  }
117
117
  exports.deleteFunction = deleteFunction;
118
- function functionFromSpec(cloudFunction, source) {
119
- if (cloudFunction.platform != "gcfv2") {
118
+ function functionFromEndpoint(endpoint, source) {
119
+ if (endpoint.platform != "gcfv2") {
120
120
  throw new error_1.FirebaseError("Trying to create a v2 CloudFunction with v1 API. This should never happen");
121
121
  }
122
- if (!runtimes.isValidRuntime(cloudFunction.runtime)) {
122
+ if (!runtimes.isValidRuntime(endpoint.runtime)) {
123
123
  throw new error_1.FirebaseError("Failed internal assertion. Trying to deploy a new function with a deprecated runtime." +
124
124
  " This should never happen");
125
125
  }
126
126
  const gcfFunction = {
127
- name: backend.functionName(cloudFunction),
127
+ name: backend.functionName(endpoint),
128
128
  buildConfig: {
129
- runtime: cloudFunction.runtime,
130
- entryPoint: cloudFunction.entryPoint,
129
+ runtime: endpoint.runtime,
130
+ entryPoint: endpoint.entryPoint,
131
131
  source: {
132
132
  storageSource: source,
133
133
  },
@@ -135,75 +135,75 @@ function functionFromSpec(cloudFunction, source) {
135
135
  },
136
136
  serviceConfig: {},
137
137
  };
138
- proto.copyIfPresent(gcfFunction.serviceConfig, cloudFunction, "availableMemoryMb", "environmentVariables", "vpcConnector", "vpcConnectorEgressSettings", "serviceAccountEmail", "ingressSettings");
139
- proto.renameIfPresent(gcfFunction.serviceConfig, cloudFunction, "timeoutSeconds", "timeout", proto.secondsFromDuration);
140
- proto.renameIfPresent(gcfFunction.serviceConfig, cloudFunction, "minInstanceCount", "minInstances");
141
- proto.renameIfPresent(gcfFunction.serviceConfig, cloudFunction, "maxInstanceCount", "maxInstances");
142
- if (backend.isEventTrigger(cloudFunction.trigger)) {
138
+ proto.copyIfPresent(gcfFunction, endpoint, "labels");
139
+ proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemoryMb", "environmentVariables", "vpcConnector", "vpcConnectorEgressSettings", "serviceAccountEmail", "ingressSettings");
140
+ proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "timeoutSeconds", "timeout", proto.secondsFromDuration);
141
+ proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "minInstanceCount", "minInstances");
142
+ proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "maxInstanceCount", "maxInstances");
143
+ if (backend.isEventTriggered(endpoint)) {
143
144
  gcfFunction.eventTrigger = {
144
- eventType: cloudFunction.trigger.eventType,
145
+ eventType: endpoint.eventTrigger.eventType,
145
146
  };
146
147
  if (gcfFunction.eventTrigger.eventType === exports.PUBSUB_PUBLISH_EVENT) {
147
- gcfFunction.eventTrigger.pubsubTopic = cloudFunction.trigger.eventFilters.resource;
148
+ gcfFunction.eventTrigger.pubsubTopic = endpoint.eventTrigger.eventFilters.resource;
148
149
  }
149
150
  else {
150
151
  gcfFunction.eventTrigger.eventFilters = [];
151
- for (const [attribute, value] of Object.entries(cloudFunction.trigger.eventFilters)) {
152
+ for (const [attribute, value] of Object.entries(endpoint.eventTrigger.eventFilters)) {
152
153
  gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
153
154
  }
154
155
  }
155
- if (cloudFunction.trigger.retry) {
156
- logger_1.logger.warn("Cannot set a retry policy on Cloud Function", cloudFunction.id);
156
+ if (endpoint.eventTrigger.retry) {
157
+ logger_1.logger.warn("Cannot set a retry policy on Cloud Function", endpoint.id);
157
158
  }
158
159
  }
159
- else if (cloudFunction.trigger.allowInsecure) {
160
- logger_1.logger.warn("Cannot enable insecure traffic for Cloud Function", cloudFunction.id);
160
+ else if (backend.isScheduleTriggered(endpoint)) {
161
+ gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { ["deployment-scheduled"]: "true" });
161
162
  }
162
- proto.copyIfPresent(gcfFunction, cloudFunction, "labels");
163
163
  return gcfFunction;
164
164
  }
165
- exports.functionFromSpec = functionFromSpec;
166
- function specFromFunction(gcfFunction) {
165
+ exports.functionFromEndpoint = functionFromEndpoint;
166
+ function endpointFromFunction(gcfFunction) {
167
+ var _a;
167
168
  const [, project, , region, , id] = gcfFunction.name.split("/");
168
169
  let trigger;
169
- if (gcfFunction.eventTrigger) {
170
+ if (((_a = gcfFunction.labels) === null || _a === void 0 ? void 0 : _a["deployment-scheduled"]) === "true") {
170
171
  trigger = {
171
- eventType: gcfFunction.eventTrigger.eventType,
172
- eventFilters: {},
173
- retry: false,
172
+ scheduleTrigger: {},
173
+ };
174
+ }
175
+ else if (gcfFunction.eventTrigger) {
176
+ trigger = {
177
+ eventTrigger: {
178
+ eventType: gcfFunction.eventTrigger.eventType,
179
+ eventFilters: {},
180
+ retry: false,
181
+ },
174
182
  };
175
183
  if (gcfFunction.eventTrigger.pubsubTopic) {
176
- trigger.eventFilters.resource = gcfFunction.eventTrigger.pubsubTopic;
184
+ trigger.eventTrigger.eventFilters.resource = gcfFunction.eventTrigger.pubsubTopic;
177
185
  }
178
186
  else {
179
187
  for (const { attribute, value } of gcfFunction.eventTrigger.eventFilters || []) {
180
- trigger.eventFilters[attribute] = value;
188
+ trigger.eventTrigger.eventFilters[attribute] = value;
181
189
  }
182
190
  }
191
+ proto.renameIfPresent(trigger.eventTrigger, gcfFunction.eventTrigger, "region", "triggerRegion");
183
192
  }
184
193
  else {
185
- trigger = {
186
- allowInsecure: false,
187
- };
194
+ trigger = { httpsTrigger: {} };
188
195
  }
189
196
  if (!runtimes.isValidRuntime(gcfFunction.buildConfig.runtime)) {
190
197
  logger_1.logger.debug("GCFv2 function has a deprecated runtime:", JSON.stringify(gcfFunction, null, 2));
191
198
  }
192
- const cloudFunction = {
193
- platform: "gcfv2",
194
- id,
199
+ const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
195
200
  project,
196
- region,
197
- trigger,
198
- entryPoint: gcfFunction.buildConfig.entryPoint,
199
- runtime: gcfFunction.buildConfig.runtime,
200
- uri: gcfFunction.serviceConfig.uri,
201
- };
202
- proto.copyIfPresent(cloudFunction, gcfFunction.serviceConfig, "serviceAccountEmail", "availableMemoryMb", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
203
- proto.renameIfPresent(cloudFunction, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
204
- proto.renameIfPresent(cloudFunction, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
205
- proto.renameIfPresent(cloudFunction, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
206
- proto.copyIfPresent(cloudFunction, gcfFunction, "labels");
207
- return cloudFunction;
201
+ region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, uri: gcfFunction.serviceConfig.uri });
202
+ proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "availableMemoryMb", "vpcConnector", "vpcConnectorEgressSettings", "ingressSettings", "environmentVariables");
203
+ proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
204
+ proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
205
+ proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
206
+ proto.copyIfPresent(endpoint, gcfFunction, "labels");
207
+ return endpoint;
208
208
  }
209
- exports.specFromFunction = specFromFunction;
209
+ exports.endpointFromFunction = endpointFromFunction;
@@ -1,22 +1,28 @@
1
1
  "use strict";
2
- var api = require("../api");
3
- var version = "v2beta1";
4
- var _listEntries = function (projectId, filter, pageSize, order) {
5
- return api
6
- .request("POST", "/" + version + "/entries:list", {
7
- auth: true,
8
- data: {
9
- projectIds: [projectId],
10
- filter: filter,
11
- orderBy: "timestamp " + order,
12
- pageSize: pageSize,
13
- },
14
- origin: api.cloudloggingOrigin,
15
- })
16
- .then(function (result) {
17
- return Promise.resolve(result.body.entries);
18
- });
19
- };
20
- module.exports = {
21
- listEntries: _listEntries,
22
- };
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listEntries = void 0;
4
+ const api = require("../api");
5
+ const error_1 = require("../error");
6
+ const API_VERSION = "v2";
7
+ async function listEntries(projectId, filter, pageSize, order) {
8
+ const endpoint = `/${API_VERSION}/entries:list`;
9
+ try {
10
+ const result = await api.request("POST", endpoint, {
11
+ auth: true,
12
+ data: {
13
+ resourceNames: [`projects/${projectId}`],
14
+ filter: filter,
15
+ orderBy: "timestamp " + order,
16
+ pageSize: pageSize,
17
+ },
18
+ origin: api.cloudloggingOrigin,
19
+ });
20
+ return result.body.entries;
21
+ }
22
+ catch (err) {
23
+ throw new error_1.FirebaseError("Failed to retrieve log entries from Google Cloud.", {
24
+ original: err,
25
+ });
26
+ }
27
+ }
28
+ exports.listEntries = listEntries;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.jobFromSpec = exports.createOrReplaceJob = exports.updateJob = exports.getJob = exports.deleteJob = exports.createJob = exports.assertValidJob = void 0;
3
+ exports.jobFromEndpoint = exports.createOrReplaceJob = exports.updateJob = exports.getJob = exports.deleteJob = exports.createJob = exports.assertValidJob = void 0;
4
4
  const _ = require("lodash");
5
5
  const error_1 = require("../error");
6
6
  const logger_1 = require("../logger");
7
7
  const api = require("../api");
8
8
  const backend = require("../deploy/functions/backend");
9
9
  const proto = require("./proto");
10
+ const functional_1 = require("../functional");
10
11
  const VERSION = "v1beta1";
11
12
  const DEFAULT_TIME_ZONE = "America/Los_Angeles";
12
13
  function assertValidJob(job) {
@@ -86,21 +87,26 @@ function isIdentical(job, otherJob) {
86
87
  job.timeZone === otherJob.timeZone &&
87
88
  _.isEqual(job.retryConfig, otherJob.retryConfig));
88
89
  }
89
- function jobFromSpec(schedule, appEngineLocation) {
90
- const job = {
91
- name: backend.scheduleName(schedule, appEngineLocation),
92
- schedule: schedule.schedule,
93
- };
94
- proto.copyIfPresent(job, schedule, "timeZone", "retryConfig");
95
- if (schedule.transport === "https") {
96
- throw new error_1.FirebaseError("HTTPS transport for scheduled functions is not yet supported");
90
+ function jobFromEndpoint(endpoint, appEngineLocation) {
91
+ const job = {};
92
+ if (endpoint.platform === "gcfv1") {
93
+ const id = backend.scheduleIdForFunction(endpoint);
94
+ const region = appEngineLocation;
95
+ job.name = `projects/${endpoint.project}/locations/${region}/jobs/${id}`;
96
+ job.pubsubTarget = {
97
+ topicName: `projects/${endpoint.project}/topics/${id}`,
98
+ attributes: {
99
+ scheduled: "true",
100
+ },
101
+ };
97
102
  }
98
- job.pubsubTarget = {
99
- topicName: backend.topicName(schedule),
100
- attributes: {
101
- scheduled: "true",
102
- },
103
- };
103
+ else if (endpoint.platform === "gcfv2") {
104
+ throw new error_1.FirebaseError("Do not know how to create a scheduled GCFv2 function");
105
+ }
106
+ else {
107
+ functional_1.assertExhaustive(endpoint.platform);
108
+ }
109
+ proto.copyIfPresent(job, endpoint.scheduleTrigger, "schedule", "retryConfig", "timeZone");
104
110
  return job;
105
111
  }
106
- exports.jobFromSpec = jobFromSpec;
112
+ exports.jobFromEndpoint = jobFromEndpoint;
package/lib/gcp/pubsub.js CHANGED
@@ -1,9 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.topicFromSpec = exports.deleteTopic = exports.updateTopic = exports.getTopic = exports.createTopic = void 0;
3
+ exports.deleteTopic = exports.updateTopic = exports.getTopic = exports.createTopic = void 0;
4
4
  const apiv2_1 = require("../apiv2");
5
5
  const api_1 = require("../api");
6
- const backend = require("../deploy/functions/backend");
7
6
  const proto = require("./proto");
8
7
  const API_VERSION = "v1";
9
8
  const client = new apiv2_1.Client({
@@ -33,10 +32,3 @@ async function deleteTopic(name) {
33
32
  await client.delete(name);
34
33
  }
35
34
  exports.deleteTopic = deleteTopic;
36
- function topicFromSpec(spec) {
37
- return {
38
- name: backend.topicName(spec),
39
- labels: Object.assign({}, spec.labels),
40
- };
41
- }
42
- exports.topicFromSpec = topicFromSpec;