firebase-tools 13.6.1 → 13.7.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.
- package/lib/api.js +1 -1
- package/lib/apphosting/githubConnections.js +0 -1
- package/lib/commands/apphosting-secrets-access.js +24 -0
- package/lib/commands/apphosting-secrets-set.js +10 -7
- package/lib/commands/index.js +1 -0
- package/lib/deploy/functions/prompts.js +39 -7
- package/lib/deploy/functions/release/index.js +17 -2
- package/lib/deploy/functions/release/planner.js +11 -3
- package/lib/deploy/functions/services/index.js +4 -0
- package/lib/emulator/controller.js +2 -5
- package/lib/experiments.js +12 -0
- package/lib/frameworks/next/constants.js +2 -1
- package/lib/frameworks/next/index.js +22 -12
- package/lib/frameworks/next/utils.js +32 -3
- package/lib/functions/events/v2.js +7 -1
- package/lib/utils.js +6 -6
- package/package.json +1 -1
package/lib/api.js
CHANGED
|
@@ -62,7 +62,7 @@ const cloudbuildOrigin = () => utils.envOverride("FIREBASE_CLOUDBUILD_URL", "htt
|
|
|
62
62
|
exports.cloudbuildOrigin = cloudbuildOrigin;
|
|
63
63
|
const developerConnectOrigin = () => utils.envOverride("FIREBASE_DEVELOPERCONNECT_URL", "https://developerconnect.googleapis.com");
|
|
64
64
|
exports.developerConnectOrigin = developerConnectOrigin;
|
|
65
|
-
const developerConnectP4SAOrigin = () => utils.envOverride("FIREBASE_DEVELOPERCONNECT_P4SA_URL", "gcp-sa-
|
|
65
|
+
const developerConnectP4SAOrigin = () => utils.envOverride("FIREBASE_DEVELOPERCONNECT_P4SA_URL", "gcp-sa-devconnect.iam.gserviceaccount.com");
|
|
66
66
|
exports.developerConnectP4SAOrigin = developerConnectP4SAOrigin;
|
|
67
67
|
const cloudschedulerOrigin = () => utils.envOverride("FIREBASE_CLOUDSCHEDULER_URL", "https://cloudscheduler.googleapis.com");
|
|
68
68
|
exports.cloudschedulerOrigin = cloudschedulerOrigin;
|
|
@@ -58,7 +58,6 @@ async function linkGitHubRepository(projectId, location) {
|
|
|
58
58
|
const oauthConn = await getOrCreateOauthConnection(projectId, location);
|
|
59
59
|
const existingConns = await listAppHostingConnections(projectId);
|
|
60
60
|
if (existingConns.length === 0) {
|
|
61
|
-
utils.logBullet("no connections exist");
|
|
62
61
|
existingConns.push(await createFullyInstalledConnection(projectId, location, generateConnectionId(), oauthConn));
|
|
63
62
|
}
|
|
64
63
|
let repoCloneUri;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const logger_1 = require("../logger");
|
|
6
|
+
const projectUtils_1 = require("../projectUtils");
|
|
7
|
+
const secretManager_1 = require("../gcp/secretManager");
|
|
8
|
+
const requireAuth_1 = require("../requireAuth");
|
|
9
|
+
const secretManager = require("../gcp/secretManager");
|
|
10
|
+
const requirePermissions_1 = require("../requirePermissions");
|
|
11
|
+
exports.command = new command_1.Command("apphosting:secrets:access <secretName>[@version]")
|
|
12
|
+
.description("Access secret value given secret and its version. Defaults to accessing the latest version.")
|
|
13
|
+
.before(requireAuth_1.requireAuth)
|
|
14
|
+
.before(secretManager.ensureApi)
|
|
15
|
+
.before(requirePermissions_1.requirePermissions, ["secretmanager.versions.access"])
|
|
16
|
+
.action(async (key, options) => {
|
|
17
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
18
|
+
let [name, version] = key.split("@");
|
|
19
|
+
if (!version) {
|
|
20
|
+
version = "latest";
|
|
21
|
+
}
|
|
22
|
+
const value = await (0, secretManager_1.accessSecretVersion)(projectId, name, version);
|
|
23
|
+
logger_1.logger.info(value);
|
|
24
|
+
});
|
|
@@ -35,9 +35,10 @@ exports.command = new command_1.Command("apphosting:secrets:set <secretName>")
|
|
|
35
35
|
.action(async (secretName, options) => {
|
|
36
36
|
var _a;
|
|
37
37
|
const howToAccess = `You can access the contents of the secret's latest value with ${clc.bold(`firebase apphosting:secrets:access ${secretName}`)}`;
|
|
38
|
+
const grantAccess = `To use this secret in your backend, you must grant access. You can do so in the future with ${clc.bold("firebase apphosting:secrets:grantAccess")}`;
|
|
38
39
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
39
40
|
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
40
|
-
const created = secrets.upsertSecret(projectId, secretName, options.location);
|
|
41
|
+
const created = await secrets.upsertSecret(projectId, secretName, options.location);
|
|
41
42
|
if (created === null) {
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
@@ -55,17 +56,19 @@ exports.command = new command_1.Command("apphosting:secrets:set <secretName>")
|
|
|
55
56
|
}
|
|
56
57
|
secretValue = fs.readFileSync(dataFile, "utf-8");
|
|
57
58
|
}
|
|
59
|
+
if (created) {
|
|
60
|
+
(0, utils_1.logSuccess)(`Created new secret projects/${projectId}/secrets/${secretName}`);
|
|
61
|
+
}
|
|
62
|
+
const version = await gcsm.addVersion(projectId, secretName, secretValue);
|
|
63
|
+
(0, utils_1.logSuccess)(`Created new secret version ${gcsm.toSecretVersionResourceName(version)}`);
|
|
64
|
+
(0, utils_1.logSuccess)(howToAccess);
|
|
58
65
|
if (!created) {
|
|
59
|
-
|
|
60
|
-
(0, utils_1.logSuccess)(`Created new secret version ${gcsm.toSecretVersionResourceName(version)}`);
|
|
61
|
-
(0, utils_1.logSuccess)(howToAccess);
|
|
66
|
+
(0, utils_1.logWarning)(grantAccess);
|
|
62
67
|
return;
|
|
63
68
|
}
|
|
64
|
-
(0, utils_1.logSuccess)(`Created new secret projects/${projectId}/secrets/${secretName}`);
|
|
65
|
-
(0, utils_1.logSuccess)(howToAccess);
|
|
66
69
|
const accounts = await dialogs.selectBackendServiceAccounts(projectNumber, projectId, options);
|
|
67
70
|
if (!accounts.buildServiceAccounts.length && !accounts.runServiceAccounts.length) {
|
|
68
|
-
(0, utils_1.logWarning)(
|
|
71
|
+
(0, utils_1.logWarning)(grantAccess);
|
|
69
72
|
}
|
|
70
73
|
else {
|
|
71
74
|
await secrets.grantSecretAccess(projectId, secretName, accounts);
|
package/lib/commands/index.js
CHANGED
|
@@ -169,6 +169,7 @@ function load(client) {
|
|
|
169
169
|
client.apphosting.secrets.set = loadCommand("apphosting-secrets-set");
|
|
170
170
|
client.apphosting.secrets.grantaccess = loadCommand("apphosting-secrets-grantaccess");
|
|
171
171
|
client.apphosting.secrets.describe = loadCommand("apphosting-secrets-describe");
|
|
172
|
+
client.apphosting.secrets.access = loadCommand("apphosting-secrets-access");
|
|
172
173
|
client.apphosting.rollouts = {};
|
|
173
174
|
client.apphosting.rollouts.create = loadCommand("apphosting-rollouts-create");
|
|
174
175
|
client.apphosting.rollouts.list = loadCommand("apphosting-rollouts-list");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.promptForMinInstances = exports.promptForFunctionDeletion = exports.promptForFailurePolicies = void 0;
|
|
3
|
+
exports.promptForMinInstances = exports.promptForUnsafeMigration = exports.promptForFunctionDeletion = exports.promptForFailurePolicies = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const functionsDeployHelper_1 = require("./functionsDeployHelper");
|
|
6
6
|
const error_1 = require("../../error");
|
|
@@ -49,16 +49,16 @@ async function promptForFailurePolicies(options, want, have) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
exports.promptForFailurePolicies = promptForFailurePolicies;
|
|
52
|
-
async function promptForFunctionDeletion(functionsToDelete,
|
|
52
|
+
async function promptForFunctionDeletion(functionsToDelete, options) {
|
|
53
53
|
let shouldDeleteFns = true;
|
|
54
|
-
if (functionsToDelete.length === 0 || force) {
|
|
54
|
+
if (functionsToDelete.length === 0 || options.force) {
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
const deleteList = functionsToDelete
|
|
58
58
|
.sort(backend.compareFunctions)
|
|
59
59
|
.map((fn) => "\t" + (0, functionsDeployHelper_1.getFunctionLabel)(fn))
|
|
60
60
|
.join("\n");
|
|
61
|
-
if (nonInteractive) {
|
|
61
|
+
if (options.nonInteractive) {
|
|
62
62
|
const deleteCommands = functionsToDelete
|
|
63
63
|
.map((func) => {
|
|
64
64
|
return "\tfirebase functions:delete " + func.id + " --region " + func.region;
|
|
@@ -75,9 +75,7 @@ async function promptForFunctionDeletion(functionsToDelete, force, nonInteractiv
|
|
|
75
75
|
"\n\nIf you are renaming a function or changing its region, it is recommended that you create the new " +
|
|
76
76
|
"function first before deleting the old one to prevent event loss. For more info, visit " +
|
|
77
77
|
clc.underline("https://firebase.google.com/docs/functions/manage-functions#modify" + "\n"));
|
|
78
|
-
shouldDeleteFns = await (0, prompt_1.
|
|
79
|
-
type: "confirm",
|
|
80
|
-
name: "confirm",
|
|
78
|
+
shouldDeleteFns = await (0, prompt_1.confirm)({
|
|
81
79
|
default: false,
|
|
82
80
|
message: "Would you like to proceed with deletion? Selecting no will continue the rest of the deployments.",
|
|
83
81
|
});
|
|
@@ -85,6 +83,40 @@ async function promptForFunctionDeletion(functionsToDelete, force, nonInteractiv
|
|
|
85
83
|
return shouldDeleteFns;
|
|
86
84
|
}
|
|
87
85
|
exports.promptForFunctionDeletion = promptForFunctionDeletion;
|
|
86
|
+
async function promptForUnsafeMigration(fnsToUpdate, options) {
|
|
87
|
+
const unsafeUpdates = fnsToUpdate.filter((eu) => eu.unsafe);
|
|
88
|
+
if (unsafeUpdates.length === 0 || options.force) {
|
|
89
|
+
return fnsToUpdate;
|
|
90
|
+
}
|
|
91
|
+
const warnMessage = "The following functions are unsafely changing event types: " +
|
|
92
|
+
clc.bold(unsafeUpdates
|
|
93
|
+
.map((eu) => eu.endpoint)
|
|
94
|
+
.sort(backend.compareFunctions)
|
|
95
|
+
.map(functionsDeployHelper_1.getFunctionLabel)
|
|
96
|
+
.join(", ")) +
|
|
97
|
+
". " +
|
|
98
|
+
"While automatic migration is allowed for these functions, updating the underlying event type may result in data loss. " +
|
|
99
|
+
"To avoid this, consider the best practices outlined in the migration guide: https://firebase.google.com/docs/functions/manage-functions?gen=2nd#modify-trigger";
|
|
100
|
+
utils.logLabeledWarning("functions", warnMessage);
|
|
101
|
+
const safeUpdates = fnsToUpdate.filter((eu) => !eu.unsafe);
|
|
102
|
+
if (options.nonInteractive) {
|
|
103
|
+
utils.logLabeledWarning("functions", "Skipping updates for functions that may be unsafe to update. To update these functions anyway, deploy again in interactive mode or use the --force option.");
|
|
104
|
+
return safeUpdates;
|
|
105
|
+
}
|
|
106
|
+
for (const eu of unsafeUpdates) {
|
|
107
|
+
const shouldUpdate = await (0, prompt_1.promptOnce)({
|
|
108
|
+
type: "confirm",
|
|
109
|
+
name: "confirm",
|
|
110
|
+
default: false,
|
|
111
|
+
message: `[${(0, functionsDeployHelper_1.getFunctionLabel)(eu.endpoint)}] Would you like to proceed with the unsafe migration?`,
|
|
112
|
+
});
|
|
113
|
+
if (shouldUpdate) {
|
|
114
|
+
safeUpdates.push(eu);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return safeUpdates;
|
|
118
|
+
}
|
|
119
|
+
exports.promptForUnsafeMigration = promptForUnsafeMigration;
|
|
88
120
|
async function promptForMinInstances(options, want, have) {
|
|
89
121
|
if (options.force) {
|
|
90
122
|
return;
|
|
@@ -11,6 +11,7 @@ const fabricator = require("./fabricator");
|
|
|
11
11
|
const reporter = require("./reporter");
|
|
12
12
|
const executor = require("./executor");
|
|
13
13
|
const prompts = require("../prompts");
|
|
14
|
+
const experiments = require("../../../experiments");
|
|
14
15
|
const functionsConfig_1 = require("../../../functionsConfig");
|
|
15
16
|
const functionsDeployHelper_1 = require("../functionsDeployHelper");
|
|
16
17
|
const error_1 = require("../../../error");
|
|
@@ -37,12 +38,24 @@ async function release(context, options, payload) {
|
|
|
37
38
|
const fnsToDelete = Object.values(plan)
|
|
38
39
|
.map((regionalChanges) => regionalChanges.endpointsToDelete)
|
|
39
40
|
.reduce(functional_1.reduceFlat, []);
|
|
40
|
-
const shouldDelete = await prompts.promptForFunctionDeletion(fnsToDelete, options
|
|
41
|
+
const shouldDelete = await prompts.promptForFunctionDeletion(fnsToDelete, options);
|
|
41
42
|
if (!shouldDelete) {
|
|
42
43
|
for (const change of Object.values(plan)) {
|
|
43
44
|
change.endpointsToDelete = [];
|
|
44
45
|
}
|
|
45
46
|
}
|
|
47
|
+
const fnsToUpdate = Object.values(plan)
|
|
48
|
+
.map((regionalChanges) => regionalChanges.endpointsToUpdate)
|
|
49
|
+
.reduce(functional_1.reduceFlat, []);
|
|
50
|
+
const fnsToUpdateSafe = await prompts.promptForUnsafeMigration(fnsToUpdate, options);
|
|
51
|
+
for (const key of Object.keys(plan)) {
|
|
52
|
+
plan[key].endpointsToUpdate = [];
|
|
53
|
+
}
|
|
54
|
+
for (const eu of fnsToUpdateSafe) {
|
|
55
|
+
const e = eu.endpoint;
|
|
56
|
+
const key = `${e.codebase || ""}-${e.region}-${e.availableMemoryMb || "default"}`;
|
|
57
|
+
plan[key].endpointsToUpdate.push(eu);
|
|
58
|
+
}
|
|
46
59
|
const throttlerOptions = {
|
|
47
60
|
retries: 30,
|
|
48
61
|
backoff: 20000,
|
|
@@ -65,7 +78,9 @@ async function release(context, options, payload) {
|
|
|
65
78
|
const deletedEndpoints = Object.values(plan)
|
|
66
79
|
.map((r) => r.endpointsToDelete)
|
|
67
80
|
.reduce(functional_1.reduceFlat, []);
|
|
68
|
-
|
|
81
|
+
if (experiments.isEnabled("automaticallydeletegcfartifacts")) {
|
|
82
|
+
await containerCleaner.cleanupBuildImages(haveEndpoints, deletedEndpoints);
|
|
83
|
+
}
|
|
69
84
|
const allErrors = summary.results.filter((r) => r.error).map((r) => r.error);
|
|
70
85
|
if (allErrors.length) {
|
|
71
86
|
const opts = allErrors.length === 1 ? { original: allErrors[0] } : { children: allErrors };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkForV2Upgrade = exports.checkForIllegalUpdate = exports.upgradedScheduleFromV1ToV2 = exports.changedV2PubSubTopic = exports.changedTriggerRegion = exports.upgradedToGCFv2WithoutSettingConcurrency = exports.createDeploymentPlan = exports.calculateUpdate = exports.calculateChangesets = void 0;
|
|
4
|
-
const clc = require("colorette");
|
|
3
|
+
exports.checkForV2Upgrade = exports.checkForIllegalUpdate = exports.checkForUnsafeUpdate = exports.upgradedScheduleFromV1ToV2 = exports.changedV2PubSubTopic = exports.changedTriggerRegion = exports.upgradedToGCFv2WithoutSettingConcurrency = exports.createDeploymentPlan = exports.calculateUpdate = exports.calculateChangesets = void 0;
|
|
5
4
|
const functionsDeployHelper_1 = require("../functionsDeployHelper");
|
|
6
5
|
const deploymentTool_1 = require("../../../deploymentTool");
|
|
7
6
|
const error_1 = require("../../../error");
|
|
8
7
|
const utils = require("../../../utils");
|
|
9
8
|
const backend = require("../backend");
|
|
10
9
|
const v2events = require("../../../functions/events/v2");
|
|
10
|
+
const v2_1 = require("../../../functions/events/v2");
|
|
11
11
|
function calculateChangesets(want, have, keyFn, deleteAll) {
|
|
12
12
|
const toCreate = utils.groupBy(Object.keys(want)
|
|
13
13
|
.filter((id) => !have[id])
|
|
@@ -29,7 +29,7 @@ function calculateChangesets(want, have, keyFn, deleteAll) {
|
|
|
29
29
|
}, {});
|
|
30
30
|
const toSkip = utils.groupBy(Object.values(toSkipEndpointsMap), keyFn);
|
|
31
31
|
if (Object.keys(toSkip).length) {
|
|
32
|
-
utils.logLabeledBullet("functions",
|
|
32
|
+
utils.logLabeledBullet("functions", "Skipping the deploy of unchanged functions.");
|
|
33
33
|
}
|
|
34
34
|
const toUpdate = utils.groupBy(Object.keys(want)
|
|
35
35
|
.filter((id) => have[id])
|
|
@@ -57,6 +57,7 @@ function calculateUpdate(want, have) {
|
|
|
57
57
|
checkForIllegalUpdate(want, have);
|
|
58
58
|
const update = {
|
|
59
59
|
endpoint: want,
|
|
60
|
+
unsafe: checkForUnsafeUpdate(want, have),
|
|
60
61
|
};
|
|
61
62
|
const needsDelete = changedTriggerRegion(want, have) ||
|
|
62
63
|
changedV2PubSubTopic(want, have) ||
|
|
@@ -164,6 +165,13 @@ function upgradedScheduleFromV1ToV2(want, have) {
|
|
|
164
165
|
return true;
|
|
165
166
|
}
|
|
166
167
|
exports.upgradedScheduleFromV1ToV2 = upgradedScheduleFromV1ToV2;
|
|
168
|
+
function checkForUnsafeUpdate(want, have) {
|
|
169
|
+
return (backend.isEventTriggered(want) &&
|
|
170
|
+
v2_1.FIRESTORE_EVENT_WITH_AUTH_CONTEXT_REGEX.test(want.eventTrigger.eventType) &&
|
|
171
|
+
backend.isEventTriggered(have) &&
|
|
172
|
+
v2_1.FIRESTORE_EVENT_REGEX.test(have.eventTrigger.eventType));
|
|
173
|
+
}
|
|
174
|
+
exports.checkForUnsafeUpdate = checkForUnsafeUpdate;
|
|
167
175
|
function checkForIllegalUpdate(want, have) {
|
|
168
176
|
const triggerType = (e) => {
|
|
169
177
|
if (backend.isHttpsTriggered(e)) {
|
|
@@ -104,6 +104,10 @@ const EVENT_SERVICE_MAPPING = {
|
|
|
104
104
|
"google.cloud.firestore.document.v1.created": firestoreService,
|
|
105
105
|
"google.cloud.firestore.document.v1.updated": firestoreService,
|
|
106
106
|
"google.cloud.firestore.document.v1.deleted": firestoreService,
|
|
107
|
+
"google.cloud.firestore.document.v1.written.withAuthContext": firestoreService,
|
|
108
|
+
"google.cloud.firestore.document.v1.created.withAuthContext": firestoreService,
|
|
109
|
+
"google.cloud.firestore.document.v1.updated.withAuthContext": firestoreService,
|
|
110
|
+
"google.cloud.firestore.document.v1.deleted.withAuthContext": firestoreService,
|
|
107
111
|
};
|
|
108
112
|
function serviceForEndpoint(endpoint) {
|
|
109
113
|
if (backend.isEventTriggered(endpoint)) {
|
|
@@ -309,11 +309,8 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
309
309
|
utils.assertIsStringOrUndefined(options.extDevDir);
|
|
310
310
|
for (const cfg of functionsCfg) {
|
|
311
311
|
const functionsDir = path.join(projectDir, cfg.source);
|
|
312
|
-
|
|
313
|
-
if (!runtime) {
|
|
314
|
-
runtime = (0, supported_1.latest)("nodejs");
|
|
315
|
-
}
|
|
316
|
-
if (!(0, supported_1.isRuntime)(runtime)) {
|
|
312
|
+
const runtime = ((_e = options.extDevRuntime) !== null && _e !== void 0 ? _e : cfg.runtime);
|
|
313
|
+
if (runtime && !(0, supported_1.isRuntime)(runtime)) {
|
|
317
314
|
throw new error_1.FirebaseError(`Cannot load functions from ${functionsDir} because it has invalid runtime ${runtime}`);
|
|
318
315
|
}
|
|
319
316
|
emulatableBackends.push({
|
package/lib/experiments.js
CHANGED
|
@@ -39,6 +39,18 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
39
39
|
"of how that image was created.",
|
|
40
40
|
public: true,
|
|
41
41
|
},
|
|
42
|
+
automaticallydeletegcfartifacts: {
|
|
43
|
+
shortDescription: "Control whether functions cleans up images after deploys",
|
|
44
|
+
fullDescription: "To control costs, Firebase defaults to automatically deleting containers " +
|
|
45
|
+
"created during the build process. This has the side-effect of preventing " +
|
|
46
|
+
"users from rolling back to previous revisions using the Run API. To change " +
|
|
47
|
+
`this behavior, call ${(0, colorette_1.bold)("experiments:disable deletegcfartifactsondeploy")} ` +
|
|
48
|
+
`consider also calling ${(0, colorette_1.bold)("experiments:enable deletegcfartifacts")} ` +
|
|
49
|
+
`to enable the new command ${(0, colorette_1.bold)("functions:deletegcfartifacts")} which` +
|
|
50
|
+
"lets you clean up images manually",
|
|
51
|
+
public: true,
|
|
52
|
+
default: true,
|
|
53
|
+
},
|
|
42
54
|
emulatoruisnapshot: {
|
|
43
55
|
shortDescription: "Load pre-release versions of the emulator UI",
|
|
44
56
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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;
|
|
3
|
+
exports.WEBPACK_LAYERS = exports.ESBUILD_VERSION = exports.CONFIG_FILES = 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";
|
|
@@ -10,6 +10,7 @@ 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
12
|
exports.SERVER_REFERENCE_MANIFEST = "server-reference-manifest.json";
|
|
13
|
+
exports.CONFIG_FILES = ["next.config.js", "next.config.mjs"];
|
|
13
14
|
exports.ESBUILD_VERSION = "0.19.2";
|
|
14
15
|
const WEBPACK_LAYERS_NAMES = {
|
|
15
16
|
shared: "shared",
|
|
@@ -7,7 +7,6 @@ const promises_1 = require("fs/promises");
|
|
|
7
7
|
const path_1 = require("path");
|
|
8
8
|
const fs_extra_1 = require("fs-extra");
|
|
9
9
|
const url_1 = require("url");
|
|
10
|
-
const fs_1 = require("fs");
|
|
11
10
|
const semver_1 = require("semver");
|
|
12
11
|
const clc = require("colorette");
|
|
13
12
|
const stream_chain_1 = require("stream-chain");
|
|
@@ -40,7 +39,7 @@ async function discover(dir) {
|
|
|
40
39
|
if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
|
|
41
40
|
return;
|
|
42
41
|
const version = (0, utils_2.getNextVersion)(dir);
|
|
43
|
-
if (!(await (0,
|
|
42
|
+
if (!(await (0, utils_2.whichNextConfigFile)(dir)) && !version)
|
|
44
43
|
return;
|
|
45
44
|
return { mayWantBackend: true, publicDirectory: (0, path_1.join)(dir, PUBLIC_DIR), version };
|
|
46
45
|
}
|
|
@@ -336,7 +335,8 @@ exports.ɵcodegenPublicDirectory = ɵcodegenPublicDirectory;
|
|
|
336
335
|
async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context) {
|
|
337
336
|
const { distDir } = await getConfig(sourceDir);
|
|
338
337
|
const packageJson = await (0, utils_1.readJSON)((0, path_1.join)(sourceDir, "package.json"));
|
|
339
|
-
|
|
338
|
+
const configFile = await (0, utils_2.whichNextConfigFile)(sourceDir);
|
|
339
|
+
if (configFile) {
|
|
340
340
|
try {
|
|
341
341
|
const productionDeps = await new Promise((resolve) => {
|
|
342
342
|
const dependencies = [];
|
|
@@ -361,8 +361,14 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
361
361
|
});
|
|
362
362
|
const esbuildArgs = productionDeps
|
|
363
363
|
.map((it) => `--external:${it}`)
|
|
364
|
-
.concat("--bundle", "--platform=node", `--target=node${constants_1.NODE_VERSION}`,
|
|
365
|
-
|
|
364
|
+
.concat("--bundle", "--platform=node", `--target=node${constants_1.NODE_VERSION}`, "--log-level=error");
|
|
365
|
+
if (configFile === "next.config.mjs") {
|
|
366
|
+
esbuildArgs.push(...[`--outfile=${(0, path_1.join)(destDir, configFile)}`, "--format=esm"]);
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
esbuildArgs.push(`--outfile=${(0, path_1.join)(destDir, configFile)}`);
|
|
370
|
+
}
|
|
371
|
+
const bundle = (0, cross_spawn_1.sync)("npx", ["--yes", `esbuild@${constants_2.ESBUILD_VERSION}`, configFile, ...esbuildArgs], {
|
|
366
372
|
cwd: sourceDir,
|
|
367
373
|
timeout: BUNDLE_NEXT_CONFIG_TIMEOUT,
|
|
368
374
|
});
|
|
@@ -371,9 +377,9 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
371
377
|
}
|
|
372
378
|
}
|
|
373
379
|
catch (e) {
|
|
374
|
-
console.warn(
|
|
380
|
+
console.warn(`Unable to bundle ${configFile} for use in Cloud Functions, proceeding with deploy but problems may be encountered.`);
|
|
375
381
|
console.error(e.message || e);
|
|
376
|
-
(0, fs_extra_1.copy)((0, path_1.join)(sourceDir,
|
|
382
|
+
await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, configFile), (0, path_1.join)(destDir, configFile));
|
|
377
383
|
}
|
|
378
384
|
}
|
|
379
385
|
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(sourceDir, "public"))) {
|
|
@@ -390,8 +396,11 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
390
396
|
dotEnv["VERCEL_URL"] = deploymentDomain;
|
|
391
397
|
}
|
|
392
398
|
}
|
|
393
|
-
|
|
394
|
-
|
|
399
|
+
const [productionDistDirfiles] = await Promise.all([
|
|
400
|
+
(0, utils_2.getProductionDistDirFiles)(sourceDir, distDir),
|
|
401
|
+
(0, fs_extra_1.mkdirp)((0, path_1.join)(destDir, distDir)),
|
|
402
|
+
]);
|
|
403
|
+
await Promise.all(productionDistDirfiles.map((file) => (0, fs_extra_1.copy)(file, file.replace(sourceDir, destDir), { recursive: true })));
|
|
395
404
|
return { packageJson, frameworksEntry: "next.js", dotEnv };
|
|
396
405
|
}
|
|
397
406
|
exports.ɵcodegenFunctionsDirectory = ɵcodegenFunctionsDirectory;
|
|
@@ -422,7 +431,8 @@ async function getConfig(dir) {
|
|
|
422
431
|
var _a;
|
|
423
432
|
var _b;
|
|
424
433
|
let config = {};
|
|
425
|
-
|
|
434
|
+
const configFile = await (0, utils_2.whichNextConfigFile)(dir);
|
|
435
|
+
if (configFile) {
|
|
426
436
|
const version = (0, utils_2.getNextVersion)(dir);
|
|
427
437
|
if (!version)
|
|
428
438
|
throw new Error("Unable to find the next dep, try NPM installing?");
|
|
@@ -435,10 +445,10 @@ async function getConfig(dir) {
|
|
|
435
445
|
}
|
|
436
446
|
else {
|
|
437
447
|
try {
|
|
438
|
-
config = await (_a = (0, url_1.pathToFileURL)((0, path_1.join)(dir,
|
|
448
|
+
config = await (_a = (0, url_1.pathToFileURL)((0, path_1.join)(dir, configFile)).toString(), Promise.resolve().then(() => require(_a)));
|
|
439
449
|
}
|
|
440
450
|
catch (e) {
|
|
441
|
-
throw new Error(
|
|
451
|
+
throw new Error(`Unable to load ${configFile}.`);
|
|
442
452
|
}
|
|
443
453
|
}
|
|
444
454
|
}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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;
|
|
3
|
+
exports.whichNextConfigFile = exports.getProductionDistDirFiles = exports.getRoutesWithServerAction = exports.hasStaticAppNotFoundComponent = exports.getNextVersion = exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = exports.isUsingNextImageInAppDirectory = exports.isUsingImageOptimization = exports.isUsingMiddleware = exports.hasUnoptimizedImage = exports.usesNextImage = exports.usesAppDirRouter = exports.getNextjsRewritesToUse = exports.isHeaderSupportedByHosting = exports.isRedirectSupportedByHosting = exports.isRewriteSupportedByHosting = exports.cleanI18n = exports.cleanCustomRouteI18n = exports.cleanEscapedChars = exports.I18N_SOURCE = void 0;
|
|
4
4
|
const fs_1 = require("fs");
|
|
5
5
|
const fs_extra_1 = require("fs-extra");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const promises_1 = require("fs/promises");
|
|
8
8
|
const glob_1 = require("glob");
|
|
9
|
+
const glob = require("glob");
|
|
9
10
|
const semver_1 = require("semver");
|
|
10
11
|
const utils_1 = require("../utils");
|
|
11
12
|
const constants_1 = require("./constants");
|
|
12
13
|
const fsutils_1 = require("../../fsutils");
|
|
14
|
+
const utils_2 = require("../../utils");
|
|
13
15
|
exports.I18N_SOURCE = /\/:nextInternalLocale(\([^\)]+\))?/;
|
|
14
16
|
function cleanEscapedChars(path) {
|
|
15
17
|
return path.replace(/\\([(){}:+?*])/g, (a, b) => b);
|
|
@@ -101,10 +103,15 @@ async function isUsingImageOptimization(projectDir, distDir) {
|
|
|
101
103
|
}
|
|
102
104
|
exports.isUsingImageOptimization = isUsingImageOptimization;
|
|
103
105
|
async function isUsingNextImageInAppDirectory(projectDir, nextDir) {
|
|
106
|
+
const nextImagePath = ["node_modules", "next", "dist", "client", "image"];
|
|
107
|
+
const nextImageString = utils_2.IS_WINDOWS
|
|
108
|
+
?
|
|
109
|
+
nextImagePath.join(path_1.sep + path_1.sep)
|
|
110
|
+
: (0, path_1.join)(...nextImagePath);
|
|
104
111
|
const files = (0, glob_1.sync)((0, path_1.join)(projectDir, nextDir, "server", "**", "*client-reference-manifest.js"));
|
|
105
112
|
for (const filepath of files) {
|
|
106
|
-
const fileContents = await (0, promises_1.readFile)(filepath);
|
|
107
|
-
if (fileContents.includes(
|
|
113
|
+
const fileContents = await (0, promises_1.readFile)(filepath, "utf-8");
|
|
114
|
+
if (fileContents.includes(nextImageString)) {
|
|
108
115
|
return true;
|
|
109
116
|
}
|
|
110
117
|
}
|
|
@@ -218,3 +225,25 @@ function getRoutesWithServerAction(serverReferenceManifest, appPathRoutesManifes
|
|
|
218
225
|
return Array.from(routesWithServerAction);
|
|
219
226
|
}
|
|
220
227
|
exports.getRoutesWithServerAction = getRoutesWithServerAction;
|
|
228
|
+
async function getProductionDistDirFiles(sourceDir, distDir) {
|
|
229
|
+
const productionDistDirFiles = await new Promise((resolve, reject) => glob("**", {
|
|
230
|
+
ignore: [(0, path_1.join)("cache", "webpack", "*-development", "**"), (0, path_1.join)("cache", "eslint", "**")],
|
|
231
|
+
cwd: (0, path_1.join)(sourceDir, distDir),
|
|
232
|
+
nodir: true,
|
|
233
|
+
absolute: true,
|
|
234
|
+
}, (err, matches) => {
|
|
235
|
+
if (err)
|
|
236
|
+
reject(err);
|
|
237
|
+
resolve(matches);
|
|
238
|
+
}));
|
|
239
|
+
return productionDistDirFiles;
|
|
240
|
+
}
|
|
241
|
+
exports.getProductionDistDirFiles = getProductionDistDirFiles;
|
|
242
|
+
async function whichNextConfigFile(dir) {
|
|
243
|
+
for (const file of constants_1.CONFIG_FILES) {
|
|
244
|
+
if (await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, file)))
|
|
245
|
+
return file;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
exports.whichNextConfigFile = whichNextConfigFile;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
3
|
+
exports.FIRESTORE_EVENT_WITH_AUTH_CONTEXT_REGEX = exports.FIRESTORE_EVENT_REGEX = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
4
4
|
exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
|
|
5
5
|
exports.STORAGE_EVENTS = [
|
|
6
6
|
"google.cloud.storage.object.v1.finalized",
|
|
@@ -22,4 +22,10 @@ exports.FIRESTORE_EVENTS = [
|
|
|
22
22
|
"google.cloud.firestore.document.v1.created",
|
|
23
23
|
"google.cloud.firestore.document.v1.updated",
|
|
24
24
|
"google.cloud.firestore.document.v1.deleted",
|
|
25
|
+
"google.cloud.firestore.document.v1.written.withAuthContext",
|
|
26
|
+
"google.cloud.firestore.document.v1.created.withAuthContext",
|
|
27
|
+
"google.cloud.firestore.document.v1.updated.withAuthContext",
|
|
28
|
+
"google.cloud.firestore.document.v1.deleted.withAuthContext",
|
|
25
29
|
];
|
|
30
|
+
exports.FIRESTORE_EVENT_REGEX = /^google\.cloud\.firestore\.document\.v1\.[^\.]*$/;
|
|
31
|
+
exports.FIRESTORE_EVENT_WITH_AUTH_CONTEXT_REGEX = /^google\.cloud\.firestore\.document\.v1\..*\.withAuthContext$/;
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getHostnameFromUrl = exports.openInBrowserPopup = exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isVSCodeExtension = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
3
|
+
exports.getHostnameFromUrl = exports.openInBrowserPopup = exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isVSCodeExtension = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = exports.IS_WINDOWS = void 0;
|
|
4
4
|
const fs = require("node:fs");
|
|
5
5
|
const path = require("node:path");
|
|
6
6
|
const _ = require("lodash");
|
|
@@ -19,10 +19,10 @@ const portfinder_1 = require("portfinder");
|
|
|
19
19
|
const configstore_1 = require("./configstore");
|
|
20
20
|
const error_1 = require("./error");
|
|
21
21
|
const logger_1 = require("./logger");
|
|
22
|
-
|
|
23
|
-
const SUCCESS_CHAR = IS_WINDOWS ? "+" : "✔";
|
|
24
|
-
const WARNING_CHAR = IS_WINDOWS ? "!" : "⚠";
|
|
25
|
-
const ERROR_CHAR = IS_WINDOWS ? "!!" : "⬢";
|
|
22
|
+
exports.IS_WINDOWS = process.platform === "win32";
|
|
23
|
+
const SUCCESS_CHAR = exports.IS_WINDOWS ? "+" : "✔";
|
|
24
|
+
const WARNING_CHAR = exports.IS_WINDOWS ? "!" : "⚠";
|
|
25
|
+
const ERROR_CHAR = exports.IS_WINDOWS ? "!!" : "⬢";
|
|
26
26
|
const THIRTY_DAYS_IN_MILLISECONDS = 30 * 24 * 60 * 60 * 1000;
|
|
27
27
|
exports.envOverrides = [];
|
|
28
28
|
function consoleUrl(project, path) {
|
|
@@ -148,7 +148,7 @@ function allSettled(promises) {
|
|
|
148
148
|
}
|
|
149
149
|
exports.allSettled = allSettled;
|
|
150
150
|
function explainStdin() {
|
|
151
|
-
if (IS_WINDOWS) {
|
|
151
|
+
if (exports.IS_WINDOWS) {
|
|
152
152
|
throw new error_1.FirebaseError("STDIN input is not available on Windows.", {
|
|
153
153
|
exit: 1,
|
|
154
154
|
});
|