firebase-tools 11.29.0 → 11.30.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 (52) hide show
  1. package/lib/commands/database-import.js +2 -2
  2. package/lib/commands/hosting-channel-deploy.js +3 -0
  3. package/lib/database/import.js +113 -18
  4. package/lib/deploy/extensions/secrets.js +2 -2
  5. package/lib/deploy/functions/ensure.js +7 -1
  6. package/lib/deploy/functions/release/fabricator.js +2 -0
  7. package/lib/deploy/functions/runtimes/discovery/index.js +1 -1
  8. package/lib/deploy/functions/runtimes/index.js +11 -3
  9. package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +3 -3
  10. package/lib/deploy/functions/runtimes/python/index.js +41 -13
  11. package/lib/deploy/hosting/convertConfig.js +8 -4
  12. package/lib/deploy/hosting/prepare.js +115 -2
  13. package/lib/deploy/index.js +24 -8
  14. package/lib/emulator/adminSdkConfig.js +8 -0
  15. package/lib/emulator/controller.js +7 -9
  16. package/lib/emulator/download.js +3 -12
  17. package/lib/emulator/downloadableEmulators.js +5 -5
  18. package/lib/emulator/functionsEmulator.js +57 -7
  19. package/lib/emulator/functionsEmulatorRuntime.js +4 -1
  20. package/lib/emulator/functionsEmulatorShared.js +1 -0
  21. package/lib/emulator/functionsRuntimeWorker.js +12 -4
  22. package/lib/experiments.js +20 -7
  23. package/lib/extensions/extensionsHelper.js +2 -2
  24. package/lib/frameworks/angular/index.js +13 -13
  25. package/lib/frameworks/astro/index.js +3 -4
  26. package/lib/frameworks/constants.js +42 -0
  27. package/lib/frameworks/express/index.js +3 -2
  28. package/lib/frameworks/flutter/index.js +39 -0
  29. package/lib/frameworks/flutter/utils.js +11 -0
  30. package/lib/frameworks/index.js +58 -131
  31. package/lib/frameworks/interfaces.js +2 -0
  32. package/lib/frameworks/next/constants.js +2 -1
  33. package/lib/frameworks/next/index.js +124 -87
  34. package/lib/frameworks/next/utils.js +71 -6
  35. package/lib/frameworks/nuxt/index.js +4 -5
  36. package/lib/frameworks/nuxt/utils.js +2 -2
  37. package/lib/frameworks/nuxt2/index.js +5 -5
  38. package/lib/frameworks/utils.js +101 -1
  39. package/lib/frameworks/vite/index.js +5 -6
  40. package/lib/functions/ensureTargeted.js +4 -4
  41. package/lib/functions/python.js +12 -5
  42. package/lib/gcp/resourceManager.js +1 -0
  43. package/lib/hosting/config.js +4 -8
  44. package/lib/init/features/functions/index.js +4 -7
  45. package/lib/init/features/hosting/github.js +7 -2
  46. package/lib/init/features/hosting/index.js +3 -2
  47. package/lib/serve/index.js +2 -1
  48. package/lib/unzip.js +126 -0
  49. package/npm-shrinkwrap.json +6 -287
  50. package/package.json +1 -2
  51. package/schema/firebase-config.json +1 -1
  52. package/templates/init/functions/python/requirements.txt +1 -1
@@ -37,6 +37,14 @@ async function getProjectAdminSdkConfig(projectId) {
37
37
  apiVersion: "v1beta1",
38
38
  urlPrefix: api_1.firebaseApiOrigin,
39
39
  });
40
+ if (projectId.startsWith("demo-")) {
41
+ logger_1.logger.debug(`Detected demo- project: ${projectId}. Using default adminSdkConfig instead of calling firebase API.`);
42
+ return {
43
+ projectId,
44
+ databaseURL: `${projectId}-default-rtdb.firebaseio.com`,
45
+ storageBucket: `${projectId}.appspot.com`,
46
+ };
47
+ }
40
48
  try {
41
49
  const res = await apiClient.get(`projects/${projectId}/adminSdkConfig`);
42
50
  return res.body;
@@ -282,15 +282,13 @@ async function startAll(options, showUI = true) {
282
282
  if (Array.isArray(hostingConfig) ? hostingConfig.some((it) => it.source) : hostingConfig === null || hostingConfig === void 0 ? void 0 : hostingConfig.source) {
283
283
  experiments.assertEnabled("webframeworks", "emulate a web framework");
284
284
  const emulators = [];
285
- if (experiments.isEnabled("webframeworks")) {
286
- for (const e of types_1.ALL_SERVICE_EMULATORS) {
287
- if (listenForEmulator[e]) {
288
- emulators.push({
289
- name: e,
290
- host: utils.connectableHostname(listenForEmulator[e][0].address),
291
- port: listenForEmulator[e][0].port,
292
- });
293
- }
285
+ for (const e of types_1.ALL_SERVICE_EMULATORS) {
286
+ if (listenForEmulator[e]) {
287
+ emulators.push({
288
+ name: e,
289
+ host: utils.connectableHostname(listenForEmulator[e][0].address),
290
+ port: listenForEmulator[e][0].port,
291
+ });
294
292
  }
295
293
  }
296
294
  await (0, frameworks_1.prepareFrameworks)(targets, options, options, emulators);
@@ -5,9 +5,9 @@ const crypto = require("crypto");
5
5
  const fs = require("fs-extra");
6
6
  const path = require("path");
7
7
  const tmp = require("tmp");
8
- const unzipper = require("unzipper");
9
8
  const emulatorLogger_1 = require("./emulatorLogger");
10
9
  const error_1 = require("../error");
10
+ const unzip_1 = require("../unzip");
11
11
  const downloadableEmulators = require("./downloadableEmulators");
12
12
  const downloadUtils = require("../downloadUtils");
13
13
  tmp.setGracefulCleanup();
@@ -25,9 +25,8 @@ async function downloadEmulator(name) {
25
25
  }
26
26
  fs.copySync(tmpfile, emulator.downloadPath);
27
27
  if (emulator.unzipDir) {
28
- await unzip(emulator.downloadPath, emulator.unzipDir);
28
+ await (0, unzip_1.unzip)(emulator.downloadPath, emulator.unzipDir);
29
29
  }
30
- await new Promise((f) => setTimeout(f, 2000));
31
30
  const executablePath = emulator.binaryPath || emulator.downloadPath;
32
31
  fs.chmodSync(executablePath, 0o755);
33
32
  removeOldFiles(name, emulator);
@@ -44,20 +43,12 @@ async function downloadExtensionVersion(extensionVersionRef, sourceDownloadUri,
44
43
  }
45
44
  emulatorLogger.logLabeled("BULLET", "extensions", `downloading ${sourceDownloadUri}...`);
46
45
  const sourceCodeZip = await downloadUtils.downloadToTmp(sourceDownloadUri);
47
- await unzip(sourceCodeZip, targetDir);
46
+ await (0, unzip_1.unzip)(sourceCodeZip, targetDir);
48
47
  fs.chmodSync(targetDir, 0o755);
49
48
  emulatorLogger.logLabeled("BULLET", "extensions", `Downloaded to ${targetDir}...`);
50
49
  await new Promise((resolve) => setTimeout(resolve, 1000));
51
50
  }
52
51
  exports.downloadExtensionVersion = downloadExtensionVersion;
53
- function unzip(zipPath, unzipDir) {
54
- return new Promise((resolve, reject) => {
55
- fs.createReadStream(zipPath)
56
- .pipe(unzipper.Extract({ path: unzipDir }))
57
- .on("error", reject)
58
- .on("close", resolve);
59
- });
60
- }
61
52
  function removeOldFiles(name, emulator, removeAllVersions = false) {
62
53
  const currentLocalPath = emulator.downloadPath;
63
54
  const currentUnzipPath = emulator.unzipDir;
@@ -23,9 +23,9 @@ const EMULATOR_UPDATE_DETAILS = {
23
23
  expectedChecksum: "311609538bd65666eb724ef47c2e6466",
24
24
  },
25
25
  firestore: {
26
- version: "1.17.2",
27
- expectedSize: 64907894,
28
- expectedChecksum: "bc56ccf2419be3242e7b53def0a51566",
26
+ version: "1.17.4",
27
+ expectedSize: 64969580,
28
+ expectedChecksum: "9d580b58e55e57b0cdc3ca8888098d43",
29
29
  },
30
30
  storage: {
31
31
  version: "1.1.3",
@@ -35,9 +35,9 @@ const EMULATOR_UPDATE_DETAILS = {
35
35
  ui: experiments.isEnabled("emulatoruisnapshot")
36
36
  ? { version: "SNAPSHOT", expectedSize: -1, expectedChecksum: "" }
37
37
  : {
38
- version: "1.11.5",
38
+ version: "1.11.6",
39
39
  expectedSize: 3063444,
40
- expectedChecksum: "4045fef65cf71fb9d83b01fb8b160141",
40
+ expectedChecksum: "14b971f4ed4909f348e647db7114d62b",
41
41
  },
42
42
  pubsub: {
43
43
  version: "0.7.1",
@@ -367,7 +367,7 @@ class FunctionsEmulator {
367
367
  const signature = (0, functionsEmulatorShared_1.getSignatureType)(definition);
368
368
  switch (service) {
369
369
  case constants_1.Constants.SERVICE_FIRESTORE:
370
- added = await this.addFirestoreTrigger(this.args.projectId, key, definition.eventTrigger);
370
+ added = await this.addFirestoreTrigger(this.args.projectId, key, definition.eventTrigger, signature);
371
371
  break;
372
372
  case constants_1.Constants.SERVICE_REALTIME_DATABASE:
373
373
  added = await this.addRealtimeDatabaseTrigger(this.args.projectId, definition.id, key, definition.eventTrigger, signature, definition.region);
@@ -531,17 +531,60 @@ class FunctionsEmulator {
531
531
  }
532
532
  return true;
533
533
  }
534
- async addFirestoreTrigger(projectId, key, eventTrigger) {
535
- if (!registry_1.EmulatorRegistry.isRunning(types_1.Emulators.FIRESTORE)) {
536
- return Promise.resolve(false);
537
- }
534
+ getV1FirestoreAttributes(projectId, key, eventTrigger) {
538
535
  const bundle = JSON.stringify({
539
536
  eventTrigger: Object.assign(Object.assign({}, eventTrigger), { service: "firestore.googleapis.com" }),
540
537
  });
538
+ const path = `/emulator/v1/projects/${projectId}/triggers/${key}`;
539
+ return { bundle, path };
540
+ }
541
+ getV2FirestoreAttributes(projectId, key, eventTrigger) {
542
+ var _a, _b, _c, _d, _e, _f;
543
+ logger_1.logger.debug("Found a v2 firestore trigger.");
544
+ const database = (_a = eventTrigger.eventFilters) === null || _a === void 0 ? void 0 : _a.database;
545
+ if (!database) {
546
+ throw new error_1.FirebaseError("A database must be supplied.");
547
+ }
548
+ const namespace = (_b = eventTrigger.eventFilters) === null || _b === void 0 ? void 0 : _b.namespace;
549
+ if (!namespace) {
550
+ throw new error_1.FirebaseError("A namespace must be supplied.");
551
+ }
552
+ let doc;
553
+ let match;
554
+ if ((_c = eventTrigger.eventFilters) === null || _c === void 0 ? void 0 : _c.document) {
555
+ doc = (_d = eventTrigger.eventFilters) === null || _d === void 0 ? void 0 : _d.document;
556
+ match = "EXACT";
557
+ }
558
+ if ((_e = eventTrigger.eventFilterPathPatterns) === null || _e === void 0 ? void 0 : _e.document) {
559
+ doc = (_f = eventTrigger.eventFilterPathPatterns) === null || _f === void 0 ? void 0 : _f.document;
560
+ match = "PATH_PATTERN";
561
+ }
562
+ if (!doc) {
563
+ throw new error_1.FirebaseError("A document must be supplied.");
564
+ }
565
+ const bundle = JSON.stringify({
566
+ eventType: eventTrigger.eventType,
567
+ database,
568
+ namespace,
569
+ document: {
570
+ value: doc,
571
+ matchType: match,
572
+ },
573
+ });
574
+ const path = `/emulator/v1/projects/${projectId}/eventarcTrigger?eventarcTriggerId=${key}`;
575
+ return { bundle, path };
576
+ }
577
+ async addFirestoreTrigger(projectId, key, eventTrigger, signature) {
578
+ if (!registry_1.EmulatorRegistry.isRunning(types_1.Emulators.FIRESTORE)) {
579
+ return Promise.resolve(false);
580
+ }
581
+ const { bundle, path } = signature === "cloudevent"
582
+ ? this.getV2FirestoreAttributes(projectId, key, eventTrigger)
583
+ : this.getV1FirestoreAttributes(projectId, key, eventTrigger);
541
584
  logger_1.logger.debug(`addFirestoreTrigger`, JSON.stringify(bundle));
542
585
  const client = registry_1.EmulatorRegistry.client(types_1.Emulators.FIRESTORE);
543
586
  try {
544
- await client.put(`/emulator/v1/projects/${projectId}/triggers/${key}`, bundle);
587
+ signature === "cloudevent" ? await client.post(path, bundle) : await client.put(path, bundle);
545
588
  }
546
589
  catch (err) {
547
590
  this.logger.log("WARN", "Error adding firestore function: " + err);
@@ -915,6 +958,7 @@ class FunctionsEmulator {
915
958
  }
916
959
  }
917
960
  async handleHttpsTrigger(req, res) {
961
+ var _a;
918
962
  const method = req.method;
919
963
  let triggerId = req.params.trigger_name;
920
964
  if (req.params.region) {
@@ -933,7 +977,13 @@ class FunctionsEmulator {
933
977
  }
934
978
  const trigger = record.def;
935
979
  logger_1.logger.debug(`Accepted request ${method} ${req.url} --> ${triggerId}`);
936
- const reqBody = req.rawBody;
980
+ let reqBody = req.rawBody;
981
+ if ((0, functionsEmulatorShared_1.getSignatureType)(trigger) === "cloudevent") {
982
+ if ((_a = req.headers["content-type"]) === null || _a === void 0 ? void 0 : _a.includes("application/protobuf")) {
983
+ reqBody = Uint8Array.from(atob(reqBody.toString()), (c) => c.charCodeAt(0));
984
+ req.headers["content-length"] = reqBody.length.toString();
985
+ }
986
+ }
937
987
  const isCallable = trigger.labels && trigger.labels["deployment-callable"] === "true";
938
988
  const authHeader = req.header("Authorization");
939
989
  if (authHeader && isCallable && trigger.platform !== "gcfv2") {
@@ -677,12 +677,15 @@ async function main() {
677
677
  switch (FUNCTION_SIGNATURE) {
678
678
  case "event":
679
679
  case "cloudevent":
680
+ let reqBody;
680
681
  const rawBody = req.rawBody;
681
- let reqBody = JSON.parse(rawBody.toString());
682
682
  if (types_2.EventUtils.isBinaryCloudEvent(req)) {
683
683
  reqBody = types_2.EventUtils.extractBinaryCloudEventContext(req);
684
684
  reqBody.data = req.body;
685
685
  }
686
+ else {
687
+ reqBody = JSON.parse(rawBody.toString());
688
+ }
686
689
  await processBackground(trigger, reqBody, FUNCTION_SIGNATURE);
687
690
  res.send({ status: "acknowledged" });
688
691
  break;
@@ -19,6 +19,7 @@ const V2_EVENTS = [
19
19
  events.v2.PUBSUB_PUBLISH_EVENT,
20
20
  ...events.v2.STORAGE_EVENTS,
21
21
  ...events.v2.DATABASE_EVENTS,
22
+ ...events.v2.FIRESTORE_EVENTS,
22
23
  ];
23
24
  exports.EVENTARC_SOURCE_ENV = "EVENTARC_CLOUD_EVENT_SOURCE";
24
25
  class HttpConstants {
@@ -110,11 +110,19 @@ class RuntimeWorker {
110
110
  }
111
111
  const proxy = http.request(reqOpts, (_resp) => {
112
112
  resp.writeHead(_resp.statusCode || 200, _resp.headers);
113
+ let finished = false;
114
+ const finishReq = (event) => {
115
+ this.logger.log("DEBUG", `Finishing up request with event=${event}`);
116
+ if (!finished) {
117
+ finished = true;
118
+ onFinish();
119
+ resolve();
120
+ }
121
+ };
122
+ _resp.on("pause", () => finishReq("pause"));
123
+ _resp.on("close", () => finishReq("close"));
113
124
  const piped = _resp.pipe(resp);
114
- piped.on("finish", () => {
115
- onFinish();
116
- resolve();
117
- });
125
+ piped.on("finish", () => finishReq("finish"));
118
126
  });
119
127
  proxy.on("timeout", () => {
120
128
  this.logger.log("ERROR", `Your function timed out after ~${this.timeoutSeconds}s. To configure this timeout, see
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.flushToDisk = exports.assertEnabled = exports.enableExperimentsFromCliEnvVariable = exports.setEnabled = exports.isEnabled = exports.experimentNameAutocorrect = exports.isValidExperiment = exports.ALL_EXPERIMENTS = void 0;
4
4
  const colorette_1 = require("colorette");
5
5
  const leven = require("leven");
6
+ const path_1 = require("path");
6
7
  const configstore_1 = require("./configstore");
7
8
  const error_1 = require("./error");
9
+ const github_1 = require("./init/features/hosting/github");
8
10
  function experiments(exp) {
9
11
  return Object.freeze(exp);
10
12
  }
@@ -25,12 +27,6 @@ exports.ALL_EXPERIMENTS = experiments({
25
27
  shortDescription: `Enables the ${(0, colorette_1.bold)("ext:dev")} family of commands`,
26
28
  docsUri: "https://firebase.google.com/docs/extensions/alpha/overview-build-extensions",
27
29
  },
28
- pythonfunctions: {
29
- shortDescription: "Python support for Cloud Functions for Firebase",
30
- fullDescription: "Adds the ability to initializea and deploy Cloud " +
31
- "Functions for Firebase in Python. While this feature is experimental " +
32
- "breaking API changes are allowed in MINOR API revisions",
33
- },
34
30
  deletegcfartifacts: {
35
31
  shortDescription: `Add the ${(0, colorette_1.bold)("functions:deletegcfartifacts")} command to purge docker build images`,
36
32
  fullDescription: `Add the ${(0, colorette_1.bold)("functions:deletegcfartifacts")}` +
@@ -123,8 +119,25 @@ function enableExperimentsFromCliEnvVariable() {
123
119
  }
124
120
  exports.enableExperimentsFromCliEnvVariable = enableExperimentsFromCliEnvVariable;
125
121
  function assertEnabled(name, task) {
122
+ var _a;
126
123
  if (!isEnabled(name)) {
127
- throw new error_1.FirebaseError(`Cannot ${task} because the experiment ${(0, colorette_1.bold)(name)} is not enabled. To enable ${(0, colorette_1.bold)(name)} run ${(0, colorette_1.bold)(`firebase experiments:enable ${name}`)}`);
124
+ const prefix = `Cannot ${task} because the experiment ${(0, colorette_1.bold)(name)} is not enabled.`;
125
+ if ((0, github_1.isRunningInGithubAction)()) {
126
+ const path = (_a = process.env.GITHUB_WORKFLOW_REF) === null || _a === void 0 ? void 0 : _a.split("@")[0];
127
+ const filename = path ? `.github/workflows/${(0, path_1.basename)(path)}` : "your action's yml";
128
+ const newValue = [process.env.FIREBASE_CLI_EXPERIMENTS, name].filter((it) => !!it).join(",");
129
+ throw new error_1.FirebaseError(`${prefix} To enable add a ${(0, colorette_1.bold)("FIREBASE_CLI_EXPERIMENTS")} environment variable to ${filename}, like so: ${(0, colorette_1.italic)(`
130
+
131
+ - uses: FirebaseExtended/action-hosting-deploy@v0
132
+ with:
133
+ ...
134
+ env:
135
+ FIREBASE_CLI_EXPERIMENTS: ${newValue}
136
+ `)}`);
137
+ }
138
+ else {
139
+ throw new error_1.FirebaseError(`${prefix} To enable ${(0, colorette_1.bold)(name)} run ${(0, colorette_1.bold)(`firebase experiments:enable ${name}`)}`);
140
+ }
128
141
  }
129
142
  }
130
143
  exports.assertEnabled = assertEnabled;
@@ -6,10 +6,10 @@ const ora = require("ora");
6
6
  const semver = require("semver");
7
7
  const tmp = require("tmp");
8
8
  const fs = require("fs-extra");
9
- const unzipper = require("unzipper");
10
9
  const node_fetch_1 = require("node-fetch");
11
10
  const path = require("path");
12
11
  const marked_1 = require("marked");
12
+ const unzip_1 = require("./../unzip");
13
13
  const TerminalRenderer = require("marked-terminal");
14
14
  marked_1.marked.setOptions({
15
15
  renderer: new TerminalRenderer(),
@@ -449,7 +449,7 @@ async function publishExtensionVersionFromRemoteRepo(args) {
449
449
  try {
450
450
  const response = await (0, node_fetch_1.default)(archiveUri);
451
451
  if (response.ok) {
452
- await response.body.pipe(unzipper.Extract({ path: tempDirectory.name })).promise();
452
+ await response.body.pipe((0, unzip_1.createUnzipTransform)(tempDirectory.name)).promise();
453
453
  }
454
454
  }
455
455
  catch (err) {
@@ -1,17 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.getDevModeHandle = exports.build = exports.init = exports.discover = exports.type = exports.support = exports.name = void 0;
3
+ exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.getDevModeHandle = exports.build = exports.init = exports.discover = exports.docsUrl = 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
6
  const cross_spawn_1 = require("cross-spawn");
7
7
  const fs_extra_1 = require("fs-extra");
8
8
  const promises_1 = require("fs/promises");
9
- const __1 = require("..");
10
9
  const prompt_1 = require("../../prompt");
11
10
  const utils_1 = require("../utils");
12
11
  exports.name = "Angular";
13
- exports.support = "experimental";
12
+ exports.support = "preview";
14
13
  exports.type = 3;
14
+ exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/angular";
15
15
  const DEFAULT_BUILD_SCRIPT = ["ng build"];
16
16
  async function discover(dir) {
17
17
  if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
@@ -42,7 +42,7 @@ async function init(setup, config) {
42
42
  }
43
43
  exports.init = init;
44
44
  async function build(dir) {
45
- const { targetStringFromTarget } = (0, __1.relativeRequire)(dir, "@angular-devkit/architect");
45
+ const { targetStringFromTarget } = (0, utils_1.relativeRequire)(dir, "@angular-devkit/architect");
46
46
  const { architect, browserTarget, prerenderTarget, serverTarget } = await getContext(dir);
47
47
  const scheduleTarget = async (target) => {
48
48
  const run = await architect.scheduleTarget(target, undefined);
@@ -54,7 +54,7 @@ async function build(dir) {
54
54
  if (!browserTarget)
55
55
  throw new Error("No build target...");
56
56
  if (prerenderTarget) {
57
- const cli = (0, __1.getNodeModuleBin)("ng", dir);
57
+ const cli = (0, utils_1.getNodeModuleBin)("ng", dir);
58
58
  (0, child_process_1.execSync)(`${cli} run ${targetStringFromTarget(prerenderTarget)}`, {
59
59
  cwd: dir,
60
60
  stdio: "inherit",
@@ -70,12 +70,12 @@ async function build(dir) {
70
70
  }
71
71
  exports.build = build;
72
72
  async function getDevModeHandle(dir) {
73
- const { targetStringFromTarget } = (0, __1.relativeRequire)(dir, "@angular-devkit/architect");
73
+ const { targetStringFromTarget } = (0, utils_1.relativeRequire)(dir, "@angular-devkit/architect");
74
74
  const { serveTarget } = await getContext(dir);
75
75
  if (!serveTarget)
76
76
  return;
77
77
  const host = new Promise((resolve) => {
78
- const cli = (0, __1.getNodeModuleBin)("ng", dir);
78
+ const cli = (0, utils_1.getNodeModuleBin)("ng", dir);
79
79
  const serve = (0, cross_spawn_1.spawn)(cli, ["run", targetStringFromTarget(serveTarget), "--host", "localhost"], {
80
80
  cwd: dir,
81
81
  });
@@ -131,7 +131,7 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
131
131
  const externalDependencies = serverTargetOptions.externalDependencies || [];
132
132
  externalDependencies.forEach((externalDependency) => {
133
133
  var _a;
134
- const packageVersion = (_a = (0, __1.findDependency)(externalDependency)) === null || _a === void 0 ? void 0 : _a.version;
134
+ const packageVersion = (_a = (0, utils_1.findDependency)(externalDependency)) === null || _a === void 0 ? void 0 : _a.version;
135
135
  if (packageVersion) {
136
136
  dependencies[externalDependency] = packageVersion;
137
137
  }
@@ -142,11 +142,11 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
142
142
  }
143
143
  exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
144
144
  async function getContext(dir) {
145
- const { NodeJsAsyncHost } = (0, __1.relativeRequire)(dir, "@angular-devkit/core/node");
146
- const { workspaces } = (0, __1.relativeRequire)(dir, "@angular-devkit/core");
147
- const { WorkspaceNodeModulesArchitectHost } = (0, __1.relativeRequire)(dir, "@angular-devkit/architect/node");
148
- const { Architect, targetFromTargetString, targetStringFromTarget } = (0, __1.relativeRequire)(dir, "@angular-devkit/architect");
149
- const { parse } = (0, __1.relativeRequire)(dir, "jsonc-parser");
145
+ const { NodeJsAsyncHost } = (0, utils_1.relativeRequire)(dir, "@angular-devkit/core/node");
146
+ const { workspaces } = (0, utils_1.relativeRequire)(dir, "@angular-devkit/core");
147
+ const { WorkspaceNodeModulesArchitectHost } = (0, utils_1.relativeRequire)(dir, "@angular-devkit/architect/node");
148
+ const { Architect, targetFromTargetString, targetStringFromTarget } = (0, utils_1.relativeRequire)(dir, "@angular-devkit/architect");
149
+ const { parse } = (0, utils_1.relativeRequire)(dir, "jsonc-parser");
150
150
  const host = workspaces.createWorkspaceHost(new NodeJsAsyncHost());
151
151
  const { workspace } = await workspaces.readWorkspace(dir, host);
152
152
  const architectHost = new WorkspaceNodeModulesArchitectHost(workspace, dir);
@@ -4,7 +4,6 @@ exports.getDevModeHandle = exports.ɵcodegenFunctionsDirectory = exports.ɵcodeg
4
4
  const cross_spawn_1 = require("cross-spawn");
5
5
  const fs_extra_1 = require("fs-extra");
6
6
  const path_1 = require("path");
7
- const __1 = require("..");
8
7
  const error_1 = require("../../error");
9
8
  const utils_1 = require("../utils");
10
9
  const utils_2 = require("./utils");
@@ -13,7 +12,7 @@ exports.support = "experimental";
13
12
  exports.type = 2;
14
13
  function getAstroVersion(cwd) {
15
14
  var _a;
16
- return (_a = (0, __1.findDependency)("astro", { cwd, depth: 0, omitDev: false })) === null || _a === void 0 ? void 0 : _a.version;
15
+ return (_a = (0, utils_1.findDependency)("astro", { cwd, depth: 0, omitDev: false })) === null || _a === void 0 ? void 0 : _a.version;
17
16
  }
18
17
  async function discover(dir) {
19
18
  if (!(0, fs_extra_1.existsSync)((0, path_1.join)(dir, "package.json")))
@@ -29,7 +28,7 @@ async function discover(dir) {
29
28
  exports.discover = discover;
30
29
  const DEFAULT_BUILD_SCRIPT = ["astro build"];
31
30
  async function build(cwd) {
32
- const cli = (0, __1.getNodeModuleBin)("astro", cwd);
31
+ const cli = (0, utils_1.getNodeModuleBin)("astro", cwd);
33
32
  await (0, utils_1.warnIfCustomBuildScript)(cwd, exports.name, DEFAULT_BUILD_SCRIPT);
34
33
  const { output, adapter } = await (0, utils_2.getConfig)(cwd);
35
34
  if (output === "server" && (adapter === null || adapter === void 0 ? void 0 : adapter.name) !== "@astrojs/node") {
@@ -59,7 +58,7 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
59
58
  exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
60
59
  async function getDevModeHandle(cwd) {
61
60
  const host = new Promise((resolve) => {
62
- const cli = (0, __1.getNodeModuleBin)("astro", cwd);
61
+ const cli = (0, utils_1.getNodeModuleBin)("astro", cwd);
63
62
  const serve = (0, cross_spawn_1.spawn)(cli, ["dev"], { cwd });
64
63
  serve.stdout.on("data", (data) => {
65
64
  process.stdout.write(data);
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebFrameworks = exports.ALLOWED_SSR_REGIONS = exports.DEFAULT_REGION = exports.VALID_ENGINES = exports.NODE_VERSION = exports.FIREBASE_ADMIN_VERSION = exports.FIREBASE_FUNCTIONS_VERSION = exports.FIREBASE_FRAMEWORKS_VERSION = exports.MAILING_LIST_URL = exports.FEATURE_REQUEST_URL = exports.FILE_BUG_URL = exports.DEFAULT_DOCS_URL = exports.SupportLevelWarnings = exports.NPM_COMMAND_TIMEOUT_MILLIES = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const clc = require("colorette");
7
+ exports.NPM_COMMAND_TIMEOUT_MILLIES = 10000;
8
+ exports.SupportLevelWarnings = {
9
+ ["experimental"]: (framework) => `Thank you for trying our ${clc.italic("experimental")} support for ${framework} on Firebase Hosting.
10
+ ${clc.yellow(`While this integration is maintained by Googlers it is not a supported Firebase product.
11
+ Issues filed on GitHub will be addressed on a best-effort basis by maintainers and other community members.`)}`,
12
+ ["preview"]: (framework) => `Thank you for trying our ${clc.italic("early preview")} of ${framework} support on Firebase Hosting.
13
+ ${clc.yellow("During the preview, support is best-effort and breaking changes can be expected. Proceed with caution.")}`,
14
+ };
15
+ exports.DEFAULT_DOCS_URL = "https://firebase.google.com/docs/hosting/frameworks/frameworks-overview";
16
+ exports.FILE_BUG_URL = "https://github.com/firebase/firebase-tools/issues/new?template=bug_report.md";
17
+ exports.FEATURE_REQUEST_URL = "https://github.com/firebase/firebase-tools/issues/new?template=feature_request.md";
18
+ exports.MAILING_LIST_URL = "https://goo.gle/41enW5X";
19
+ exports.FIREBASE_FRAMEWORKS_VERSION = "^0.9.0";
20
+ exports.FIREBASE_FUNCTIONS_VERSION = "^4.3.0";
21
+ exports.FIREBASE_ADMIN_VERSION = "^11.0.1";
22
+ exports.NODE_VERSION = parseInt(process.versions.node, 10);
23
+ exports.VALID_ENGINES = { node: [16, 18] };
24
+ exports.DEFAULT_REGION = "us-central1";
25
+ exports.ALLOWED_SSR_REGIONS = [
26
+ { name: "us-central1 (Iowa)", value: "us-central1" },
27
+ { name: "us-west1 (Oregon)", value: "us-west1" },
28
+ { name: "us-east1 (South Carolina)", value: "us-east1" },
29
+ { name: "europe-west1 (Belgium)", value: "europe-west1" },
30
+ { name: "asia-east1 (Taiwan)", value: "asia-east1" },
31
+ ];
32
+ exports.WebFrameworks = Object.fromEntries((0, fs_1.readdirSync)(__dirname)
33
+ .filter((path) => (0, fs_1.statSync)((0, path_1.join)(__dirname, path)).isDirectory())
34
+ .map((path) => {
35
+ try {
36
+ return [path, require((0, path_1.join)(__dirname, path))];
37
+ }
38
+ catch (e) {
39
+ return [];
40
+ }
41
+ })
42
+ .filter(([, obj]) => obj && obj.name && obj.discover && obj.build && obj.type !== undefined && obj.support));
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.type = exports.support = exports.name = void 0;
3
+ exports.ɵcodegenFunctionsDirectory = exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.docsUrl = exports.type = exports.support = exports.name = void 0;
4
4
  const child_process_1 = require("child_process");
5
5
  const fs_extra_1 = require("fs-extra");
6
6
  const promises_1 = require("fs/promises");
7
7
  const path_1 = require("path");
8
8
  const { dynamicImport } = require(true && "../../dynamicImport");
9
9
  exports.name = "Express.js";
10
- exports.support = "experimental";
10
+ exports.support = "preview";
11
11
  exports.type = 0;
12
+ exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/express";
12
13
  async function getConfig(root) {
13
14
  var _a, _b;
14
15
  const packageJsonBuffer = await (0, promises_1.readFile)((0, path_1.join)(root, "package.json"));
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ɵcodegenPublicDirectory = exports.build = exports.discover = exports.support = exports.type = exports.name = void 0;
4
+ const cross_spawn_1 = require("cross-spawn");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const path_1 = require("path");
7
+ const js_yaml_1 = require("js-yaml");
8
+ const promises_1 = require("fs/promises");
9
+ const error_1 = require("../../error");
10
+ const utils_1 = require("./utils");
11
+ exports.name = "Flutter";
12
+ exports.type = 3;
13
+ exports.support = "experimental";
14
+ async function discover(dir) {
15
+ var _a;
16
+ if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "pubspec.yaml"))))
17
+ return;
18
+ if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "web"))))
19
+ return;
20
+ const pubSpecBuffer = await (0, promises_1.readFile)((0, path_1.join)(dir, "pubspec.yaml"));
21
+ const pubSpec = (0, js_yaml_1.load)(pubSpecBuffer.toString());
22
+ const usingFlutter = (_a = pubSpec.dependencies) === null || _a === void 0 ? void 0 : _a.flutter;
23
+ if (!usingFlutter)
24
+ return;
25
+ return { mayWantBackend: false, publicDirectory: (0, path_1.join)(dir, "web") };
26
+ }
27
+ exports.discover = discover;
28
+ function build(cwd) {
29
+ (0, utils_1.assertFlutterCliExists)();
30
+ const build = (0, cross_spawn_1.sync)("flutter", ["build", "web"], { cwd, stdio: "inherit" });
31
+ if (build.status)
32
+ throw new error_1.FirebaseError("Unable to build your Flutter app");
33
+ return Promise.resolve({ wantsBackend: false });
34
+ }
35
+ exports.build = build;
36
+ async function ɵcodegenPublicDirectory(sourceDir, destDir) {
37
+ await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, "build", "web"), destDir);
38
+ }
39
+ exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertFlutterCliExists = void 0;
4
+ const cross_spawn_1 = require("cross-spawn");
5
+ const error_1 = require("../../error");
6
+ function assertFlutterCliExists() {
7
+ const process = (0, cross_spawn_1.sync)("flutter", ["--version"], { stdio: "ignore" });
8
+ if (process.status)
9
+ throw new error_1.FirebaseError("Flutter CLI not found.");
10
+ }
11
+ exports.assertFlutterCliExists = assertFlutterCliExists;