firebase-tools 12.4.4 → 12.4.6
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 +4 -8
- package/lib/auth.js +1 -1
- package/lib/commands/functions-secrets-set.js +18 -2
- package/lib/deploy/firestore/prepare.js +4 -4
- package/lib/deploy/functions/release/fabricator.js +6 -6
- package/lib/emulator/auth/operations.js +2 -2
- package/lib/emulator/constants.js +1 -0
- package/lib/emulator/ui.js +3 -0
- package/lib/ensureApiEnabled.js +22 -1
- package/lib/extensions/tos.js +35 -23
- package/lib/firestore/fsConfig.js +8 -1
- package/lib/frameworks/frameworks.js +2 -0
- package/lib/frameworks/next/index.js +4 -9
- package/lib/frameworks/next/utils.js +32 -9
- package/lib/functions/secrets.js +36 -16
- package/lib/functionsShellCommandAction.js +4 -3
- package/lib/gcp/cloudfunctionsv2.js +7 -7
- package/lib/utils.js +1 -9
- package/package.json +2 -2
package/lib/apiv2.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Client = exports.setAccessToken = exports.setRefreshToken = void 0;
|
|
4
4
|
const url_1 = require("url");
|
|
5
5
|
const stream_1 = require("stream");
|
|
6
|
-
const
|
|
6
|
+
const proxy_agent_1 = require("proxy-agent");
|
|
7
7
|
const retry = require("retry");
|
|
8
8
|
const abort_controller_1 = require("abort-controller");
|
|
9
9
|
const node_fetch_1 = require("node-fetch");
|
|
@@ -146,7 +146,7 @@ class Client {
|
|
|
146
146
|
if (accessToken) {
|
|
147
147
|
return accessToken;
|
|
148
148
|
}
|
|
149
|
-
const data =
|
|
149
|
+
const data = await auth.getAccessToken(refreshToken, []);
|
|
150
150
|
return data.access_token;
|
|
151
151
|
}
|
|
152
152
|
requestURL(options) {
|
|
@@ -179,12 +179,8 @@ class Client {
|
|
|
179
179
|
redirect: options.redirect,
|
|
180
180
|
compress: options.compress,
|
|
181
181
|
};
|
|
182
|
-
if (
|
|
183
|
-
fetchOptions.agent = new ProxyAgent(
|
|
184
|
-
}
|
|
185
|
-
const envProxy = proxyURIFromEnv();
|
|
186
|
-
if (envProxy) {
|
|
187
|
-
fetchOptions.agent = new ProxyAgent(envProxy);
|
|
182
|
+
if (proxyURIFromEnv()) {
|
|
183
|
+
fetchOptions.agent = new proxy_agent_1.ProxyAgent();
|
|
188
184
|
}
|
|
189
185
|
if (options.signal) {
|
|
190
186
|
fetchOptions.signal = options.signal;
|
package/lib/auth.js
CHANGED
|
@@ -509,7 +509,7 @@ async function refreshTokens(refreshToken, authScopes) {
|
|
|
509
509
|
}
|
|
510
510
|
}
|
|
511
511
|
async function getAccessToken(refreshToken, authScopes) {
|
|
512
|
-
if (haveValidTokens(refreshToken, authScopes)) {
|
|
512
|
+
if (haveValidTokens(refreshToken, authScopes) && lastAccessToken) {
|
|
513
513
|
return lastAccessToken;
|
|
514
514
|
}
|
|
515
515
|
return refreshTokens(refreshToken, authScopes);
|
|
@@ -12,9 +12,9 @@ const prompt_1 = require("../prompt");
|
|
|
12
12
|
const utils_1 = require("../utils");
|
|
13
13
|
const projectUtils_1 = require("../projectUtils");
|
|
14
14
|
const secretManager_1 = require("../gcp/secretManager");
|
|
15
|
+
const ensureApiEnabled_1 = require("../ensureApiEnabled");
|
|
15
16
|
const secrets = require("../functions/secrets");
|
|
16
17
|
const backend = require("../deploy/functions/backend");
|
|
17
|
-
const ensureApiEnabled_1 = require("../ensureApiEnabled");
|
|
18
18
|
exports.command = new command_1.Command("functions:secrets:set <KEY>")
|
|
19
19
|
.description("Create or update a secret for use in Cloud Functions for Firebase.")
|
|
20
20
|
.withForce("Automatically updates functions to use the new secret.")
|
|
@@ -58,7 +58,7 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
|
|
|
58
58
|
logger_1.logger.debug("Customer set secrets before enabling functions. Exiting");
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
let haveBackend = await backend.existingBackend({ projectId });
|
|
62
62
|
const endpointsToUpdate = backend
|
|
63
63
|
.allEndpoints(haveBackend)
|
|
64
64
|
.filter((e) => secrets.inUse({ projectId, projectNumber }, secret, e));
|
|
@@ -87,4 +87,20 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
|
|
|
87
87
|
return updated;
|
|
88
88
|
});
|
|
89
89
|
await Promise.all(updateOps);
|
|
90
|
+
haveBackend = await backend.existingBackend({ projectId }, true);
|
|
91
|
+
const staleEndpoints = backend.allEndpoints(backend.matchingBackend(haveBackend, (e) => {
|
|
92
|
+
const pInfo = { projectId, projectNumber };
|
|
93
|
+
return secrets.inUse(pInfo, secret, e) && !secrets.versionInUse(pInfo, secretVersion, e);
|
|
94
|
+
}));
|
|
95
|
+
if (staleEndpoints.length !== 0) {
|
|
96
|
+
(0, utils_1.logWarning)(`${staleEndpoints.length} functions are unexpectedly using old version of secret ${secret.name} still:\n\t` +
|
|
97
|
+
staleEndpoints.map((e) => `${e.id}(${e.region})`).join("\n\t"));
|
|
98
|
+
(0, utils_1.logBullet)("Please deploy your functions manually for the change to take effect by running:\n\t" +
|
|
99
|
+
clc.bold("firebase deploy --only functions"));
|
|
100
|
+
}
|
|
101
|
+
const secretsToPrune = (await secrets.pruneSecrets({ projectId, projectNumber }, backend.allEndpoints(haveBackend))).filter((sv) => sv.key === key);
|
|
102
|
+
(0, utils_1.logBullet)(`Removing secret versions: ${secretsToPrune
|
|
103
|
+
.map((sv) => sv.key + "[" + sv.version + "]")
|
|
104
|
+
.join(", ")}`);
|
|
105
|
+
await Promise.all(secretsToPrune.map((sv) => (0, secretManager_1.destroySecretVersion)(projectId, sv.secret, sv.version)));
|
|
90
106
|
});
|
|
@@ -25,11 +25,11 @@ function prepareIndexes(context, options, databaseId, indexesFileName) {
|
|
|
25
25
|
async function default_1(context, options) {
|
|
26
26
|
if (options.only) {
|
|
27
27
|
const targets = options.only.split(",");
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const excludeRules = targets.indexOf("firestore:indexes") >= 0;
|
|
29
|
+
const excludeIndexes = targets.indexOf("firestore:rules") >= 0;
|
|
30
30
|
const onlyFirestore = targets.indexOf("firestore") >= 0;
|
|
31
|
-
context.firestoreIndexes =
|
|
32
|
-
context.firestoreRules =
|
|
31
|
+
context.firestoreIndexes = !excludeIndexes || onlyFirestore;
|
|
32
|
+
context.firestoreRules = !excludeRules || onlyFirestore;
|
|
33
33
|
}
|
|
34
34
|
else {
|
|
35
35
|
context.firestoreIndexes = true;
|
|
@@ -223,12 +223,12 @@ class Fabricator {
|
|
|
223
223
|
}
|
|
224
224
|
async createV2Function(endpoint) {
|
|
225
225
|
var _a, _b, _c, _d, _e;
|
|
226
|
-
const
|
|
227
|
-
if (!
|
|
226
|
+
const storageSource = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
|
|
227
|
+
if (!storageSource) {
|
|
228
228
|
logger_1.logger.debug("Precondition failed. Cannot create a GCFv2 function without storage");
|
|
229
229
|
throw new Error("Precondition failed");
|
|
230
230
|
}
|
|
231
|
-
const apiFunction = gcfV2.functionFromEndpoint(endpoint,
|
|
231
|
+
const apiFunction = gcfV2.functionFromEndpoint(Object.assign(Object.assign({}, endpoint), { source: { storageSource } }));
|
|
232
232
|
const topic = (_b = apiFunction.eventTrigger) === null || _b === void 0 ? void 0 : _b.pubsubTopic;
|
|
233
233
|
if (topic) {
|
|
234
234
|
await this.executor
|
|
@@ -368,12 +368,12 @@ class Fabricator {
|
|
|
368
368
|
}
|
|
369
369
|
async updateV2Function(endpoint) {
|
|
370
370
|
var _a, _b, _c, _d;
|
|
371
|
-
const
|
|
372
|
-
if (!
|
|
371
|
+
const storageSource = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
|
|
372
|
+
if (!storageSource) {
|
|
373
373
|
logger_1.logger.debug("Precondition failed. Cannot update a GCFv2 function without storage");
|
|
374
374
|
throw new Error("Precondition failed");
|
|
375
375
|
}
|
|
376
|
-
const apiFunction = gcfV2.functionFromEndpoint(endpoint,
|
|
376
|
+
const apiFunction = gcfV2.functionFromEndpoint(Object.assign(Object.assign({}, endpoint), { source: { storageSource } }));
|
|
377
377
|
if ((_b = apiFunction.eventTrigger) === null || _b === void 0 ? void 0 : _b.pubsubTopic) {
|
|
378
378
|
delete apiFunction.eventTrigger.pubsubTopic;
|
|
379
379
|
}
|
|
@@ -146,13 +146,13 @@ async function signUp(state, reqBody, ctx) {
|
|
|
146
146
|
(0, errors_1.assert)(state.enableAnonymousUser, "ADMIN_ONLY_OPERATION");
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
|
-
if (
|
|
149
|
+
if (reqBody.email || (reqBody.email === "" && provider)) {
|
|
150
150
|
(0, errors_1.assert)((0, utils_1.isValidEmailAddress)(reqBody.email), "INVALID_EMAIL");
|
|
151
151
|
const email = (0, utils_1.canonicalizeEmailAddress)(reqBody.email);
|
|
152
152
|
(0, errors_1.assert)(!state.getUserByEmail(email), "EMAIL_EXISTS");
|
|
153
153
|
updates.email = email;
|
|
154
154
|
}
|
|
155
|
-
if (
|
|
155
|
+
if (reqBody.password) {
|
|
156
156
|
(0, errors_1.assert)(reqBody.password.length >= PASSWORD_MIN_LENGTH, `WEAK_PASSWORD : Password should be at least ${PASSWORD_MIN_LENGTH} characters`);
|
|
157
157
|
updates.salt = "fakeSalt" + (0, utils_1.randomId)(20);
|
|
158
158
|
updates.passwordHash = hashPassword(reqBody.password, updates.salt);
|
|
@@ -88,6 +88,7 @@ exports.Constants = Constants;
|
|
|
88
88
|
Constants.FAKE_PROJECT_ID_PREFIX = "demo-";
|
|
89
89
|
Constants.FAKE_PROJECT_NUMBER = "0";
|
|
90
90
|
Constants.DEFAULT_DATABASE_EMULATOR_NAMESPACE = "fake-server";
|
|
91
|
+
Constants.FIREBASE_ENABLED_EXPERIMENTS = "FIREBASE_ENABLED_EXPERIMENTS";
|
|
91
92
|
Constants.FIRESTORE_EMULATOR_HOST = "FIRESTORE_EMULATOR_HOST";
|
|
92
93
|
Constants.FIRESTORE_EMULATOR_ENV_ALT = "FIREBASE_FIRESTORE_EMULATOR_ADDRESS";
|
|
93
94
|
Constants.FIREBASE_DATABASE_EMULATOR_HOST = "FIREBASE_DATABASE_EMULATOR_HOST";
|
package/lib/emulator/ui.js
CHANGED
|
@@ -8,6 +8,7 @@ const error_1 = require("../error");
|
|
|
8
8
|
const constants_1 = require("./constants");
|
|
9
9
|
const track_1 = require("../track");
|
|
10
10
|
const ExpressBasedEmulator_1 = require("./ExpressBasedEmulator");
|
|
11
|
+
const experiments_1 = require("../experiments");
|
|
11
12
|
class EmulatorUI {
|
|
12
13
|
constructor(args) {
|
|
13
14
|
this.args = args;
|
|
@@ -26,6 +27,8 @@ class EmulatorUI {
|
|
|
26
27
|
if (session) {
|
|
27
28
|
env[constants_1.Constants.FIREBASE_GA_SESSION] = JSON.stringify(session);
|
|
28
29
|
}
|
|
30
|
+
const enabledExperiments = Object.keys(experiments_1.ALL_EXPERIMENTS).filter((experimentName) => (0, experiments_1.isEnabled)(experimentName));
|
|
31
|
+
env[constants_1.Constants.FIREBASE_ENABLED_EXPERIMENTS] = JSON.stringify(enabledExperiments);
|
|
29
32
|
return downloadableEmulators.start(types_1.Emulators.UI, { auto_download: autoDownload }, env);
|
|
30
33
|
}
|
|
31
34
|
connect() {
|
package/lib/ensureApiEnabled.js
CHANGED
|
@@ -27,6 +27,10 @@ async function check(projectId, apiName, prefix, silent = false) {
|
|
|
27
27
|
return isEnabled;
|
|
28
28
|
}
|
|
29
29
|
exports.check = check;
|
|
30
|
+
function isPermissionError(e) {
|
|
31
|
+
var _a, _b, _c;
|
|
32
|
+
return ((_c = (_b = (_a = e.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.status) === "PERMISSION_DENIED";
|
|
33
|
+
}
|
|
30
34
|
async function enable(projectId, apiName) {
|
|
31
35
|
try {
|
|
32
36
|
await apiClient.post(`/projects/${projectId}/services/${apiName}:enable`, undefined, {
|
|
@@ -40,7 +44,24 @@ async function enable(projectId, apiName) {
|
|
|
40
44
|
|
|
41
45
|
https://console.firebase.google.com/project/${projectId}/usage/details`);
|
|
42
46
|
}
|
|
43
|
-
|
|
47
|
+
else if (isPermissionError(err)) {
|
|
48
|
+
const apiPermissionDeniedRegex = new RegExp(/Permission denied to enable service \[([.a-zA-Z]+)\]/);
|
|
49
|
+
const permissionsError = apiPermissionDeniedRegex.exec(err.message);
|
|
50
|
+
if (permissionsError && permissionsError[1]) {
|
|
51
|
+
const serviceUrl = permissionsError[1];
|
|
52
|
+
err.message = `Permissions denied enabling ${serviceUrl}.
|
|
53
|
+
Please ask a project owner to visit the following URL to enable this service:
|
|
54
|
+
|
|
55
|
+
https://console.cloud.google.com/apis/library/${serviceUrl}?project=${projectId}`;
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw err;
|
|
64
|
+
}
|
|
44
65
|
}
|
|
45
66
|
}
|
|
46
67
|
async function pollCheckEnabled(projectId, apiName, prefix, silent, enablementRetries, pollRetries = 0) {
|
package/lib/extensions/tos.js
CHANGED
|
@@ -39,36 +39,48 @@ async function acceptPublisherTOS(projectId, tosVersion) {
|
|
|
39
39
|
}
|
|
40
40
|
exports.acceptPublisherTOS = acceptPublisherTOS;
|
|
41
41
|
async function acceptLatestPublisherTOS(options, projectId) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
try {
|
|
43
|
+
logger_1.logger.debug(`Checking if latest publisher TOS has been accepted by ${projectId}...`);
|
|
44
|
+
const currentAcceptance = await getPublisherTOSStatus(projectId);
|
|
45
|
+
if (currentAcceptance.lastAcceptedVersion) {
|
|
46
|
+
logger_1.logger.debug(`Already accepted version ${currentAcceptance.lastAcceptedVersion} of Extensions publisher TOS.`);
|
|
47
|
+
return currentAcceptance;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const tosLink = extensionsTosUrl("publisher");
|
|
51
|
+
logger_1.logger.info(`To continue, you must accept the Firebase Extensions Publisher Terms of Service: ${tosLink}`);
|
|
52
|
+
if (await (0, prompt_1.confirm)(Object.assign(Object.assign({}, options), { message: "Do you accept the Firebase Extensions Publisher Terms of Service?" }))) {
|
|
53
|
+
return acceptPublisherTOS(projectId, currentAcceptance.latestTosVersion);
|
|
54
|
+
}
|
|
53
55
|
}
|
|
54
|
-
throw new error_1.FirebaseError("You must accept the terms of service to continue.");
|
|
55
56
|
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
logger_1.logger.debug(`Error when checking Publisher TOS for ${projectId}. This is expected if authenticated via a service account: ${err}`);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
throw new error_1.FirebaseError("You must accept the terms of service to continue.");
|
|
56
62
|
}
|
|
57
63
|
exports.acceptLatestPublisherTOS = acceptLatestPublisherTOS;
|
|
58
64
|
async function acceptLatestAppDeveloperTOS(options, projectId, instanceIds) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
try {
|
|
66
|
+
logger_1.logger.debug(`Checking if latest AppDeveloper TOS has been accepted by ${projectId}...`);
|
|
67
|
+
displayDeveloperTOSWarning();
|
|
68
|
+
const currentAcceptance = await getAppDeveloperTOSStatus(projectId);
|
|
69
|
+
if (currentAcceptance.lastAcceptedVersion) {
|
|
70
|
+
logger_1.logger.debug(`User Terms of Service aready accepted on project ${projectId}.`);
|
|
71
|
+
}
|
|
72
|
+
else if (!(await (0, prompt_1.confirm)(Object.assign(Object.assign({}, options), { message: "Do you accept the Firebase Extensions User Terms of Service?" })))) {
|
|
73
|
+
throw new error_1.FirebaseError("You must accept the terms of service to continue.");
|
|
74
|
+
}
|
|
75
|
+
const tosPromises = instanceIds.map((instanceId) => {
|
|
76
|
+
return acceptAppDeveloperTOS(projectId, currentAcceptance.latestTosVersion, instanceId);
|
|
77
|
+
});
|
|
78
|
+
return Promise.all(tosPromises);
|
|
64
79
|
}
|
|
65
|
-
|
|
66
|
-
|
|
80
|
+
catch (err) {
|
|
81
|
+
logger_1.logger.debug(`Error when checking App Developer TOS for ${projectId}. This is expected if authenticated via a service account: ${err}`);
|
|
82
|
+
return [];
|
|
67
83
|
}
|
|
68
|
-
const tosPromises = instanceIds.map((instanceId) => {
|
|
69
|
-
return acceptAppDeveloperTOS(projectId, currentAcceptance.latestTosVersion, instanceId);
|
|
70
|
-
});
|
|
71
|
-
return Promise.all(tosPromises);
|
|
72
84
|
}
|
|
73
85
|
exports.acceptLatestAppDeveloperTOS = acceptLatestAppDeveloperTOS;
|
|
74
86
|
function displayDeveloperTOSWarning() {
|
|
@@ -49,14 +49,21 @@ function getFirestoreConfig(projectId, options) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
else if (database) {
|
|
52
|
-
if (allDatabases) {
|
|
52
|
+
if (allDatabases || onlyDatabases.has(database)) {
|
|
53
53
|
results.push(c);
|
|
54
|
+
onlyDatabases.delete(database);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
else {
|
|
57
58
|
throw new error_1.FirebaseError('Must supply either "target" or "databaseId" in firestore config');
|
|
58
59
|
}
|
|
59
60
|
}
|
|
61
|
+
if (onlyDatabases.has("rules")) {
|
|
62
|
+
onlyDatabases.delete("rules");
|
|
63
|
+
}
|
|
64
|
+
if (onlyDatabases.has("indexes")) {
|
|
65
|
+
onlyDatabases.delete("indexes");
|
|
66
|
+
}
|
|
60
67
|
if (!allDatabases && onlyDatabases.size !== 0) {
|
|
61
68
|
throw new error_1.FirebaseError(`Could not find configurations in firebase.json for the following database targets: ${[
|
|
62
69
|
...onlyDatabases,
|
|
@@ -13,6 +13,7 @@ const svelte = require("./svelte");
|
|
|
13
13
|
const svelekit = require("./sveltekit");
|
|
14
14
|
const react = require("./react");
|
|
15
15
|
const vite = require("./vite");
|
|
16
|
+
const flutter = require("./flutter");
|
|
16
17
|
exports.WebFrameworks = {
|
|
17
18
|
angular,
|
|
18
19
|
astro,
|
|
@@ -26,4 +27,5 @@ exports.WebFrameworks = {
|
|
|
26
27
|
svelekit,
|
|
27
28
|
react,
|
|
28
29
|
vite,
|
|
30
|
+
flutter,
|
|
29
31
|
};
|
|
@@ -30,10 +30,6 @@ exports.support = "preview";
|
|
|
30
30
|
exports.type = 2;
|
|
31
31
|
exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/nextjs";
|
|
32
32
|
const DEFAULT_NUMBER_OF_REASONS_TO_LIST = 5;
|
|
33
|
-
function getNextVersion(cwd) {
|
|
34
|
-
var _a;
|
|
35
|
-
return (_a = (0, utils_1.findDependency)("next", { cwd, depth: 0, omitDev: false })) === null || _a === void 0 ? void 0 : _a.version;
|
|
36
|
-
}
|
|
37
33
|
function getReactVersion(cwd) {
|
|
38
34
|
var _a;
|
|
39
35
|
return (_a = (0, utils_1.findDependency)("react-dom", { cwd, omitDev: false })) === null || _a === void 0 ? void 0 : _a.version;
|
|
@@ -41,7 +37,7 @@ function getReactVersion(cwd) {
|
|
|
41
37
|
async function discover(dir) {
|
|
42
38
|
if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
|
|
43
39
|
return;
|
|
44
|
-
if (!(await (0, fs_extra_1.pathExists)("next.config.js")) && !getNextVersion(dir))
|
|
40
|
+
if (!(await (0, fs_extra_1.pathExists)("next.config.js")) && !(0, utils_2.getNextVersion)(dir))
|
|
45
41
|
return;
|
|
46
42
|
return { mayWantBackend: true, publicDirectory: (0, path_1.join)(dir, PUBLIC_DIR) };
|
|
47
43
|
}
|
|
@@ -72,7 +68,7 @@ async function build(dir) {
|
|
|
72
68
|
if (await (0, utils_2.isUsingMiddleware)((0, path_1.join)(dir, distDir), false)) {
|
|
73
69
|
reasonsForBackend.add("middleware");
|
|
74
70
|
}
|
|
75
|
-
if (await (0, utils_2.isUsingImageOptimization)(
|
|
71
|
+
if (await (0, utils_2.isUsingImageOptimization)(dir, distDir)) {
|
|
76
72
|
reasonsForBackend.add(`Image Optimization`);
|
|
77
73
|
}
|
|
78
74
|
const prerenderManifest = await (0, utils_1.readJSON)((0, path_1.join)(dir, distDir, constants_2.PRERENDER_MANIFEST));
|
|
@@ -349,8 +345,7 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir) {
|
|
|
349
345
|
await (0, promises_1.mkdir)((0, path_1.join)(destDir, "public"));
|
|
350
346
|
await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, "public"), (0, path_1.join)(destDir, "public"));
|
|
351
347
|
}
|
|
352
|
-
if (
|
|
353
|
-
((0, utils_2.usesAppDirRouter)(sourceDir) || (await (0, utils_2.usesNextImage)(sourceDir, distDir)))) {
|
|
348
|
+
if (await (0, utils_2.isUsingImageOptimization)(sourceDir, distDir)) {
|
|
354
349
|
packageJson.dependencies["sharp"] = constants_1.SHARP_VERSION;
|
|
355
350
|
}
|
|
356
351
|
await (0, fs_extra_1.mkdirp)((0, path_1.join)(destDir, distDir));
|
|
@@ -386,7 +381,7 @@ async function getConfig(dir) {
|
|
|
386
381
|
var _b;
|
|
387
382
|
let config = {};
|
|
388
383
|
if ((0, fs_1.existsSync)((0, path_1.join)(dir, "next.config.js"))) {
|
|
389
|
-
const version = getNextVersion(dir);
|
|
384
|
+
const version = (0, utils_2.getNextVersion)(dir);
|
|
390
385
|
if (!version)
|
|
391
386
|
throw new Error("Unable to find the next dep, try NPM installing?");
|
|
392
387
|
if ((0, semver_1.gte)(version, "12.0.0")) {
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getBuildId = exports.getHeadersFromMetaFiles = exports.getNonStaticServerComponents = exports.getNonStaticRoutes = exports.getMiddlewareMatcherRegexes = exports.allDependencyNames = exports.isUsingAppDirectory = 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.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
|
+
const promises_1 = require("fs/promises");
|
|
8
|
+
const glob_1 = require("glob");
|
|
9
|
+
const semver_1 = require("semver");
|
|
7
10
|
const utils_1 = require("../utils");
|
|
8
11
|
const constants_1 = require("./constants");
|
|
9
12
|
const fsutils_1 = require("../../fsutils");
|
|
10
|
-
const promises_1 = require("fs/promises");
|
|
11
13
|
exports.I18N_SOURCE = /\/:nextInternalLocale(\([^\)]+\))?/;
|
|
12
14
|
function cleanEscapedChars(path) {
|
|
13
15
|
return path.replace(/\\([(){}:+?*])/g, (a, b) => b);
|
|
@@ -84,20 +86,31 @@ async function isUsingMiddleware(dir, isDevMode) {
|
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
exports.isUsingMiddleware = isUsingMiddleware;
|
|
87
|
-
async function isUsingImageOptimization(
|
|
88
|
-
let
|
|
89
|
-
if (!isNextImageImported && isUsingAppDirectory(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
async function isUsingImageOptimization(projectDir, distDir) {
|
|
90
|
+
let isNextImageImported = await usesNextImage(projectDir, distDir);
|
|
91
|
+
if (!isNextImageImported && isUsingAppDirectory((0, path_1.join)(projectDir, distDir))) {
|
|
92
|
+
if (await isUsingNextImageInAppDirectory(projectDir, distDir)) {
|
|
93
|
+
isNextImageImported = true;
|
|
94
|
+
}
|
|
93
95
|
}
|
|
94
96
|
if (isNextImageImported) {
|
|
95
|
-
const imagesManifest = await (0, utils_1.readJSON)((0, path_1.join)(
|
|
97
|
+
const imagesManifest = await (0, utils_1.readJSON)((0, path_1.join)(projectDir, distDir, constants_1.IMAGES_MANIFEST));
|
|
96
98
|
return !imagesManifest.images.unoptimized;
|
|
97
99
|
}
|
|
98
100
|
return false;
|
|
99
101
|
}
|
|
100
102
|
exports.isUsingImageOptimization = isUsingImageOptimization;
|
|
103
|
+
async function isUsingNextImageInAppDirectory(projectDir, nextDir) {
|
|
104
|
+
const files = (0, glob_1.sync)((0, path_1.join)(projectDir, nextDir, "server", "**", "*client-reference-manifest.js"));
|
|
105
|
+
for (const filepath of files) {
|
|
106
|
+
const fileContents = await (0, promises_1.readFile)(filepath);
|
|
107
|
+
if (fileContents.includes("node_modules/next/dist/client/image")) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
exports.isUsingNextImageInAppDirectory = isUsingNextImageInAppDirectory;
|
|
101
114
|
function isUsingAppDirectory(dir) {
|
|
102
115
|
const appPathRoutesManifestPath = (0, path_1.join)(dir, constants_1.APP_PATH_ROUTES_MANIFEST);
|
|
103
116
|
return (0, fsutils_1.fileExistsSync)(appPathRoutesManifestPath);
|
|
@@ -172,3 +185,13 @@ async function getBuildId(distDir) {
|
|
|
172
185
|
return buildId.toString();
|
|
173
186
|
}
|
|
174
187
|
exports.getBuildId = getBuildId;
|
|
188
|
+
function getNextVersion(cwd) {
|
|
189
|
+
const dependency = (0, utils_1.findDependency)("next", { cwd, depth: 0, omitDev: false });
|
|
190
|
+
if (!dependency)
|
|
191
|
+
return undefined;
|
|
192
|
+
const nextVersionSemver = (0, semver_1.coerce)(dependency.version);
|
|
193
|
+
if (!nextVersionSemver)
|
|
194
|
+
return dependency.version;
|
|
195
|
+
return nextVersionSemver.toString();
|
|
196
|
+
}
|
|
197
|
+
exports.getNextVersion = getNextVersion;
|
package/lib/functions/secrets.js
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.inUse = exports.getSecretVersions = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.ensureApi = exports.labels = exports.isFirebaseManaged = void 0;
|
|
3
|
+
exports.updateEndpointSecret = exports.pruneAndDestroySecrets = exports.pruneSecrets = exports.versionInUse = exports.inUse = exports.getSecretVersions = exports.of = exports.ensureSecret = exports.ensureValidKey = exports.ensureApi = exports.labels = exports.isFirebaseManaged = void 0;
|
|
4
4
|
const utils = require("../utils");
|
|
5
5
|
const poller = require("../operation-poller");
|
|
6
|
-
const
|
|
6
|
+
const gcfV1 = require("../gcp/cloudfunctions");
|
|
7
|
+
const gcfV2 = require("../gcp/cloudfunctionsv2");
|
|
7
8
|
const ensureApiEnabled = require("../ensureApiEnabled");
|
|
9
|
+
const api_1 = require("../api");
|
|
8
10
|
const secretManager_1 = require("../gcp/secretManager");
|
|
9
11
|
const error_1 = require("../error");
|
|
10
12
|
const utils_1 = require("../utils");
|
|
11
13
|
const prompt_1 = require("../prompt");
|
|
12
14
|
const env_1 = require("./env");
|
|
13
15
|
const logger_1 = require("../logger");
|
|
14
|
-
const api_1 = require("../api");
|
|
15
16
|
const functional_1 = require("../functional");
|
|
16
17
|
const projectUtils_1 = require("../projectUtils");
|
|
17
18
|
const FIREBASE_MANAGED = "firebase-managed";
|
|
19
|
+
const gcfV1PollerOptions = {
|
|
20
|
+
apiOrigin: api_1.functionsOrigin,
|
|
21
|
+
apiVersion: "v1",
|
|
22
|
+
masterTimeout: 25 * 60 * 1000,
|
|
23
|
+
maxBackoff: 10000,
|
|
24
|
+
};
|
|
25
|
+
const gcfV2PollerOptions = {
|
|
26
|
+
apiOrigin: api_1.functionsV2Origin,
|
|
27
|
+
apiVersion: "v2",
|
|
28
|
+
masterTimeout: 25 * 60 * 1000,
|
|
29
|
+
maxBackoff: 10000,
|
|
30
|
+
};
|
|
18
31
|
function isFirebaseManaged(secret) {
|
|
19
32
|
return Object.keys(secret.labels || []).includes(FIREBASE_MANAGED);
|
|
20
33
|
}
|
|
@@ -110,6 +123,18 @@ function inUse(projectInfo, secret, endpoint) {
|
|
|
110
123
|
return false;
|
|
111
124
|
}
|
|
112
125
|
exports.inUse = inUse;
|
|
126
|
+
function versionInUse(projectInfo, sv, endpoint) {
|
|
127
|
+
const { projectId, projectNumber } = projectInfo;
|
|
128
|
+
for (const sev of of([endpoint])) {
|
|
129
|
+
if ((sev.projectId === projectId || sev.projectId === projectNumber) &&
|
|
130
|
+
sev.secret === sv.secret.name &&
|
|
131
|
+
sev.version === sv.versionId) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
exports.versionInUse = versionInUse;
|
|
113
138
|
async function pruneSecrets(projectInfo, endpoints) {
|
|
114
139
|
const { projectId, projectNumber } = projectInfo;
|
|
115
140
|
const pruneKey = (name, version) => `${name}@${version}`;
|
|
@@ -191,26 +216,21 @@ async function updateEndpointSecret(projectInfo, secretVersion, endpoint) {
|
|
|
191
216
|
updatedSevs.push(updatedSev);
|
|
192
217
|
}
|
|
193
218
|
if (endpoint.platform === "gcfv1") {
|
|
194
|
-
const fn =
|
|
195
|
-
const op = await
|
|
219
|
+
const fn = gcfV1.functionFromEndpoint(endpoint, "");
|
|
220
|
+
const op = await gcfV1.updateFunction({
|
|
196
221
|
name: fn.name,
|
|
197
222
|
runtime: fn.runtime,
|
|
198
223
|
entryPoint: fn.entryPoint,
|
|
199
224
|
secretEnvironmentVariables: updatedSevs,
|
|
200
225
|
});
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
apiVersion: gcf.API_VERSION,
|
|
204
|
-
masterTimeout: 25 * 60 * 1000,
|
|
205
|
-
maxBackoff: 10000,
|
|
206
|
-
pollerName: `update-${endpoint.region}-${endpoint.id}`,
|
|
207
|
-
operationResourceName: op.name,
|
|
208
|
-
};
|
|
209
|
-
const cfn = await poller.pollOperation(gcfV1PollerOptions);
|
|
210
|
-
return gcf.endpointFromFunction(cfn);
|
|
226
|
+
const cfn = await poller.pollOperation(Object.assign(Object.assign({}, gcfV1PollerOptions), { operationResourceName: op.name }));
|
|
227
|
+
return gcfV1.endpointFromFunction(cfn);
|
|
211
228
|
}
|
|
212
229
|
else if (endpoint.platform === "gcfv2") {
|
|
213
|
-
|
|
230
|
+
const fn = gcfV2.functionFromEndpoint(endpoint);
|
|
231
|
+
const op = await gcfV2.updateFunction(Object.assign(Object.assign({}, fn), { serviceConfig: Object.assign(Object.assign({}, fn.serviceConfig), { secretEnvironmentVariables: updatedSevs }) }));
|
|
232
|
+
const cfn = await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { operationResourceName: op.name }));
|
|
233
|
+
return gcfV2.endpointFromFunction(cfn);
|
|
214
234
|
}
|
|
215
235
|
else {
|
|
216
236
|
(0, functional_1.assertExhaustive)(endpoint.platform);
|
|
@@ -6,16 +6,17 @@ const repl = require("repl");
|
|
|
6
6
|
const _ = require("lodash");
|
|
7
7
|
const request = require("request");
|
|
8
8
|
const util = require("util");
|
|
9
|
+
const shell = require("./emulator/functionsEmulatorShell");
|
|
10
|
+
const commandUtils = require("./emulator/commandUtils");
|
|
9
11
|
const functions_1 = require("./serve/functions");
|
|
10
12
|
const localFunction_1 = require("./localFunction");
|
|
11
13
|
const utils = require("./utils");
|
|
12
14
|
const logger_1 = require("./logger");
|
|
13
|
-
const shell = require("./emulator/functionsEmulatorShell");
|
|
14
|
-
const commandUtils = require("./emulator/commandUtils");
|
|
15
15
|
const types_1 = require("./emulator/types");
|
|
16
16
|
const hubClient_1 = require("./emulator/hubClient");
|
|
17
17
|
const portUtils_1 = require("./emulator/portUtils");
|
|
18
18
|
const constants_1 = require("./emulator/constants");
|
|
19
|
+
const projectUtils_1 = require("./projectUtils");
|
|
19
20
|
const serveFunctions = new functions_1.FunctionsServer();
|
|
20
21
|
const actionFunction = async (options) => {
|
|
21
22
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -26,7 +27,7 @@ const actionFunction = async (options) => {
|
|
|
26
27
|
if (options.inspectFunctions) {
|
|
27
28
|
debugPort = commandUtils.parseInspectionPort(options);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
(0, projectUtils_1.needProjectId)(options);
|
|
30
31
|
const hubClient = new hubClient_1.EmulatorHubClient(options.project);
|
|
31
32
|
let remoteEmulators = {};
|
|
32
33
|
if (hubClient.foundHub()) {
|
|
@@ -168,8 +168,8 @@ async function deleteFunction(cloudFunction) {
|
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
exports.deleteFunction = deleteFunction;
|
|
171
|
-
function functionFromEndpoint(endpoint
|
|
172
|
-
var _a, _b;
|
|
171
|
+
function functionFromEndpoint(endpoint) {
|
|
172
|
+
var _a, _b, _c;
|
|
173
173
|
if (endpoint.platform !== "gcfv2") {
|
|
174
174
|
throw new error_1.FirebaseError("Trying to create a v2 CloudFunction with v1 API. This should never happen");
|
|
175
175
|
}
|
|
@@ -183,7 +183,7 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
183
183
|
runtime: endpoint.runtime,
|
|
184
184
|
entryPoint: endpoint.entryPoint,
|
|
185
185
|
source: {
|
|
186
|
-
storageSource: source,
|
|
186
|
+
storageSource: (_a = endpoint.source) === null || _a === void 0 ? void 0 : _a.storageSource,
|
|
187
187
|
},
|
|
188
188
|
environmentVariables: {},
|
|
189
189
|
},
|
|
@@ -213,7 +213,7 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
213
213
|
eventType: endpoint.eventTrigger.eventType,
|
|
214
214
|
};
|
|
215
215
|
if (gcfFunction.eventTrigger.eventType === v2_1.PUBSUB_PUBLISH_EVENT) {
|
|
216
|
-
if (!((
|
|
216
|
+
if (!((_b = endpoint.eventTrigger.eventFilters) === null || _b === void 0 ? void 0 : _b.topic)) {
|
|
217
217
|
throw new error_1.FirebaseError("Error: Pub/Sub event trigger is missing topic: " +
|
|
218
218
|
JSON.stringify(endpoint.eventTrigger, null, 2));
|
|
219
219
|
}
|
|
@@ -262,7 +262,7 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
262
262
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.CODEBASE_LABEL]: codebase });
|
|
263
263
|
}
|
|
264
264
|
else {
|
|
265
|
-
(
|
|
265
|
+
(_c = gcfFunction.labels) === null || _c === void 0 ? true : delete _c[constants_1.CODEBASE_LABEL];
|
|
266
266
|
}
|
|
267
267
|
if (endpoint.hash) {
|
|
268
268
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.HASH_LABEL]: endpoint.hash });
|
|
@@ -335,7 +335,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
335
335
|
}
|
|
336
336
|
const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
|
|
337
337
|
project,
|
|
338
|
-
region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime });
|
|
338
|
+
region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, source: gcfFunction.buildConfig.source });
|
|
339
339
|
if (gcfFunction.serviceConfig) {
|
|
340
340
|
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "ingressSettings", "environmentVariables", "secretEnvironmentVariables", "timeoutSeconds", "uri");
|
|
341
341
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccount", "serviceAccountEmail");
|
|
@@ -346,7 +346,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
346
346
|
}
|
|
347
347
|
const mem = mebibytes(prod);
|
|
348
348
|
if (!backend.isValidMemoryOption(mem)) {
|
|
349
|
-
logger_1.logger.
|
|
349
|
+
logger_1.logger.debug("Converting a function to an endpoint with an invalid memory option", mem);
|
|
350
350
|
}
|
|
351
351
|
return mem;
|
|
352
352
|
});
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.
|
|
3
|
+
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.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;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const url = require("url");
|
|
6
6
|
const clc = require("colorette");
|
|
@@ -375,14 +375,6 @@ function thirtyDaysFromNow() {
|
|
|
375
375
|
return new Date(Date.now() + THIRTY_DAYS_IN_MILLISECONDS);
|
|
376
376
|
}
|
|
377
377
|
exports.thirtyDaysFromNow = thirtyDaysFromNow;
|
|
378
|
-
function assertDefined(val, message) {
|
|
379
|
-
if (val === undefined || val === null) {
|
|
380
|
-
throw new assert_1.AssertionError({
|
|
381
|
-
message: message || `expected value to be defined but got "${val}"`,
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
exports.assertDefined = assertDefined;
|
|
386
378
|
function assertIsString(val, message) {
|
|
387
379
|
if (typeof val !== "string") {
|
|
388
380
|
throw new assert_1.AssertionError({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-tools",
|
|
3
|
-
"version": "12.4.
|
|
3
|
+
"version": "12.4.6",
|
|
4
4
|
"description": "Command-Line Interface for Firebase",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"p-limit": "^3.0.1",
|
|
100
100
|
"portfinder": "^1.0.32",
|
|
101
101
|
"progress": "^2.0.3",
|
|
102
|
-
"proxy-agent": "^
|
|
102
|
+
"proxy-agent": "^6.3.0",
|
|
103
103
|
"request": "^2.87.0",
|
|
104
104
|
"retry": "^0.13.1",
|
|
105
105
|
"rimraf": "^3.0.0",
|