firebase-tools 13.14.2 → 13.15.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 (61) hide show
  1. package/lib/bin/firebase.js +2 -4
  2. package/lib/commands/deploy.js +10 -2
  3. package/lib/commands/ext-configure.js +1 -6
  4. package/lib/commands/ext-dev-init.js +2 -4
  5. package/lib/commands/ext-dev-upload.js +4 -6
  6. package/lib/commands/ext-info.js +3 -5
  7. package/lib/commands/ext-install.js +0 -5
  8. package/lib/commands/ext-uninstall.js +0 -5
  9. package/lib/commands/ext-update.js +0 -5
  10. package/lib/commands/firestore-databases-create.js +19 -1
  11. package/lib/commands/functions-secrets-set.js +9 -6
  12. package/lib/commands/hosting-channel-create.js +1 -1
  13. package/lib/commands/hosting-channel-delete.js +1 -1
  14. package/lib/commands/hosting-channel-deploy.js +1 -1
  15. package/lib/commands/hosting-clone.js +1 -2
  16. package/lib/dataconnect/fileUtils.js +63 -1
  17. package/lib/dataconnect/provisionCloudSql.js +5 -1
  18. package/lib/dataconnect/types.js +8 -1
  19. package/lib/deploy/extensions/planner.js +46 -1
  20. package/lib/deploy/extensions/prepare.js +99 -23
  21. package/lib/deploy/functions/build.js +5 -5
  22. package/lib/deploy/functions/deploy.js +12 -12
  23. package/lib/deploy/functions/params.js +5 -3
  24. package/lib/deploy/functions/prepare.js +16 -1
  25. package/lib/deploy/functions/release/index.js +4 -0
  26. package/lib/deploy/functions/runtimes/discovery/parsing.js +1 -1
  27. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +46 -0
  28. package/lib/emulator/dataconnectEmulator.js +2 -0
  29. package/lib/emulator/downloadableEmulators.js +11 -12
  30. package/lib/emulator/functionsEmulator.js +8 -1
  31. package/lib/extensions/askUserForEventsConfig.js +18 -8
  32. package/lib/extensions/askUserForParam.js +3 -2
  33. package/lib/extensions/change-log.js +2 -4
  34. package/lib/extensions/displayExtensionInfo.js +5 -10
  35. package/lib/extensions/extensionsApi.js +1 -1
  36. package/lib/extensions/extensionsHelper.js +47 -10
  37. package/lib/extensions/localHelper.js +1 -1
  38. package/lib/extensions/provisioningHelper.js +1 -1
  39. package/lib/extensions/refs.js +26 -11
  40. package/lib/extensions/runtimes/common.js +75 -0
  41. package/lib/extensions/types.js +56 -1
  42. package/lib/extensions/updateHelper.js +1 -2
  43. package/lib/extensions/warnings.js +2 -7
  44. package/lib/firestore/api.js +8 -7
  45. package/lib/firestore/pretty-print.js +21 -1
  46. package/lib/firestore/pretty-print.test.js +8 -0
  47. package/lib/frameworks/constants.js +1 -1
  48. package/lib/frameworks/next/constants.js +1 -1
  49. package/lib/frameworks/next/index.js +26 -14
  50. package/lib/frameworks/next/utils.js +45 -1
  51. package/lib/init/features/dataconnect/index.js +29 -15
  52. package/lib/init/features/dataconnect/sdk.js +72 -56
  53. package/lib/prompt.js +22 -1
  54. package/lib/rulesDeploy.js +14 -12
  55. package/package.json +3 -3
  56. package/templates/init/dataconnect/connector.yaml +5 -3
  57. package/templates/init/dataconnect/dataconnect.yaml +5 -5
  58. package/templates/init/dataconnect/mutations.gql +44 -29
  59. package/templates/init/dataconnect/queries.gql +66 -38
  60. package/templates/init/dataconnect/schema.gql +38 -21
  61. package/lib/extensions/billingMigrationHelper.js +0 -61
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prepare = void 0;
3
+ exports.prepare = exports.prepareDynamicExtensions = void 0;
4
4
  const planner = require("./planner");
5
5
  const deploymentSummary = require("./deploymentSummary");
6
6
  const prompt = require("../../prompt");
@@ -16,32 +16,29 @@ const warnings_1 = require("../../extensions/warnings");
16
16
  const etags_1 = require("../../extensions/etags");
17
17
  const v2FunctionHelper_1 = require("./v2FunctionHelper");
18
18
  const tos_1 = require("../../extensions/tos");
19
- async function prepare(context, options, payload) {
19
+ const common_1 = require("../../extensions/runtimes/common");
20
+ const projectConfig_1 = require("../../functions/projectConfig");
21
+ const functionsDeployHelper_1 = require("../functions/functionsDeployHelper");
22
+ async function prepareHelper(context, options, payload, wantExtensions, noDeleteExtensions, isPrimaryCall) {
20
23
  var _a, _b;
21
- context.extensionsStartTime = Date.now();
22
24
  const projectId = (0, projectUtils_1.needProjectId)(options);
23
- const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
24
- const aliases = (0, projectUtils_1.getAliases)(options, projectId);
25
- await (0, extensionsHelper_1.ensureExtensionsApiEnabled)(options);
26
- await (0, requirePermissions_1.requirePermissions)(options, ["firebaseextensions.instances.list"]);
27
25
  context.have = await planner.have(projectId);
28
- context.want = await planner.want({
29
- projectId,
30
- projectNumber,
31
- aliases,
32
- projectDir: options.config.projectDir,
33
- extensions: options.config.get("extensions"),
34
- });
26
+ context.want = wantExtensions;
35
27
  const etagsChanged = (0, etags_1.detectEtagChanges)(options.rc, projectId, context.have);
36
28
  if (etagsChanged.length) {
37
- (0, warnings_1.outOfBandChangesWarning)(etagsChanged);
38
- if (!(await prompt.confirm({
39
- message: `Do you wish to continue deploying these extension instances?`,
40
- default: false,
41
- nonInteractive: options.nonInteractive,
42
- force: options.force,
43
- }))) {
44
- throw new error_1.FirebaseError("Deployment cancelled");
29
+ const wantChangedIds = wantExtensions
30
+ .map((e) => e.instanceId)
31
+ .filter((id) => etagsChanged.includes(id));
32
+ if (wantChangedIds.length) {
33
+ (0, warnings_1.outOfBandChangesWarning)(wantChangedIds);
34
+ if (!(await prompt.confirm({
35
+ message: `Do you wish to continue deploying these extension instances?`,
36
+ default: false,
37
+ nonInteractive: options.nonInteractive,
38
+ force: options.force,
39
+ }))) {
40
+ throw new error_1.FirebaseError("Deployment cancelled");
41
+ }
45
42
  }
46
43
  }
47
44
  const usingSecrets = await Promise.all((_a = context.want) === null || _a === void 0 ? void 0 : _a.map(secrets_1.checkSpecForSecrets));
@@ -55,7 +52,7 @@ async function prepare(context, options, payload) {
55
52
  payload.instancesToCreate = context.want.filter((i) => { var _a; return !((_a = context.have) === null || _a === void 0 ? void 0 : _a.some(matchesInstanceId(i))); });
56
53
  payload.instancesToConfigure = context.want.filter((i) => { var _a; return (_a = context.have) === null || _a === void 0 ? void 0 : _a.some(isConfigure(i)); });
57
54
  payload.instancesToUpdate = context.want.filter((i) => { var _a; return (_a = context.have) === null || _a === void 0 ? void 0 : _a.some(isUpdate(i)); });
58
- payload.instancesToDelete = context.have.filter((i) => { var _a; return !((_a = context.want) === null || _a === void 0 ? void 0 : _a.some(matchesInstanceId(i))); });
55
+ payload.instancesToDelete = context.have.filter((i) => { var _a; return !((_a = context.want) === null || _a === void 0 ? void 0 : _a.some(matchesInstanceId(i))) && !(noDeleteExtensions === null || noDeleteExtensions === void 0 ? void 0 : noDeleteExtensions.some(matchesInstanceId(i))); });
59
56
  if (await (0, warnings_1.displayWarningsForDeploy)(payload.instancesToCreate)) {
60
57
  if (!(await prompt.confirm({
61
58
  message: `Do you wish to continue deploying these extension instances?`,
@@ -67,6 +64,9 @@ async function prepare(context, options, payload) {
67
64
  }
68
65
  }
69
66
  const permissionsNeeded = [];
67
+ if (!isPrimaryCall) {
68
+ payload.instancesToDelete = [];
69
+ }
70
70
  if (payload.instancesToCreate.length) {
71
71
  permissionsNeeded.push("firebaseextensions.instances.create");
72
72
  logger_1.logger.info(deploymentSummary.createsSummary(payload.instancesToCreate));
@@ -98,6 +98,82 @@ async function prepare(context, options, payload) {
98
98
  await (0, requirePermissions_1.requirePermissions)(options, permissionsNeeded);
99
99
  await (0, tos_1.acceptLatestAppDeveloperTOS)(options, projectId, context.want.map((i) => i.instanceId));
100
100
  }
101
+ async function prepareDynamicExtensions(context, options, payload, builds) {
102
+ const filters = (0, functionsDeployHelper_1.getEndpointFilters)(options);
103
+ const extensions = (0, common_1.extractExtensionsFromBuilds)(builds, filters);
104
+ if (Object.keys(extensions).length === 0) {
105
+ return;
106
+ }
107
+ const projectId = (0, projectUtils_1.needProjectId)(options);
108
+ const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
109
+ const aliases = (0, projectUtils_1.getAliases)(options, projectId);
110
+ const projectDir = options.config.projectDir;
111
+ const isPrimaryCall = !!options.only && !options.only.split(",").includes("extensions");
112
+ if (isPrimaryCall) {
113
+ await (0, extensionsHelper_1.ensureExtensionsApiEnabled)(options);
114
+ }
115
+ await (0, requirePermissions_1.requirePermissions)(options, ["firebaseextensions.instances.list"]);
116
+ const dynamicWant = await planner.wantDynamic({
117
+ projectId,
118
+ projectNumber,
119
+ extensions,
120
+ });
121
+ let noDeleteExtensions = [];
122
+ if (isPrimaryCall) {
123
+ const firebaseJsonWant = await planner.want({
124
+ projectId,
125
+ projectNumber,
126
+ aliases,
127
+ projectDir,
128
+ extensions: options.config.get("extensions"),
129
+ });
130
+ noDeleteExtensions = noDeleteExtensions.concat(firebaseJsonWant);
131
+ if (hasNonDeployingCodebases(options)) {
132
+ const dynamicAll = await planner.wantDynamic({
133
+ projectId,
134
+ projectNumber,
135
+ extensions: await (0, common_1.extractAllDynamicExtensions)(options),
136
+ });
137
+ noDeleteExtensions = noDeleteExtensions.concat(dynamicAll);
138
+ }
139
+ }
140
+ return prepareHelper(context, options, payload, dynamicWant, noDeleteExtensions, isPrimaryCall);
141
+ }
142
+ exports.prepareDynamicExtensions = prepareDynamicExtensions;
143
+ function hasNonDeployingCodebases(options) {
144
+ const functionFilters = (0, functionsDeployHelper_1.getEndpointFilters)(options);
145
+ if (functionFilters === null || functionFilters === void 0 ? void 0 : functionFilters.length) {
146
+ return true;
147
+ }
148
+ const functionsConfig = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions);
149
+ const allCodebases = (0, functionsDeployHelper_1.targetCodebases)(functionsConfig);
150
+ const deployingCodebases = (0, functionsDeployHelper_1.targetCodebases)(functionsConfig, functionFilters);
151
+ if (allCodebases.length > deployingCodebases.length) {
152
+ return true;
153
+ }
154
+ }
155
+ async function prepare(context, options, payload) {
156
+ context.extensionsStartTime = Date.now();
157
+ const projectId = (0, projectUtils_1.needProjectId)(options);
158
+ const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
159
+ const aliases = (0, projectUtils_1.getAliases)(options, projectId);
160
+ const projectDir = options.config.projectDir;
161
+ await (0, extensionsHelper_1.ensureExtensionsApiEnabled)(options);
162
+ await (0, requirePermissions_1.requirePermissions)(options, ["firebaseextensions.instances.list"]);
163
+ const firebaseJsonWant = await planner.want({
164
+ projectId,
165
+ projectNumber,
166
+ aliases,
167
+ projectDir,
168
+ extensions: options.config.get("extensions"),
169
+ });
170
+ const dynamicWant = await planner.wantDynamic({
171
+ projectId,
172
+ projectNumber,
173
+ extensions: await (0, common_1.extractAllDynamicExtensions)(options),
174
+ });
175
+ return prepareHelper(context, options, payload, firebaseJsonWant, dynamicWant, true);
176
+ }
101
177
  exports.prepare = prepare;
102
178
  const matchesInstanceId = (dep) => (test) => {
103
179
  return dep.instanceId === test.instanceId;
@@ -55,19 +55,19 @@ exports.AllIngressSettings = [
55
55
  "ALLOW_INTERNAL_ONLY",
56
56
  "ALLOW_INTERNAL_AND_GCLB",
57
57
  ];
58
- async function resolveBackend(build, firebaseConfig, userEnvOpt, userEnvs, nonInteractive) {
58
+ async function resolveBackend(opts) {
59
59
  let paramValues = {};
60
- paramValues = await params.resolveParams(build.params, firebaseConfig, envWithTypes(build.params, userEnvs), nonInteractive);
60
+ paramValues = await params.resolveParams(opts.build.params, opts.firebaseConfig, envWithTypes(opts.build.params, opts.userEnvs), opts.nonInteractive, opts.isEmulator);
61
61
  const toWrite = {};
62
62
  for (const paramName of Object.keys(paramValues)) {
63
63
  const paramValue = paramValues[paramName];
64
- if (Object.prototype.hasOwnProperty.call(userEnvs, paramName) || paramValue.internal) {
64
+ if (Object.prototype.hasOwnProperty.call(opts.userEnvs, paramName) || paramValue.internal) {
65
65
  continue;
66
66
  }
67
67
  toWrite[paramName] = paramValue.toString();
68
68
  }
69
- (0, env_1.writeUserEnvs)(toWrite, userEnvOpt);
70
- return { backend: toBackend(build, paramValues), envs: paramValues };
69
+ (0, env_1.writeUserEnvs)(toWrite, opts.userEnvOpt);
70
+ return { backend: toBackend(opts.build, paramValues), envs: paramValues };
71
71
  }
72
72
  exports.resolveBackend = resolveBackend;
73
73
  function envWithTypes(definedParams, rawEnvs) {
@@ -12,6 +12,7 @@ const gcf = require("../../gcp/cloudfunctions");
12
12
  const gcfv2 = require("../../gcp/cloudfunctionsv2");
13
13
  const backend = require("./backend");
14
14
  const backend_1 = require("./backend");
15
+ const extensions_1 = require("../extensions");
15
16
  (0, tmp_1.setGracefulCleanup)();
16
17
  async function uploadSourceV1(projectId, source, wantBackend) {
17
18
  const v1Endpoints = backend.allEndpoints(wantBackend).filter((e) => e.platform === "gcfv1");
@@ -77,21 +78,20 @@ async function uploadCodebase(context, codebase, wantBackend) {
77
78
  }
78
79
  }
79
80
  async function deploy(context, options, payload) {
80
- if (!context.config) {
81
- return;
82
- }
83
- if (!payload.functions) {
84
- return;
81
+ if (payload.extensions && context.extensions) {
82
+ await (0, extensions_1.deploy)(context.extensions, options, payload.extensions);
85
83
  }
86
- await (0, checkIam_1.checkHttpIam)(context, options, payload);
87
- const uploads = [];
88
- for (const [codebase, { wantBackend, haveBackend }] of Object.entries(payload.functions)) {
89
- if (shouldUploadBeSkipped(context, wantBackend, haveBackend)) {
90
- continue;
84
+ if (payload.functions && context.config) {
85
+ await (0, checkIam_1.checkHttpIam)(context, options, payload);
86
+ const uploads = [];
87
+ for (const [codebase, { wantBackend, haveBackend }] of Object.entries(payload.functions)) {
88
+ if (shouldUploadBeSkipped(context, wantBackend, haveBackend)) {
89
+ continue;
90
+ }
91
+ uploads.push(uploadCodebase(context, codebase, wantBackend));
91
92
  }
92
- uploads.push(uploadCodebase(context, codebase, wantBackend));
93
+ await Promise.all(uploads);
93
94
  }
94
- await Promise.all(uploads);
95
95
  }
96
96
  exports.deploy = deploy;
97
97
  function shouldUploadBeSkipped(context, wantBackend, haveBackend) {
@@ -154,7 +154,7 @@ function canSatisfyParam(param, value) {
154
154
  }
155
155
  (0, functional_1.assertExhaustive)(param);
156
156
  }
157
- async function resolveParams(params, firebaseConfig, userEnvs, nonInteractive) {
157
+ async function resolveParams(params, firebaseConfig, userEnvs, nonInteractive, isEmulator = false) {
158
158
  const paramValues = populateDefaultParams(firebaseConfig);
159
159
  const [resolved, outstanding] = (0, functional_1.partition)(params, (param) => {
160
160
  return {}.hasOwnProperty.call(userEnvs, param.name);
@@ -163,8 +163,10 @@ async function resolveParams(params, firebaseConfig, userEnvs, nonInteractive) {
163
163
  paramValues[param.name] = userEnvs[param.name];
164
164
  }
165
165
  const [needSecret, needPrompt] = (0, functional_1.partition)(outstanding, (param) => param.type === "secret");
166
- for (const param of needSecret) {
167
- await handleSecret(param, firebaseConfig.projectId);
166
+ if (!isEmulator) {
167
+ for (const param of needSecret) {
168
+ await handleSecret(param, firebaseConfig.projectId);
169
+ }
168
170
  }
169
171
  if (nonInteractive && needPrompt.length > 0) {
170
172
  const envNames = outstanding.map((p) => p.name).join(", ");
@@ -27,6 +27,7 @@ const serviceusage_1 = require("../../gcp/serviceusage");
27
27
  const applyHash_1 = require("./cache/applyHash");
28
28
  const backend_1 = require("./backend");
29
29
  const functional_1 = require("../../functional");
30
+ const prepare_1 = require("../extensions/prepare");
30
31
  exports.EVENTARC_SOURCE_ENV = "EVENTARC_CLOUD_EVENT_SOURCE";
31
32
  async function prepare(context, options, payload) {
32
33
  var _a, _b;
@@ -55,6 +56,13 @@ async function prepare(context, options, payload) {
55
56
  }
56
57
  context.codebaseDeployEvents = {};
57
58
  const wantBuilds = await loadCodebases(context.config, options, firebaseConfig, runtimeConfig, context.filters);
59
+ if (Object.values(wantBuilds).some((b) => b.extensions)) {
60
+ const extContext = {};
61
+ const extPayload = {};
62
+ await (0, prepare_1.prepareDynamicExtensions)(extContext, options, extPayload, wantBuilds);
63
+ context.extensions = extContext;
64
+ payload.extensions = extPayload;
65
+ }
58
66
  const codebaseUsesEnvs = [];
59
67
  const wantBackends = {};
60
68
  for (const [codebase, wantBuild] of Object.entries(wantBuilds)) {
@@ -67,7 +75,14 @@ async function prepare(context, options, payload) {
67
75
  };
68
76
  const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
69
77
  const envs = Object.assign(Object.assign({}, userEnvs), firebaseEnvs);
70
- const { backend: wantBackend, envs: resolvedEnvs } = await build.resolveBackend(wantBuild, firebaseConfig, userEnvOpt, userEnvs, options.nonInteractive);
78
+ const { backend: wantBackend, envs: resolvedEnvs } = await build.resolveBackend({
79
+ build: wantBuild,
80
+ firebaseConfig,
81
+ userEnvOpt,
82
+ userEnvs,
83
+ nonInteractive: options.nonInteractive,
84
+ isEmulator: false,
85
+ });
71
86
  let hasEnvsFromParams = false;
72
87
  wantBackend.environmentVariables = envs;
73
88
  for (const envName of Object.keys(resolvedEnvs)) {
@@ -16,7 +16,11 @@ const functionsConfig_1 = require("../../../functionsConfig");
16
16
  const functionsDeployHelper_1 = require("../functionsDeployHelper");
17
17
  const error_1 = require("../../../error");
18
18
  const getProjectNumber_1 = require("../../../getProjectNumber");
19
+ const extensions_1 = require("../../extensions");
19
20
  async function release(context, options, payload) {
21
+ if (context.extensions && payload.extensions) {
22
+ await (0, extensions_1.release)(context.extensions, options, payload.extensions);
23
+ }
20
24
  if (!context.config) {
21
25
  return;
22
26
  }
@@ -21,7 +21,7 @@ function assertKeyTypes(prefix, yaml, schema) {
21
21
  const key = keyAsString;
22
22
  const fullKey = prefix ? `${prefix}.${keyAsString}` : keyAsString;
23
23
  if (!schema[key] || schema[key] === "omit") {
24
- throw new error_1.FirebaseError(`Unexpected key ${fullKey}. You may need to install a newer version of the Firebase CLI.`);
24
+ throw new error_1.FirebaseError(`Unexpected key '${fullKey}'. You may need to install a newer version of the Firebase CLI.`);
25
25
  }
26
26
  let schemaType = schema[key];
27
27
  if (typeof schemaType === "function") {
@@ -21,6 +21,7 @@ function buildFromV1Alpha1(yaml, project, region, runtime) {
21
21
  params: "array",
22
22
  requiredAPIs: "array",
23
23
  endpoints: "object",
24
+ extensions: "object",
24
25
  });
25
26
  const bd = build.empty();
26
27
  bd.params = manifest.params || [];
@@ -31,6 +32,15 @@ function buildFromV1Alpha1(yaml, project, region, runtime) {
31
32
  const be = parseEndpointForBuild(id, me, project, region, runtime);
32
33
  bd.endpoints[id] = be;
33
34
  }
35
+ if (manifest.extensions) {
36
+ bd.extensions = {};
37
+ for (const id of Object.keys(manifest.extensions)) {
38
+ const me = manifest.extensions[id];
39
+ assertBuildExtension(me, id);
40
+ const be = parseExtensionForBuild(me);
41
+ bd.extensions[id] = be;
42
+ }
43
+ }
34
44
  return bd;
35
45
  }
36
46
  exports.buildFromV1Alpha1 = buildFromV1Alpha1;
@@ -272,6 +282,42 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
272
282
  });
273
283
  return parsed;
274
284
  }
285
+ function assertBuildExtension(ex, id) {
286
+ const prefix = `extensions[${id}]`;
287
+ (0, parsing_1.assertKeyTypes)(prefix, ex, {
288
+ params: "object",
289
+ ref: "string?",
290
+ localPath: "string?",
291
+ events: "array",
292
+ });
293
+ let refOrPath = 0;
294
+ if (ex.ref) {
295
+ refOrPath++;
296
+ }
297
+ if (ex.localPath) {
298
+ refOrPath++;
299
+ }
300
+ if (refOrPath === 0) {
301
+ throw new error_1.FirebaseError(`Expected either extension reference or local path in extension: ${id}`);
302
+ }
303
+ if (refOrPath > 1) {
304
+ throw new error_1.FirebaseError(`Multiple definitions for extension ${id}. Do not specify both reference and local path.`);
305
+ }
306
+ }
307
+ function parseExtensionForBuild(ex) {
308
+ const parsed = {
309
+ params: {},
310
+ events: [],
311
+ };
312
+ if (ex.localPath) {
313
+ parsed.localPath = ex.localPath;
314
+ }
315
+ else {
316
+ parsed.ref = ex.ref;
317
+ }
318
+ (0, proto_1.copyIfPresent)(parsed, ex, "params", "events");
319
+ return parsed;
320
+ }
275
321
  function resolveChannelName(projectId, channel, defaultRegion) {
276
322
  if (!channel.includes("/")) {
277
323
  const location = defaultRegion;
@@ -53,6 +53,8 @@ class DataConnectEmulator {
53
53
  auto_download: this.args.auto_download,
54
54
  listen: (0, portUtils_1.listenSpecsToString)(this.args.listen),
55
55
  config_dir: resolvedConfigDir,
56
+ enable_output_schema_extensions: true,
57
+ enable_output_generated_sdk: true,
56
58
  });
57
59
  this.usingExistingEmulator = false;
58
60
  }
@@ -46,20 +46,20 @@ const EMULATOR_UPDATE_DETAILS = {
46
46
  },
47
47
  dataconnect: process.platform === "darwin"
48
48
  ? {
49
- version: "1.3.1",
50
- expectedSize: 24175424,
51
- expectedChecksum: "9ce1ee2ed6994ca62df6dfef3fdece62",
49
+ version: "1.3.4",
50
+ expectedSize: 24216320,
51
+ expectedChecksum: "f57bc0b9a10837ecb4f2808c49ae3ff5",
52
52
  }
53
53
  : process.platform === "win32"
54
54
  ? {
55
- version: "1.3.1",
56
- expectedSize: 24587264,
57
- expectedChecksum: "1d31fd26506cfc9b822fdb8e8834d14c",
55
+ version: "1.3.4",
56
+ expectedSize: 24631296,
57
+ expectedChecksum: "c8f1433fbff26f5e9da30cf205f2af78",
58
58
  }
59
59
  : {
60
- version: "1.3.1",
61
- expectedSize: 24088728,
62
- expectedChecksum: "223f7eebde618ba92788579dd35fec43",
60
+ version: "1.3.4",
61
+ expectedSize: 24125592,
62
+ expectedChecksum: "a7b9a79d66fa5ebfb1a0f65e535d5c33",
63
63
  },
64
64
  };
65
65
  exports.DownloadDetails = {
@@ -243,9 +243,8 @@ const Commands = {
243
243
  optionalArgs: [
244
244
  "listen",
245
245
  "config_dir",
246
- "disable_sdk_generation",
247
- "resolvers_emulator",
248
- "rpc_retry_count",
246
+ "enable_output_schema_extensions",
247
+ "enable_output_generated_sdk",
249
248
  ],
250
249
  joinArgs: true,
251
250
  shell: false,
@@ -315,7 +315,14 @@ class FunctionsEmulator {
315
315
  };
316
316
  const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
317
317
  const discoveredBuild = await runtimeDelegate.discoverBuild(runtimeConfig, environment);
318
- const resolution = await (0, build_1.resolveBackend)(discoveredBuild, JSON.parse(firebaseConfig), userEnvOpt, userEnvs);
318
+ const resolution = await (0, build_1.resolveBackend)({
319
+ build: discoveredBuild,
320
+ firebaseConfig: JSON.parse(firebaseConfig),
321
+ userEnvOpt,
322
+ userEnvs,
323
+ nonInteractive: false,
324
+ isEmulator: true,
325
+ });
319
326
  const discoveredBackend = resolution.backend;
320
327
  const endpoints = backend.allEndpoints(discoveredBackend);
321
328
  (0, functionsEmulatorShared_1.prepareEndpoints)(endpoints);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.askForEventArcLocation = exports.askShouldCollectEventsConfig = exports.askForAllowedEventTypes = exports.askForEventsConfig = exports.checkAllowedEventTypesResponse = void 0;
3
+ exports.askForEventArcLocation = exports.EXTENSIONS_DEFAULT_EVENT_ARC_REGION = exports.ALLOWED_EVENT_ARC_REGIONS = exports.askShouldCollectEventsConfig = exports.askForAllowedEventTypes = exports.getEventArcChannel = exports.askForEventsConfig = exports.checkAllowedEventTypesResponse = void 0;
4
4
  const prompt_1 = require("../prompt");
5
5
  const extensionsApi = require("../extensions/extensionsApi");
6
6
  const utils = require("../utils");
@@ -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")}: ${(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)).")}`);
26
+ logger_1.logger.info(`\n${clc.bold("Enable Events")}: ${await (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
  }
@@ -38,11 +38,15 @@ async function askForEventsConfig(events, projectId, instanceId) {
38
38
  const preselectedTypes = (_a = existingInstance === null || existingInstance === void 0 ? void 0 : existingInstance.config.allowedEventTypes) !== null && _a !== void 0 ? _a : [];
39
39
  const oldLocation = (_b = existingInstance === null || existingInstance === void 0 ? void 0 : existingInstance.config.eventarcChannel) === null || _b === void 0 ? void 0 : _b.split("/")[3];
40
40
  const location = await askForEventArcLocation(oldLocation);
41
- const channel = `projects/${projectId}/locations/${location}/channels/firebase`;
41
+ const channel = getEventArcChannel(projectId, location);
42
42
  const allowedEventTypes = await askForAllowedEventTypes(events, preselectedTypes);
43
43
  return { channel, allowedEventTypes };
44
44
  }
45
45
  exports.askForEventsConfig = askForEventsConfig;
46
+ function getEventArcChannel(projectId, location) {
47
+ return `projects/${projectId}/locations/${location}/channels/firebase`;
48
+ }
49
+ exports.getEventArcChannel = getEventArcChannel;
46
50
  async function askForAllowedEventTypes(eventDescriptors, preselectedTypes) {
47
51
  let valid = false;
48
52
  let response = [];
@@ -75,21 +79,27 @@ async function askShouldCollectEventsConfig() {
75
79
  });
76
80
  }
77
81
  exports.askShouldCollectEventsConfig = askShouldCollectEventsConfig;
82
+ exports.ALLOWED_EVENT_ARC_REGIONS = [
83
+ "us-central1",
84
+ "us-west1",
85
+ "europe-west4",
86
+ "asia-northeast1",
87
+ ];
88
+ exports.EXTENSIONS_DEFAULT_EVENT_ARC_REGION = "us-central1";
78
89
  async function askForEventArcLocation(preselectedLocation) {
79
90
  let valid = false;
80
- const allowedRegions = ["us-central1", "us-west1", "europe-west4", "asia-northeast1"];
81
91
  let location = "";
82
92
  while (!valid) {
83
93
  location = await (0, prompt_1.promptOnce)({
84
94
  name: "input",
85
95
  type: "list",
86
- default: preselectedLocation !== null && preselectedLocation !== void 0 ? preselectedLocation : "us-central1",
96
+ default: preselectedLocation !== null && preselectedLocation !== void 0 ? preselectedLocation : exports.EXTENSIONS_DEFAULT_EVENT_ARC_REGION,
87
97
  message: "Which location would you like the Eventarc channel to live in? We recommend using the default option. A channel location that differs from the extension's Cloud Functions location can incur egress cost.",
88
- choices: allowedRegions.map((e) => ({ checked: false, value: e })),
98
+ choices: exports.ALLOWED_EVENT_ARC_REGIONS.map((e) => ({ checked: false, value: e })),
89
99
  });
90
- valid = allowedRegions.includes(location);
100
+ valid = exports.ALLOWED_EVENT_ARC_REGIONS.includes(location);
91
101
  if (!valid) {
92
- utils.logWarning(`Unexpected EventArc region '${location}' was specified. Allowed regions: ${allowedRegions.join(", ")}`);
102
+ utils.logWarning(`Unexpected EventArc region '${location}' was specified. Allowed regions: ${exports.ALLOWED_EVENT_ARC_REGIONS.join(", ")}`);
93
103
  }
94
104
  }
95
105
  return location;
@@ -122,7 +122,7 @@ async function askForParam(args) {
122
122
  let secretLocations = [];
123
123
  const description = paramSpec.description || "";
124
124
  const label = paramSpec.label.trim();
125
- logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(0, marked_1.marked)(description).trim()}`);
125
+ logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(await (0, marked_1.marked)(description)).trim()}`);
126
126
  while (!valid) {
127
127
  switch (paramSpec.type) {
128
128
  case types_1.ParamType.SELECT:
@@ -255,7 +255,7 @@ async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
255
255
  ],
256
256
  });
257
257
  switch (action) {
258
- case SecretUpdateAction.SET_NEW:
258
+ case SecretUpdateAction.SET_NEW: {
259
259
  let secret;
260
260
  let secretName;
261
261
  if (paramSpec.default) {
@@ -288,6 +288,7 @@ async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
288
288
  else {
289
289
  return "";
290
290
  }
291
+ }
291
292
  case SecretUpdateAction.LEAVE:
292
293
  default:
293
294
  return paramSpec.default || "";
@@ -5,16 +5,14 @@ const clc = require("colorette");
5
5
  const marked_1 = require("marked");
6
6
  const path = require("path");
7
7
  const semver = require("semver");
8
- const TerminalRenderer = require("marked-terminal");
8
+ const marked_terminal_1 = require("marked-terminal");
9
9
  const Table = require("cli-table");
10
10
  const extensionsApi_1 = require("./extensionsApi");
11
11
  const localHelper_1 = require("./localHelper");
12
12
  const logger_1 = require("../logger");
13
13
  const refs = require("./refs");
14
14
  const utils_1 = require("../utils");
15
- marked_1.marked.setOptions({
16
- renderer: new TerminalRenderer(),
17
- });
15
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
18
16
  const EXTENSIONS_CHANGELOG = "CHANGELOG.md";
19
17
  const VERSION_LINE_REGEX = /##.+?(\d+\.\d+\.\d+(?:-((\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?).*/;
20
18
  async function getReleaseNotesForUpdate(args) {
@@ -2,18 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.retrieveRoleInfo = exports.displayResources = exports.displayEvents = exports.displayExternalServices = exports.displayExtensionVersionInfo = void 0;
4
4
  const clc = require("colorette");
5
- const marked_1 = require("marked");
6
5
  const semver = require("semver");
7
- const TerminalRenderer = require("marked-terminal");
8
6
  const path = require("path");
9
7
  const refs = require("../extensions/refs");
10
8
  const logger_1 = require("../logger");
11
9
  const types_1 = require("./types");
12
10
  const iam = require("../gcp/iam");
13
11
  const secretsUtils_1 = require("./secretsUtils");
14
- marked_1.marked.setOptions({
15
- renderer: new TerminalRenderer(),
16
- });
17
12
  const TASKS_ROLE = "cloudtasks.enqueuer";
18
13
  const TASKS_API = "cloudtasks.googleapis.com";
19
14
  async function displayExtensionVersionInfo(args) {
@@ -55,7 +50,7 @@ async function displayExtensionVersionInfo(args) {
55
50
  if (extensionVersion.buildSourceUri) {
56
51
  const buildSourceUri = new URL(extensionVersion.buildSourceUri);
57
52
  buildSourceUri.pathname = path.join(buildSourceUri.pathname, (_c = extensionVersion.extensionRoot) !== null && _c !== void 0 ? _c : "");
58
- lines.push(`${clc.bold("Source in GitHub:")} ${buildSourceUri}`);
53
+ lines.push(`${clc.bold("Source in GitHub:")} ${buildSourceUri.toString()}`);
59
54
  }
60
55
  else {
61
56
  lines.push(`${clc.bold("Source download URI:")} ${(_d = extensionVersion.sourceDownloadUri) !== null && _d !== void 0 ? _d : "-"}`);
@@ -110,24 +105,24 @@ function displayResources(spec) {
110
105
  break;
111
106
  default:
112
107
  }
113
- return ` - ${clc.blue(`${resource.name} (${type})`)}${resource.description ? `: ${resource.description}` : ""}`;
108
+ return ` - ${clc.blueBright(`${resource.name} (${type})`)}${resource.description ? `: ${resource.description}` : ""}`;
114
109
  });
115
110
  lines.push(...new Set((_a = spec.lifecycleEvents) === null || _a === void 0 ? void 0 : _a.map((event) => {
116
- return ` - ${clc.blue(`${event.taskQueueTriggerFunction} (Cloud Task queue)`)}`;
111
+ return ` - ${clc.blueBright(`${event.taskQueueTriggerFunction} (Cloud Task queue)`)}`;
117
112
  })));
118
113
  lines.push(...spec.params
119
114
  .filter((param) => {
120
115
  return param.type === "SECRET";
121
116
  })
122
117
  .map((param) => {
123
- return ` - ${clc.blue(`${param.param} (Cloud Secret Manager secret)`)}`;
118
+ return ` - ${clc.blueBright(`${param.param} (Cloud Secret Manager secret)`)}`;
124
119
  }));
125
120
  return clc.bold("Resources created:\n") + (lines.length ? lines.join("\n") : " - None");
126
121
  }
127
122
  exports.displayResources = displayResources;
128
123
  async function retrieveRoleInfo(role) {
129
124
  const res = await iam.getRole(role);
130
- return ` - ${clc.yellow(res.title)}${res.description ? `: ${res.description}` : ""}`;
125
+ return ` - ${clc.yellow(res.title || res.name)}${res.description ? `: ${res.description}` : ""}`;
131
126
  }
132
127
  exports.retrieveRoleInfo = retrieveRoleInfo;
133
128
  async function displayRoles(roles) {
@@ -356,6 +356,6 @@ function refNotFoundError(ref) {
356
356
  return new error_1.FirebaseError(`The extension reference '${clc.bold(ref.version ? refs.toExtensionVersionRef(ref) : refs.toExtensionRef(ref))}' doesn't exist. This could happen for two reasons:\n` +
357
357
  ` -The publisher ID '${clc.bold(ref.publisherId)}' doesn't exist or could be misspelled\n` +
358
358
  ` -The name of the ${ref.version ? "extension version" : "extension"} '${clc.bold(ref.version ? `${ref.extensionId}@${ref.version}` : ref.extensionId)}' doesn't exist or could be misspelled\n\n` +
359
- `Please correct the extension reference and try again. If you meant to install an extension from a local source, please provide a relative path prefixed with '${clc.bold("./")}', '${clc.bold("../")}', or '${clc.bold("~/")}'.}`, { status: 404 });
359
+ `Please correct the extension reference and try again. If you meant to reference an extension from a local source, please provide a relative path prefixed with '${clc.bold("./")}', '${clc.bold("../")}', or '${clc.bold("~/")}'.}`, { status: 404 });
360
360
  }
361
361
  exports.refNotFoundError = refNotFoundError;