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,13 @@
1
1
  "use strict";
2
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
3
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
4
+ var m = o[Symbol.asyncIterator], i;
5
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
6
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
7
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
8
+ };
2
9
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.diagnoseAndFixProject = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.getMissingPublisherError = exports.uploadExtensionVersionFromLocalSource = exports.uploadExtensionVersionFromGitHubSource = exports.unpackExtensionState = exports.getNextVersionByStage = exports.ensureExtensionsPublisherApiEnabled = exports.ensureExtensionsApiEnabled = exports.promptForExtensionRoot = exports.promptForValidRepoURI = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
10
+ exports.diagnoseAndFixProject = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.getMissingPublisherError = exports.uploadExtensionVersionFromLocalSource = exports.uploadExtensionVersionFromGitHubSource = exports.unpackExtensionState = exports.getNextVersionByStage = exports.ensureExtensionsPublisherApiEnabled = exports.ensureExtensionsApiEnabled = exports.promptForExtensionRoot = exports.promptForValidRepoURI = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteSecretParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
4
11
  const clc = require("colorette");
5
12
  const ora = require("ora");
6
13
  const semver = require("semver");
@@ -9,11 +16,9 @@ const fs = require("fs-extra");
9
16
  const node_fetch_1 = require("node-fetch");
10
17
  const path = require("path");
11
18
  const marked_1 = require("marked");
19
+ const marked_terminal_1 = require("marked-terminal");
12
20
  const unzip_1 = require("./../unzip");
13
- const TerminalRenderer = require("marked-terminal");
14
- marked_1.marked.setOptions({
15
- renderer: new TerminalRenderer(),
16
- });
21
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
17
22
  const api_1 = require("../api");
18
23
  const archiveDirectory_1 = require("../archiveDirectory");
19
24
  const utils_1 = require("./utils");
@@ -128,6 +133,38 @@ function substituteParams(original, params) {
128
133
  return JSON.parse(s);
129
134
  }
130
135
  exports.substituteParams = substituteParams;
136
+ async function substituteSecretParams(projectNumber, params) {
137
+ var _a, e_1, _b, _c;
138
+ const newParams = {};
139
+ try {
140
+ for (var _d = true, _e = __asyncValues(Object.entries(params)), _f; _f = await _e.next(), _a = _f.done, !_a;) {
141
+ _c = _f.value;
142
+ _d = false;
143
+ try {
144
+ const [key, value] = _c;
145
+ if (typeof value !== "string") {
146
+ newParams[key] =
147
+ `projects/${projectNumber}/secrets/${value.name}/versions/latest`;
148
+ }
149
+ else {
150
+ newParams[key] = value;
151
+ }
152
+ }
153
+ finally {
154
+ _d = true;
155
+ }
156
+ }
157
+ }
158
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
159
+ finally {
160
+ try {
161
+ if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
162
+ }
163
+ finally { if (e_1) throw e_1.error; }
164
+ }
165
+ return newParams;
166
+ }
167
+ exports.substituteSecretParams = substituteSecretParams;
131
168
  function populateDefaultParams(paramVars, paramSpecs) {
132
169
  const newParams = paramVars;
133
170
  for (const param of paramSpecs) {
@@ -417,12 +454,12 @@ function validateReleaseNotes(rootDirectory, newVersion, extension) {
417
454
  catch (err) {
418
455
  throw new error_1.FirebaseError("No CHANGELOG.md file found. " +
419
456
  "Please create one and add an entry for this version. " +
420
- (0, marked_1.marked)("See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details."));
457
+ "See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
421
458
  }
422
459
  if (!notes && !semver.prerelease(newVersion) && extension) {
423
460
  throw new error_1.FirebaseError(`No entry for version ${newVersion} found in CHANGELOG.md. ` +
424
461
  "Please add one so users know what has changed in this version. " +
425
- (0, marked_1.marked)("See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details."));
462
+ "See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
426
463
  }
427
464
  return notes;
428
465
  }
@@ -474,7 +511,7 @@ function displayExtensionHeader(extensionRef, extension, extensionRoot) {
474
511
  }
475
512
  else {
476
513
  logger_1.logger.info(`\n${clc.bold("Extension:")} ${extensionRef}\n` +
477
- `${clc.bold("State:")} ${clc.bold(clc.blue("New"))}\n`);
514
+ `${clc.bold("State:")} ${clc.bold(clc.blueBright("New"))}\n`);
478
515
  }
479
516
  }
480
517
  async function fetchExtensionSource(repoUri, sourceRef, extensionRoot) {
@@ -701,7 +738,7 @@ async function uploadExtensionVersionFromLocalSource(args) {
701
738
  }
702
739
  exports.uploadExtensionVersionFromLocalSource = uploadExtensionVersionFromLocalSource;
703
740
  function getMissingPublisherError(publisherId) {
704
- return new error_1.FirebaseError((0, marked_1.marked)(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. For step-by-step instructions on getting started as a publisher, see https://firebase.google.com/docs/extensions/publishers/get-started.`));
741
+ return new error_1.FirebaseError(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. For step-by-step instructions on getting started as a publisher, see https://firebase.google.com/docs/extensions/publishers/get-started.`);
705
742
  }
706
743
  exports.getMissingPublisherError = getMissingPublisherError;
707
744
  async function createSourceFromLocation(projectId, sourceUri) {
@@ -796,7 +833,7 @@ async function instanceIdExists(projectId, instanceId) {
796
833
  if (err.status === 404) {
797
834
  return false;
798
835
  }
799
- const msg = `Unexpected error when checking if instance ID exists: ${err}`;
836
+ const msg = `Unexpected error when checking if instance ID exists: ${err.message}`;
800
837
  throw new error_1.FirebaseError(msg, {
801
838
  original: err,
802
839
  });
@@ -38,7 +38,7 @@ function readFile(pathToFile) {
38
38
  }
39
39
  catch (err) {
40
40
  if (err.code === "ENOENT") {
41
- throw new error_1.FirebaseError(`Could not find "${pathToFile}""`, { original: err });
41
+ throw new error_1.FirebaseError(`Could not find "${pathToFile}"`, { original: err });
42
42
  }
43
43
  throw new error_1.FirebaseError(`Failed to read file at "${pathToFile}"`, { original: err });
44
44
  }
@@ -64,7 +64,7 @@ async function checkProducts(projectId, usedProducts) {
64
64
  "without server-side code.\n";
65
65
  errorMessage += ` https://console.firebase.google.com/project/${projectId}/authentication/users`;
66
66
  }
67
- throw new error_1.FirebaseError((0, marked_1.marked)(errorMessage), { exit: 2 });
67
+ throw new error_1.FirebaseError(await (0, marked_1.marked)(errorMessage), { exit: 2 });
68
68
  }
69
69
  }
70
70
  function getUsedProducts(spec) {
@@ -7,13 +7,16 @@ const refRegex = new RegExp(/^([^/@\n]+)\/{1}([^/@\n]+)(@{1}([^\n]+)|)$/);
7
7
  function parse(refOrName) {
8
8
  const ret = parseRef(refOrName) || parseName(refOrName);
9
9
  if (!ret || !ret.publisherId || !ret.extensionId) {
10
- throw new error_1.FirebaseError(`Unable to parse ${refOrName} as an extension ref`);
10
+ throw new error_1.FirebaseError(`Unable to parse ${refOrName} as an extension ref.\n` +
11
+ "Expected format is either publisherId/extensionId@version or " +
12
+ "publishers/publisherId/extensions/extensionId/versions/version. If you " +
13
+ "are referring to a local extension directory, please ensure the directory exists.");
11
14
  }
12
15
  if (ret.version &&
13
16
  !semver.valid(ret.version) &&
14
17
  !semver.validRange(ret.version) &&
15
18
  !["latest", "latest-approved"].includes(ret.version)) {
16
- throw new error_1.FirebaseError(`Extension reference ${ret} contains an invalid version ${ret.version}.`);
19
+ throw new error_1.FirebaseError(`Extension reference ${JSON.stringify(ret, null, 2)} contains an invalid version ${ret.version}.`);
17
20
  }
18
21
  return ret;
19
22
  }
@@ -21,19 +24,31 @@ exports.parse = parse;
21
24
  function parseRef(ref) {
22
25
  const parts = refRegex.exec(ref);
23
26
  if (parts && (parts.length === 5 || parts.length === 7)) {
24
- const publisherId = parts[1];
25
- const extensionId = parts[2];
26
- const version = parts[4];
27
- return { publisherId, extensionId, version };
27
+ return {
28
+ publisherId: parts[1],
29
+ extensionId: parts[2],
30
+ version: parts[4],
31
+ };
28
32
  }
29
33
  }
30
34
  function parseName(name) {
31
35
  const parts = name.split("/");
32
- return {
33
- publisherId: parts[1],
34
- extensionId: parts[3],
35
- version: parts[5],
36
- };
36
+ if (parts[0] !== "publishers" || parts[2] !== "extensions") {
37
+ return;
38
+ }
39
+ if (parts.length === 4) {
40
+ return {
41
+ publisherId: parts[1],
42
+ extensionId: parts[3],
43
+ };
44
+ }
45
+ if (parts.length === 6 && parts[4] === "versions") {
46
+ return {
47
+ publisherId: parts[1],
48
+ extensionId: parts[3],
49
+ version: parts[5],
50
+ };
51
+ }
37
52
  }
38
53
  function toExtensionRef(ref) {
39
54
  return `${ref.publisherId}/${ref.extensionId}`;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.extractExtensionsFromBuilds = exports.extractAllDynamicExtensions = void 0;
4
+ const projectConfig_1 = require("../../functions/projectConfig");
5
+ const prepare_1 = require("../../deploy/functions/prepare");
6
+ const functionsConfig_1 = require("../../functionsConfig");
7
+ const functionsDeployHelper_1 = require("../../deploy/functions/functionsDeployHelper");
8
+ const logger_1 = require("../../logger");
9
+ const savedLoggerSilent = logger_1.logger.silent;
10
+ function silenceLogging() {
11
+ logger_1.logger.silent = true;
12
+ }
13
+ function resumeLogging() {
14
+ logger_1.logger.silent = savedLoggerSilent;
15
+ }
16
+ async function extractAllDynamicExtensions(options) {
17
+ const firebaseConfig = await (0, functionsConfig_1.getFirebaseConfig)(options);
18
+ const runtimeConfig = { firebase: firebaseConfig };
19
+ const functionsConfig = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions);
20
+ let functionsBuilds = {};
21
+ const codebases = (0, functionsDeployHelper_1.targetCodebases)(functionsConfig);
22
+ silenceLogging();
23
+ for (const codebase of codebases) {
24
+ try {
25
+ const filters = [{ codebase: `${codebase}` }];
26
+ const builds = await (0, prepare_1.loadCodebases)(functionsConfig, options, firebaseConfig, runtimeConfig, filters);
27
+ functionsBuilds = Object.assign(Object.assign({}, functionsBuilds), builds);
28
+ }
29
+ catch (err) {
30
+ }
31
+ }
32
+ resumeLogging();
33
+ return extractExtensionsFromBuilds(functionsBuilds);
34
+ }
35
+ exports.extractAllDynamicExtensions = extractAllDynamicExtensions;
36
+ function extractExtensionsFromBuilds(builds, filters) {
37
+ const extRecords = {};
38
+ for (const [codebase, build] of Object.entries(builds)) {
39
+ if (build.extensions) {
40
+ for (const [id, ext] of Object.entries(build.extensions)) {
41
+ if (extensionMatchesAnyFilter(codebase, id, filters)) {
42
+ extRecords[id] = ext;
43
+ }
44
+ }
45
+ }
46
+ }
47
+ return extRecords;
48
+ }
49
+ exports.extractExtensionsFromBuilds = extractExtensionsFromBuilds;
50
+ function extensionMatchesAnyFilter(codebase, extensionId, filters) {
51
+ if (!filters) {
52
+ return true;
53
+ }
54
+ return filters.some((f) => extensionMatchesFilter(codebase, extensionId, f));
55
+ }
56
+ function extensionMatchesFilter(codebase, extensionId, filter) {
57
+ if (codebase && filter.codebase) {
58
+ if (codebase !== filter.codebase) {
59
+ return false;
60
+ }
61
+ }
62
+ if (!filter.idChunks) {
63
+ return true;
64
+ }
65
+ const idChunks = extensionId.split("-");
66
+ if (idChunks.length < filter.idChunks.length) {
67
+ return false;
68
+ }
69
+ for (let i = 0; i < filter.idChunks.length; i++) {
70
+ if (idChunks[i] !== filter.idChunks[i]) {
71
+ return false;
72
+ }
73
+ }
74
+ return true;
75
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ParamType = exports.FUNCTIONS_V2_RESOURCE_TYPE = exports.FUNCTIONS_RESOURCE_TYPE = exports.Visibility = exports.RegistryLaunchStage = void 0;
3
+ exports.isExtensionSpec = exports.isResource = exports.isParam = exports.ParamType = exports.FUNCTIONS_V2_RESOURCE_TYPE = exports.FUNCTIONS_RESOURCE_TYPE = exports.Visibility = exports.RegistryLaunchStage = void 0;
4
4
  var RegistryLaunchStage;
5
5
  (function (RegistryLaunchStage) {
6
6
  RegistryLaunchStage["EXPERIMENTAL"] = "EXPERIMENTAL";
@@ -21,5 +21,60 @@ var ParamType;
21
21
  ParamType["STRING"] = "STRING";
22
22
  ParamType["SELECT"] = "SELECT";
23
23
  ParamType["MULTISELECT"] = "MULTISELECT";
24
+ ParamType["SELECT_RESOURCE"] = "SELECT_RESOURCE";
24
25
  ParamType["SECRET"] = "SECRET";
25
26
  })(ParamType = exports.ParamType || (exports.ParamType = {}));
27
+ function isObject(value) {
28
+ return typeof value === "object" && value !== null;
29
+ }
30
+ const isParam = (param) => {
31
+ return (isObject(param) && typeof param["param"] === "string" && typeof param["label"] === "string");
32
+ };
33
+ exports.isParam = isParam;
34
+ const isResource = (res) => {
35
+ return isObject(res) && typeof res["name"] === "string";
36
+ };
37
+ exports.isResource = isResource;
38
+ const isExtensionSpec = (spec) => {
39
+ if (!isObject(spec) || typeof spec.name !== "string" || typeof spec.version !== "string") {
40
+ return false;
41
+ }
42
+ let validResources = true;
43
+ if (spec.resources && Array.isArray(spec.resources)) {
44
+ for (const res of spec.resources) {
45
+ validResources = validResources && (0, exports.isResource)(res);
46
+ if (!validResources) {
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ else {
52
+ return false;
53
+ }
54
+ let validParams = true;
55
+ if (spec.params && Array.isArray(spec.params)) {
56
+ for (const param of spec.params) {
57
+ validParams = validParams && (0, exports.isParam)(param);
58
+ if (!validParams) {
59
+ break;
60
+ }
61
+ }
62
+ }
63
+ else {
64
+ return false;
65
+ }
66
+ let validSysParams = true;
67
+ if (spec.systemParams && Array.isArray(spec.systemParams)) {
68
+ for (const param of spec.systemParams) {
69
+ validSysParams = validSysParams && (0, exports.isParam)(param);
70
+ if (!validSysParams) {
71
+ break;
72
+ }
73
+ }
74
+ }
75
+ else {
76
+ return false;
77
+ }
78
+ return true;
79
+ };
80
+ exports.isExtensionSpec = isExtensionSpec;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.inferUpdateSource = exports.updateFromUrlSource = exports.updateFromLocalSource = exports.update = exports.warningUpdateToOtherSource = exports.getExistingSourceOrigin = void 0;
4
4
  const clc = require("colorette");
5
5
  const semver = require("semver");
6
- const marked_1 = require("marked");
7
6
  const error_1 = require("../error");
8
7
  const logger_1 = require("../logger");
9
8
  const extensionsApi = require("./extensionsApi");
@@ -47,7 +46,7 @@ function warningUpdateToOtherSource(sourceOrigin) {
47
46
  targetText = "URL";
48
47
  }
49
48
  const warning = `All the instance's resources and logic will be overwritten to use the source code and files from the ${targetText}.\n`;
50
- logger_1.logger.info((0, marked_1.marked)(warning));
49
+ logger_1.logger.info(warning);
51
50
  }
52
51
  exports.warningUpdateToOtherSource = warningUpdateToOtherSource;
53
52
  async function update(updateOptions) {
@@ -2,11 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.outOfBandChangesWarning = exports.displayWarningsForDeploy = void 0;
4
4
  const clc = require("colorette");
5
- const TerminalRenderer = require("marked-terminal");
6
- const marked_1 = require("marked");
7
- marked_1.marked.setOptions({
8
- renderer: new TerminalRenderer(),
9
- });
10
5
  const extensionsHelper_1 = require("./extensionsHelper");
11
6
  const deploymentSummary_1 = require("../deploy/extensions/deploymentSummary");
12
7
  const planner_1 = require("../deploy/extensions/planner");
@@ -29,9 +24,9 @@ async function displayWarningsForDeploy(instancesToCreate) {
29
24
  const unpublishedExtensions = uploadedExtensionInstances.filter((i) => { var _a, _b; return ((_b = (_a = i.extensionVersion) === null || _a === void 0 ? void 0 : _a.listing) === null || _b === void 0 ? void 0 : _b.state) !== "APPROVED"; });
30
25
  if (unpublishedExtensions.length) {
31
26
  const humanReadableList = unpublishedExtensions.map(toListEntry).join("\n");
32
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`The following extension versions have not been published to the Firebase Extensions Hub:\n${humanReadableList}\n.` +
27
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, `The following extension versions have not been published to the Firebase Extensions Hub:\n${humanReadableList}\n.` +
33
28
  "Unpublished extensions have not been reviewed by " +
34
- "Firebase. Please make sure you trust the extension publisher before installing this extension.", { gfm: false }));
29
+ "Firebase. Please make sure you trust the extension publisher before installing this extension.");
35
30
  }
36
31
  return unpublishedExtensions.length > 0;
37
32
  }
@@ -420,15 +420,16 @@ class FirestoreApi {
420
420
  }
421
421
  return database;
422
422
  }
423
- async createDatabase(project, databaseId, locationId, type, deleteProtectionState, pointInTimeRecoveryEnablement) {
424
- const url = `/projects/${project}/databases`;
423
+ async createDatabase(req) {
424
+ const url = `/projects/${req.project}/databases`;
425
425
  const payload = {
426
- type,
427
- locationId,
428
- deleteProtectionState,
429
- pointInTimeRecoveryEnablement,
426
+ locationId: req.locationId,
427
+ type: req.type,
428
+ deleteProtectionState: req.deleteProtectionState,
429
+ pointInTimeRecoveryEnablement: req.pointInTimeRecoveryEnablement,
430
+ cmekConfig: req.cmekConfig,
430
431
  };
431
- const options = { queryParams: { databaseId: databaseId } };
432
+ const options = { queryParams: { databaseId: req.databaseId } };
432
433
  const res = await this.apiClient.post(url, payload, options);
433
434
  const database = res.body.response;
434
435
  if (!database) {
@@ -33,13 +33,33 @@ class PrettyPrint {
33
33
  logger_1.logger.info(table.toString());
34
34
  }
35
35
  prettyPrintDatabase(database) {
36
+ let colValueWidth = Math.max(50, 5 + database.name.length);
37
+ if (database.cmekConfig) {
38
+ colValueWidth = Math.max(140, 20 + database.cmekConfig.kmsKeyName.length);
39
+ }
36
40
  const table = new Table({
37
41
  head: ["Field", "Value"],
38
- colWidths: [25, Math.max(50, 5 + database.name.length)],
42
+ colWidths: [30, colValueWidth],
39
43
  });
40
44
  table.push(["Name", clc.yellow(database.name)], ["Create Time", clc.yellow(database.createTime)], ["Last Update Time", clc.yellow(database.updateTime)], ["Type", clc.yellow(database.type)], ["Location", clc.yellow(database.locationId)], ["Delete Protection State", clc.yellow(database.deleteProtectionState)], ["Point In Time Recovery", clc.yellow(database.pointInTimeRecoveryEnablement)], ["Earliest Version Time", clc.yellow(database.earliestVersionTime)], ["Version Retention Period", clc.yellow(database.versionRetentionPeriod)]);
45
+ if (database.cmekConfig) {
46
+ table.push(["KMS Key Name", clc.yellow(database.cmekConfig.kmsKeyName)]);
47
+ if (database.cmekConfig.activeKeyVersion) {
48
+ table.push([
49
+ "Active Key Versions",
50
+ clc.yellow(this.prettyStringArray(database.cmekConfig.activeKeyVersion)),
51
+ ]);
52
+ }
53
+ }
41
54
  logger_1.logger.info(table.toString());
42
55
  }
56
+ prettyStringArray(stringArray) {
57
+ let result = "";
58
+ stringArray.forEach((str) => {
59
+ result += `${str}\n`;
60
+ });
61
+ return result;
62
+ }
43
63
  prettyPrintBackups(backups) {
44
64
  if (backups.length === 0) {
45
65
  logger_1.logger.info("No backups found.");
@@ -51,3 +51,11 @@ describe("firebaseConsoleDatabaseUrl", () => {
51
51
  (0, chai_1.expect)(printer.firebaseConsoleDatabaseUrl("example-project", "(default)")).to.equal("https://console.firebase.google.com/project/example-project/firestore/databases/-default-/data");
52
52
  });
53
53
  });
54
+ describe("prettyStringArray", () => {
55
+ it("should correctly print an array of strings", () => {
56
+ (0, chai_1.expect)(printer.prettyStringArray(["kms-key-1", "kms-key-2"])).to.equal("kms-key-1\nkms-key-2\n");
57
+ });
58
+ it("should print nothing if the array is empty", () => {
59
+ (0, chai_1.expect)(printer.prettyStringArray([])).to.equal("");
60
+ });
61
+ });
@@ -20,7 +20,7 @@ exports.FIREBASE_FRAMEWORKS_VERSION = (experiments.isEnabled("internaltesting")
20
20
  DEFAULT_FIREBASE_FRAMEWORKS_VERSION;
21
21
  exports.FIREBASE_FUNCTIONS_VERSION = "^4.5.0";
22
22
  exports.FIREBASE_ADMIN_VERSION = "^11.11.1";
23
- exports.SHARP_VERSION = "^0.32.1";
23
+ exports.SHARP_VERSION = "^0.32 || ^0.33";
24
24
  exports.NODE_VERSION = parseInt(process.versions.node, 10);
25
25
  exports.VALID_ENGINES = { node: [16, 18, 20] };
26
26
  exports.VALID_LOCALE_FORMATS = [/^ALL_[a-z]+$/, /^[a-z]+_ALL$/, /^[a-z]+(_[a-z]+)?$/];
@@ -11,7 +11,7 @@ exports.ROUTES_MANIFEST = "routes-manifest.json";
11
11
  exports.APP_PATHS_MANIFEST = "app-paths-manifest.json";
12
12
  exports.SERVER_REFERENCE_MANIFEST = "server-reference-manifest.json";
13
13
  exports.CONFIG_FILES = ["next.config.js", "next.config.mjs"];
14
- exports.ESBUILD_VERSION = "0.19.2";
14
+ exports.ESBUILD_VERSION = "^0.19.2";
15
15
  const WEBPACK_LAYERS_NAMES = {
16
16
  shared: "shared",
17
17
  reactServerComponents: "rsc",
@@ -29,7 +29,6 @@ exports.name = "Next.js";
29
29
  exports.support = "preview";
30
30
  exports.type = 2;
31
31
  exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/nextjs";
32
- const BUNDLE_NEXT_CONFIG_TIMEOUT = 60000;
33
32
  const DEFAULT_NUMBER_OF_REASONS_TO_LIST = 5;
34
33
  function getReactVersion(cwd) {
35
34
  var _a;
@@ -338,6 +337,19 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
338
337
  const configFile = await (0, utils_2.whichNextConfigFile)(sourceDir);
339
338
  if (configFile) {
340
339
  try {
340
+ let esbuildPath = (0, utils_2.findEsbuildPath)();
341
+ if (!esbuildPath || !(0, fs_extra_1.pathExistsSync)(esbuildPath)) {
342
+ console.warn("esbuild not found, installing...");
343
+ (0, utils_2.installEsbuild)(constants_2.ESBUILD_VERSION);
344
+ esbuildPath = (0, utils_2.findEsbuildPath)();
345
+ if (!esbuildPath || !(0, fs_extra_1.pathExistsSync)(esbuildPath)) {
346
+ throw new error_1.FirebaseError("Failed to locate esbuild after installation.");
347
+ }
348
+ }
349
+ const esbuild = require(esbuildPath);
350
+ if (!esbuild) {
351
+ throw new error_1.FirebaseError(`Failed to load esbuild from path: ${esbuildPath}`);
352
+ }
341
353
  const productionDeps = await new Promise((resolve) => {
342
354
  const dependencies = [];
343
355
  const npmLs = (0, cross_spawn_1.spawn)("npm", ["ls", "--omit=dev", "--all", "--json=true"], {
@@ -359,21 +371,21 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
359
371
  resolve([...new Set(dependencies)]);
360
372
  });
361
373
  });
362
- const esbuildArgs = productionDeps
363
- .map((it) => `--external:${it}`)
364
- .concat("--bundle", "--platform=node", `--target=node${constants_1.NODE_VERSION}`, "--log-level=error");
374
+ const esbuildArgs = {
375
+ entryPoints: [(0, path_1.join)(sourceDir, configFile)],
376
+ outfile: (0, path_1.join)(destDir, configFile),
377
+ bundle: true,
378
+ platform: "node",
379
+ target: `node${constants_1.NODE_VERSION}`,
380
+ logLevel: "error",
381
+ external: productionDeps,
382
+ };
365
383
  if (configFile === "next.config.mjs") {
366
- esbuildArgs.push(...[`--outfile=${(0, path_1.join)(destDir, configFile)}`, "--format=esm"]);
384
+ esbuildArgs.format = "esm";
367
385
  }
368
- else {
369
- esbuildArgs.push(`--outfile=${(0, path_1.join)(destDir, configFile)}`);
370
- }
371
- const bundle = (0, cross_spawn_1.sync)("npx", ["--yes", `esbuild@${constants_2.ESBUILD_VERSION}`, configFile, ...esbuildArgs], {
372
- cwd: sourceDir,
373
- timeout: BUNDLE_NEXT_CONFIG_TIMEOUT,
374
- });
375
- if (bundle.status !== 0) {
376
- throw new error_1.FirebaseError(bundle.stderr.toString());
386
+ const bundle = await esbuild.build(esbuildArgs);
387
+ if (bundle.errors && bundle.errors.length > 0) {
388
+ throw new error_1.FirebaseError(bundle.errors.toString());
377
389
  }
378
390
  }
379
391
  catch (e) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.whichNextConfigFile = exports.getProductionDistDirFiles = exports.getRoutesWithServerAction = exports.hasStaticAppNotFoundComponent = exports.getNextVersion = exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingNextImageInAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
3
+ exports.installEsbuild = exports.getGlobalEsbuildVersion = exports.findEsbuildPath = exports.whichNextConfigFile = exports.getProductionDistDirFiles = exports.getRoutesWithServerAction = exports.hasStaticAppNotFoundComponent = exports.getNextVersion = exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingNextImageInAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const fs_extra_1 = require("fs-extra");
6
6
  const path_1 = require("path");
@@ -11,6 +11,8 @@ const utils_1 = require("../utils");
11
11
  const constants_1 = require("./constants");
12
12
  const fsutils_1 = require("../../fsutils");
13
13
  const utils_2 = require("../../utils");
14
+ const child_process_1 = require("child_process");
15
+ const error_1 = require("../../error");
14
16
  exports.I18N_SOURCE = /\/:nextInternalLocale(\([^\)]+\))?/;
15
17
  function cleanEscapedChars(path) {
16
18
  return path.replace(/\\([(){}:+?*])/g, (a, b) => b);
@@ -241,3 +243,45 @@ async function whichNextConfigFile(dir) {
241
243
  return null;
242
244
  }
243
245
  exports.whichNextConfigFile = whichNextConfigFile;
246
+ function findEsbuildPath() {
247
+ try {
248
+ const esbuildBinPath = (0, child_process_1.execSync)("npx which esbuild", { encoding: "utf8" }).trim();
249
+ const globalVersion = getGlobalEsbuildVersion();
250
+ if (globalVersion && !(0, semver_1.satisfies)(globalVersion, constants_1.ESBUILD_VERSION)) {
251
+ console.warn(`Warning: Global esbuild version (${globalVersion}) does not match the required version (${constants_1.ESBUILD_VERSION}).`);
252
+ }
253
+ return (0, path_1.resolve)((0, path_1.dirname)(esbuildBinPath), "../esbuild");
254
+ }
255
+ catch (error) {
256
+ console.error(`Failed to find esbuild with npx which: ${error}`);
257
+ return null;
258
+ }
259
+ }
260
+ exports.findEsbuildPath = findEsbuildPath;
261
+ function getGlobalEsbuildVersion() {
262
+ try {
263
+ const versionOutput = (0, child_process_1.execSync)("esbuild --version", { encoding: "utf8" }).trim();
264
+ const versionMatch = versionOutput.match(/(\d+\.\d+\.\d+)/);
265
+ return versionMatch ? versionMatch[0] : null;
266
+ }
267
+ catch (error) {
268
+ console.error(`Failed to get global esbuild version: ${error}`);
269
+ return null;
270
+ }
271
+ }
272
+ exports.getGlobalEsbuildVersion = getGlobalEsbuildVersion;
273
+ function installEsbuild(version) {
274
+ const installCommand = `npm install esbuild@${version} --no-save`;
275
+ try {
276
+ (0, child_process_1.execSync)(installCommand, { stdio: "inherit" });
277
+ }
278
+ catch (error) {
279
+ if (error instanceof error_1.FirebaseError) {
280
+ throw error;
281
+ }
282
+ else {
283
+ throw new error_1.FirebaseError(`Failed to install esbuild: ${error}`, { original: error });
284
+ }
285
+ }
286
+ }
287
+ exports.installEsbuild = installEsbuild;