firebase-tools 11.21.0 → 11.23.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 (94) hide show
  1. package/lib/commands/ext-configure.js +3 -3
  2. package/lib/commands/ext-dev-init.js +16 -4
  3. package/lib/commands/ext-dev-publish.js +3 -3
  4. package/lib/commands/ext-dev-register.js +2 -2
  5. package/lib/commands/ext-info.js +3 -3
  6. package/lib/commands/ext-install.js +2 -2
  7. package/lib/commands/ext-uninstall.js +2 -2
  8. package/lib/commands/ext-update.js +2 -2
  9. package/lib/commands/hosting-channel-create.js +2 -2
  10. package/lib/commands/hosting-channel-delete.js +2 -2
  11. package/lib/commands/hosting-channel-deploy.js +2 -2
  12. package/lib/commands/hosting-clone.js +2 -2
  13. package/lib/deploy/functions/release/fabricator.js +3 -0
  14. package/lib/deploy/functions/runtimes/discovery/index.js +1 -1
  15. package/lib/deploy/functions/runtimes/index.js +5 -2
  16. package/lib/deploy/functions/runtimes/node/index.js +70 -27
  17. package/lib/deploy/functions/runtimes/node/versioning.js +4 -2
  18. package/lib/deploy/functions/runtimes/python/index.js +132 -0
  19. package/lib/deploy/hosting/convertConfig.js +2 -1
  20. package/lib/emulator/auth/apiSpec.js +21 -1
  21. package/lib/emulator/controller.js +5 -5
  22. package/lib/emulator/downloadableEmulators.js +6 -6
  23. package/lib/emulator/extensionsEmulator.js +3 -2
  24. package/lib/emulator/functionsEmulator.js +119 -87
  25. package/lib/emulator/functionsEmulatorRuntime.js +26 -42
  26. package/lib/emulator/functionsRuntimeWorker.js +51 -35
  27. package/lib/emulator/hub.js +6 -6
  28. package/lib/emulator/pubsubEmulator.js +12 -9
  29. package/lib/emulator/storage/apis/shared.js +2 -1
  30. package/lib/emulator/storage/cloudFunctions.js +1 -1
  31. package/lib/emulator/storage/files.js +18 -11
  32. package/lib/emulator/types.js +9 -9
  33. package/lib/extensions/askUserForConsent.js +4 -4
  34. package/lib/extensions/askUserForEventsConfig.js +2 -2
  35. package/lib/extensions/askUserForParam.js +34 -3
  36. package/lib/extensions/billingMigrationHelper.js +4 -4
  37. package/lib/extensions/change-log.js +4 -4
  38. package/lib/extensions/displayExtensionInfo.js +4 -4
  39. package/lib/extensions/emulator/optionsHelper.js +3 -3
  40. package/lib/extensions/emulator/specHelper.js +17 -16
  41. package/lib/extensions/extensionsApi.js +2 -2
  42. package/lib/extensions/extensionsHelper.js +6 -6
  43. package/lib/extensions/provisioningHelper.js +2 -2
  44. package/lib/extensions/updateHelper.js +2 -2
  45. package/lib/extensions/warnings.js +5 -5
  46. package/lib/firestore/checkDatabaseType.js +3 -3
  47. package/lib/frameworks/angular/index.js +6 -4
  48. package/lib/frameworks/index.js +47 -11
  49. package/lib/frameworks/lit/index.js +5 -1
  50. package/lib/frameworks/next/index.js +48 -20
  51. package/lib/frameworks/next/utils.js +1 -1
  52. package/lib/frameworks/nuxt/index.js +18 -26
  53. package/lib/frameworks/nuxt/interfaces.js +2 -0
  54. package/lib/frameworks/nuxt/utils.js +13 -0
  55. package/lib/frameworks/nuxt2/index.js +91 -0
  56. package/lib/frameworks/preact/index.js +5 -1
  57. package/lib/frameworks/react/index.js +5 -1
  58. package/lib/frameworks/svelte/index.js +5 -1
  59. package/lib/frameworks/vite/index.js +6 -4
  60. package/lib/functions/python.js +16 -0
  61. package/lib/gcp/cloudfunctionsv2.js +8 -0
  62. package/lib/getDefaultHostingSite.js +3 -1
  63. package/lib/init/features/firestore/index.js +1 -3
  64. package/lib/init/features/functions/index.js +10 -0
  65. package/lib/init/features/functions/python.js +48 -0
  66. package/lib/init/features/hosting/index.js +3 -2
  67. package/lib/projectUtils.js +2 -2
  68. package/lib/rc.js +4 -4
  69. package/lib/serve/functions.js +1 -3
  70. package/npm-shrinkwrap.json +1295 -276
  71. package/package.json +2 -2
  72. package/templates/extensions/extension.yaml +1 -1
  73. package/templates/extensions/integration-test.env +2 -0
  74. package/templates/extensions/integration-test.json +14 -0
  75. package/templates/extensions/javascript/WELCOME.md +14 -5
  76. package/templates/extensions/javascript/index.js +10 -10
  77. package/templates/extensions/javascript/integration-test.js +13 -0
  78. package/templates/extensions/javascript/package.lint.json +12 -4
  79. package/templates/extensions/javascript/package.nolint.json +11 -2
  80. package/templates/extensions/typescript/WELCOME.md +18 -5
  81. package/templates/extensions/typescript/_mocharc +10 -0
  82. package/templates/extensions/typescript/index.ts +16 -15
  83. package/templates/extensions/typescript/integration-test.ts +13 -0
  84. package/templates/extensions/typescript/package.lint.json +16 -4
  85. package/templates/extensions/typescript/package.nolint.json +12 -4
  86. package/templates/init/functions/javascript/_eslintrc +16 -2
  87. package/templates/init/functions/javascript/package.lint.json +4 -4
  88. package/templates/init/functions/javascript/package.nolint.json +3 -3
  89. package/templates/init/functions/python/_gitignore +0 -0
  90. package/templates/init/functions/python/main.py +13 -0
  91. package/templates/init/functions/python/requirements.txt +1 -0
  92. package/templates/init/functions/typescript/_eslintrc +1 -0
  93. package/templates/init/functions/typescript/package.lint.json +4 -4
  94. package/templates/init/functions/typescript/package.nolint.json +4 -3
@@ -41,6 +41,27 @@ function requireResolveAsync(moduleName, opts) {
41
41
  });
42
42
  }
43
43
  class Proxied {
44
+ static getOriginal(target, key) {
45
+ const value = target[key];
46
+ if (!Proxied.isExists(value)) {
47
+ return undefined;
48
+ }
49
+ else if (Proxied.isConstructor(value) || typeof value !== "function") {
50
+ return value;
51
+ }
52
+ else {
53
+ return value.bind(target);
54
+ }
55
+ }
56
+ static applyOriginal(target, thisArg, argArray) {
57
+ return target.apply(thisArg, argArray);
58
+ }
59
+ static isConstructor(obj) {
60
+ return !!obj.prototype && !!obj.prototype.constructor.name;
61
+ }
62
+ static isExists(obj) {
63
+ return obj !== undefined;
64
+ }
44
65
  constructor(original) {
45
66
  this.original = original;
46
67
  this.rewrites = {};
@@ -65,27 +86,6 @@ class Proxied {
65
86
  },
66
87
  });
67
88
  }
68
- static getOriginal(target, key) {
69
- const value = target[key];
70
- if (!Proxied.isExists(value)) {
71
- return undefined;
72
- }
73
- else if (Proxied.isConstructor(value) || typeof value !== "function") {
74
- return value;
75
- }
76
- else {
77
- return value.bind(target);
78
- }
79
- }
80
- static applyOriginal(target, thisArg, argArray) {
81
- return target.apply(thisArg, argArray);
82
- }
83
- static isConstructor(obj) {
84
- return !!obj.prototype && !!obj.prototype.constructor.name;
85
- }
86
- static isExists(obj) {
87
- return obj !== undefined;
88
- }
89
89
  when(key, value) {
90
90
  this.rewrites[key] = value;
91
91
  return this;
@@ -395,7 +395,8 @@ async function initializeFirebaseAdminStubs() {
395
395
  return Proxied.getOriginal(target, "storage");
396
396
  })
397
397
  .finalize();
398
- require.cache[adminResolution.resolution] = Object.assign(require.cache[adminResolution.resolution], {
398
+ const v = require.cache[adminResolution.resolution];
399
+ require.cache[adminResolution.resolution] = Object.assign(v, {
399
400
  exports: proxiedAdminModule,
400
401
  path: path.dirname(adminResolution.resolution),
401
402
  });
@@ -472,7 +473,8 @@ async function initializeFunctionsConfigHelper() {
472
473
  return proxiedConfig;
473
474
  })
474
475
  .finalize();
475
- require.cache[functionsResolution.resolution] = Object.assign(require.cache[functionsResolution.resolution], {
476
+ const v = require.cache[functionsResolution.resolution];
477
+ require.cache[functionsResolution.resolution] = Object.assign(v, {
476
478
  exports: proxiedFunctionsModule,
477
479
  path: path.dirname(functionsResolution.resolution),
478
480
  });
@@ -666,18 +668,12 @@ async function main() {
666
668
  });
667
669
  app.all(`/*`, async (req, res) => {
668
670
  try {
669
- new types_1.EmulatorLog("INFO", "runtime-status", `Beginning execution of "${FUNCTION_TARGET_NAME}"`).log();
670
671
  const trigger = FUNCTION_TARGET_NAME.split(".").reduce((mod, functionTargetPart) => {
671
672
  return mod === null || mod === void 0 ? void 0 : mod[functionTargetPart];
672
673
  }, functionModule);
673
674
  if (!trigger) {
674
675
  throw new Error(`Failed to find function ${FUNCTION_TARGET_NAME} in the loaded module`);
675
676
  }
676
- const startHrTime = process.hrtime();
677
- res.on("finish", () => {
678
- const elapsedHrTime = process.hrtime(startHrTime);
679
- new types_1.EmulatorLog("INFO", "runtime-status", `Finished "${FUNCTION_TARGET_NAME}" in ${elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1000000}ms`).log();
680
- });
681
677
  switch (FUNCTION_SIGNATURE) {
682
678
  case "event":
683
679
  case "cloudevent":
@@ -699,21 +695,9 @@ async function main() {
699
695
  res.status(500).send(err.message);
700
696
  }
701
697
  });
702
- const server = app.listen(process.env.PORT, () => {
698
+ app.listen(process.env.PORT, () => {
703
699
  logDebug(`Listening to port: ${process.env.PORT}`);
704
700
  });
705
- if (!FUNCTION_DEBUG_MODE) {
706
- let timeout = process.env.FUNCTIONS_EMULATOR_TIMEOUT_SECONDS || "60";
707
- if (timeout.endsWith("s")) {
708
- timeout = timeout.slice(0, -1);
709
- }
710
- const timeoutMs = parseInt(timeout, 10) * 1000;
711
- server.setTimeout(timeoutMs, () => {
712
- new types_1.EmulatorLog("FATAL", "runtime-error", `Your function timed out after ~${timeout}s. To configure this timeout, see
713
- https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.`).log();
714
- return flushAndExit(1);
715
- });
716
- }
717
701
  let messageHandlePromise = Promise.resolve();
718
702
  process.on("message", (message) => {
719
703
  messageHandlePromise = messageHandlePromise
@@ -15,13 +15,17 @@ var RuntimeWorkerState;
15
15
  RuntimeWorkerState["FINISHING"] = "FINISHING";
16
16
  RuntimeWorkerState["FINISHED"] = "FINISHED";
17
17
  })(RuntimeWorkerState = exports.RuntimeWorkerState || (exports.RuntimeWorkerState = {}));
18
+ const FREE_WORKER_KEY = "~free~";
18
19
  class RuntimeWorker {
19
- constructor(key, runtime) {
20
+ constructor(triggerId, runtime, extensionLogInfo, timeoutSeconds) {
21
+ this.runtime = runtime;
22
+ this.extensionLogInfo = extensionLogInfo;
23
+ this.timeoutSeconds = timeoutSeconds;
20
24
  this.stateEvents = new events_1.EventEmitter();
21
25
  this.logListeners = [];
22
26
  this._state = RuntimeWorkerState.CREATED;
23
27
  this.id = uuid.v4();
24
- this.key = key;
28
+ this.triggerKey = triggerId || FREE_WORKER_KEY;
25
29
  this.runtime = runtime;
26
30
  const childProc = this.runtime.process;
27
31
  let msgBuffer = "";
@@ -39,8 +43,14 @@ class RuntimeWorker {
39
43
  stdBuffer = this.processStream(data, stdBuffer);
40
44
  });
41
45
  }
46
+ this.logger = triggerId
47
+ ? emulatorLogger_1.EmulatorLogger.forFunction(triggerId, extensionLogInfo)
48
+ : emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
49
+ this.onLogs((log) => {
50
+ this.logger.handleRuntimeLog(log);
51
+ }, true);
42
52
  childProc.on("exit", () => {
43
- this.log("exited");
53
+ this.logDebug("exited");
44
54
  this.state = RuntimeWorkerState.FINISHED;
45
55
  });
46
56
  }
@@ -75,23 +85,30 @@ class RuntimeWorker {
75
85
  });
76
86
  }
77
87
  request(req, resp, body) {
88
+ if (this.triggerKey !== FREE_WORKER_KEY) {
89
+ this.logInfo(`Beginning execution of "${this.triggerKey}"`);
90
+ }
91
+ const startHrTime = process.hrtime();
78
92
  this.state = RuntimeWorkerState.BUSY;
79
93
  const onFinish = () => {
94
+ if (this.triggerKey !== FREE_WORKER_KEY) {
95
+ const elapsedHrTime = process.hrtime(startHrTime);
96
+ this.logInfo(`Finished "${this.triggerKey}" in ${elapsedHrTime[0] * 1000 + elapsedHrTime[1] / 1000000}ms`);
97
+ }
80
98
  if (this.state === RuntimeWorkerState.BUSY) {
81
99
  this.state = RuntimeWorkerState.IDLE;
82
100
  }
83
101
  else if (this.state === RuntimeWorkerState.FINISHING) {
84
- this.log(`IDLE --> FINISHING`);
102
+ this.logDebug(`IDLE --> FINISHING`);
85
103
  this.runtime.process.kill();
86
104
  }
87
105
  };
88
106
  return new Promise((resolve) => {
89
- const proxy = http.request({
90
- method: req.method,
91
- path: req.path,
92
- headers: req.headers,
93
- socketPath: this.runtime.socketPath,
94
- }, (_resp) => {
107
+ const reqOpts = Object.assign(Object.assign({}, this.runtime.conn.httpReqOpts()), { method: req.method, path: req.path, headers: req.headers });
108
+ if (this.timeoutSeconds) {
109
+ reqOpts.timeout = this.timeoutSeconds * 1000;
110
+ }
111
+ const proxy = http.request(reqOpts, (_resp) => {
95
112
  resp.writeHead(_resp.statusCode || 200, _resp.headers);
96
113
  const piped = _resp.pipe(resp);
97
114
  piped.on("finish", () => {
@@ -99,7 +116,13 @@ class RuntimeWorker {
99
116
  resolve();
100
117
  });
101
118
  });
119
+ proxy.on("timeout", () => {
120
+ this.logger.log("ERROR", `Your function timed out after ~${this.timeoutSeconds}s. To configure this timeout, see
121
+ https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.`);
122
+ proxy.destroy();
123
+ });
102
124
  proxy.on("error", (err) => {
125
+ this.logger.log("ERROR", `Request to function failed: ${err}`);
103
126
  resp.writeHead(500);
104
127
  resp.write(JSON.stringify(err));
105
128
  resp.end();
@@ -125,7 +148,7 @@ class RuntimeWorker {
125
148
  if (state === RuntimeWorkerState.FINISHED) {
126
149
  this.runtime.events.removeAllListeners();
127
150
  }
128
- this.log(state);
151
+ this.logDebug(state);
129
152
  this._state = state;
130
153
  this.stateEvents.emit(this._state);
131
154
  }
@@ -137,16 +160,11 @@ class RuntimeWorker {
137
160
  }
138
161
  isSocketReady() {
139
162
  return new Promise((resolve, reject) => {
140
- const req = http
141
- .request({
142
- method: "GET",
143
- path: "/__/health",
144
- socketPath: this.runtime.socketPath,
145
- }, () => {
163
+ const req = http.request(Object.assign(Object.assign({}, this.runtime.conn.httpReqOpts()), { method: "GET", path: "/__/health" }), () => {
146
164
  this.readyForWork();
147
165
  resolve();
148
- })
149
- .end();
166
+ });
167
+ req.end();
150
168
  req.on("error", (error) => {
151
169
  reject(error);
152
170
  });
@@ -173,8 +191,11 @@ class RuntimeWorker {
173
191
  }
174
192
  }
175
193
  }
176
- log(msg) {
177
- emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS).log("DEBUG", `[worker-${this.key}-${this.id}]: ${msg}`);
194
+ logDebug(msg) {
195
+ this.logger.log("DEBUG", `[worker-${this.triggerKey}-${this.id}]: ${msg}`);
196
+ }
197
+ logInfo(msg) {
198
+ this.logger.logLabeled("BULLET", "functions", msg);
178
199
  }
179
200
  }
180
201
  exports.RuntimeWorker = RuntimeWorker;
@@ -195,12 +216,12 @@ class RuntimeWorkerPool {
195
216
  for (const arr of this.workers.values()) {
196
217
  arr.forEach((w) => {
197
218
  if (w.state === RuntimeWorkerState.IDLE) {
198
- this.log(`Shutting down IDLE worker (${w.key})`);
219
+ this.log(`Shutting down IDLE worker (${w.triggerKey})`);
199
220
  w.state = RuntimeWorkerState.FINISHING;
200
221
  w.runtime.process.kill();
201
222
  }
202
223
  else if (w.state === RuntimeWorkerState.BUSY) {
203
- this.log(`Marking BUSY worker to finish (${w.key})`);
224
+ this.log(`Marking BUSY worker to finish (${w.triggerKey})`);
204
225
  w.state = RuntimeWorkerState.FINISHING;
205
226
  }
206
227
  });
@@ -247,19 +268,14 @@ class RuntimeWorkerPool {
247
268
  }
248
269
  return;
249
270
  }
250
- addWorker(triggerId, runtime, extensionLogInfo) {
251
- const worker = new RuntimeWorker(this.getKey(triggerId), runtime);
252
- this.log(`addWorker(${worker.key})`);
253
- const keyWorkers = this.getTriggerWorkers(triggerId);
271
+ addWorker(trigger, runtime, extensionLogInfo) {
272
+ this.log(`addWorker(${this.getKey(trigger === null || trigger === void 0 ? void 0 : trigger.id)})`);
273
+ const disableTimeout = !(trigger === null || trigger === void 0 ? void 0 : trigger.id) || this.mode === types_1.FunctionsExecutionMode.SEQUENTIAL;
274
+ const worker = new RuntimeWorker(trigger === null || trigger === void 0 ? void 0 : trigger.id, runtime, extensionLogInfo, disableTimeout ? undefined : trigger === null || trigger === void 0 ? void 0 : trigger.timeoutSeconds);
275
+ const keyWorkers = this.getTriggerWorkers(trigger === null || trigger === void 0 ? void 0 : trigger.id);
254
276
  keyWorkers.push(worker);
255
- this.setTriggerWorkers(triggerId, keyWorkers);
256
- const logger = triggerId
257
- ? emulatorLogger_1.EmulatorLogger.forFunction(triggerId, extensionLogInfo)
258
- : emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
259
- worker.onLogs((log) => {
260
- logger.handleRuntimeLog(log);
261
- }, true);
262
- this.log(`Adding worker with key ${worker.key}, total=${keyWorkers.length}`);
277
+ this.setTriggerWorkers(trigger === null || trigger === void 0 ? void 0 : trigger.id, keyWorkers);
278
+ this.log(`Adding worker with key ${worker.triggerKey}, total=${keyWorkers.length}`);
263
279
  return worker;
264
280
  }
265
281
  getTriggerWorkers(triggerId) {
@@ -12,12 +12,6 @@ const registry_1 = require("./registry");
12
12
  const ExpressBasedEmulator_1 = require("./ExpressBasedEmulator");
13
13
  const pkg = require("../../package.json");
14
14
  class EmulatorHub extends ExpressBasedEmulator_1.ExpressBasedEmulator {
15
- constructor(args) {
16
- super({
17
- listen: args.listen,
18
- });
19
- this.args = args;
20
- }
21
15
  static readLocatorFile(projectId) {
22
16
  const locatorPath = this.getLocatorFilePath(projectId);
23
17
  if (!fs.existsSync(locatorPath)) {
@@ -36,6 +30,12 @@ class EmulatorHub extends ExpressBasedEmulator_1.ExpressBasedEmulator {
36
30
  const filename = `hub-${projectId}.json`;
37
31
  return path.join(dir, filename);
38
32
  }
33
+ constructor(args) {
34
+ super({
35
+ listen: args.listen,
36
+ });
37
+ this.args = args;
38
+ }
39
39
  async start() {
40
40
  await super.start();
41
41
  await this.writeLocatorFile();
@@ -13,12 +13,6 @@ const child_process_1 = require("child_process");
13
13
  const PUBSUB_KILL_COMMAND = "pubsub_pids=$(ps aux | grep '[p]ubsub-emulator' | awk '{print $2}');" +
14
14
  " if [ ! -z '$pubsub_pids' ]; then kill -9 $pubsub_pids; fi;";
15
15
  class PubsubEmulator {
16
- constructor(args) {
17
- this.args = args;
18
- this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.PUBSUB);
19
- this.triggersForTopic = new Map();
20
- this.subscriptionForTopic = new Map();
21
- }
22
16
  get pubsub() {
23
17
  if (!this._pubsub) {
24
18
  this._pubsub = new pubsub_1.PubSub({
@@ -28,6 +22,12 @@ class PubsubEmulator {
28
22
  }
29
23
  return this._pubsub;
30
24
  }
25
+ constructor(args) {
26
+ this.args = args;
27
+ this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.PUBSUB);
28
+ this.triggersForTopic = new Map();
29
+ this.subscriptionForTopic = new Map();
30
+ }
31
31
  async start() {
32
32
  return downloadableEmulators.start(types_1.Emulators.PUBSUB, this.args);
33
33
  }
@@ -132,20 +132,23 @@ class PubsubEmulator {
132
132
  };
133
133
  }
134
134
  createCloudEventRequestBody(topic, message) {
135
+ const truncatedPublishTime = new Date(message.publishTime.getMilliseconds()).toISOString();
135
136
  const data = {
136
137
  message: {
137
138
  messageId: message.id,
138
- publishTime: message.publishTime,
139
+ publishTime: truncatedPublishTime,
139
140
  attributes: message.attributes,
140
141
  orderingKey: message.orderingKey,
141
142
  data: message.data.toString("base64"),
143
+ message_id: message.id,
144
+ publish_time: truncatedPublishTime,
142
145
  },
143
146
  subscription: this.subscriptionForTopic.get(topic).name,
144
147
  };
145
148
  return {
146
- specversion: "1",
149
+ specversion: "1.0",
147
150
  id: uuid.v4(),
148
- time: message.publishTime.toISOString(),
151
+ time: truncatedPublishTime,
149
152
  type: "google.cloud.pubsub.topic.v1.messagePublished",
150
153
  source: `//pubsub.googleapis.com/projects/${this.args.projectId}/topics/${topic}`,
151
154
  data,
@@ -15,7 +15,8 @@ function sendFileBytes(md, data, req, res) {
15
15
  }
16
16
  res.setHeader("Accept-Ranges", "bytes");
17
17
  res.setHeader("Content-Type", md.contentType || "application/octet-stream");
18
- res.setHeader("Content-Disposition", md.contentDisposition || "attachment");
18
+ const fileName = md.name.split("/").pop();
19
+ res.setHeader("Content-Disposition", `${md.contentDisposition || "attachment"}; filename=${fileName}`);
19
20
  if (didGunzip) {
20
21
  res.setHeader("Transfer-Encoding", "chunked");
21
22
  }
@@ -76,7 +76,7 @@ class StorageCloudFunctions {
76
76
  time = typeof data.updated === "string" ? data.updated : data.updated.toISOString();
77
77
  }
78
78
  return {
79
- specversion: "1",
79
+ specversion: "1.0",
80
80
  id: uuid.v4(),
81
81
  type: `google.cloud.storage.object.v1.${ceAction}`,
82
82
  source: `//storage.googleapis.com/projects/_/buckets/${objectMetadataPayload.bucket}/objects/${objectMetadataPayload.name}`,
@@ -20,15 +20,15 @@ const upload_1 = require("./upload");
20
20
  const track_1 = require("../../track");
21
21
  const types_2 = require("../types");
22
22
  class StoredFile {
23
- constructor(metadata) {
24
- this.metadata = metadata;
25
- }
26
23
  get metadata() {
27
24
  return this._metadata;
28
25
  }
29
26
  set metadata(value) {
30
27
  this._metadata = value;
31
28
  }
29
+ constructor(metadata) {
30
+ this.metadata = metadata;
31
+ }
32
32
  }
33
33
  exports.StoredFile = StoredFile;
34
34
  const TRAILING_SLASHES_PATTERN = /\/+$/;
@@ -305,7 +305,7 @@ class StorageLayer {
305
305
  return this._persistence.dirPath;
306
306
  }
307
307
  async export(storageExportPath, options) {
308
- var e_1, _a;
308
+ var _a, e_1, _b, _c;
309
309
  const bucketsList = {
310
310
  buckets: [],
311
311
  };
@@ -324,18 +324,25 @@ class StorageLayer {
324
324
  const metadataDirPath = path.join(storageExportPath, "metadata");
325
325
  await fse.ensureDir(metadataDirPath);
326
326
  try {
327
- for (var _b = __asyncValues(this._files.entries()), _c; _c = await _b.next(), !_c.done;) {
328
- const [, file] = _c.value;
329
- const diskFileName = this._persistence.getDiskFileName(this.path(file.metadata.bucket, file.metadata.name));
330
- await fse.copy(path.join(this.dirPath, diskFileName), path.join(blobsDirPath, diskFileName));
331
- const metadataExportPath = path.join(metadataDirPath, encodeURIComponent(diskFileName)) + ".json";
332
- await fse.writeFile(metadataExportPath, metadata_1.StoredFileMetadata.toJSON(file.metadata));
327
+ for (var _d = true, _e = __asyncValues(this._files.entries()), _f; _f = await _e.next(), _a = _f.done, !_a;) {
328
+ _c = _f.value;
329
+ _d = false;
330
+ try {
331
+ const [, file] = _c;
332
+ const diskFileName = this._persistence.getDiskFileName(this.path(file.metadata.bucket, file.metadata.name));
333
+ await fse.copy(path.join(this.dirPath, diskFileName), path.join(blobsDirPath, diskFileName));
334
+ const metadataExportPath = path.join(metadataDirPath, encodeURIComponent(diskFileName)) + ".json";
335
+ await fse.writeFile(metadataExportPath, metadata_1.StoredFileMetadata.toJSON(file.metadata));
336
+ }
337
+ finally {
338
+ _d = true;
339
+ }
333
340
  }
334
341
  }
335
342
  catch (e_1_1) { e_1 = { error: e_1_1 }; }
336
343
  finally {
337
344
  try {
338
- if (_c && !_c.done && (_a = _b.return)) await _a.call(_b);
345
+ if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
339
346
  }
340
347
  finally { if (e_1) throw e_1.error; }
341
348
  }
@@ -82,15 +82,6 @@ var FunctionsExecutionMode;
82
82
  FunctionsExecutionMode["SEQUENTIAL"] = "sequential";
83
83
  })(FunctionsExecutionMode = exports.FunctionsExecutionMode || (exports.FunctionsExecutionMode = {}));
84
84
  class EmulatorLog {
85
- constructor(level, type, text, data, timestamp) {
86
- this.level = level;
87
- this.type = type;
88
- this.text = text;
89
- this.data = data;
90
- this.timestamp = timestamp;
91
- this.timestamp = this.timestamp || new Date().toISOString();
92
- this.data = this.data || {};
93
- }
94
85
  get date() {
95
86
  if (!this.timestamp) {
96
87
  return new Date(0);
@@ -145,6 +136,15 @@ class EmulatorLog {
145
136
  }
146
137
  return new EmulatorLog(parsedLog.level, parsedLog.type, parsedLog.text, parsedLog.data, parsedLog.timestamp);
147
138
  }
139
+ constructor(level, type, text, data, timestamp) {
140
+ this.level = level;
141
+ this.type = type;
142
+ this.text = text;
143
+ this.data = data;
144
+ this.timestamp = timestamp;
145
+ this.timestamp = this.timestamp || new Date().toISOString();
146
+ this.data = this.data || {};
147
+ }
148
148
  toString() {
149
149
  return this.toStringCore(false);
150
150
  }
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.promptForPublisherTOS = void 0;
4
- const { marked } = require("marked");
4
+ const marked_1 = require("marked");
5
5
  const TerminalRenderer = require("marked-terminal");
6
6
  const error_1 = require("../error");
7
7
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
8
8
  const prompt_1 = require("../prompt");
9
9
  const utils = require("../utils");
10
- marked.setOptions({
10
+ marked_1.marked.setOptions({
11
11
  renderer: new TerminalRenderer(),
12
12
  });
13
13
  async function promptForPublisherTOS() {
@@ -17,11 +17,11 @@ async function promptForPublisherTOS() {
17
17
  " - If you become aware or should be aware of a critical security issue in your extension, you will provide either a resolution or a written resolution plan within 48 hours.\n" +
18
18
  " - If Google requests a critical security matter to be patched for your extension, you will respond to Google within 48 hours with either a resolution or a written resolution plan.\n" +
19
19
  " - Google may remove your extension or terminate the agreement, if you violate any terms.";
20
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(termsOfServiceMsg));
20
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(termsOfServiceMsg));
21
21
  const consented = await (0, prompt_1.promptOnce)({
22
22
  name: "consent",
23
23
  type: "confirm",
24
- message: marked("Do you accept the [Firebase Extensions Publisher Terms and Conditions](https://firebase.google.com/docs/extensions/alpha/terms-of-service) and acknowledge that your information will be used in accordance with [Google's Privacy Policy](https://policies.google.com/privacy?hl=en)?"),
24
+ message: (0, marked_1.marked)("Do you accept the [Firebase Extensions Publisher Terms and Conditions](https://firebase.google.com/docs/extensions/alpha/terms-of-service) and acknowledge that your information will be used in accordance with [Google's Privacy Policy](https://policies.google.com/privacy?hl=en)?"),
25
25
  default: false,
26
26
  });
27
27
  if (!consented) {
@@ -6,7 +6,7 @@ const extensionsApi = require("../extensions/extensionsApi");
6
6
  const utils = require("../utils");
7
7
  const clc = require("colorette");
8
8
  const logger_1 = require("../logger");
9
- const { marked } = require("marked");
9
+ const marked_1 = require("marked");
10
10
  function checkAllowedEventTypesResponse(response, validEvents) {
11
11
  const validEventTypes = validEvents.map((e) => e.type);
12
12
  if (response.length === 0) {
@@ -23,7 +23,7 @@ function checkAllowedEventTypesResponse(response, validEvents) {
23
23
  exports.checkAllowedEventTypesResponse = checkAllowedEventTypesResponse;
24
24
  async function askForEventsConfig(events, projectId, instanceId) {
25
25
  var _a, _b;
26
- logger_1.logger.info(`\n${clc.bold("Enable Events")}: ${marked("If you enable events, you can write custom event handlers ([https://firebase.google.com/docs/extensions/install-extensions#eventarc](https://firebase.google.com/docs/extensions/install-extensions#eventarc)) that respond to these events.\n\nYou can always enable or disable events later. Events will be emitted via Eventarc. Fees apply ([https://cloud.google.com/eventarc/pricing](https://cloud.google.com/eventarc/pricing)).")}`);
26
+ logger_1.logger.info(`\n${clc.bold("Enable Events")}: ${(0, marked_1.marked)("If you enable events, you can write custom event handlers ([https://firebase.google.com/docs/extensions/install-extensions#eventarc](https://firebase.google.com/docs/extensions/install-extensions#eventarc)) that respond to these events.\n\nYou can always enable or disable events later. Events will be emitted via Eventarc. Fees apply ([https://cloud.google.com/eventarc/pricing](https://cloud.google.com/eventarc/pricing)).")}`);
27
27
  if (!(await askShouldCollectEventsConfig())) {
28
28
  return undefined;
29
29
  }
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getInquirerDefault = exports.promptCreateSecret = exports.askForParam = exports.ask = exports.checkResponse = exports.SecretLocation = void 0;
4
4
  const _ = require("lodash");
5
5
  const clc = require("colorette");
6
- const { marked } = require("marked");
6
+ const marked_1 = require("marked");
7
7
  const types_1 = require("./types");
8
8
  const secretManagerApi = require("../gcp/secretManager");
9
9
  const secretsUtils = require("./secretsUtils");
@@ -13,6 +13,7 @@ const logger_1 = require("../logger");
13
13
  const prompt_1 = require("../prompt");
14
14
  const utils = require("../utils");
15
15
  const projectUtils_1 = require("../projectUtils");
16
+ const functional_1 = require("../functional");
16
17
  var SecretLocation;
17
18
  (function (SecretLocation) {
18
19
  SecretLocation[SecretLocation["CLOUD"] = 1] = "CLOUD";
@@ -67,8 +68,9 @@ async function ask(args) {
67
68
  }
68
69
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, "answer the questions below to configure your extension:");
69
70
  const substituted = (0, extensionsHelper_1.substituteParams)(args.paramSpecs, args.firebaseProjectParams);
71
+ const [advancedParams, standardParams] = (0, functional_1.partition)(substituted, (p) => { var _a; return (_a = p.advanced) !== null && _a !== void 0 ? _a : false; });
70
72
  const result = {};
71
- const promises = substituted.map((paramSpec) => {
73
+ const promises = standardParams.map((paramSpec) => {
72
74
  return async () => {
73
75
  result[paramSpec.param] = await askForParam({
74
76
  projectId: args.projectId,
@@ -78,6 +80,35 @@ async function ask(args) {
78
80
  });
79
81
  };
80
82
  });
83
+ if (advancedParams.length) {
84
+ promises.push(async () => {
85
+ const shouldPrompt = await (0, prompt_1.promptOnce)({
86
+ type: "confirm",
87
+ message: "Do you want to configure any advanced parameters for this instance?",
88
+ default: false,
89
+ });
90
+ if (shouldPrompt) {
91
+ const advancedPromises = advancedParams.map((paramSpec) => {
92
+ return async () => {
93
+ result[paramSpec.param] = await askForParam({
94
+ projectId: args.projectId,
95
+ instanceId: args.instanceId,
96
+ paramSpec: paramSpec,
97
+ reconfiguring: args.reconfiguring,
98
+ });
99
+ };
100
+ });
101
+ await advancedPromises.reduce((prev, cur) => prev.then(cur), Promise.resolve());
102
+ }
103
+ else {
104
+ for (const paramSpec of advancedParams) {
105
+ if (paramSpec.required && paramSpec.default) {
106
+ result[paramSpec.param] = { baseValue: paramSpec.default };
107
+ }
108
+ }
109
+ }
110
+ });
111
+ }
81
112
  await promises.reduce((prev, cur) => prev.then(cur), Promise.resolve());
82
113
  logger_1.logger.info();
83
114
  return result;
@@ -91,7 +122,7 @@ async function askForParam(args) {
91
122
  let secretLocations = [];
92
123
  const description = paramSpec.description || "";
93
124
  const label = paramSpec.label.trim();
94
- logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${marked(description).trim()}`);
125
+ logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(0, marked_1.marked)(description).trim()}`);
95
126
  while (!valid) {
96
127
  switch (paramSpec.type) {
97
128
  case types_1.ParamType.SELECT:
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.displayNode10CreateBillingNotice = exports.displayNode10UpdateBillingNotice = void 0;
4
- const { marked } = require("marked");
4
+ const marked_1 = require("marked");
5
5
  const TerminalRenderer = require("marked-terminal");
6
6
  const error_1 = require("../error");
7
7
  const extensionsHelper_1 = require("./extensionsHelper");
8
8
  const prompt_1 = require("../prompt");
9
9
  const utils = require("../utils");
10
10
  const utils_1 = require("./utils");
11
- marked.setOptions({
11
+ marked_1.marked.setOptions({
12
12
  renderer: new TerminalRenderer(),
13
13
  });
14
14
  const urlPricingExamples = "https://cloud.google.com/functions/pricing#pricing_examples";
@@ -39,13 +39,13 @@ function hasRuntime(spec, runtime) {
39
39
  }
40
40
  function displayNode10UpdateBillingNotice(curSpec, newSpec) {
41
41
  if (hasRuntime(curSpec, "nodejs8") && hasRuntime(newSpec, "nodejs10")) {
42
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, marked(billingMsgUpdate));
42
+ utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(billingMsgUpdate));
43
43
  }
44
44
  }
45
45
  exports.displayNode10UpdateBillingNotice = displayNode10UpdateBillingNotice;
46
46
  async function displayNode10CreateBillingNotice(spec, prompt) {
47
47
  if (hasRuntime(spec, "nodejs10")) {
48
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, marked(billingMsgCreate));
48
+ utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(billingMsgCreate));
49
49
  if (prompt) {
50
50
  const continueUpdate = await (0, prompt_1.promptOnce)({
51
51
  type: "confirm",