firebase-tools 13.4.0 → 13.5.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.
- package/lib/apiv2.js +8 -3
- package/lib/deploy/functions/backend.js +5 -1
- package/lib/deploy/functions/build.js +9 -6
- package/lib/deploy/functions/release/fabricator.js +6 -2
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +2 -1
- package/lib/emulator/commandUtils.js +7 -4
- package/lib/emulator/controller.js +3 -4
- package/lib/emulator/downloadableEmulators.js +3 -3
- package/lib/emulator/functionsEmulator.js +21 -2
- package/lib/fetchWebSetup.js +2 -1
- package/lib/frameworks/index.js +6 -2
- package/lib/frameworks/next/constants.js +35 -1
- package/lib/frameworks/next/index.js +25 -3
- package/lib/frameworks/next/utils.js +20 -1
- package/lib/gcp/apphosting.js +20 -14
- package/lib/gcp/cloudfunctionsv2.js +3 -0
- package/lib/gcp/cloudscheduler.js +2 -1
- package/lib/hosting/api.js +12 -1
- package/lib/init/features/apphosting/index.js +2 -24
- package/lib/serve/functions.js +2 -1
- package/package.json +1 -1
package/lib/apiv2.js
CHANGED
|
@@ -15,7 +15,9 @@ const responseToError_1 = require("./responseToError");
|
|
|
15
15
|
const FormData = require("form-data");
|
|
16
16
|
const pkg = require("../package.json");
|
|
17
17
|
const CLI_VERSION = pkg.version;
|
|
18
|
-
const
|
|
18
|
+
const GOOG_QUOTA_USER_HEADER = "x-goog-quota-user";
|
|
19
|
+
const GOOG_USER_PROJECT_HEADER = "x-goog-user-project";
|
|
20
|
+
const GOOGLE_CLOUD_QUOTA_PROJECT = process.env.GOOGLE_CLOUD_QUOTA_PROJECT;
|
|
19
21
|
let accessToken = "";
|
|
20
22
|
let refreshToken = "";
|
|
21
23
|
function setRefreshToken(token = "") {
|
|
@@ -133,6 +135,9 @@ class Client {
|
|
|
133
135
|
reqOptions.headers.set("Content-Type", "application/json");
|
|
134
136
|
}
|
|
135
137
|
}
|
|
138
|
+
if (GOOGLE_CLOUD_QUOTA_PROJECT && GOOGLE_CLOUD_QUOTA_PROJECT !== "") {
|
|
139
|
+
reqOptions.headers.set(GOOG_USER_PROJECT_HEADER, GOOGLE_CLOUD_QUOTA_PROJECT);
|
|
140
|
+
}
|
|
136
141
|
return reqOptions;
|
|
137
142
|
}
|
|
138
143
|
async addAuthHeader(reqOptions) {
|
|
@@ -315,8 +320,8 @@ class Client {
|
|
|
315
320
|
const logURL = this.requestURL(options);
|
|
316
321
|
logger_1.logger.debug(`>>> [apiv2][query] ${options.method} ${logURL} ${queryParamsLog}`);
|
|
317
322
|
const headers = options.headers;
|
|
318
|
-
if (headers && headers.has(
|
|
319
|
-
logger_1.logger.debug(`>>> [apiv2][(partial)header] ${options.method} ${logURL} x-goog-quota-user=${headers.get(
|
|
323
|
+
if (headers && headers.has(GOOG_QUOTA_USER_HEADER)) {
|
|
324
|
+
logger_1.logger.debug(`>>> [apiv2][(partial)header] ${options.method} ${logURL} x-goog-quota-user=${headers.get(GOOG_QUOTA_USER_HEADER) || ""}`);
|
|
320
325
|
}
|
|
321
326
|
if (options.body !== undefined) {
|
|
322
327
|
let logBody = "[omitted]";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.merge = exports.of = exports.empty = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.AllFunctionsPlatforms = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_CPU_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.DEFAULT_CONCURRENCY = exports.memoryToGen2Cpu = exports.memoryToGen1Cpu = exports.memoryOptionDisplayName = exports.isValidMemoryOption = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.endpointTriggerType = void 0;
|
|
3
|
+
exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.merge = exports.of = exports.empty = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.AllFunctionsPlatforms = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_CPU_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.DEFAULT_CONCURRENCY = exports.memoryToGen2Cpu = exports.memoryToGen1Cpu = exports.memoryOptionDisplayName = exports.isValidEgressSetting = exports.isValidMemoryOption = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.endpointTriggerType = void 0;
|
|
4
4
|
const gcf = require("../../gcp/cloudfunctions");
|
|
5
5
|
const gcfV2 = require("../../gcp/cloudfunctionsv2");
|
|
6
6
|
const utils = require("../../utils");
|
|
@@ -41,6 +41,10 @@ function isValidMemoryOption(mem) {
|
|
|
41
41
|
return allMemoryOptions.includes(mem);
|
|
42
42
|
}
|
|
43
43
|
exports.isValidMemoryOption = isValidMemoryOption;
|
|
44
|
+
function isValidEgressSetting(egress) {
|
|
45
|
+
return egress === "PRIVATE_RANGES_ONLY" || egress === "ALL_TRAFFIC";
|
|
46
|
+
}
|
|
47
|
+
exports.isValidEgressSetting = isValidEgressSetting;
|
|
44
48
|
function memoryOptionDisplayName(option) {
|
|
45
49
|
return {
|
|
46
50
|
128: "128MB",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toBackend = exports.resolveBackend = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.AllFunctionsPlatforms = exports.
|
|
3
|
+
exports.toBackend = exports.resolveBackend = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.AllFunctionsPlatforms = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.of = exports.empty = void 0;
|
|
4
4
|
const backend = require("./backend");
|
|
5
5
|
const proto = require("../../gcp/proto");
|
|
6
6
|
const api = require("../../.../../api");
|
|
@@ -48,10 +48,6 @@ function isBlockingTriggered(triggered) {
|
|
|
48
48
|
}
|
|
49
49
|
exports.isBlockingTriggered = isBlockingTriggered;
|
|
50
50
|
const allMemoryOptions = [128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768];
|
|
51
|
-
function isValidMemoryOption(mem) {
|
|
52
|
-
return allMemoryOptions.includes(mem);
|
|
53
|
-
}
|
|
54
|
-
exports.isValidMemoryOption = isValidMemoryOption;
|
|
55
51
|
exports.AllFunctionsPlatforms = ["gcfv1", "gcfv2"];
|
|
56
52
|
exports.AllVpcEgressSettings = ["PRIVATE_RANGES_ONLY", "ALL_TRAFFIC"];
|
|
57
53
|
exports.AllIngressSettings = [
|
|
@@ -222,7 +218,14 @@ function toBackend(build, paramValues) {
|
|
|
222
218
|
bdEndpoint.vpc.connector = `projects/${bdEndpoint.project}/locations/${region}/connectors/${bdEndpoint.vpc.connector}`;
|
|
223
219
|
}
|
|
224
220
|
bkEndpoint.vpc = { connector: bdEndpoint.vpc.connector };
|
|
225
|
-
|
|
221
|
+
if (bdEndpoint.vpc.egressSettings) {
|
|
222
|
+
const egressSettings = r.resolveString(bdEndpoint.vpc.egressSettings);
|
|
223
|
+
if (!backend.isValidEgressSetting(egressSettings)) {
|
|
224
|
+
throw new error_1.FirebaseError(`Value "${egressSettings}" is an invalid ` +
|
|
225
|
+
"egress setting. Valid values are PRIVATE_RANGES_ONLY and ALL_TRAFFIC");
|
|
226
|
+
}
|
|
227
|
+
bkEndpoint.vpc.egressSettings = egressSettings;
|
|
228
|
+
}
|
|
226
229
|
}
|
|
227
230
|
else if (bdEndpoint.vpc === null) {
|
|
228
231
|
bkEndpoint.vpc = null;
|
|
@@ -330,7 +330,9 @@ class Fabricator {
|
|
|
330
330
|
.catch(rethrowAs(endpoint, "set invoker"));
|
|
331
331
|
}
|
|
332
332
|
else if (backend.isScheduleTriggered(endpoint)) {
|
|
333
|
-
const invoker =
|
|
333
|
+
const invoker = endpoint.serviceAccount
|
|
334
|
+
? [endpoint.serviceAccount]
|
|
335
|
+
: [(0, checkIam_1.getDefaultComputeServiceAgent)(this.projectNumber)];
|
|
334
336
|
await this.executor
|
|
335
337
|
.run(() => run.setInvokerCreate(endpoint.project, serviceName, invoker))
|
|
336
338
|
.catch(rethrowAs(endpoint, "set invoker"));
|
|
@@ -411,7 +413,9 @@ class Fabricator {
|
|
|
411
413
|
invoker = ["public"];
|
|
412
414
|
}
|
|
413
415
|
else if (backend.isScheduleTriggered(endpoint)) {
|
|
414
|
-
invoker =
|
|
416
|
+
invoker = endpoint.serviceAccount
|
|
417
|
+
? [endpoint.serviceAccount]
|
|
418
|
+
: [(0, checkIam_1.getDefaultComputeServiceAgent)(this.projectNumber)];
|
|
415
419
|
}
|
|
416
420
|
if (invoker) {
|
|
417
421
|
await this.executor
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildFromV1Alpha1 = void 0;
|
|
4
4
|
const build = require("../../build");
|
|
5
|
+
const backend = require("../../backend");
|
|
5
6
|
const proto_1 = require("../../../../gcp/proto");
|
|
6
7
|
const parsing_1 = require("./parsing");
|
|
7
8
|
const error_1 = require("../../../../error");
|
|
@@ -52,7 +53,7 @@ function assertBuildEndpoint(ep, id) {
|
|
|
52
53
|
platform: (platform) => build.AllFunctionsPlatforms.includes(platform),
|
|
53
54
|
entryPoint: "string",
|
|
54
55
|
omit: "Field<boolean>?",
|
|
55
|
-
availableMemoryMb: (mem) => mem === null || isCEL(mem) ||
|
|
56
|
+
availableMemoryMb: (mem) => mem === null || isCEL(mem) || backend.isValidMemoryOption(mem),
|
|
56
57
|
maxInstances: "Field<number>?",
|
|
57
58
|
minInstances: "Field<number>?",
|
|
58
59
|
concurrency: "Field<number>?",
|
|
@@ -117,13 +117,16 @@ async function beforeEmulatorCommand(options) {
|
|
|
117
117
|
}
|
|
118
118
|
exports.beforeEmulatorCommand = beforeEmulatorCommand;
|
|
119
119
|
function parseInspectionPort(options) {
|
|
120
|
-
|
|
121
|
-
if (port ===
|
|
122
|
-
|
|
120
|
+
const port = options.inspectFunctions;
|
|
121
|
+
if (typeof port === "undefined") {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
else if (typeof port === "boolean") {
|
|
125
|
+
return port;
|
|
123
126
|
}
|
|
124
127
|
const parsed = Number(port);
|
|
125
128
|
if (isNaN(parsed) || parsed < 1024 || parsed > 65535) {
|
|
126
|
-
throw new error_1.FirebaseError(`"${port}" is not a valid port for debugging, please pass an integer between 1024 and 65535.`);
|
|
129
|
+
throw new error_1.FirebaseError(`"${port}" is not a valid port for debugging, please pass an integer between 1024 and 65535 or true for a dynamic port.`);
|
|
127
130
|
}
|
|
128
131
|
return parsed;
|
|
129
132
|
}
|
|
@@ -332,10 +332,9 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
332
332
|
const functionsLogger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
|
|
333
333
|
const functionsAddr = legacyGetFirstAddr(types_1.Emulators.FUNCTIONS);
|
|
334
334
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
335
|
-
|
|
336
|
-
if (
|
|
337
|
-
|
|
338
|
-
functionsLogger.logLabeled("WARN", "functions", `You are running the Functions emulator in debug mode (port=${inspectFunctions}). This means that functions will execute in sequence rather than in parallel.`);
|
|
335
|
+
const inspectFunctions = commandUtils.parseInspectionPort(options);
|
|
336
|
+
if (inspectFunctions) {
|
|
337
|
+
functionsLogger.logLabeled("WARN", "functions", `You are running the Functions emulator in debug mode. This means that functions will execute in sequence rather than in parallel.`);
|
|
339
338
|
}
|
|
340
339
|
const emulatorsNotRunning = types_1.ALL_SERVICE_EMULATORS.filter((e) => {
|
|
341
340
|
return e !== types_1.Emulators.FUNCTIONS && !listenForEmulator[e];
|
|
@@ -23,9 +23,9 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
23
23
|
expectedChecksum: "2fd771101c0e1f7898c04c9204f2ce63",
|
|
24
24
|
},
|
|
25
25
|
firestore: {
|
|
26
|
-
version: "1.19.
|
|
27
|
-
expectedSize:
|
|
28
|
-
expectedChecksum: "
|
|
26
|
+
version: "1.19.3",
|
|
27
|
+
expectedSize: 67296394,
|
|
28
|
+
expectedChecksum: "08a9b882a5c38570b6333f3931b1e52b",
|
|
29
29
|
},
|
|
30
30
|
storage: {
|
|
31
31
|
version: "1.1.3",
|
|
@@ -84,6 +84,11 @@ class FunctionsEmulator {
|
|
|
84
84
|
this.debugMode = false;
|
|
85
85
|
emulatorLogger_1.EmulatorLogger.setVerbosity(this.args.verbosity ? emulatorLogger_1.Verbosity[this.args.verbosity] : emulatorLogger_1.Verbosity["DEBUG"]);
|
|
86
86
|
if (this.args.debugPort) {
|
|
87
|
+
const maybeNodeCodebases = this.args.emulatableBackends.filter((b) => !b.runtime || b.runtime.startsWith("node"));
|
|
88
|
+
if (maybeNodeCodebases.length > 1 && typeof this.args.debugPort === "number") {
|
|
89
|
+
throw new error_1.FirebaseError("Cannot debug on a single port with multiple codebases. " +
|
|
90
|
+
"Use --inspect-functions=true to assign dynamic ports to each codebase");
|
|
91
|
+
}
|
|
87
92
|
this.args.disabledRuntimeFeatures = this.args.disabledRuntimeFeatures || {};
|
|
88
93
|
this.args.disabledRuntimeFeatures.timeout = true;
|
|
89
94
|
this.debugMode = true;
|
|
@@ -847,8 +852,22 @@ class FunctionsEmulator {
|
|
|
847
852
|
this.logger.log("WARN", `To enable function inspection, please run "npm i node@${semver.coerce(backend.runtime || "18.0.0")} --save-dev" in your functions directory`);
|
|
848
853
|
}
|
|
849
854
|
else {
|
|
855
|
+
let port;
|
|
856
|
+
if (typeof this.args.debugPort === "number") {
|
|
857
|
+
port = this.args.debugPort;
|
|
858
|
+
}
|
|
859
|
+
else {
|
|
860
|
+
port = await portfinder.getPortPromise({ port: 9229 });
|
|
861
|
+
if (port === 9229) {
|
|
862
|
+
this.logger.logLabeled("SUCCESS", "functions", `Using debug port 9229 for functions codebase ${backend.codebase}`);
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
this.logger.logLabeled("SUCCESS", "functions", `Using debug port ${port} for functions codebase ${backend.codebase}. ` +
|
|
866
|
+
"You may need to add manually add this port to your inspector.");
|
|
867
|
+
}
|
|
868
|
+
}
|
|
850
869
|
const { host } = this.getInfo();
|
|
851
|
-
args.unshift(`--inspect=${(0, utils_1.connectableHostname)(host)}:${
|
|
870
|
+
args.unshift(`--inspect=${(0, utils_1.connectableHostname)(host)}:${port}`);
|
|
852
871
|
}
|
|
853
872
|
}
|
|
854
873
|
const pnpPath = path.join(backend.functionsDir, ".pnp.js");
|
|
@@ -865,7 +884,7 @@ class FunctionsEmulator {
|
|
|
865
884
|
const socketPath = (0, functionsEmulatorShared_1.getTemporarySocketPath)();
|
|
866
885
|
const childProcess = spawn(bin, args, {
|
|
867
886
|
cwd: backend.functionsDir,
|
|
868
|
-
env: Object.assign(Object.assign(Object.assign({ node: backend.bin }, process.env), envs), { PORT: socketPath }),
|
|
887
|
+
env: Object.assign(Object.assign(Object.assign({ node: backend.bin, METADATA_SERVER_DETECTION: "none" }, process.env), envs), { PORT: socketPath }),
|
|
869
888
|
stdio: ["pipe", "pipe", "pipe", "ipc"],
|
|
870
889
|
});
|
|
871
890
|
return Promise.resolve({
|
package/lib/fetchWebSetup.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fetchWebSetup = exports.getCachedWebSetup = void 0;
|
|
3
|
+
exports.fetchWebSetup = exports.constructDefaultWebSetup = exports.getCachedWebSetup = void 0;
|
|
4
4
|
const apiv2_1 = require("./apiv2");
|
|
5
5
|
const configstore_1 = require("./configstore");
|
|
6
6
|
const api_1 = require("./api");
|
|
@@ -46,6 +46,7 @@ function constructDefaultWebSetup(projectId) {
|
|
|
46
46
|
authDomain: `${projectId}.firebaseapp.com`,
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
+
exports.constructDefaultWebSetup = constructDefaultWebSetup;
|
|
49
50
|
async function fetchWebSetup(options) {
|
|
50
51
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
51
52
|
if (constants_1.Constants.isDemoProject(projectId)) {
|
package/lib/frameworks/index.js
CHANGED
|
@@ -32,6 +32,7 @@ const projectPath_1 = require("../projectPath");
|
|
|
32
32
|
const logger_1 = require("../logger");
|
|
33
33
|
const frameworks_1 = require("./frameworks");
|
|
34
34
|
Object.defineProperty(exports, "WebFrameworks", { enumerable: true, get: function () { return frameworks_1.WebFrameworks; } });
|
|
35
|
+
const fetchWebSetup_1 = require("../fetchWebSetup");
|
|
35
36
|
async function discover(dir, warn = true) {
|
|
36
37
|
const allFrameworkTypes = [
|
|
37
38
|
...new Set(Object.values(frameworks_1.WebFrameworks).map(({ type }) => type)),
|
|
@@ -149,12 +150,15 @@ async function prepareFrameworks(purpose, targetNames, context, options, emulato
|
|
|
149
150
|
});
|
|
150
151
|
let firebaseConfig = null;
|
|
151
152
|
if (usesFirebaseJsSdk) {
|
|
152
|
-
const
|
|
153
|
+
const isDemoProject = constants_1.Constants.isDemoProject(project);
|
|
154
|
+
const sites = isDemoProject ? (0, api_1.listDemoSites)(project) : await (0, api_1.listSites)(project);
|
|
153
155
|
const selectedSite = sites.find((it) => it.name && it.name.split("/").pop() === site);
|
|
154
156
|
if (selectedSite) {
|
|
155
157
|
const { appId } = selectedSite;
|
|
156
158
|
if (appId) {
|
|
157
|
-
firebaseConfig =
|
|
159
|
+
firebaseConfig = isDemoProject
|
|
160
|
+
? (0, fetchWebSetup_1.constructDefaultWebSetup)(project)
|
|
161
|
+
: await (0, apps_1.getAppConfig)(appId, apps_1.AppPlatform.WEB);
|
|
158
162
|
firebaseDefaults || (firebaseDefaults = {});
|
|
159
163
|
firebaseDefaults.config = firebaseConfig;
|
|
160
164
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ESBUILD_VERSION = exports.APP_PATHS_MANIFEST = exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
|
|
3
|
+
exports.WEBPACK_LAYERS = exports.ESBUILD_VERSION = exports.SERVER_REFERENCE_MANIFEST = exports.APP_PATHS_MANIFEST = exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
|
|
4
4
|
exports.APP_PATH_ROUTES_MANIFEST = "app-path-routes-manifest.json";
|
|
5
5
|
exports.EXPORT_MARKER = "export-marker.json";
|
|
6
6
|
exports.IMAGES_MANIFEST = "images-manifest.json";
|
|
@@ -9,4 +9,38 @@ exports.PAGES_MANIFEST = "pages-manifest.json";
|
|
|
9
9
|
exports.PRERENDER_MANIFEST = "prerender-manifest.json";
|
|
10
10
|
exports.ROUTES_MANIFEST = "routes-manifest.json";
|
|
11
11
|
exports.APP_PATHS_MANIFEST = "app-paths-manifest.json";
|
|
12
|
+
exports.SERVER_REFERENCE_MANIFEST = "server-reference-manifest.json";
|
|
12
13
|
exports.ESBUILD_VERSION = "0.19.2";
|
|
14
|
+
const WEBPACK_LAYERS_NAMES = {
|
|
15
|
+
shared: "shared",
|
|
16
|
+
reactServerComponents: "rsc",
|
|
17
|
+
serverSideRendering: "ssr",
|
|
18
|
+
actionBrowser: "action-browser",
|
|
19
|
+
api: "api",
|
|
20
|
+
middleware: "middleware",
|
|
21
|
+
edgeAsset: "edge-asset",
|
|
22
|
+
appPagesBrowser: "app-pages-browser",
|
|
23
|
+
appMetadataRoute: "app-metadata-route",
|
|
24
|
+
appRouteHandler: "app-route-handler",
|
|
25
|
+
};
|
|
26
|
+
exports.WEBPACK_LAYERS = Object.assign(Object.assign({}, WEBPACK_LAYERS_NAMES), { GROUP: {
|
|
27
|
+
server: [
|
|
28
|
+
WEBPACK_LAYERS_NAMES.reactServerComponents,
|
|
29
|
+
WEBPACK_LAYERS_NAMES.actionBrowser,
|
|
30
|
+
WEBPACK_LAYERS_NAMES.appMetadataRoute,
|
|
31
|
+
WEBPACK_LAYERS_NAMES.appRouteHandler,
|
|
32
|
+
],
|
|
33
|
+
nonClientServerTarget: [
|
|
34
|
+
WEBPACK_LAYERS_NAMES.middleware,
|
|
35
|
+
WEBPACK_LAYERS_NAMES.api,
|
|
36
|
+
],
|
|
37
|
+
app: [
|
|
38
|
+
WEBPACK_LAYERS_NAMES.reactServerComponents,
|
|
39
|
+
WEBPACK_LAYERS_NAMES.actionBrowser,
|
|
40
|
+
WEBPACK_LAYERS_NAMES.appMetadataRoute,
|
|
41
|
+
WEBPACK_LAYERS_NAMES.appRouteHandler,
|
|
42
|
+
WEBPACK_LAYERS_NAMES.serverSideRendering,
|
|
43
|
+
WEBPACK_LAYERS_NAMES.appPagesBrowser,
|
|
44
|
+
WEBPACK_LAYERS_NAMES.shared,
|
|
45
|
+
],
|
|
46
|
+
} });
|
|
@@ -114,9 +114,10 @@ async function build(dir, target, context) {
|
|
|
114
114
|
source: (0, utils_2.cleanEscapedChars)(source),
|
|
115
115
|
headers,
|
|
116
116
|
}));
|
|
117
|
-
const [appPathsManifest, appPathRoutesManifest] = await Promise.all([
|
|
117
|
+
const [appPathsManifest, appPathRoutesManifest, serverReferenceManifest] = await Promise.all([
|
|
118
118
|
(0, utils_1.readJSON)((0, path_1.join)(dir, distDir, "server", constants_2.APP_PATHS_MANIFEST)).catch(() => undefined),
|
|
119
119
|
(0, utils_1.readJSON)((0, path_1.join)(dir, distDir, constants_2.APP_PATH_ROUTES_MANIFEST)).catch(() => undefined),
|
|
120
|
+
(0, utils_1.readJSON)((0, path_1.join)(dir, distDir, "server", constants_2.SERVER_REFERENCE_MANIFEST)).catch(() => undefined),
|
|
120
121
|
]);
|
|
121
122
|
if (appPathRoutesManifest) {
|
|
122
123
|
const headersFromMetaFiles = await (0, utils_2.getHeadersFromMetaFiles)(dir, distDir, baseUrl, appPathRoutesManifest);
|
|
@@ -131,6 +132,12 @@ async function build(dir, target, context) {
|
|
|
131
132
|
reasonsForBackend.add(`non-static component ${key}`);
|
|
132
133
|
}
|
|
133
134
|
}
|
|
135
|
+
if (serverReferenceManifest) {
|
|
136
|
+
const routesWithServerAction = (0, utils_2.getRoutesWithServerAction)(serverReferenceManifest, appPathRoutesManifest);
|
|
137
|
+
for (const key of routesWithServerAction) {
|
|
138
|
+
reasonsForBackend.add(`route with server action ${key}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
134
141
|
}
|
|
135
142
|
const isEveryRedirectSupported = nextJsRedirects
|
|
136
143
|
.filter((it) => !it.internal)
|
|
@@ -212,12 +219,13 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
|
|
|
212
219
|
await (0, fs_extra_1.copy)(publicPath, (0, path_1.join)(destDir, basePath));
|
|
213
220
|
}
|
|
214
221
|
await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, distDir, "static"), (0, path_1.join)(destDir, basePath, "_next", "static"));
|
|
215
|
-
const [middlewareManifest, prerenderManifest, routesManifest, pagesManifest, appPathRoutesManifest,] = await Promise.all([
|
|
222
|
+
const [middlewareManifest, prerenderManifest, routesManifest, pagesManifest, appPathRoutesManifest, serverReferenceManifest,] = await Promise.all([
|
|
216
223
|
(0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.MIDDLEWARE_MANIFEST)),
|
|
217
224
|
(0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, constants_2.PRERENDER_MANIFEST)),
|
|
218
225
|
(0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, constants_2.ROUTES_MANIFEST)),
|
|
219
226
|
(0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.PAGES_MANIFEST)),
|
|
220
227
|
(0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, constants_2.APP_PATH_ROUTES_MANIFEST)).catch(() => ({})),
|
|
228
|
+
(0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.SERVER_REFERENCE_MANIFEST)).catch(() => ({ node: {}, edge: {}, encryptionKey: "" })),
|
|
221
229
|
]);
|
|
222
230
|
const appPathRoutesEntries = Object.entries(appPathRoutesManifest);
|
|
223
231
|
const middlewareMatcherRegexes = (0, utils_2.getMiddlewareMatcherRegexes)(middlewareManifest);
|
|
@@ -240,10 +248,20 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
|
|
|
240
248
|
...redirectsRegexesNotSupportedByHosting,
|
|
241
249
|
...headersRegexesNotSupportedByHosting,
|
|
242
250
|
];
|
|
251
|
+
const staticRoutesUsingServerActions = (0, utils_2.getRoutesWithServerAction)(serverReferenceManifest, appPathRoutesManifest);
|
|
243
252
|
const pagesManifestLikePrerender = Object.fromEntries(Object.entries(pagesManifest)
|
|
244
253
|
.filter(([, srcRoute]) => srcRoute.endsWith(".html"))
|
|
245
254
|
.map(([path]) => {
|
|
246
|
-
return [
|
|
255
|
+
return [
|
|
256
|
+
path,
|
|
257
|
+
{
|
|
258
|
+
srcRoute: null,
|
|
259
|
+
initialRevalidateSeconds: false,
|
|
260
|
+
dataRoute: "",
|
|
261
|
+
experimentalPPR: false,
|
|
262
|
+
prefetchDataRoute: "",
|
|
263
|
+
},
|
|
264
|
+
];
|
|
247
265
|
}));
|
|
248
266
|
const routesToCopy = Object.assign(Object.assign({}, prerenderManifest.routes), pagesManifestLikePrerender);
|
|
249
267
|
await Promise.all(Object.entries(routesToCopy).map(async ([path, route]) => {
|
|
@@ -256,6 +274,10 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
|
|
|
256
274
|
logger_1.logger.debug(`skipping ${path} due to it matching an unsupported rewrite/redirect/header or middlware`);
|
|
257
275
|
return;
|
|
258
276
|
}
|
|
277
|
+
if (staticRoutesUsingServerActions.some((it) => path === it)) {
|
|
278
|
+
logger_1.logger.debug(`skipping ${path} due to server action`);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
259
281
|
const appPathRoute = route.srcRoute && ((_a = appPathRoutesEntries.find(([, it]) => it === route.srcRoute)) === null || _a === void 0 ? void 0 : _a[0]);
|
|
260
282
|
const contentDist = (0, path_1.join)(sourceDir, distDir, "server", appPathRoute ? "app" : "pages");
|
|
261
283
|
const sourceParts = path.split("/").filter((it) => !!it);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasStaticAppNotFoundComponent = exports.getNextVersion = exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingNextImageInAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
|
|
3
|
+
exports.getRoutesWithServerAction = exports.hasStaticAppNotFoundComponent = exports.getNextVersion = exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingNextImageInAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const fs_extra_1 = require("fs-extra");
|
|
6
6
|
const path_1 = require("path");
|
|
@@ -199,3 +199,22 @@ async function hasStaticAppNotFoundComponent(sourceDir, distDir) {
|
|
|
199
199
|
return (0, fs_extra_1.pathExists)((0, path_1.join)(sourceDir, distDir, "server", "app", "_not-found.html"));
|
|
200
200
|
}
|
|
201
201
|
exports.hasStaticAppNotFoundComponent = hasStaticAppNotFoundComponent;
|
|
202
|
+
function getRoutesWithServerAction(serverReferenceManifest, appPathRoutesManifest) {
|
|
203
|
+
const routesWithServerAction = new Set();
|
|
204
|
+
for (const key of Object.keys(serverReferenceManifest)) {
|
|
205
|
+
if (key !== "edge" && key !== "node")
|
|
206
|
+
continue;
|
|
207
|
+
const edgeOrNode = serverReferenceManifest[key];
|
|
208
|
+
for (const actionId of Object.keys(edgeOrNode)) {
|
|
209
|
+
if (!edgeOrNode[actionId].layer)
|
|
210
|
+
continue;
|
|
211
|
+
for (const [route, type] of Object.entries(edgeOrNode[actionId].layer)) {
|
|
212
|
+
if (type === constants_1.WEBPACK_LAYERS.actionBrowser) {
|
|
213
|
+
routesWithServerAction.add(appPathRoutesManifest[route.replace("app", "")]);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return Array.from(routesWithServerAction);
|
|
219
|
+
}
|
|
220
|
+
exports.getRoutesWithServerAction = getRoutesWithServerAction;
|
package/lib/gcp/apphosting.js
CHANGED
|
@@ -129,7 +129,7 @@ async function ensureApiEnabled(options) {
|
|
|
129
129
|
}
|
|
130
130
|
exports.ensureApiEnabled = ensureApiEnabled;
|
|
131
131
|
async function getNextRolloutId(projectId, location, backendId, counter) {
|
|
132
|
-
var _a;
|
|
132
|
+
var _a, _b;
|
|
133
133
|
const date = new Date();
|
|
134
134
|
const year = date.getUTCFullYear();
|
|
135
135
|
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
@@ -137,22 +137,28 @@ async function getNextRolloutId(projectId, location, backendId, counter) {
|
|
|
137
137
|
if (counter) {
|
|
138
138
|
return `build-${year}-${month}-${day}-${String(counter).padStart(3, "0")}`;
|
|
139
139
|
}
|
|
140
|
-
const
|
|
141
|
-
|
|
140
|
+
const rolloutsPromise = exports.listRollouts(projectId, location, backendId);
|
|
141
|
+
const buildsPromise = exports.listBuilds(projectId, location, backendId);
|
|
142
|
+
const [rollouts, builds] = await Promise.all([rolloutsPromise, buildsPromise]);
|
|
143
|
+
if (((_a = builds.unreachable) === null || _a === void 0 ? void 0 : _a.includes(location)) || ((_b = rollouts.unreachable) === null || _b === void 0 ? void 0 : _b.includes(location))) {
|
|
142
144
|
throw new error_1.FirebaseError(`Firebase App Hosting is currently unreachable in location ${location}`);
|
|
143
145
|
}
|
|
144
|
-
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
highest
|
|
146
|
+
const test = new RegExp(`projects/${projectId}/locations/${location}/backends/${backendId}/(rollouts|builds)/build-${year}-${month}-${day}-(\\d+)`);
|
|
147
|
+
const highestId = (input) => {
|
|
148
|
+
let highest = 0;
|
|
149
|
+
for (const i of input) {
|
|
150
|
+
const match = i.name.match(test);
|
|
151
|
+
if (!match) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const n = Number(match[2]);
|
|
155
|
+
if (n > highest) {
|
|
156
|
+
highest = n;
|
|
157
|
+
}
|
|
154
158
|
}
|
|
155
|
-
|
|
159
|
+
return highest;
|
|
160
|
+
};
|
|
161
|
+
const highest = Math.max(highestId(builds.builds), highestId(rollouts.rollouts));
|
|
156
162
|
return `build-${year}-${month}-${day}-${String(highest + 1).padStart(3, "0")}`;
|
|
157
163
|
}
|
|
158
164
|
exports.getNextRolloutId = getNextRolloutId;
|
|
@@ -215,6 +215,9 @@ function functionFromEndpoint(endpoint) {
|
|
|
215
215
|
eventType: endpoint.eventTrigger.eventType,
|
|
216
216
|
retryPolicy: "RETRY_POLICY_UNSPECIFIED",
|
|
217
217
|
};
|
|
218
|
+
if (endpoint.serviceAccount) {
|
|
219
|
+
gcfFunction.eventTrigger.serviceAccountEmail = endpoint.serviceAccount;
|
|
220
|
+
}
|
|
218
221
|
if (gcfFunction.eventTrigger.eventType === v2_1.PUBSUB_PUBLISH_EVENT) {
|
|
219
222
|
if (!((_b = endpoint.eventTrigger.eventFilters) === null || _b === void 0 ? void 0 : _b.topic)) {
|
|
220
223
|
throw new error_1.FirebaseError("Error: Pub/Sub event trigger is missing topic: " +
|
|
@@ -112,6 +112,7 @@ function topicNameForEndpoint(endpoint) {
|
|
|
112
112
|
}
|
|
113
113
|
exports.topicNameForEndpoint = topicNameForEndpoint;
|
|
114
114
|
function jobFromEndpoint(endpoint, location, projectNumber) {
|
|
115
|
+
var _a;
|
|
115
116
|
const job = {};
|
|
116
117
|
job.name = jobNameForEndpoint(endpoint, location);
|
|
117
118
|
if (endpoint.platform === "gcfv1") {
|
|
@@ -129,7 +130,7 @@ function jobFromEndpoint(endpoint, location, projectNumber) {
|
|
|
129
130
|
uri: endpoint.uri,
|
|
130
131
|
httpMethod: "POST",
|
|
131
132
|
oidcToken: {
|
|
132
|
-
serviceAccountEmail: (0, checkIam_1.getDefaultComputeServiceAgent)(projectNumber),
|
|
133
|
+
serviceAccountEmail: (_a = endpoint.serviceAccount) !== null && _a !== void 0 ? _a : (0, checkIam_1.getDefaultComputeServiceAgent)(projectNumber),
|
|
133
134
|
},
|
|
134
135
|
};
|
|
135
136
|
}
|
package/lib/hosting/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDeploymentDomain = exports.getAllSiteDomains = exports.getSiteDomains = exports.cleanAuthState = exports.getCleanDomains = exports.removeAuthDomain = exports.addAuthDomains = exports.deleteSite = exports.updateSite = exports.createSite = exports.getSite = exports.listSites = exports.createRelease = exports.cloneVersion = exports.listVersions = exports.updateVersion = exports.createVersion = exports.deleteChannel = exports.updateChannelTtl = exports.createChannel = exports.listChannels = exports.getChannel = exports.normalizeName = exports.SiteType = void 0;
|
|
3
|
+
exports.getDeploymentDomain = exports.getAllSiteDomains = exports.getSiteDomains = exports.cleanAuthState = exports.getCleanDomains = exports.removeAuthDomain = exports.addAuthDomains = exports.deleteSite = exports.updateSite = exports.createSite = exports.getSite = exports.listDemoSites = exports.listSites = exports.createRelease = exports.cloneVersion = exports.listVersions = exports.updateVersion = exports.createVersion = exports.deleteChannel = exports.updateChannelTtl = exports.createChannel = exports.listChannels = exports.getChannel = exports.normalizeName = exports.SiteType = void 0;
|
|
4
4
|
const error_1 = require("../error");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
6
|
const apiv2_1 = require("../apiv2");
|
|
@@ -159,6 +159,17 @@ async function listSites(project) {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
exports.listSites = listSites;
|
|
162
|
+
function listDemoSites(projectId) {
|
|
163
|
+
return [
|
|
164
|
+
{
|
|
165
|
+
name: `projects/${projectId}/sites/${projectId}`,
|
|
166
|
+
defaultUrl: `https://${projectId}.firebaseapp.com`,
|
|
167
|
+
appId: "fake-app-id",
|
|
168
|
+
labels: {},
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
exports.listDemoSites = listDemoSites;
|
|
162
173
|
async function getSite(project, site) {
|
|
163
174
|
try {
|
|
164
175
|
const res = await apiClient.get(`/projects/${project}/sites/${site}`);
|
|
@@ -172,31 +172,9 @@ async function orchestrateRollout(projectId, location, backendId, buildInput) {
|
|
|
172
172
|
(0, utils_1.logBullet)("Starting a new rollout... this may take a few minutes.");
|
|
173
173
|
const buildId = await apphosting.getNextRolloutId(projectId, location, backendId, 1);
|
|
174
174
|
const buildOp = await apphosting.createBuild(projectId, location, backendId, buildId, buildInput);
|
|
175
|
-
const
|
|
175
|
+
const rolloutOp = await apphosting.createRollout(projectId, location, backendId, buildId, {
|
|
176
176
|
build: `projects/${projectId}/locations/${location}/backends/${backendId}/builds/${buildId}`,
|
|
177
|
-
};
|
|
178
|
-
let tries = 0;
|
|
179
|
-
let done = false;
|
|
180
|
-
while (!done) {
|
|
181
|
-
tries++;
|
|
182
|
-
try {
|
|
183
|
-
const validateOnly = true;
|
|
184
|
-
await apphosting.createRollout(projectId, location, backendId, buildId, rolloutBody, validateOnly);
|
|
185
|
-
done = true;
|
|
186
|
-
}
|
|
187
|
-
catch (err) {
|
|
188
|
-
if (err instanceof error_1.FirebaseError && err.status === 400) {
|
|
189
|
-
if (tries >= 5) {
|
|
190
|
-
throw err;
|
|
191
|
-
}
|
|
192
|
-
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
throw err;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
const rolloutOp = await apphosting.createRollout(projectId, location, backendId, buildId, rolloutBody);
|
|
177
|
+
});
|
|
200
178
|
const rolloutPoll = poller.pollOperation(Object.assign(Object.assign({}, apphostingPollerOptions), { pollerName: `create-${projectId}-${location}-backend-${backendId}-rollout-${buildId}`, operationResourceName: rolloutOp.name }));
|
|
201
179
|
const buildPoll = poller.pollOperation(Object.assign(Object.assign({}, apphostingPollerOptions), { pollerName: `create-${projectId}-${location}-backend-${backendId}-build-${buildId}`, operationResourceName: buildOp.name }));
|
|
202
180
|
const [rollout, build] = await Promise.all([rolloutPoll, buildPoll]);
|
package/lib/serve/functions.js
CHANGED
|
@@ -8,6 +8,7 @@ const auth_1 = require("../auth");
|
|
|
8
8
|
const projectConfig = require("../functions/projectConfig");
|
|
9
9
|
const utils = require("../utils");
|
|
10
10
|
const registry_1 = require("../emulator/registry");
|
|
11
|
+
const commandUtils_1 = require("../emulator/commandUtils");
|
|
11
12
|
class FunctionsServer {
|
|
12
13
|
assertServer() {
|
|
13
14
|
if (!this.emulator || !this.backends) {
|
|
@@ -31,7 +32,7 @@ class FunctionsServer {
|
|
|
31
32
|
}
|
|
32
33
|
this.backends = backends;
|
|
33
34
|
const account = (0, auth_1.getProjectDefaultAccount)(options.config.projectDir);
|
|
34
|
-
const args = Object.assign({ projectId, projectDir: options.config.projectDir, emulatableBackends: this.backends, projectAlias: options.projectAlias, account }, partialArgs);
|
|
35
|
+
const args = Object.assign(Object.assign({ projectId, projectDir: options.config.projectDir, emulatableBackends: this.backends, projectAlias: options.projectAlias, account }, partialArgs), { debugPort: (0, commandUtils_1.parseInspectionPort)(options) });
|
|
35
36
|
if (options.host) {
|
|
36
37
|
utils.assertIsStringOrUndefined(options.host);
|
|
37
38
|
args.host = options.host;
|