firebase-tools 12.4.0 → 12.4.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 (49) hide show
  1. package/lib/api/frameworks.js +21 -0
  2. package/lib/api.js +4 -2
  3. package/lib/auth.js +3 -3
  4. package/lib/command.js +15 -4
  5. package/lib/commands/ext-install.js +10 -4
  6. package/lib/commands/index.js +2 -0
  7. package/lib/commands/init.js +8 -0
  8. package/lib/commands/internaltesting-frameworks-init.js +14 -0
  9. package/lib/config.js +1 -0
  10. package/lib/deploy/extensions/prepare.js +1 -0
  11. package/lib/deploy/extensions/release.js +11 -1
  12. package/lib/deploy/functions/checkIam.js +4 -1
  13. package/lib/deploy/functions/prepare.js +2 -1
  14. package/lib/deploy/functions/runtimes/discovery/index.js +6 -0
  15. package/lib/deploy/functions/runtimes/node/index.js +12 -4
  16. package/lib/deploy/functions/runtimes/python/index.js +19 -25
  17. package/lib/deploy/hosting/deploy.js +0 -6
  18. package/lib/deploy/hosting/prepare.js +7 -1
  19. package/lib/deploy/index.js +11 -4
  20. package/lib/deploy/lifecycleHooks.js +3 -0
  21. package/lib/detectProjectRoot.js +4 -1
  22. package/lib/dynamicImport.js +11 -1
  23. package/lib/emulator/commandUtils.js +4 -4
  24. package/lib/emulator/controller.js +9 -7
  25. package/lib/emulator/downloadableEmulators.js +3 -3
  26. package/lib/emulator/functionsEmulator.js +1 -2
  27. package/lib/emulator/storage/index.js +6 -0
  28. package/lib/emulator/storage/rules/manager.js +0 -4
  29. package/lib/emulator/storage/server.js +52 -0
  30. package/lib/ensureApiEnabled.js +3 -1
  31. package/lib/experiments.js +5 -0
  32. package/lib/extensions/paramHelper.js +0 -5
  33. package/lib/frameworks/constants.js +2 -15
  34. package/lib/frameworks/index.js +13 -8
  35. package/lib/frameworks/utils.js +50 -20
  36. package/lib/functionsConfig.js +2 -2
  37. package/lib/gcp/cloudbuild.js +50 -0
  38. package/lib/init/features/composer/repo.js +121 -0
  39. package/lib/init/features/frameworks/constants.js +7 -0
  40. package/lib/init/features/frameworks/index.js +36 -0
  41. package/lib/init/features/index.js +3 -1
  42. package/lib/init/index.js +4 -0
  43. package/lib/management/projects.js +5 -1
  44. package/lib/monospace/index.js +7 -7
  45. package/lib/requireAuth.js +1 -1
  46. package/lib/track.js +91 -52
  47. package/lib/utils.js +6 -1
  48. package/package.json +1 -1
  49. package/schema/extension-yaml.json +432 -0
@@ -23,9 +23,9 @@ const EMULATOR_UPDATE_DETAILS = {
23
23
  expectedChecksum: "2fd771101c0e1f7898c04c9204f2ce63",
24
24
  },
25
25
  firestore: {
26
- version: "1.17.4",
27
- expectedSize: 64969580,
28
- expectedChecksum: "9d580b58e55e57b0cdc3ca8888098d43",
26
+ version: "1.18.1",
27
+ expectedSize: 64866257,
28
+ expectedChecksum: "743211a3e33217fe71dc20aff1fa26a5",
29
29
  },
30
30
  storage: {
31
31
  version: "1.1.3",
@@ -36,7 +36,6 @@ const v1_1 = require("../functions/events/v1");
36
36
  const build_1 = require("../deploy/functions/build");
37
37
  const env_1 = require("./env");
38
38
  const python_1 = require("../functions/python");
39
- const EVENT_INVOKE = "functions:invoke";
40
39
  const EVENT_INVOKE_GA4 = "functions_invoke";
41
40
  const DATABASE_PATH_PATTERN = new RegExp("^projects/[^/]+/instances/([^/]+)/refs(/.*)$");
42
41
  class IPCConn {
@@ -754,6 +753,7 @@ class FunctionsEmulator {
754
753
  envs.GCLOUD_PROJECT = this.args.projectId;
755
754
  envs.K_REVISION = "1";
756
755
  envs.PORT = "80";
756
+ envs.GOOGLE_CLOUD_QUOTA_PROJECT = this.args.projectId;
757
757
  if (trigger) {
758
758
  const target = trigger.entryPoint;
759
759
  envs.FUNCTION_TARGET = target;
@@ -1003,7 +1003,6 @@ class FunctionsEmulator {
1003
1003
  req.headers[functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER] = encodeURIComponent(JSON.stringify(contextAuth));
1004
1004
  }
1005
1005
  }
1006
- void (0, track_1.track)(EVENT_INVOKE, (0, functionsEmulatorShared_1.getFunctionService)(trigger));
1007
1006
  void (0, track_1.trackEmulator)(EVENT_INVOKE_GA4, {
1008
1007
  function_service: (0, functionsEmulatorShared_1.getFunctionService)(trigger),
1009
1008
  });
@@ -64,6 +64,7 @@ class StorageEmulator {
64
64
  }
65
65
  async stop() {
66
66
  await this._persistence.deleteAll();
67
+ await this._rulesRuntime.stop();
67
68
  await this._rulesManager.stop();
68
69
  return this.destroyServer ? this.destroyServer() : Promise.resolve();
69
70
  }
@@ -85,6 +86,11 @@ class StorageEmulator {
85
86
  createRulesManager(rules) {
86
87
  return (0, manager_1.createStorageRulesManager)(rules, this._rulesRuntime);
87
88
  }
89
+ async replaceRules(rules) {
90
+ await this._rulesManager.stop();
91
+ this._rulesManager = this.createRulesManager(rules);
92
+ return this._rulesManager.start();
93
+ }
88
94
  getPersistenceTmpDir() {
89
95
  return `${(0, os_1.tmpdir)()}/firebase/storage/blobs`;
90
96
  }
@@ -20,7 +20,6 @@ class DefaultStorageRulesManager {
20
20
  this._rules = _rules;
21
21
  }
22
22
  async start() {
23
- this._runtime.start();
24
23
  const issues = await this.loadRuleset();
25
24
  this.updateWatcher(this._rules.name);
26
25
  return issues;
@@ -30,9 +29,6 @@ class DefaultStorageRulesManager {
30
29
  }
31
30
  async stop() {
32
31
  await this._watcher.close();
33
- if (this._runtime.alive) {
34
- await this._runtime.stop();
35
- }
36
32
  }
37
33
  updateWatcher(rulesFile) {
38
34
  this._watcher = chokidar
@@ -8,6 +8,7 @@ const types_1 = require("../types");
8
8
  const bodyParser = require("body-parser");
9
9
  const gcloud_1 = require("./apis/gcloud");
10
10
  const firebase_1 = require("./apis/firebase");
11
+ const errors_1 = require("../auth/errors");
11
12
  function createApp(defaultProjectId, emulator) {
12
13
  const { storageLayer } = emulator;
13
14
  const app = express();
@@ -50,6 +51,54 @@ function createApp(defaultProjectId, emulator) {
50
51
  await storageLayer.export(path, { initiatedBy });
51
52
  res.sendStatus(200);
52
53
  });
54
+ app.put("/internal/setRules", async (req, res) => {
55
+ const rulesRaw = req.body.rules;
56
+ if (!(rulesRaw && Array.isArray(rulesRaw.files) && rulesRaw.files.length > 0)) {
57
+ res.status(400).json({
58
+ message: "Request body must include 'rules.files' array",
59
+ });
60
+ return;
61
+ }
62
+ const { files } = rulesRaw;
63
+ function parseRulesFromFiles(files) {
64
+ if (files.length === 1) {
65
+ const file = files[0];
66
+ if (!isRulesFile(file)) {
67
+ throw new errors_1.InvalidArgumentError("Each member of 'rules.files' array must contain 'name' and 'content'");
68
+ }
69
+ return { name: file.name, content: file.content };
70
+ }
71
+ const rules = [];
72
+ for (const file of files) {
73
+ if (!isRulesFile(file) || !file.resource) {
74
+ throw new errors_1.InvalidArgumentError("Each member of 'rules.files' array must contain 'name', 'content', and 'resource'");
75
+ }
76
+ rules.push({ resource: file.resource, rules: { name: file.name, content: file.content } });
77
+ }
78
+ return rules;
79
+ }
80
+ let rules;
81
+ try {
82
+ rules = parseRulesFromFiles(files);
83
+ }
84
+ catch (err) {
85
+ if (err instanceof errors_1.InvalidArgumentError) {
86
+ res.status(400).json({ message: err.message });
87
+ return;
88
+ }
89
+ throw err;
90
+ }
91
+ const issues = await emulator.replaceRules(rules);
92
+ if (issues.errors.length > 0) {
93
+ res.status(400).json({
94
+ message: "There was an error updating rules, see logs for more details",
95
+ });
96
+ return;
97
+ }
98
+ res.status(200).json({
99
+ message: "Rules updated successfully",
100
+ });
101
+ });
53
102
  app.post("/internal/reset", (req, res) => {
54
103
  emulator.reset();
55
104
  res.sendStatus(200);
@@ -59,3 +108,6 @@ function createApp(defaultProjectId, emulator) {
59
108
  return Promise.resolve(app);
60
109
  }
61
110
  exports.createApp = createApp;
111
+ function isRulesFile(file) {
112
+ return (typeof file.name === "string" && typeof file.content === "string");
113
+ }
@@ -52,7 +52,9 @@ async function pollCheckEnabled(projectId, apiName, prefix, silent, enablementRe
52
52
  });
53
53
  const isEnabled = await check(projectId, apiName, prefix, silent);
54
54
  if (isEnabled) {
55
- void (0, track_1.track)("api_enabled", apiName);
55
+ void (0, track_1.trackGA4)("api_enabled", {
56
+ api_name: apiName,
57
+ });
56
58
  return;
57
59
  }
58
60
  if (!silent) {
@@ -72,6 +72,11 @@ exports.ALL_EXPERIMENTS = experiments({
72
72
  "These commands are not meant for public consumption and may break or disappear " +
73
73
  "without a notice.",
74
74
  },
75
+ frameworks: {
76
+ shortDescription: "Allow CLI option for Frameworks",
77
+ default: true,
78
+ public: false,
79
+ },
75
80
  });
76
81
  function isValidExperiment(name) {
77
82
  return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
@@ -8,7 +8,6 @@ const error_1 = require("../error");
8
8
  const logger_1 = require("../logger");
9
9
  const extensionsHelper_1 = require("./extensionsHelper");
10
10
  const askUserForParam = require("./askUserForParam");
11
- const track_1 = require("../track");
12
11
  const env = require("../functions/env");
13
12
  const utils_1 = require("../utils");
14
13
  const NONINTERACTIVE_ERROR_MESSAGE = "As of firebase-tools@11, `ext:install`, `ext:update` and `ext:configure` are interactive only commands. " +
@@ -61,8 +60,6 @@ async function getParams(args) {
61
60
  reconfiguring: !!args.reconfiguring,
62
61
  });
63
62
  }
64
- const paramNames = Object.keys(params);
65
- void (0, track_1.track)("Extension Params", paramNames.length ? "Not Present" : "Present", paramNames.length);
66
63
  return params;
67
64
  }
68
65
  exports.getParams = getParams;
@@ -80,8 +77,6 @@ async function getParamsForUpdate(args) {
80
77
  instanceId: args.instanceId,
81
78
  });
82
79
  }
83
- const paramNames = Object.keys(params);
84
- void (0, track_1.track)("Extension Params", paramNames.length ? "Not Present" : "Present", paramNames.length);
85
80
  return params;
86
81
  }
87
82
  exports.getParamsForUpdate = getParamsForUpdate;
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_SHOULD_USE_DEV_MODE_HANDLE = exports.GET_DEFAULT_BUILD_TARGETS = exports.WebFrameworks = exports.I18N_ROOT = exports.ALLOWED_SSR_REGIONS = exports.DEFAULT_REGION = exports.VALID_LOCALE_FORMATS = exports.VALID_ENGINES = exports.NODE_VERSION = exports.SHARP_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");
3
+ exports.DEFAULT_SHOULD_USE_DEV_MODE_HANDLE = exports.GET_DEFAULT_BUILD_TARGETS = exports.I18N_ROOT = exports.ALLOWED_SSR_REGIONS = exports.DEFAULT_REGION = exports.VALID_LOCALE_FORMATS = exports.VALID_ENGINES = exports.NODE_VERSION = exports.SHARP_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;
6
4
  const clc = require("colorette");
7
5
  exports.NPM_COMMAND_TIMEOUT_MILLIES = 10000;
8
6
  exports.SupportLevelWarnings = {
@@ -16,7 +14,7 @@ exports.DEFAULT_DOCS_URL = "https://firebase.google.com/docs/hosting/frameworks/
16
14
  exports.FILE_BUG_URL = "https://github.com/firebase/firebase-tools/issues/new?template=bug_report.md";
17
15
  exports.FEATURE_REQUEST_URL = "https://github.com/firebase/firebase-tools/issues/new?template=feature_request.md";
18
16
  exports.MAILING_LIST_URL = "https://goo.gle/41enW5X";
19
- exports.FIREBASE_FRAMEWORKS_VERSION = "^0.10.1";
17
+ exports.FIREBASE_FRAMEWORKS_VERSION = "^0.10.4";
20
18
  exports.FIREBASE_FUNCTIONS_VERSION = "^4.3.0";
21
19
  exports.FIREBASE_ADMIN_VERSION = "^11.0.1";
22
20
  exports.SHARP_VERSION = "^0.32.1";
@@ -32,17 +30,6 @@ exports.ALLOWED_SSR_REGIONS = [
32
30
  { name: "asia-east1 (Taiwan)", value: "asia-east1" },
33
31
  ];
34
32
  exports.I18N_ROOT = "/";
35
- exports.WebFrameworks = Object.fromEntries((0, fs_1.readdirSync)(__dirname)
36
- .filter((path) => (0, fs_1.statSync)((0, path_1.join)(__dirname, path)).isDirectory())
37
- .map((path) => {
38
- try {
39
- return [path, require((0, path_1.join)(__dirname, path))];
40
- }
41
- catch (e) {
42
- return [];
43
- }
44
- })
45
- .filter(([, obj]) => obj && obj.name && obj.discover && obj.build && obj.type !== undefined && obj.support));
46
33
  function GET_DEFAULT_BUILD_TARGETS() {
47
34
  return Promise.resolve(["production", "development"]);
48
35
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prepareFrameworks = exports.discover = exports.WebFrameworks = void 0;
3
+ exports.prepareFrameworks = exports.generateSSRCodebaseId = exports.discover = exports.WebFrameworks = void 0;
4
4
  const path_1 = require("path");
5
5
  const process_1 = require("process");
6
6
  const child_process_1 = require("child_process");
@@ -25,21 +25,22 @@ const experiments = require("../experiments");
25
25
  const implicitInit_1 = require("../hosting/implicitInit");
26
26
  const utils_1 = require("./utils");
27
27
  const constants_2 = require("./constants");
28
- Object.defineProperty(exports, "WebFrameworks", { enumerable: true, get: function () { return constants_2.WebFrameworks; } });
29
28
  const utils_2 = require("../utils");
30
29
  const ensureTargeted_1 = require("../functions/ensureTargeted");
31
30
  const util_1 = require("util");
32
31
  const projectPath_1 = require("../projectPath");
33
32
  const logger_1 = require("../logger");
33
+ const frameworks_1 = require("./frameworks");
34
+ Object.defineProperty(exports, "WebFrameworks", { enumerable: true, get: function () { return frameworks_1.WebFrameworks; } });
34
35
  async function discover(dir, warn = true) {
35
36
  const allFrameworkTypes = [
36
- ...new Set(Object.values(constants_2.WebFrameworks).map(({ type }) => type)),
37
+ ...new Set(Object.values(frameworks_1.WebFrameworks).map(({ type }) => type)),
37
38
  ].sort();
38
39
  for (const discoveryType of allFrameworkTypes) {
39
40
  const frameworksDiscovered = [];
40
- for (const framework in constants_2.WebFrameworks) {
41
- if (constants_2.WebFrameworks[framework]) {
42
- const { discover, type } = constants_2.WebFrameworks[framework];
41
+ for (const framework in frameworks_1.WebFrameworks) {
42
+ if (frameworks_1.WebFrameworks[framework]) {
43
+ const { discover, type } = frameworks_1.WebFrameworks[framework];
43
44
  if (type !== discoveryType)
44
45
  continue;
45
46
  const result = await discover(dir);
@@ -72,6 +73,10 @@ function memoizeBuild(dir, build, deps, target) {
72
73
  BUILD_MEMO.set(key, value);
73
74
  return value;
74
75
  }
76
+ function generateSSRCodebaseId(site) {
77
+ return `firebase-frameworks-${site}`;
78
+ }
79
+ exports.generateSSRCodebaseId = generateSSRCodebaseId;
75
80
  async function prepareFrameworks(purpose, targetNames, context, options, emulators = []) {
76
81
  var _a, _b, _c, _d, _e, _f;
77
82
  var _g, _h, _j, _k, _l;
@@ -185,7 +190,7 @@ async function prepareFrameworks(purpose, targetNames, context, options, emulato
185
190
  throw new error_1.FirebaseError((0, utils_1.frameworksCallToAction)("Unable to detect the web framework in use, check firebase-debug.log for more info."));
186
191
  }
187
192
  const { framework, mayWantBackend, publicDirectory } = results;
188
- const { build, ɵcodegenPublicDirectory, ɵcodegenFunctionsDirectory: codegenProdModeFunctionsDirectory, getDevModeHandle, name, support, docsUrl, getValidBuildTargets = constants_2.GET_DEFAULT_BUILD_TARGETS, shouldUseDevModeHandle = constants_2.DEFAULT_SHOULD_USE_DEV_MODE_HANDLE, } = constants_2.WebFrameworks[framework];
193
+ const { build, ɵcodegenPublicDirectory, ɵcodegenFunctionsDirectory: codegenProdModeFunctionsDirectory, getDevModeHandle, name, support, docsUrl, getValidBuildTargets = constants_2.GET_DEFAULT_BUILD_TARGETS, shouldUseDevModeHandle = constants_2.DEFAULT_SHOULD_USE_DEV_MODE_HANDLE, } = frameworks_1.WebFrameworks[framework];
189
194
  logger_1.logger.info(`\n${(0, utils_1.frameworksCallToAction)(constants_2.SupportLevelWarnings[support](name), docsUrl, " ")}\n`);
190
195
  const hostingEmulatorInfo = emulators.find((e) => e.name === types_1.Emulators.HOSTING);
191
196
  const validBuildTargets = await getValidBuildTargets(purpose, getProjectPath());
@@ -242,7 +247,7 @@ async function prepareFrameworks(purpose, targetNames, context, options, emulato
242
247
  if (context === null || context === void 0 ? void 0 : context.hostingChannel) {
243
248
  experiments.assertEnabled("pintags", "deploy an app that requires a backend to a preview channel");
244
249
  }
245
- const codebase = `firebase-frameworks-${site}`;
250
+ const codebase = generateSSRCodebaseId(site);
246
251
  const existingFunctionsConfig = options.config.get("functions")
247
252
  ? [].concat(options.config.get("functions"))
248
253
  : [];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFrameworksBuildTarget = exports.validateLocales = exports.frameworksCallToAction = exports.conjoinOptions = exports.relativeRequire = exports.findDependency = exports.getNodeModuleBin = exports.getNpmRoot = exports.simpleProxy = exports.warnIfCustomBuildScript = exports.readJSON = exports.isUrl = void 0;
3
+ exports.getFrameworksBuildTarget = exports.validateLocales = exports.frameworksCallToAction = exports.conjoinOptions = exports.relativeRequire = exports.findDependency = exports.getNodeModuleBin = exports.getNpmRoot = exports.simpleProxy = exports.proxyResponse = exports.warnIfCustomBuildScript = exports.readJSON = exports.isUrl = void 0;
4
4
  const fs_extra_1 = require("fs-extra");
5
5
  const path_1 = require("path");
6
6
  const promises_1 = require("fs/promises");
@@ -32,21 +32,51 @@ async function warnIfCustomBuildScript(dir, framework, defaultBuildScripts) {
32
32
  }
33
33
  }
34
34
  exports.warnIfCustomBuildScript = warnIfCustomBuildScript;
35
- function proxyResponse(original, next) {
36
- return (response) => {
37
- const { statusCode, statusMessage } = response;
38
- if (!statusCode) {
39
- original.end();
40
- return;
41
- }
42
- if (statusCode === 404) {
43
- return next();
44
- }
45
- const headers = "getHeaders" in response ? response.getHeaders() : response.headers;
46
- original.writeHead(statusCode, statusMessage, headers);
47
- response.pipe(original);
48
- };
35
+ function proxyResponse(req, res, next) {
36
+ const proxiedRes = new http_1.ServerResponse(req);
37
+ const buffer = [];
38
+ proxiedRes.write = new Proxy(proxiedRes.write.bind(proxiedRes), {
39
+ apply: (target, thisArg, args) => {
40
+ target.call(thisArg, ...args);
41
+ buffer.push(["write", args]);
42
+ },
43
+ });
44
+ proxiedRes.setHeader = new Proxy(proxiedRes.setHeader.bind(proxiedRes), {
45
+ apply: (target, thisArg, args) => {
46
+ target.call(thisArg, ...args);
47
+ buffer.push(["setHeader", args]);
48
+ },
49
+ });
50
+ proxiedRes.removeHeader = new Proxy(proxiedRes.removeHeader.bind(proxiedRes), {
51
+ apply: (target, thisArg, args) => {
52
+ target.call(thisArg, ...args);
53
+ buffer.push(["removeHeader", args]);
54
+ },
55
+ });
56
+ proxiedRes.writeHead = new Proxy(proxiedRes.writeHead.bind(proxiedRes), {
57
+ apply: (target, thisArg, args) => {
58
+ target.call(thisArg, ...args);
59
+ buffer.push(["writeHead", args]);
60
+ },
61
+ });
62
+ proxiedRes.end = new Proxy(proxiedRes.end.bind(proxiedRes), {
63
+ apply: (target, thisArg, args) => {
64
+ target.call(thisArg, ...args);
65
+ if (proxiedRes.statusCode === 404) {
66
+ next();
67
+ }
68
+ else {
69
+ for (const [fn, args] of buffer) {
70
+ res[fn](...args);
71
+ }
72
+ res.end(...args);
73
+ buffer.length = 0;
74
+ }
75
+ },
76
+ });
77
+ return proxiedRes;
49
78
  }
79
+ exports.proxyResponse = proxyResponse;
50
80
  function simpleProxy(hostOrRequestHandler) {
51
81
  const agent = new http_1.Agent({ keepAlive: true });
52
82
  const firebaseDefaultsJSON = process.env.__FIREBASE_DEFAULTS__;
@@ -91,9 +121,8 @@ function simpleProxy(hostOrRequestHandler) {
91
121
  });
92
122
  }
93
123
  else {
94
- await Promise.resolve(hostOrRequestHandler(originalReq, originalRes, next));
95
- const proxiedRes = new http_1.ServerResponse(originalReq);
96
- proxyResponse(originalRes, next)(proxiedRes);
124
+ const proxiedRes = proxyResponse(originalReq, originalRes, next);
125
+ await hostOrRequestHandler(originalReq, proxiedRes, next);
97
126
  }
98
127
  };
99
128
  }
@@ -153,12 +182,13 @@ function findDependency(name, options = {}) {
153
182
  exports.findDependency = findDependency;
154
183
  function relativeRequire(dir, mod) {
155
184
  try {
156
- const path = require.resolve(mod, { paths: [dir] });
185
+ const requireFunc = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
186
+ const path = requireFunc.resolve(mod, { paths: [dir] });
157
187
  if ((0, path_1.extname)(path) === ".mjs") {
158
188
  return dynamicImport((0, url_1.pathToFileURL)(path).toString());
159
189
  }
160
190
  else {
161
- return require(path);
191
+ return requireFunc(path);
162
192
  }
163
193
  }
164
194
  catch (e) {
@@ -82,7 +82,7 @@ exports.setVariablesRecursive = setVariablesRecursive;
82
82
  async function materializeConfig(configName, output) {
83
83
  const materializeVariable = async function (varName) {
84
84
  const variable = await runtimeconfig.variables.get(varName);
85
- const id = exports.varNameToIds(variable.name);
85
+ const id = varNameToIds(variable.name);
86
86
  const key = id.config + "." + id.variable.split("/").join(".");
87
87
  _.set(output, key, variable.text);
88
88
  };
@@ -106,7 +106,7 @@ async function materializeAll(projectId) {
106
106
  if (config.name.match(new RegExp("configs/firebase"))) {
107
107
  return;
108
108
  }
109
- return exports.materializeConfig(config.name, output);
109
+ return materializeConfig(config.name, output);
110
110
  }));
111
111
  return output;
112
112
  }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteRepository = exports.getRepository = exports.createRepository = exports.fetchLinkableRepositories = exports.deleteConnection = exports.getConnection = exports.createConnection = void 0;
4
+ const apiv2_1 = require("../apiv2");
5
+ const api_1 = require("../api");
6
+ const client = new apiv2_1.Client({
7
+ urlPrefix: api_1.cloudbuildOrigin,
8
+ auth: true,
9
+ apiVersion: "v2",
10
+ });
11
+ async function createConnection(projectId, location, connectionId) {
12
+ const res = await client.post(`projects/${projectId}/locations/${location}/connections`, { githubConfig: {} }, { queryParams: { connectionId } });
13
+ return res.body;
14
+ }
15
+ exports.createConnection = createConnection;
16
+ async function getConnection(projectId, location, connectionId) {
17
+ const name = `projects/${projectId}/locations/${location}/connections/${connectionId}`;
18
+ const res = await client.get(name);
19
+ return res.body;
20
+ }
21
+ exports.getConnection = getConnection;
22
+ async function deleteConnection(projectId, location, connectionId) {
23
+ const name = `projects/${projectId}/locations/${location}/connections/${connectionId}`;
24
+ const res = await client.delete(name);
25
+ return res.body;
26
+ }
27
+ exports.deleteConnection = deleteConnection;
28
+ async function fetchLinkableRepositories(projectId, location, connectionId) {
29
+ const name = `projects/${projectId}/locations/${location}/connections/${connectionId}:fetchLinkableRepositories`;
30
+ const res = await client.get(name);
31
+ return res.body;
32
+ }
33
+ exports.fetchLinkableRepositories = fetchLinkableRepositories;
34
+ async function createRepository(projectId, location, connectionId, repositoryId, remoteUri) {
35
+ const res = await client.post(`projects/${projectId}/locations/${location}/connections/${connectionId}/repositories`, { remoteUri }, { queryParams: { repositoryId } });
36
+ return res.body;
37
+ }
38
+ exports.createRepository = createRepository;
39
+ async function getRepository(projectId, location, connectionId, repositoryId) {
40
+ const name = `projects/${projectId}/locations/${location}/connections/${connectionId}/repositories/${repositoryId}`;
41
+ const res = await client.get(name);
42
+ return res.body;
43
+ }
44
+ exports.getRepository = getRepository;
45
+ async function deleteRepository(projectId, location, connectionId, repositoryId) {
46
+ const name = `projects/${projectId}/locations/${location}/connections/${connectionId}/repositories/${repositoryId}`;
47
+ const res = await client.delete(name);
48
+ return res.body;
49
+ }
50
+ exports.deleteRepository = deleteRepository;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOrCreateRepository = exports.getOrCreateConnection = exports.linkGitHubRepository = void 0;
4
+ const api_1 = require("../../../api");
5
+ const error_1 = require("../../../error");
6
+ const gcb = require("../../../gcp/cloudbuild");
7
+ const logger_1 = require("../../../logger");
8
+ const poller = require("../../../operation-poller");
9
+ const utils = require("../../../utils");
10
+ const prompt_1 = require("../../../prompt");
11
+ const gcbPollerOptions = {
12
+ apiOrigin: api_1.cloudbuildOrigin,
13
+ apiVersion: "v2",
14
+ masterTimeout: 25 * 60 * 1000,
15
+ maxBackoff: 10000,
16
+ };
17
+ function extractRepoSlugFromURI(remoteUri) {
18
+ const match = /github.com\/(.+).git/.exec(remoteUri);
19
+ if (!match) {
20
+ return undefined;
21
+ }
22
+ return match[1];
23
+ }
24
+ function generateConnectionId(stackId) {
25
+ return `composer-${stackId}-conn`;
26
+ }
27
+ function generateRepositoryId() {
28
+ return `composer-repo`;
29
+ }
30
+ async function linkGitHubRepository(projectId, location, stackId) {
31
+ const connectionId = generateConnectionId(stackId);
32
+ await getOrCreateConnection(projectId, location, connectionId);
33
+ let remoteUri = await promptRepositoryURI(projectId, location, connectionId);
34
+ while (remoteUri === "") {
35
+ await utils.openInBrowser("https://github.com/apps/google-cloud-build/installations/new");
36
+ await (0, prompt_1.promptOnce)({
37
+ type: "input",
38
+ message: "Press any key once you have finished configuring your installation's access settings.",
39
+ });
40
+ remoteUri = await promptRepositoryURI(projectId, location, connectionId);
41
+ }
42
+ const repo = await getOrCreateRepository(projectId, location, connectionId, remoteUri);
43
+ logger_1.logger.info(`Successfully linked GitHub repository at remote URI ${remoteUri}.`);
44
+ return repo;
45
+ }
46
+ exports.linkGitHubRepository = linkGitHubRepository;
47
+ async function promptRepositoryURI(projectId, location, connectionId) {
48
+ const resp = await gcb.fetchLinkableRepositories(projectId, location, connectionId);
49
+ if (!resp.repositories || resp.repositories.length === 0) {
50
+ throw new error_1.FirebaseError("The GitHub App does not have access to any repositories. Please configure " +
51
+ "your app installation permissions at https://github.com/settings/installations.");
52
+ }
53
+ const choices = resp.repositories.map((repo) => ({
54
+ name: extractRepoSlugFromURI(repo.remoteUri) || repo.remoteUri,
55
+ value: repo.remoteUri,
56
+ }));
57
+ choices.push({
58
+ name: "Missing a repo? Select this option to configure your installation's access settings",
59
+ value: "",
60
+ });
61
+ return await (0, prompt_1.promptOnce)({
62
+ type: "list",
63
+ message: "Which of the following repositories would you like to link?",
64
+ choices,
65
+ });
66
+ }
67
+ async function promptConnectionAuth(conn, projectId, location, connectionId) {
68
+ logger_1.logger.info(conn.installationState.message);
69
+ logger_1.logger.info(conn.installationState.actionUri);
70
+ await utils.openInBrowser(conn.installationState.actionUri);
71
+ await (0, prompt_1.promptOnce)({
72
+ type: "input",
73
+ message: "Press any key once you have authorized the app (Cloud Build) to access your GitHub repo.",
74
+ });
75
+ return await gcb.getConnection(projectId, location, connectionId);
76
+ }
77
+ async function getOrCreateConnection(projectId, location, connectionId) {
78
+ let conn;
79
+ try {
80
+ conn = await gcb.getConnection(projectId, location, connectionId);
81
+ }
82
+ catch (err) {
83
+ if (err.status === 404) {
84
+ const op = await gcb.createConnection(projectId, location, connectionId);
85
+ conn = await poller.pollOperation(Object.assign(Object.assign({}, gcbPollerOptions), { pollerName: `create-${location}-${connectionId}`, operationResourceName: op.name }));
86
+ }
87
+ else {
88
+ throw err;
89
+ }
90
+ }
91
+ while (conn.installationState.stage !== "COMPLETE") {
92
+ conn = await promptConnectionAuth(conn, projectId, location, connectionId);
93
+ }
94
+ return conn;
95
+ }
96
+ exports.getOrCreateConnection = getOrCreateConnection;
97
+ async function getOrCreateRepository(projectId, location, connectionId, remoteUri) {
98
+ const repositoryId = generateRepositoryId();
99
+ if (!repositoryId) {
100
+ throw new error_1.FirebaseError(`Failed to generate repositoryId for URI "${remoteUri}".`);
101
+ }
102
+ let repo;
103
+ try {
104
+ repo = await gcb.getRepository(projectId, location, connectionId, repositoryId);
105
+ const repoSlug = extractRepoSlugFromURI(repo.remoteUri);
106
+ if (repoSlug) {
107
+ throw new error_1.FirebaseError(`${repoSlug} has already been linked.`);
108
+ }
109
+ }
110
+ catch (err) {
111
+ if (err.status === 404) {
112
+ const op = await gcb.createRepository(projectId, location, connectionId, repositoryId, remoteUri);
113
+ repo = await poller.pollOperation(Object.assign(Object.assign({}, gcbPollerOptions), { pollerName: `create-${location}-${connectionId}-${repositoryId}`, operationResourceName: op.name }));
114
+ }
115
+ else {
116
+ throw err;
117
+ }
118
+ }
119
+ return repo;
120
+ }
121
+ exports.getOrCreateRepository = getOrCreateRepository;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALLOWED_DEPLOY_METHODS = exports.DEFAULT_DEPLOY_METHOD = exports.ALLOWED_REGIONS = exports.DEFAULT_REGION = void 0;
4
+ exports.DEFAULT_REGION = "us-central1";
5
+ exports.ALLOWED_REGIONS = [{ name: "us-central1 (Iowa)", value: "us-central1" }];
6
+ exports.DEFAULT_DEPLOY_METHOD = "github";
7
+ exports.ALLOWED_DEPLOY_METHODS = [{ name: "Deploy using github", value: "github" }];
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.doSetup = void 0;
4
+ const clc = require("colorette");
5
+ const utils = require("../../../utils");
6
+ const logger_1 = require("../../../logger");
7
+ const prompt_1 = require("../../../prompt");
8
+ const constants_1 = require("./constants");
9
+ async function doSetup(setup) {
10
+ setup.frameworks = {};
11
+ utils.logBullet("First we need a few details to create your service.");
12
+ await (0, prompt_1.promptOnce)({
13
+ name: "serviceName",
14
+ type: "input",
15
+ default: "acme-inc-web",
16
+ message: "Create a name for your service [6-32 characters]",
17
+ }, setup.frameworks);
18
+ await (0, prompt_1.promptOnce)({
19
+ name: "region",
20
+ type: "list",
21
+ default: constants_1.DEFAULT_REGION,
22
+ message: "Please select a region " +
23
+ `(${clc.yellow("info")}: Your region determines where your backend is located):\n`,
24
+ choices: constants_1.ALLOWED_REGIONS,
25
+ }, setup.frameworks);
26
+ utils.logSuccess(`Region set to ${setup.frameworks.region}.`);
27
+ logger_1.logger.info(clc.bold(`\n${clc.white("===")} Deploy Setup`));
28
+ await (0, prompt_1.promptOnce)({
29
+ name: "deployMethod",
30
+ type: "list",
31
+ default: constants_1.DEFAULT_DEPLOY_METHOD,
32
+ message: "How do you want to deploy",
33
+ choices: constants_1.ALLOWED_DEPLOY_METHODS,
34
+ }, setup.frameworks);
35
+ }
36
+ exports.doSetup = doSetup;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hostingGithub = exports.remoteconfig = exports.project = exports.extensions = exports.emulators = exports.storage = exports.hosting = exports.functions = exports.firestore = exports.database = exports.account = void 0;
3
+ exports.frameworks = exports.hostingGithub = exports.remoteconfig = exports.project = exports.extensions = exports.emulators = exports.storage = exports.hosting = exports.functions = exports.firestore = exports.database = exports.account = void 0;
4
4
  var account_1 = require("./account");
5
5
  Object.defineProperty(exports, "account", { enumerable: true, get: function () { return account_1.doSetup; } });
6
6
  var database_1 = require("./database");
@@ -23,3 +23,5 @@ var remoteconfig_1 = require("./remoteconfig");
23
23
  Object.defineProperty(exports, "remoteconfig", { enumerable: true, get: function () { return remoteconfig_1.doSetup; } });
24
24
  var github_1 = require("./hosting/github");
25
25
  Object.defineProperty(exports, "hostingGithub", { enumerable: true, get: function () { return github_1.initGitHub; } });
26
+ var frameworks_1 = require("./frameworks");
27
+ Object.defineProperty(exports, "frameworks", { enumerable: true, get: function () { return frameworks_1.doSetup; } });