firebase-tools 11.22.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 (79) 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/python/index.js +26 -13
  15. package/lib/deploy/hosting/convertConfig.js +2 -1
  16. package/lib/emulator/auth/apiSpec.js +17 -1
  17. package/lib/emulator/downloadableEmulators.js +6 -6
  18. package/lib/emulator/functionsEmulator.js +12 -15
  19. package/lib/emulator/functionsEmulatorRuntime.js +26 -42
  20. package/lib/emulator/functionsRuntimeWorker.js +48 -22
  21. package/lib/emulator/hub.js +6 -6
  22. package/lib/emulator/pubsubEmulator.js +12 -9
  23. package/lib/emulator/storage/apis/shared.js +2 -1
  24. package/lib/emulator/storage/cloudFunctions.js +1 -1
  25. package/lib/emulator/storage/files.js +18 -11
  26. package/lib/emulator/types.js +9 -9
  27. package/lib/extensions/askUserForConsent.js +4 -4
  28. package/lib/extensions/askUserForEventsConfig.js +2 -2
  29. package/lib/extensions/askUserForParam.js +2 -2
  30. package/lib/extensions/billingMigrationHelper.js +4 -4
  31. package/lib/extensions/change-log.js +4 -4
  32. package/lib/extensions/displayExtensionInfo.js +4 -4
  33. package/lib/extensions/extensionsApi.js +2 -2
  34. package/lib/extensions/extensionsHelper.js +6 -6
  35. package/lib/extensions/provisioningHelper.js +2 -2
  36. package/lib/extensions/updateHelper.js +2 -2
  37. package/lib/extensions/warnings.js +5 -5
  38. package/lib/frameworks/angular/index.js +6 -4
  39. package/lib/frameworks/index.js +38 -3
  40. package/lib/frameworks/lit/index.js +5 -1
  41. package/lib/frameworks/next/index.js +42 -16
  42. package/lib/frameworks/next/utils.js +1 -1
  43. package/lib/frameworks/preact/index.js +5 -1
  44. package/lib/frameworks/react/index.js +5 -1
  45. package/lib/frameworks/svelte/index.js +5 -1
  46. package/lib/frameworks/vite/index.js +6 -4
  47. package/lib/functions/python.js +2 -7
  48. package/lib/gcp/cloudfunctionsv2.js +8 -0
  49. package/lib/getDefaultHostingSite.js +3 -1
  50. package/lib/init/features/functions/index.js +10 -0
  51. package/lib/init/features/functions/python.js +48 -0
  52. package/lib/init/features/hosting/index.js +3 -2
  53. package/lib/projectUtils.js +2 -2
  54. package/lib/rc.js +4 -4
  55. package/npm-shrinkwrap.json +87 -79
  56. package/package.json +2 -2
  57. package/templates/extensions/extension.yaml +1 -1
  58. package/templates/extensions/integration-test.env +2 -0
  59. package/templates/extensions/integration-test.json +14 -0
  60. package/templates/extensions/javascript/WELCOME.md +14 -5
  61. package/templates/extensions/javascript/index.js +10 -10
  62. package/templates/extensions/javascript/integration-test.js +13 -0
  63. package/templates/extensions/javascript/package.lint.json +12 -4
  64. package/templates/extensions/javascript/package.nolint.json +11 -2
  65. package/templates/extensions/typescript/WELCOME.md +18 -5
  66. package/templates/extensions/typescript/_mocharc +10 -0
  67. package/templates/extensions/typescript/index.ts +16 -15
  68. package/templates/extensions/typescript/integration-test.ts +13 -0
  69. package/templates/extensions/typescript/package.lint.json +16 -4
  70. package/templates/extensions/typescript/package.nolint.json +12 -4
  71. package/templates/init/functions/javascript/_eslintrc +16 -2
  72. package/templates/init/functions/javascript/package.lint.json +4 -4
  73. package/templates/init/functions/javascript/package.nolint.json +3 -3
  74. package/templates/init/functions/python/_gitignore +0 -0
  75. package/templates/init/functions/python/main.py +13 -0
  76. package/templates/init/functions/python/requirements.txt +1 -0
  77. package/templates/init/functions/typescript/_eslintrc +1 -0
  78. package/templates/init/functions/typescript/package.lint.json +4 -4
  79. package/templates/init/functions/typescript/package.nolint.json +4 -3
@@ -4,9 +4,9 @@ exports.canonicalizeRefInput = exports.diagnoseAndFixProject = exports.confirm =
4
4
  const clc = require("colorette");
5
5
  const ora = require("ora");
6
6
  const semver = require("semver");
7
- const { marked } = require("marked");
7
+ const marked_1 = require("marked");
8
8
  const TerminalRenderer = require("marked-terminal");
9
- marked.setOptions({
9
+ marked_1.marked.setOptions({
10
10
  renderer: new TerminalRenderer(),
11
11
  });
12
12
  const api_1 = require("../api");
@@ -329,12 +329,12 @@ async function publishExtensionVersionFromLocalSource(args) {
329
329
  catch (err) {
330
330
  throw new error_1.FirebaseError("No CHANGELOG.md file found. " +
331
331
  "Please create one and add an entry for this version. " +
332
- marked("See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."));
332
+ (0, marked_1.marked)("See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."));
333
333
  }
334
334
  if (!notes && !semver.prerelease(extensionSpec.version) && extension) {
335
335
  throw new error_1.FirebaseError(`No entry for version ${extensionSpec.version} found in CHANGELOG.md. ` +
336
336
  "Please add one so users know what has changed in this version. " +
337
- marked("See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."));
337
+ (0, marked_1.marked)("See https://firebase.google.com/docs/extensions/alpha/create-user-docs#writing-changelog for more details."));
338
338
  }
339
339
  displayReleaseNotes(args.publisherId, args.extensionId, extensionSpec.version, notes);
340
340
  if (!(await confirm({
@@ -380,7 +380,7 @@ async function publishExtensionVersionFromLocalSource(args) {
380
380
  catch (err) {
381
381
  publishSpinner.fail();
382
382
  if (err.status === 404) {
383
- throw new error_1.FirebaseError(marked(`Couldn't find publisher ID '${clc.bold(args.publisherId)}'. Please ensure that you have registered this ID. To register as a publisher, you can check out the [Firebase documentation](https://firebase.google.com/docs/extensions/alpha/share#register_as_an_extensions_publisher) for step-by-step instructions.`));
383
+ throw new error_1.FirebaseError((0, marked_1.marked)(`Couldn't find publisher ID '${clc.bold(args.publisherId)}'. Please ensure that you have registered this ID. To register as a publisher, you can check out the [Firebase documentation](https://firebase.google.com/docs/extensions/alpha/share#register_as_an_extensions_publisher) for step-by-step instructions.`));
384
384
  }
385
385
  throw err;
386
386
  }
@@ -433,7 +433,7 @@ function getPublisherProjectFromName(publisherName) {
433
433
  exports.getPublisherProjectFromName = getPublisherProjectFromName;
434
434
  function displayReleaseNotes(publisherId, extensionId, versionId, releaseNotes) {
435
435
  const releaseNotesMessage = releaseNotes
436
- ? ` Release notes for this version:\n${marked(releaseNotes)}\n`
436
+ ? ` Release notes for this version:\n${(0, marked_1.marked)(releaseNotes)}\n`
437
437
  : "\n";
438
438
  const message = `You are about to publish version ${clc.green(versionId)} of ${clc.green(`${publisherId}/${extensionId}`)} to Firebase's registry of extensions.${releaseNotesMessage}` +
439
439
  "Once an extension version is published, it cannot be changed. If you wish to make changes after publishing, you will need to publish a new version.\n\n";
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getUsedProducts = exports.bulkCheckProductsProvisioned = exports.checkProductsProvisioned = exports.DeferredProduct = void 0;
4
- const { marked } = require("marked");
4
+ const marked_1 = require("marked");
5
5
  const api_1 = require("../api");
6
6
  const apiv2_1 = require("../apiv2");
7
7
  const functional_1 = require("../functional");
@@ -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(marked(errorMessage), { exit: 2 });
67
+ throw new error_1.FirebaseError((0, marked_1.marked)(errorMessage), { exit: 2 });
68
68
  }
69
69
  }
70
70
  function getUsedProducts(spec) {
@@ -3,7 +3,7 @@ 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 } = require("marked");
6
+ const marked_1 = require("marked");
7
7
  const error_1 = require("../error");
8
8
  const logger_1 = require("../logger");
9
9
  const extensionsApi = require("./extensionsApi");
@@ -47,7 +47,7 @@ function warningUpdateToOtherSource(sourceOrigin) {
47
47
  targetText = "URL";
48
48
  }
49
49
  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(marked(warning));
50
+ logger_1.logger.info((0, marked_1.marked)(warning));
51
51
  }
52
52
  exports.warningUpdateToOtherSource = warningUpdateToOtherSource;
53
53
  async function update(updateOptions) {
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.outOfBandChangesWarning = exports.paramsFlagDeprecationWarning = exports.displayWarningsForDeploy = exports.displayWarningPrompts = void 0;
4
- const { marked } = require("marked");
4
+ const marked_1 = require("marked");
5
5
  const clc = require("colorette");
6
6
  const types_1 = require("./types");
7
7
  const displayExtensionInfo_1 = require("./displayExtensionInfo");
@@ -16,11 +16,11 @@ function displayEAPWarning({ publisherId, sourceDownloadUri, githubLink, }) {
16
16
  const publisherNameLink = githubLink ? `[${publisherId}](${githubLink})` : publisherId;
17
17
  const warningMsg = `This extension is in preview and is built by a developer in the [Extensions Publisher Early Access Program](http://bit.ly/firex-provider). Its functionality might change in backward-incompatible ways. Since this extension isn't built by Firebase, reach out to ${publisherNameLink} with questions about this extension.`;
18
18
  const legalMsg = "\n\nIt is provided “AS IS”, without any warranty, express or implied, from Google. Google disclaims all liability for any damages, direct or indirect, resulting from the use of the extension, and its functionality might change in backward - incompatible ways.";
19
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(warningMsg + legalMsg));
19
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(warningMsg + legalMsg));
20
20
  (0, displayExtensionInfo_1.printSourceDownloadLink)(sourceDownloadUri);
21
21
  }
22
22
  function displayExperimentalWarning() {
23
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`${clc.yellow(clc.bold("Important"))}: This extension is ${clc.bold("experimental")} and may not be production-ready. Its functionality might change in backward-incompatible ways before its official release, or it may be discontinued.`));
23
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`${clc.yellow(clc.bold("Important"))}: This extension is ${clc.bold("experimental")} and may not be production-ready. Its functionality might change in backward-incompatible ways before its official release, or it may be discontinued.`));
24
24
  }
25
25
  async function displayWarningPrompts(publisherId, launchStage, extensionVersion) {
26
26
  const trustedPublishers = await (0, resolveSource_1.getTrustedPublishers)();
@@ -58,11 +58,11 @@ async function displayWarningsForDeploy(instancesToCreate) {
58
58
  const experimental = nonEapExtensions.filter((i) => i.extension.registryLaunchStage === types_1.RegistryLaunchStage.EXPERIMENTAL);
59
59
  if (experimental.length) {
60
60
  const humanReadableList = experimental.map((i) => `\t${(0, deploymentSummary_1.humanReadable)(i)}`).join("\n");
61
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`The following are instances of ${clc.bold("experimental")} extensions.They may not be production-ready. Their functionality may change in backward-incompatible ways before their official release, or they may be discontinued.\n${humanReadableList}\n`, { gfm: false }));
61
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`The following are instances of ${clc.bold("experimental")} extensions.They may not be production-ready. Their functionality may change in backward-incompatible ways before their official release, or they may be discontinued.\n${humanReadableList}\n`, { gfm: false }));
62
62
  }
63
63
  if (eapExtensions.length) {
64
64
  const humanReadableList = eapExtensions.map(toListEntry).join("\n");
65
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`These extensions are in preview and are built by a developer in the Extensions Publisher Early Access Program (http://bit.ly/firex-provider). Their functionality might change in backwards-incompatible ways. Since these extensions aren't built by Firebase, reach out to their publisher with questions about them.` +
65
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`These extensions are in preview and are built by a developer in the Extensions Publisher Early Access Program (http://bit.ly/firex-provider). Their functionality might change in backwards-incompatible ways. Since these extensions aren't built by Firebase, reach out to their publisher with questions about them.` +
66
66
  ` They are provided “AS IS”, without any warranty, express or implied, from Google.` +
67
67
  ` Google disclaims all liability for any damages, direct or indirect, resulting from the use of these extensions\n${humanReadableList}`, { gfm: false }));
68
68
  }
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.getDevModeHandle = exports.build = exports.init = exports.discover = exports.type = exports.support = exports.name = void 0;
4
4
  const path_1 = require("path");
5
5
  const child_process_1 = require("child_process");
6
+ const cross_spawn_1 = require("cross-spawn");
6
7
  const fs_extra_1 = require("fs-extra");
7
8
  const promises_1 = require("fs/promises");
8
9
  const __1 = require("..");
@@ -23,9 +24,10 @@ async function discover(dir) {
23
24
  return { mayWantBackend: !!serverTarget, publicDirectory: (0, path_1.join)(dir, "src", "assets") };
24
25
  }
25
26
  exports.discover = discover;
26
- async function init(setup) {
27
- (0, child_process_1.execSync)(`npx --yes -p @angular/cli@latest ng new ${setup.hosting.source} --skip-git`, {
27
+ async function init(setup, config) {
28
+ (0, child_process_1.execSync)(`npx --yes -p @angular/cli@latest ng new ${setup.projectId} --directory ${setup.hosting.source} --skip-git`, {
28
29
  stdio: "inherit",
30
+ cwd: config.projectDir,
29
31
  });
30
32
  const useAngularUniversal = await (0, prompt_1.promptOnce)({
31
33
  name: "useAngularUniversal",
@@ -36,7 +38,7 @@ async function init(setup) {
36
38
  if (useAngularUniversal) {
37
39
  (0, child_process_1.execSync)("ng add @nguniversal/express-engine --skip-confirmation", {
38
40
  stdio: "inherit",
39
- cwd: setup.hosting.source,
41
+ cwd: (0, path_1.join)(config.projectDir, setup.hosting.source),
40
42
  });
41
43
  }
42
44
  }
@@ -74,7 +76,7 @@ async function getDevModeHandle(dir) {
74
76
  if (!serveTarget)
75
77
  return;
76
78
  const host = new Promise((resolve) => {
77
- const serve = (0, child_process_1.spawn)(CLI_COMMAND, ["run", targetStringFromTarget(serveTarget), "--host", "localhost"], { cwd: dir });
79
+ const serve = (0, cross_spawn_1.spawn)(CLI_COMMAND, ["run", targetStringFromTarget(serveTarget), "--host", "localhost"], { cwd: dir });
78
80
  serve.stdout.on("data", (data) => {
79
81
  process.stdout.write(data);
80
82
  const match = data.toString().match(/(http:\/\/localhost:\d+)/);
@@ -4,6 +4,7 @@ exports.createServerResponseProxy = exports.prepareFrameworks = exports.findDepe
4
4
  const path_1 = require("path");
5
5
  const process_1 = require("process");
6
6
  const child_process_1 = require("child_process");
7
+ const cross_spawn_1 = require("cross-spawn");
7
8
  const fs_1 = require("fs");
8
9
  const url_1 = require("url");
9
10
  const http_1 = require("http");
@@ -12,6 +13,7 @@ const fs_extra_1 = require("fs-extra");
12
13
  const clc = require("colorette");
13
14
  const process = require("node:process");
14
15
  const semver = require("semver");
16
+ const glob = require("glob");
15
17
  const projectUtils_1 = require("../projectUtils");
16
18
  const config_1 = require("../hosting/config");
17
19
  const api_1 = require("../hosting/api");
@@ -106,7 +108,7 @@ function findDependency(name, options = {}) {
106
108
  const { cwd, depth, omitDev } = Object.assign(Object.assign({}, DEFAULT_FIND_DEP_OPTIONS), options);
107
109
  const env = Object.assign({}, process.env);
108
110
  delete env.NODE_ENV;
109
- const result = (0, child_process_1.spawnSync)(NPM_COMMAND, [
111
+ const result = (0, cross_spawn_1.sync)(NPM_COMMAND, [
110
112
  "list",
111
113
  name,
112
114
  "--json",
@@ -325,14 +327,47 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
325
327
  (_e = packageJson.dependencies)["firebase-admin"] || (_e["firebase-admin"] = exports.FIREBASE_ADMIN_VERSION);
326
328
  packageJson.engines || (packageJson.engines = {});
327
329
  (_f = packageJson.engines).node || (_f.node = exports.NODE_VERSION);
330
+ for (const [name, version] of Object.entries(packageJson.dependencies)) {
331
+ if (version.startsWith("file:")) {
332
+ const path = version.replace(/^file:/, "");
333
+ if (!(await (0, fs_extra_1.pathExists)(path)))
334
+ continue;
335
+ const stats = await (0, fs_extra_1.stat)(path);
336
+ if (stats.isDirectory()) {
337
+ const result = (0, cross_spawn_1.sync)("npm", ["pack", (0, path_1.relative)(functionsDist, path)], {
338
+ cwd: functionsDist,
339
+ });
340
+ if (!result.stdout)
341
+ throw new Error(`Error running \`npm pack\` at ${path}`);
342
+ const filename = result.stdout.toString().trim();
343
+ packageJson.dependencies[name] = `file:${filename}`;
344
+ }
345
+ else {
346
+ const filename = (0, path_1.basename)(path);
347
+ await (0, promises_1.copyFile)(path, (0, path_1.join)(functionsDist, filename));
348
+ packageJson.dependencies[name] = `file:${filename}`;
349
+ }
350
+ }
351
+ }
328
352
  await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, "package.json"), JSON.stringify(packageJson, null, 2));
329
- await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, ".env"), `__FIREBASE_FRAMEWORKS_ENTRY__=${frameworksEntry}
330
- ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\n` : ""}`);
331
353
  await (0, promises_1.copyFile)(getProjectPath("package-lock.json"), (0, path_1.join)(functionsDist, "package-lock.json")).catch(() => {
332
354
  });
333
355
  if (await (0, fs_extra_1.pathExists)(getProjectPath(".npmrc"))) {
334
356
  await (0, promises_1.copyFile)(getProjectPath(".npmrc"), (0, path_1.join)(functionsDist, ".npmrc"));
335
357
  }
358
+ let existingDotEnvContents = "";
359
+ if (await (0, fs_extra_1.pathExists)(getProjectPath(".env"))) {
360
+ existingDotEnvContents = (await (0, promises_1.readFile)(getProjectPath(".env"))).toString();
361
+ }
362
+ await (0, promises_1.writeFile)((0, path_1.join)(functionsDist, ".env"), `${existingDotEnvContents}
363
+ __FIREBASE_FRAMEWORKS_ENTRY__=${frameworksEntry}
364
+ ${firebaseDefaults ? `__FIREBASE_DEFAULTS__=${JSON.stringify(firebaseDefaults)}\n` : ""}`);
365
+ const envs = await new Promise((resolve, reject) => glob(getProjectPath(".env.*"), (err, matches) => {
366
+ if (err)
367
+ reject(err);
368
+ resolve(matches);
369
+ }));
370
+ await Promise.all(envs.map((path) => (0, promises_1.copyFile)(path, (0, path_1.join)(functionsDist, (0, path_1.basename)(path)))));
336
371
  (0, child_process_1.execSync)(`${NPM_COMMAND} i --omit dev --no-audit`, {
337
372
  cwd: functionsDist,
338
373
  stdio: "inherit",
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDevModeHandle = exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.init = exports.build = exports.discover = exports.type = exports.support = exports.name = void 0;
4
4
  const child_process_1 = require("child_process");
5
+ const cross_spawn_1 = require("cross-spawn");
5
6
  const promises_1 = require("fs/promises");
6
7
  const path_1 = require("path");
7
8
  const fs_extra_1 = require("fs-extra");
@@ -9,6 +10,10 @@ const url_1 = require("url");
9
10
  const fs_1 = require("fs");
10
11
  const semver_1 = require("semver");
11
12
  const clc = require("colorette");
13
+ const stream_chain_1 = require("stream-chain");
14
+ const stream_json_1 = require("stream-json");
15
+ const Pick_1 = require("stream-json/filters/Pick");
16
+ const StreamObject_1 = require("stream-json/streamers/StreamObject");
12
17
  const __1 = require("..");
13
18
  const prompt_1 = require("../../prompt");
14
19
  const error_1 = require("../../error");
@@ -139,14 +144,14 @@ async function build(dir) {
139
144
  return { wantsBackend, headers, redirects, rewrites, trailingSlash };
140
145
  }
141
146
  exports.build = build;
142
- async function init(setup) {
147
+ async function init(setup, config) {
143
148
  const language = await (0, prompt_1.promptOnce)({
144
149
  type: "list",
145
- default: "JavaScript",
150
+ default: "TypeScript",
146
151
  message: "What language would you like to use?",
147
152
  choices: ["JavaScript", "TypeScript"],
148
153
  });
149
- (0, child_process_1.execSync)(`npx --yes create-next-app@latest -e hello-world ${setup.hosting.source} --use-npm ${language === "TypeScript" ? "--ts" : ""}`, { stdio: "inherit" });
154
+ (0, child_process_1.execSync)(`npx --yes create-next-app@latest -e hello-world ${setup.hosting.source} --use-npm ${language === "TypeScript" ? "--ts" : "--js"}`, { stdio: "inherit", cwd: config.projectDir });
150
155
  }
151
156
  exports.init = init;
152
157
  async function ɵcodegenPublicDirectory(sourceDir, destDir) {
@@ -217,18 +222,38 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
217
222
  const { distDir } = await getConfig(sourceDir);
218
223
  const packageJson = await (0, utils_2.readJSON)((0, path_1.join)(sourceDir, "package.json"));
219
224
  if ((0, fs_1.existsSync)((0, path_1.join)(sourceDir, "next.config.js"))) {
220
- const dependencyTree = JSON.parse((0, child_process_1.spawnSync)("npm", ["ls", "--omit=dev", "--all", "--json"], {
221
- cwd: sourceDir,
222
- }).stdout.toString());
223
- const esbuildArgs = (0, utils_1.allDependencyNames)(dependencyTree)
224
- .map((it) => `--external:${it}`)
225
- .concat("--bundle", "--platform=node", `--target=node${__1.NODE_VERSION}`, `--outdir=${destDir}`, "--log-level=error");
226
- const bundle = (0, child_process_1.spawnSync)("npx", ["--yes", "esbuild", "next.config.js", ...esbuildArgs], {
227
- cwd: sourceDir,
228
- });
229
- if (bundle.status) {
230
- console.error(bundle.stderr.toString());
231
- throw new error_1.FirebaseError("Unable to bundle next.config.js for use in Cloud Functions");
225
+ try {
226
+ const productionDeps = await new Promise((resolve) => {
227
+ const dependencies = [];
228
+ const pipeline = (0, stream_chain_1.chain)([
229
+ (0, cross_spawn_1.spawn)("npm", ["ls", "--omit=dev", "--all", "--json"], { cwd: sourceDir }).stdout,
230
+ (0, stream_json_1.parser)({ packValues: false, packKeys: true, streamValues: false }),
231
+ (0, Pick_1.pick)({ filter: "dependencies" }),
232
+ (0, StreamObject_1.streamObject)(),
233
+ ({ key, value }) => [
234
+ key,
235
+ ...(0, utils_1.allDependencyNames)(value),
236
+ ],
237
+ ]);
238
+ pipeline.on("data", (it) => dependencies.push(it));
239
+ pipeline.on("end", () => {
240
+ resolve([...new Set(dependencies)]);
241
+ });
242
+ });
243
+ const esbuildArgs = productionDeps
244
+ .map((it) => `--external:${it}`)
245
+ .concat("--bundle", "--platform=node", `--target=node${__1.NODE_VERSION}`, `--outdir=${destDir}`, "--log-level=error");
246
+ const bundle = (0, cross_spawn_1.sync)("npx", ["--yes", "esbuild", "next.config.js", ...esbuildArgs], {
247
+ cwd: sourceDir,
248
+ });
249
+ if (bundle.status) {
250
+ throw new error_1.FirebaseError(bundle.stderr.toString());
251
+ }
252
+ }
253
+ catch (e) {
254
+ console.warn("Unable to bundle next.config.js for use in Cloud Functions, proceeding with deploy but problems may be enountered.");
255
+ console.error(e.message);
256
+ (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, "next.config.js"), (0, path_1.join)(destDir, "next.config.js"));
232
257
  }
233
258
  }
234
259
  if (await (0, fs_extra_1.pathExists)((0, path_1.join)(sourceDir, "public"))) {
@@ -267,6 +292,7 @@ async function getDevModeHandle(dir, hostingEmulatorInfo) {
267
292
  }
268
293
  exports.getDevModeHandle = getDevModeHandle;
269
294
  async function getConfig(dir) {
295
+ var _a;
270
296
  let config = {};
271
297
  if ((0, fs_1.existsSync)((0, path_1.join)(dir, "next.config.js"))) {
272
298
  const version = getNextVersion(dir);
@@ -279,7 +305,7 @@ async function getConfig(dir) {
279
305
  }
280
306
  else {
281
307
  try {
282
- config = await Promise.resolve().then(() => require((0, url_1.pathToFileURL)((0, path_1.join)(dir, "next.config.js")).toString()));
308
+ config = await (_a = (0, url_1.pathToFileURL)((0, path_1.join)(dir, "next.config.js")).toString(), Promise.resolve().then(() => require(_a)));
283
309
  }
284
310
  catch (e) {
285
311
  throw new Error("Unable to load next.config.js.");
@@ -87,6 +87,6 @@ function allDependencyNames(mod) {
87
87
  if (!mod.dependencies)
88
88
  return [];
89
89
  const dependencyNames = Object.keys(mod.dependencies).reduce((acc, it) => [...acc, it, ...allDependencyNames(mod.dependencies[it])], []);
90
- return [...new Set(dependencyNames)];
90
+ return dependencyNames;
91
91
  }
92
92
  exports.allDependencyNames = allDependencyNames;
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDevModeHandle = exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.vitePluginDiscover = exports.viteDiscoverWithNpmDependency = exports.init = exports.initViteTemplate = exports.DEFAULT_BUILD_SCRIPT = exports.type = exports.support = exports.name = void 0;
4
4
  const child_process_1 = require("child_process");
5
+ const cross_spawn_1 = require("cross-spawn");
5
6
  const fs_1 = require("fs");
6
7
  const fs_extra_1 = require("fs-extra");
7
8
  const path_1 = require("path");
@@ -14,9 +15,9 @@ exports.support = "experimental";
14
15
  exports.type = 4;
15
16
  const CLI_COMMAND = (0, path_1.join)("node_modules", ".bin", process.platform === "win32" ? "vite.cmd" : "vite");
16
17
  exports.DEFAULT_BUILD_SCRIPT = ["vite build", "tsc && vite build"];
17
- const initViteTemplate = (template) => async (setup) => await init(setup, template);
18
+ const initViteTemplate = (template) => async (setup, config) => await init(setup, config, template);
18
19
  exports.initViteTemplate = initViteTemplate;
19
- async function init(setup, baseTemplate = "vanilla") {
20
+ async function init(setup, config, baseTemplate = "vanilla") {
20
21
  const template = await (0, prompt_1.promptOnce)({
21
22
  type: "list",
22
23
  default: "JavaScript",
@@ -28,8 +29,9 @@ async function init(setup, baseTemplate = "vanilla") {
28
29
  });
29
30
  (0, child_process_1.execSync)(`npm create vite@latest ${setup.hosting.source} --yes -- --template ${template}`, {
30
31
  stdio: "inherit",
32
+ cwd: config.projectDir,
31
33
  });
32
- (0, child_process_1.execSync)(`npm install`, { stdio: "inherit", cwd: setup.hosting.source });
34
+ (0, child_process_1.execSync)(`npm install`, { stdio: "inherit", cwd: (0, path_1.join)(config.projectDir, setup.hosting.source) });
33
35
  }
34
36
  exports.init = init;
35
37
  const viteDiscoverWithNpmDependency = (dep) => async (dir) => await discover(dir, undefined, dep);
@@ -70,7 +72,7 @@ async function ɵcodegenPublicDirectory(root, dest) {
70
72
  exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
71
73
  async function getDevModeHandle(dir) {
72
74
  const host = new Promise((resolve) => {
73
- const serve = (0, child_process_1.spawn)(CLI_COMMAND, [], { cwd: dir });
75
+ const serve = (0, cross_spawn_1.spawn)(CLI_COMMAND, [], { cwd: dir });
74
76
  serve.stdout.on("data", (data) => {
75
77
  process.stdout.write(data);
76
78
  const match = data.toString().match(/(http:\/\/.+:\d+)/);
@@ -5,17 +5,12 @@ const path = require("path");
5
5
  const spawn = require("cross-spawn");
6
6
  const logger_1 = require("../logger");
7
7
  const DEFAULT_VENV_DIR = "venv";
8
- function runWithVirtualEnv(commandAndArgs, cwd, envs, venvDir = DEFAULT_VENV_DIR) {
8
+ function runWithVirtualEnv(commandAndArgs, cwd, envs, spawnOpts = {}, venvDir = DEFAULT_VENV_DIR) {
9
9
  const activateScriptPath = process.platform === "win32" ? ["Scripts", "activate.bat"] : ["bin", "activate"];
10
10
  const venvActivate = path.join(cwd, venvDir, ...activateScriptPath);
11
11
  const command = process.platform === "win32" ? venvActivate : "source";
12
12
  const args = [process.platform === "win32" ? "" : venvActivate, "&&", ...commandAndArgs];
13
13
  logger_1.logger.debug(`Running command with virtualenv: command=${command}, args=${JSON.stringify(args)}`);
14
- return spawn(command, args, {
15
- shell: true,
16
- cwd,
17
- stdio: ["pipe", "pipe", "pipe", "pipe"],
18
- env: envs,
19
- });
14
+ return spawn(command, args, Object.assign(Object.assign({ shell: true, cwd, stdio: ["pipe", "pipe", "pipe", "pipe"] }, spawnOpts), { env: envs }));
20
15
  }
21
16
  exports.runWithVirtualEnv = runWithVirtualEnv;
@@ -342,6 +342,14 @@ function endpointFromFunction(gcfFunction) {
342
342
  if ((_f = gcfFunction.labels) === null || _f === void 0 ? void 0 : _f[constants_1.HASH_LABEL]) {
343
343
  endpoint.hash = gcfFunction.labels[constants_1.HASH_LABEL];
344
344
  }
345
+ const serviceName = gcfFunction.serviceConfig.service;
346
+ if (!serviceName) {
347
+ logger_1.logger.debug("Got a v2 function without a service name." +
348
+ "Maybe we've migrated to using the v2 API everywhere and missed this code");
349
+ }
350
+ else {
351
+ endpoint.runServiceId = utils.last(serviceName.split("/"));
352
+ }
345
353
  return endpoint;
346
354
  }
347
355
  exports.endpointFromFunction = endpointFromFunction;
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDefaultHostingSite = void 0;
4
4
  const logger_1 = require("./logger");
5
5
  const projects_1 = require("./management/projects");
6
+ const projectUtils_1 = require("./projectUtils");
6
7
  async function getDefaultHostingSite(options) {
7
8
  var _a;
8
- const project = await (0, projects_1.getFirebaseProject)(options.project);
9
+ const projectId = (0, projectUtils_1.needProjectId)(options);
10
+ const project = await (0, projects_1.getFirebaseProject)(projectId);
9
11
  const site = (_a = project.resources) === null || _a === void 0 ? void 0 : _a.hostingSite;
10
12
  if (!site) {
11
13
  logger_1.logger.debug(`No default hosting site found for project: ${options.project}. Using projectId as hosting site name.`);
@@ -8,6 +8,7 @@ const requirePermissions_1 = require("../../../requirePermissions");
8
8
  const ensureApiEnabled_1 = require("../../../ensureApiEnabled");
9
9
  const projectConfig_1 = require("../../../functions/projectConfig");
10
10
  const error_1 = require("../../../error");
11
+ const experiments_1 = require("../../../experiments");
11
12
  const MAX_ATTEMPTS = 5;
12
13
  async function doSetup(setup, config, options) {
13
14
  var _a, _b;
@@ -139,6 +140,12 @@ async function languageSetup(setup, config) {
139
140
  value: "typescript",
140
141
  },
141
142
  ];
143
+ if ((0, experiments_1.isEnabled)("pythonfunctions")) {
144
+ choices.push({
145
+ name: "Python",
146
+ value: "python",
147
+ });
148
+ }
142
149
  const language = await (0, prompt_1.promptOnce)({
143
150
  type: "list",
144
151
  message: "What language would you like to use to write Cloud Functions?",
@@ -153,6 +160,9 @@ async function languageSetup(setup, config) {
153
160
  case "typescript":
154
161
  cbconfig.ignore = ["node_modules", ".git", "firebase-debug.log", "firebase-debug.*.log"];
155
162
  break;
163
+ case "python":
164
+ cbconfig.ignore = ["venv", ".git", "firebase-debug.log", "firebase-debug.*.log"];
165
+ break;
156
166
  }
157
167
  return require("./" + language).setup(setup, config);
158
168
  }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setup = void 0;
4
+ const fs = require("fs");
5
+ const spawn = require("cross-spawn");
6
+ const path = require("path");
7
+ const python_1 = require("../../../deploy/functions/runtimes/python");
8
+ const python_2 = require("../../../functions/python");
9
+ const prompt_1 = require("../../../prompt");
10
+ const TEMPLATE_ROOT = path.resolve(__dirname, "../../../../templates/init/functions/python");
11
+ const MAIN_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "main.py"), "utf8");
12
+ const REQUIREMENTS_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "requirements.txt"), "utf8");
13
+ const GITIGNORE_TEMPLATE = fs.readFileSync(path.join(TEMPLATE_ROOT, "_gitignore"), "utf8");
14
+ async function setup(setup, config) {
15
+ await config.askWriteProjectFile(`${setup.functions.source}/requirements.txt`, REQUIREMENTS_TEMPLATE);
16
+ await config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
17
+ await config.askWriteProjectFile(`${setup.functions.source}/main.py`, MAIN_TEMPLATE);
18
+ config.set("functions.runtime", python_1.LATEST_VERSION);
19
+ config.set("functions.ignore", ["venv", "__pycache__"]);
20
+ const venvProcess = spawn((0, python_1.getPythonBinary)(python_1.LATEST_VERSION), ["-m", "venv", "venv"], {
21
+ shell: true,
22
+ cwd: config.path(setup.functions.source),
23
+ stdio: ["pipe", "pipe", "pipe", "pipe"],
24
+ });
25
+ await new Promise((resolve, reject) => {
26
+ venvProcess.on("exit", resolve);
27
+ venvProcess.on("error", reject);
28
+ });
29
+ const install = await (0, prompt_1.promptOnce)({
30
+ name: "install",
31
+ type: "confirm",
32
+ message: "Do you want to install dependencies now?",
33
+ default: true,
34
+ });
35
+ if (install) {
36
+ const upgradeProcess = (0, python_2.runWithVirtualEnv)(["pip3", "install", "--upgrade", "pip"], config.path(setup.functions.source), {}, { stdio: ["inherit", "inherit", "inherit"] });
37
+ await new Promise((resolve, reject) => {
38
+ upgradeProcess.on("exit", resolve);
39
+ upgradeProcess.on("error", reject);
40
+ });
41
+ const installProcess = (0, python_2.runWithVirtualEnv)([(0, python_1.getPythonBinary)(python_1.LATEST_VERSION), "-m", "pip", "install", "-r", "requirements.txt"], config.path(setup.functions.source), {}, { stdio: ["inherit", "inherit", "inherit"] });
42
+ await new Promise((resolve, reject) => {
43
+ installProcess.on("exit", resolve);
44
+ installProcess.on("error", reject);
45
+ });
46
+ }
47
+ }
48
+ exports.setup = setup;
@@ -10,6 +10,7 @@ const prompt_1 = require("../../../prompt");
10
10
  const logger_1 = require("../../../logger");
11
11
  const frameworks_1 = require("../../../frameworks");
12
12
  const experiments = require("../../../experiments");
13
+ const path_1 = require("path");
13
14
  const INDEX_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/hosting/index.html", "utf8");
14
15
  const MISSING_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/hosting/404.html", "utf8");
15
16
  const DEFAULT_IGNORES = ["firebase.json", "**/.*", "**/node_modules/**"];
@@ -51,7 +52,7 @@ async function doSetup(setup, config) {
51
52
  }, setup.hosting);
52
53
  if (setup.hosting.source !== ".")
53
54
  delete setup.hosting.useDiscoveredFramework;
54
- discoveredFramework = await (0, frameworks_1.discover)(setup.hosting.source);
55
+ discoveredFramework = await (0, frameworks_1.discover)((0, path_1.join)(config.projectDir, setup.hosting.source));
55
56
  if (discoveredFramework) {
56
57
  const name = frameworks_1.WebFrameworks[discoveredFramework.framework].name;
57
58
  await (0, prompt_1.promptOnce)({
@@ -83,7 +84,7 @@ async function doSetup(setup, config) {
83
84
  }, setup.hosting);
84
85
  if (discoveredFramework)
85
86
  (0, rimraf_1.sync)(setup.hosting.source);
86
- await frameworks_1.WebFrameworks[setup.hosting.whichFramework].init(setup);
87
+ await frameworks_1.WebFrameworks[setup.hosting.whichFramework].init(setup, config);
87
88
  }
88
89
  setup.config.hosting = {
89
90
  source: setup.hosting.source,
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAliases = exports.needProjectNumber = exports.needProjectId = exports.getProjectId = void 0;
4
4
  const projects_1 = require("./management/projects");
5
5
  const clc = require("colorette");
6
- const { marked } = require("marked");
6
+ const marked_1 = require("marked");
7
7
  const { FirebaseError } = require("./error");
8
8
  function getProjectId({ projectId, project, }) {
9
9
  return projectId || project;
@@ -27,7 +27,7 @@ function needProjectId({ projectId, project, rc, }) {
27
27
  "To list all the Firebase projects to which you have access, run " +
28
28
  clc.bold("firebase projects:list") +
29
29
  ".\n" +
30
- marked("To learn about active projects for the CLI, visit https://firebase.google.com/docs/cli#project_aliases"));
30
+ (0, marked_1.marked)("To learn about active projects for the CLI, visit https://firebase.google.com/docs/cli#project_aliases"));
31
31
  }
32
32
  const aliasList = Object.entries(aliases)
33
33
  .map(([aname, projectId]) => ` ${aname} (${projectId})`)