firebase-tools 13.15.0 → 13.15.2
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/commands/deploy.js +3 -1
- package/lib/dataconnect/fileUtils.js +52 -11
- package/lib/dataconnect/provisionCloudSql.js +5 -1
- package/lib/deploy/extensions/planner.js +46 -1
- package/lib/deploy/extensions/prepare.js +99 -23
- package/lib/deploy/functions/build.js +5 -5
- package/lib/deploy/functions/deploy.js +12 -12
- package/lib/deploy/functions/params.js +5 -3
- package/lib/deploy/functions/prepare.js +16 -1
- package/lib/deploy/functions/release/index.js +4 -0
- package/lib/deploy/functions/runtimes/discovery/parsing.js +1 -1
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +46 -0
- package/lib/emulator/downloadableEmulators.js +9 -9
- package/lib/emulator/functionsEmulator.js +8 -1
- package/lib/extensions/askUserForEventsConfig.js +18 -8
- package/lib/extensions/askUserForParam.js +2 -1
- package/lib/extensions/displayExtensionInfo.js +5 -5
- package/lib/extensions/extensionsApi.js +1 -1
- package/lib/extensions/extensionsHelper.js +42 -3
- package/lib/extensions/localHelper.js +1 -1
- package/lib/extensions/refs.js +26 -11
- package/lib/extensions/runtimes/common.js +75 -0
- package/lib/extensions/types.js +56 -1
- package/lib/frameworks/constants.js +1 -1
- package/lib/frameworks/next/constants.js +1 -1
- package/lib/frameworks/next/index.js +35 -15
- package/lib/frameworks/next/utils.js +53 -1
- package/lib/init/features/dataconnect/index.js +10 -7
- package/lib/init/features/dataconnect/sdk.js +67 -51
- package/lib/prompt.js +22 -1
- package/package.json +1 -1
- package/templates/init/dataconnect/connector.yaml +5 -3
- package/templates/init/dataconnect/dataconnect.yaml +5 -5
- package/templates/init/dataconnect/mutations.gql +44 -29
- package/templates/init/dataconnect/queries.gql +66 -38
- package/templates/init/dataconnect/schema.gql +38 -21
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.askForEventArcLocation = exports.askShouldCollectEventsConfig = exports.askForAllowedEventTypes = exports.askForEventsConfig = exports.checkAllowedEventTypesResponse = void 0;
|
|
3
|
+
exports.askForEventArcLocation = exports.EXTENSIONS_DEFAULT_EVENT_ARC_REGION = exports.ALLOWED_EVENT_ARC_REGIONS = exports.askShouldCollectEventsConfig = exports.askForAllowedEventTypes = exports.getEventArcChannel = exports.askForEventsConfig = exports.checkAllowedEventTypesResponse = void 0;
|
|
4
4
|
const prompt_1 = require("../prompt");
|
|
5
5
|
const extensionsApi = require("../extensions/extensionsApi");
|
|
6
6
|
const utils = require("../utils");
|
|
@@ -23,7 +23,7 @@ function checkAllowedEventTypesResponse(response, validEvents) {
|
|
|
23
23
|
exports.checkAllowedEventTypesResponse = checkAllowedEventTypesResponse;
|
|
24
24
|
async function askForEventsConfig(events, projectId, instanceId) {
|
|
25
25
|
var _a, _b;
|
|
26
|
-
logger_1.logger.info(`\n${clc.bold("Enable Events")}: ${(0, marked_1.marked)("If you enable events, you can write custom event handlers ([https://firebase.google.com/docs/extensions/install-extensions#eventarc](https://firebase.google.com/docs/extensions/install-extensions#eventarc)) that respond to these events.\n\nYou can always enable or disable events later. Events will be emitted via Eventarc. Fees apply ([https://cloud.google.com/eventarc/pricing](https://cloud.google.com/eventarc/pricing)).")}`);
|
|
26
|
+
logger_1.logger.info(`\n${clc.bold("Enable Events")}: ${await (0, marked_1.marked)("If you enable events, you can write custom event handlers ([https://firebase.google.com/docs/extensions/install-extensions#eventarc](https://firebase.google.com/docs/extensions/install-extensions#eventarc)) that respond to these events.\n\nYou can always enable or disable events later. Events will be emitted via Eventarc. Fees apply ([https://cloud.google.com/eventarc/pricing](https://cloud.google.com/eventarc/pricing)).")}`);
|
|
27
27
|
if (!(await askShouldCollectEventsConfig())) {
|
|
28
28
|
return undefined;
|
|
29
29
|
}
|
|
@@ -38,11 +38,15 @@ async function askForEventsConfig(events, projectId, instanceId) {
|
|
|
38
38
|
const preselectedTypes = (_a = existingInstance === null || existingInstance === void 0 ? void 0 : existingInstance.config.allowedEventTypes) !== null && _a !== void 0 ? _a : [];
|
|
39
39
|
const oldLocation = (_b = existingInstance === null || existingInstance === void 0 ? void 0 : existingInstance.config.eventarcChannel) === null || _b === void 0 ? void 0 : _b.split("/")[3];
|
|
40
40
|
const location = await askForEventArcLocation(oldLocation);
|
|
41
|
-
const channel =
|
|
41
|
+
const channel = getEventArcChannel(projectId, location);
|
|
42
42
|
const allowedEventTypes = await askForAllowedEventTypes(events, preselectedTypes);
|
|
43
43
|
return { channel, allowedEventTypes };
|
|
44
44
|
}
|
|
45
45
|
exports.askForEventsConfig = askForEventsConfig;
|
|
46
|
+
function getEventArcChannel(projectId, location) {
|
|
47
|
+
return `projects/${projectId}/locations/${location}/channels/firebase`;
|
|
48
|
+
}
|
|
49
|
+
exports.getEventArcChannel = getEventArcChannel;
|
|
46
50
|
async function askForAllowedEventTypes(eventDescriptors, preselectedTypes) {
|
|
47
51
|
let valid = false;
|
|
48
52
|
let response = [];
|
|
@@ -75,21 +79,27 @@ async function askShouldCollectEventsConfig() {
|
|
|
75
79
|
});
|
|
76
80
|
}
|
|
77
81
|
exports.askShouldCollectEventsConfig = askShouldCollectEventsConfig;
|
|
82
|
+
exports.ALLOWED_EVENT_ARC_REGIONS = [
|
|
83
|
+
"us-central1",
|
|
84
|
+
"us-west1",
|
|
85
|
+
"europe-west4",
|
|
86
|
+
"asia-northeast1",
|
|
87
|
+
];
|
|
88
|
+
exports.EXTENSIONS_DEFAULT_EVENT_ARC_REGION = "us-central1";
|
|
78
89
|
async function askForEventArcLocation(preselectedLocation) {
|
|
79
90
|
let valid = false;
|
|
80
|
-
const allowedRegions = ["us-central1", "us-west1", "europe-west4", "asia-northeast1"];
|
|
81
91
|
let location = "";
|
|
82
92
|
while (!valid) {
|
|
83
93
|
location = await (0, prompt_1.promptOnce)({
|
|
84
94
|
name: "input",
|
|
85
95
|
type: "list",
|
|
86
|
-
default: preselectedLocation !== null && preselectedLocation !== void 0 ? preselectedLocation :
|
|
96
|
+
default: preselectedLocation !== null && preselectedLocation !== void 0 ? preselectedLocation : exports.EXTENSIONS_DEFAULT_EVENT_ARC_REGION,
|
|
87
97
|
message: "Which location would you like the Eventarc channel to live in? We recommend using the default option. A channel location that differs from the extension's Cloud Functions location can incur egress cost.",
|
|
88
|
-
choices:
|
|
98
|
+
choices: exports.ALLOWED_EVENT_ARC_REGIONS.map((e) => ({ checked: false, value: e })),
|
|
89
99
|
});
|
|
90
|
-
valid =
|
|
100
|
+
valid = exports.ALLOWED_EVENT_ARC_REGIONS.includes(location);
|
|
91
101
|
if (!valid) {
|
|
92
|
-
utils.logWarning(`Unexpected EventArc region '${location}' was specified. Allowed regions: ${
|
|
102
|
+
utils.logWarning(`Unexpected EventArc region '${location}' was specified. Allowed regions: ${exports.ALLOWED_EVENT_ARC_REGIONS.join(", ")}`);
|
|
93
103
|
}
|
|
94
104
|
}
|
|
95
105
|
return location;
|
|
@@ -255,7 +255,7 @@ async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
|
|
|
255
255
|
],
|
|
256
256
|
});
|
|
257
257
|
switch (action) {
|
|
258
|
-
case SecretUpdateAction.SET_NEW:
|
|
258
|
+
case SecretUpdateAction.SET_NEW: {
|
|
259
259
|
let secret;
|
|
260
260
|
let secretName;
|
|
261
261
|
if (paramSpec.default) {
|
|
@@ -288,6 +288,7 @@ async function promptReconfigureSecret(projectId, instanceId, paramSpec) {
|
|
|
288
288
|
else {
|
|
289
289
|
return "";
|
|
290
290
|
}
|
|
291
|
+
}
|
|
291
292
|
case SecretUpdateAction.LEAVE:
|
|
292
293
|
default:
|
|
293
294
|
return paramSpec.default || "";
|
|
@@ -50,7 +50,7 @@ async function displayExtensionVersionInfo(args) {
|
|
|
50
50
|
if (extensionVersion.buildSourceUri) {
|
|
51
51
|
const buildSourceUri = new URL(extensionVersion.buildSourceUri);
|
|
52
52
|
buildSourceUri.pathname = path.join(buildSourceUri.pathname, (_c = extensionVersion.extensionRoot) !== null && _c !== void 0 ? _c : "");
|
|
53
|
-
lines.push(`${clc.bold("Source in GitHub:")} ${buildSourceUri}`);
|
|
53
|
+
lines.push(`${clc.bold("Source in GitHub:")} ${buildSourceUri.toString()}`);
|
|
54
54
|
}
|
|
55
55
|
else {
|
|
56
56
|
lines.push(`${clc.bold("Source download URI:")} ${(_d = extensionVersion.sourceDownloadUri) !== null && _d !== void 0 ? _d : "-"}`);
|
|
@@ -105,24 +105,24 @@ function displayResources(spec) {
|
|
|
105
105
|
break;
|
|
106
106
|
default:
|
|
107
107
|
}
|
|
108
|
-
return ` - ${clc.
|
|
108
|
+
return ` - ${clc.blueBright(`${resource.name} (${type})`)}${resource.description ? `: ${resource.description}` : ""}`;
|
|
109
109
|
});
|
|
110
110
|
lines.push(...new Set((_a = spec.lifecycleEvents) === null || _a === void 0 ? void 0 : _a.map((event) => {
|
|
111
|
-
return ` - ${clc.
|
|
111
|
+
return ` - ${clc.blueBright(`${event.taskQueueTriggerFunction} (Cloud Task queue)`)}`;
|
|
112
112
|
})));
|
|
113
113
|
lines.push(...spec.params
|
|
114
114
|
.filter((param) => {
|
|
115
115
|
return param.type === "SECRET";
|
|
116
116
|
})
|
|
117
117
|
.map((param) => {
|
|
118
|
-
return ` - ${clc.
|
|
118
|
+
return ` - ${clc.blueBright(`${param.param} (Cloud Secret Manager secret)`)}`;
|
|
119
119
|
}));
|
|
120
120
|
return clc.bold("Resources created:\n") + (lines.length ? lines.join("\n") : " - None");
|
|
121
121
|
}
|
|
122
122
|
exports.displayResources = displayResources;
|
|
123
123
|
async function retrieveRoleInfo(role) {
|
|
124
124
|
const res = await iam.getRole(role);
|
|
125
|
-
return ` - ${clc.yellow(res.title)}${res.description ? `: ${res.description}` : ""}`;
|
|
125
|
+
return ` - ${clc.yellow(res.title || res.name)}${res.description ? `: ${res.description}` : ""}`;
|
|
126
126
|
}
|
|
127
127
|
exports.retrieveRoleInfo = retrieveRoleInfo;
|
|
128
128
|
async function displayRoles(roles) {
|
|
@@ -356,6 +356,6 @@ function refNotFoundError(ref) {
|
|
|
356
356
|
return new error_1.FirebaseError(`The extension reference '${clc.bold(ref.version ? refs.toExtensionVersionRef(ref) : refs.toExtensionRef(ref))}' doesn't exist. This could happen for two reasons:\n` +
|
|
357
357
|
` -The publisher ID '${clc.bold(ref.publisherId)}' doesn't exist or could be misspelled\n` +
|
|
358
358
|
` -The name of the ${ref.version ? "extension version" : "extension"} '${clc.bold(ref.version ? `${ref.extensionId}@${ref.version}` : ref.extensionId)}' doesn't exist or could be misspelled\n\n` +
|
|
359
|
-
`Please correct the extension reference and try again. If you meant to
|
|
359
|
+
`Please correct the extension reference and try again. If you meant to reference an extension from a local source, please provide a relative path prefixed with '${clc.bold("./")}', '${clc.bold("../")}', or '${clc.bold("~/")}'.}`, { status: 404 });
|
|
360
360
|
}
|
|
361
361
|
exports.refNotFoundError = refNotFoundError;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
3
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
4
|
+
var m = o[Symbol.asyncIterator], i;
|
|
5
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
6
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
7
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
8
|
+
};
|
|
2
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.diagnoseAndFixProject = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.getMissingPublisherError = exports.uploadExtensionVersionFromLocalSource = exports.uploadExtensionVersionFromGitHubSource = exports.unpackExtensionState = exports.getNextVersionByStage = exports.ensureExtensionsPublisherApiEnabled = exports.ensureExtensionsApiEnabled = exports.promptForExtensionRoot = exports.promptForValidRepoURI = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
|
|
10
|
+
exports.diagnoseAndFixProject = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.getMissingPublisherError = exports.uploadExtensionVersionFromLocalSource = exports.uploadExtensionVersionFromGitHubSource = exports.unpackExtensionState = exports.getNextVersionByStage = exports.ensureExtensionsPublisherApiEnabled = exports.ensureExtensionsApiEnabled = exports.promptForExtensionRoot = exports.promptForValidRepoURI = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteSecretParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
|
|
4
11
|
const clc = require("colorette");
|
|
5
12
|
const ora = require("ora");
|
|
6
13
|
const semver = require("semver");
|
|
@@ -126,6 +133,38 @@ function substituteParams(original, params) {
|
|
|
126
133
|
return JSON.parse(s);
|
|
127
134
|
}
|
|
128
135
|
exports.substituteParams = substituteParams;
|
|
136
|
+
async function substituteSecretParams(projectNumber, params) {
|
|
137
|
+
var _a, e_1, _b, _c;
|
|
138
|
+
const newParams = {};
|
|
139
|
+
try {
|
|
140
|
+
for (var _d = true, _e = __asyncValues(Object.entries(params)), _f; _f = await _e.next(), _a = _f.done, !_a;) {
|
|
141
|
+
_c = _f.value;
|
|
142
|
+
_d = false;
|
|
143
|
+
try {
|
|
144
|
+
const [key, value] = _c;
|
|
145
|
+
if (typeof value !== "string") {
|
|
146
|
+
newParams[key] =
|
|
147
|
+
`projects/${projectNumber}/secrets/${value.name}/versions/latest`;
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
newParams[key] = value;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
_d = true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
159
|
+
finally {
|
|
160
|
+
try {
|
|
161
|
+
if (!_d && !_a && (_b = _e.return)) await _b.call(_e);
|
|
162
|
+
}
|
|
163
|
+
finally { if (e_1) throw e_1.error; }
|
|
164
|
+
}
|
|
165
|
+
return newParams;
|
|
166
|
+
}
|
|
167
|
+
exports.substituteSecretParams = substituteSecretParams;
|
|
129
168
|
function populateDefaultParams(paramVars, paramSpecs) {
|
|
130
169
|
const newParams = paramVars;
|
|
131
170
|
for (const param of paramSpecs) {
|
|
@@ -472,7 +511,7 @@ function displayExtensionHeader(extensionRef, extension, extensionRoot) {
|
|
|
472
511
|
}
|
|
473
512
|
else {
|
|
474
513
|
logger_1.logger.info(`\n${clc.bold("Extension:")} ${extensionRef}\n` +
|
|
475
|
-
`${clc.bold("State:")} ${clc.bold(clc.
|
|
514
|
+
`${clc.bold("State:")} ${clc.bold(clc.blueBright("New"))}\n`);
|
|
476
515
|
}
|
|
477
516
|
}
|
|
478
517
|
async function fetchExtensionSource(repoUri, sourceRef, extensionRoot) {
|
|
@@ -794,7 +833,7 @@ async function instanceIdExists(projectId, instanceId) {
|
|
|
794
833
|
if (err.status === 404) {
|
|
795
834
|
return false;
|
|
796
835
|
}
|
|
797
|
-
const msg = `Unexpected error when checking if instance ID exists: ${err}`;
|
|
836
|
+
const msg = `Unexpected error when checking if instance ID exists: ${err.message}`;
|
|
798
837
|
throw new error_1.FirebaseError(msg, {
|
|
799
838
|
original: err,
|
|
800
839
|
});
|
|
@@ -38,7 +38,7 @@ function readFile(pathToFile) {
|
|
|
38
38
|
}
|
|
39
39
|
catch (err) {
|
|
40
40
|
if (err.code === "ENOENT") {
|
|
41
|
-
throw new error_1.FirebaseError(`Could not find "${pathToFile}"
|
|
41
|
+
throw new error_1.FirebaseError(`Could not find "${pathToFile}"`, { original: err });
|
|
42
42
|
}
|
|
43
43
|
throw new error_1.FirebaseError(`Failed to read file at "${pathToFile}"`, { original: err });
|
|
44
44
|
}
|
package/lib/extensions/refs.js
CHANGED
|
@@ -7,13 +7,16 @@ const refRegex = new RegExp(/^([^/@\n]+)\/{1}([^/@\n]+)(@{1}([^\n]+)|)$/);
|
|
|
7
7
|
function parse(refOrName) {
|
|
8
8
|
const ret = parseRef(refOrName) || parseName(refOrName);
|
|
9
9
|
if (!ret || !ret.publisherId || !ret.extensionId) {
|
|
10
|
-
throw new error_1.FirebaseError(`Unable to parse ${refOrName} as an extension ref`
|
|
10
|
+
throw new error_1.FirebaseError(`Unable to parse ${refOrName} as an extension ref.\n` +
|
|
11
|
+
"Expected format is either publisherId/extensionId@version or " +
|
|
12
|
+
"publishers/publisherId/extensions/extensionId/versions/version. If you " +
|
|
13
|
+
"are referring to a local extension directory, please ensure the directory exists.");
|
|
11
14
|
}
|
|
12
15
|
if (ret.version &&
|
|
13
16
|
!semver.valid(ret.version) &&
|
|
14
17
|
!semver.validRange(ret.version) &&
|
|
15
18
|
!["latest", "latest-approved"].includes(ret.version)) {
|
|
16
|
-
throw new error_1.FirebaseError(`Extension reference ${ret} contains an invalid version ${ret.version}.`);
|
|
19
|
+
throw new error_1.FirebaseError(`Extension reference ${JSON.stringify(ret, null, 2)} contains an invalid version ${ret.version}.`);
|
|
17
20
|
}
|
|
18
21
|
return ret;
|
|
19
22
|
}
|
|
@@ -21,19 +24,31 @@ exports.parse = parse;
|
|
|
21
24
|
function parseRef(ref) {
|
|
22
25
|
const parts = refRegex.exec(ref);
|
|
23
26
|
if (parts && (parts.length === 5 || parts.length === 7)) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
return {
|
|
28
|
+
publisherId: parts[1],
|
|
29
|
+
extensionId: parts[2],
|
|
30
|
+
version: parts[4],
|
|
31
|
+
};
|
|
28
32
|
}
|
|
29
33
|
}
|
|
30
34
|
function parseName(name) {
|
|
31
35
|
const parts = name.split("/");
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
if (parts[0] !== "publishers" || parts[2] !== "extensions") {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (parts.length === 4) {
|
|
40
|
+
return {
|
|
41
|
+
publisherId: parts[1],
|
|
42
|
+
extensionId: parts[3],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (parts.length === 6 && parts[4] === "versions") {
|
|
46
|
+
return {
|
|
47
|
+
publisherId: parts[1],
|
|
48
|
+
extensionId: parts[3],
|
|
49
|
+
version: parts[5],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
37
52
|
}
|
|
38
53
|
function toExtensionRef(ref) {
|
|
39
54
|
return `${ref.publisherId}/${ref.extensionId}`;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractExtensionsFromBuilds = exports.extractAllDynamicExtensions = void 0;
|
|
4
|
+
const projectConfig_1 = require("../../functions/projectConfig");
|
|
5
|
+
const prepare_1 = require("../../deploy/functions/prepare");
|
|
6
|
+
const functionsConfig_1 = require("../../functionsConfig");
|
|
7
|
+
const functionsDeployHelper_1 = require("../../deploy/functions/functionsDeployHelper");
|
|
8
|
+
const logger_1 = require("../../logger");
|
|
9
|
+
const savedLoggerSilent = logger_1.logger.silent;
|
|
10
|
+
function silenceLogging() {
|
|
11
|
+
logger_1.logger.silent = true;
|
|
12
|
+
}
|
|
13
|
+
function resumeLogging() {
|
|
14
|
+
logger_1.logger.silent = savedLoggerSilent;
|
|
15
|
+
}
|
|
16
|
+
async function extractAllDynamicExtensions(options) {
|
|
17
|
+
const firebaseConfig = await (0, functionsConfig_1.getFirebaseConfig)(options);
|
|
18
|
+
const runtimeConfig = { firebase: firebaseConfig };
|
|
19
|
+
const functionsConfig = (0, projectConfig_1.normalizeAndValidate)(options.config.src.functions);
|
|
20
|
+
let functionsBuilds = {};
|
|
21
|
+
const codebases = (0, functionsDeployHelper_1.targetCodebases)(functionsConfig);
|
|
22
|
+
silenceLogging();
|
|
23
|
+
for (const codebase of codebases) {
|
|
24
|
+
try {
|
|
25
|
+
const filters = [{ codebase: `${codebase}` }];
|
|
26
|
+
const builds = await (0, prepare_1.loadCodebases)(functionsConfig, options, firebaseConfig, runtimeConfig, filters);
|
|
27
|
+
functionsBuilds = Object.assign(Object.assign({}, functionsBuilds), builds);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
resumeLogging();
|
|
33
|
+
return extractExtensionsFromBuilds(functionsBuilds);
|
|
34
|
+
}
|
|
35
|
+
exports.extractAllDynamicExtensions = extractAllDynamicExtensions;
|
|
36
|
+
function extractExtensionsFromBuilds(builds, filters) {
|
|
37
|
+
const extRecords = {};
|
|
38
|
+
for (const [codebase, build] of Object.entries(builds)) {
|
|
39
|
+
if (build.extensions) {
|
|
40
|
+
for (const [id, ext] of Object.entries(build.extensions)) {
|
|
41
|
+
if (extensionMatchesAnyFilter(codebase, id, filters)) {
|
|
42
|
+
extRecords[id] = ext;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return extRecords;
|
|
48
|
+
}
|
|
49
|
+
exports.extractExtensionsFromBuilds = extractExtensionsFromBuilds;
|
|
50
|
+
function extensionMatchesAnyFilter(codebase, extensionId, filters) {
|
|
51
|
+
if (!filters) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
return filters.some((f) => extensionMatchesFilter(codebase, extensionId, f));
|
|
55
|
+
}
|
|
56
|
+
function extensionMatchesFilter(codebase, extensionId, filter) {
|
|
57
|
+
if (codebase && filter.codebase) {
|
|
58
|
+
if (codebase !== filter.codebase) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (!filter.idChunks) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
const idChunks = extensionId.split("-");
|
|
66
|
+
if (idChunks.length < filter.idChunks.length) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
for (let i = 0; i < filter.idChunks.length; i++) {
|
|
70
|
+
if (idChunks[i] !== filter.idChunks[i]) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return true;
|
|
75
|
+
}
|
package/lib/extensions/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ParamType = exports.FUNCTIONS_V2_RESOURCE_TYPE = exports.FUNCTIONS_RESOURCE_TYPE = exports.Visibility = exports.RegistryLaunchStage = void 0;
|
|
3
|
+
exports.isExtensionSpec = exports.isResource = exports.isParam = exports.ParamType = exports.FUNCTIONS_V2_RESOURCE_TYPE = exports.FUNCTIONS_RESOURCE_TYPE = exports.Visibility = exports.RegistryLaunchStage = void 0;
|
|
4
4
|
var RegistryLaunchStage;
|
|
5
5
|
(function (RegistryLaunchStage) {
|
|
6
6
|
RegistryLaunchStage["EXPERIMENTAL"] = "EXPERIMENTAL";
|
|
@@ -21,5 +21,60 @@ var ParamType;
|
|
|
21
21
|
ParamType["STRING"] = "STRING";
|
|
22
22
|
ParamType["SELECT"] = "SELECT";
|
|
23
23
|
ParamType["MULTISELECT"] = "MULTISELECT";
|
|
24
|
+
ParamType["SELECT_RESOURCE"] = "SELECT_RESOURCE";
|
|
24
25
|
ParamType["SECRET"] = "SECRET";
|
|
25
26
|
})(ParamType = exports.ParamType || (exports.ParamType = {}));
|
|
27
|
+
function isObject(value) {
|
|
28
|
+
return typeof value === "object" && value !== null;
|
|
29
|
+
}
|
|
30
|
+
const isParam = (param) => {
|
|
31
|
+
return (isObject(param) && typeof param["param"] === "string" && typeof param["label"] === "string");
|
|
32
|
+
};
|
|
33
|
+
exports.isParam = isParam;
|
|
34
|
+
const isResource = (res) => {
|
|
35
|
+
return isObject(res) && typeof res["name"] === "string";
|
|
36
|
+
};
|
|
37
|
+
exports.isResource = isResource;
|
|
38
|
+
const isExtensionSpec = (spec) => {
|
|
39
|
+
if (!isObject(spec) || typeof spec.name !== "string" || typeof spec.version !== "string") {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
let validResources = true;
|
|
43
|
+
if (spec.resources && Array.isArray(spec.resources)) {
|
|
44
|
+
for (const res of spec.resources) {
|
|
45
|
+
validResources = validResources && (0, exports.isResource)(res);
|
|
46
|
+
if (!validResources) {
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
let validParams = true;
|
|
55
|
+
if (spec.params && Array.isArray(spec.params)) {
|
|
56
|
+
for (const param of spec.params) {
|
|
57
|
+
validParams = validParams && (0, exports.isParam)(param);
|
|
58
|
+
if (!validParams) {
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
let validSysParams = true;
|
|
67
|
+
if (spec.systemParams && Array.isArray(spec.systemParams)) {
|
|
68
|
+
for (const param of spec.systemParams) {
|
|
69
|
+
validSysParams = validSysParams && (0, exports.isParam)(param);
|
|
70
|
+
if (!validSysParams) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
80
|
+
exports.isExtensionSpec = isExtensionSpec;
|
|
@@ -20,7 +20,7 @@ exports.FIREBASE_FRAMEWORKS_VERSION = (experiments.isEnabled("internaltesting")
|
|
|
20
20
|
DEFAULT_FIREBASE_FRAMEWORKS_VERSION;
|
|
21
21
|
exports.FIREBASE_FUNCTIONS_VERSION = "^4.5.0";
|
|
22
22
|
exports.FIREBASE_ADMIN_VERSION = "^11.11.1";
|
|
23
|
-
exports.SHARP_VERSION = "^0.32.
|
|
23
|
+
exports.SHARP_VERSION = "^0.32 || ^0.33";
|
|
24
24
|
exports.NODE_VERSION = parseInt(process.versions.node, 10);
|
|
25
25
|
exports.VALID_ENGINES = { node: [16, 18, 20] };
|
|
26
26
|
exports.VALID_LOCALE_FORMATS = [/^ALL_[a-z]+$/, /^[a-z]+_ALL$/, /^[a-z]+(_[a-z]+)?$/];
|
|
@@ -11,7 +11,7 @@ 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
13
|
exports.CONFIG_FILES = ["next.config.js", "next.config.mjs"];
|
|
14
|
-
exports.ESBUILD_VERSION = "0.19.2";
|
|
14
|
+
exports.ESBUILD_VERSION = "^0.19.2";
|
|
15
15
|
const WEBPACK_LAYERS_NAMES = {
|
|
16
16
|
shared: "shared",
|
|
17
17
|
reactServerComponents: "rsc",
|
|
@@ -22,6 +22,7 @@ const constants_1 = require("../constants");
|
|
|
22
22
|
const constants_2 = require("./constants");
|
|
23
23
|
const api_1 = require("../../hosting/api");
|
|
24
24
|
const logger_1 = require("../../logger");
|
|
25
|
+
const env_1 = require("../../functions/env");
|
|
25
26
|
const DEFAULT_BUILD_SCRIPT = ["next build"];
|
|
26
27
|
const PUBLIC_DIR = "public";
|
|
27
28
|
exports.supportedRange = "12 - 14.0";
|
|
@@ -29,7 +30,6 @@ exports.name = "Next.js";
|
|
|
29
30
|
exports.support = "preview";
|
|
30
31
|
exports.type = 2;
|
|
31
32
|
exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/nextjs";
|
|
32
|
-
const BUNDLE_NEXT_CONFIG_TIMEOUT = 60000;
|
|
33
33
|
const DEFAULT_NUMBER_OF_REASONS_TO_LIST = 5;
|
|
34
34
|
function getReactVersion(cwd) {
|
|
35
35
|
var _a;
|
|
@@ -51,7 +51,14 @@ async function build(dir, target, context) {
|
|
|
51
51
|
if (reactVersion && (0, semver_1.gte)(reactVersion, "18.0.0")) {
|
|
52
52
|
process.env.__NEXT_REACT_ROOT = "true";
|
|
53
53
|
}
|
|
54
|
-
|
|
54
|
+
let env = Object.assign({}, process.env);
|
|
55
|
+
if (context === null || context === void 0 ? void 0 : context.projectId) {
|
|
56
|
+
const projectEnvPath = (0, path_1.join)(dir, `.env.${context.projectId}`);
|
|
57
|
+
if (await (0, fs_extra_1.pathExists)(projectEnvPath)) {
|
|
58
|
+
const projectEnvVars = (0, env_1.parseStrict)((await (0, fs_extra_1.readFile)(projectEnvPath)).toString());
|
|
59
|
+
env = Object.assign(Object.assign({}, projectEnvVars), env);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
55
62
|
if ((context === null || context === void 0 ? void 0 : context.projectId) && (context === null || context === void 0 ? void 0 : context.site)) {
|
|
56
63
|
const deploymentDomain = await (0, api_1.getDeploymentDomain)(context.projectId, context.site, context.hostingChannel);
|
|
57
64
|
if (deploymentDomain) {
|
|
@@ -338,6 +345,19 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
338
345
|
const configFile = await (0, utils_2.whichNextConfigFile)(sourceDir);
|
|
339
346
|
if (configFile) {
|
|
340
347
|
try {
|
|
348
|
+
let esbuildPath = (0, utils_2.findEsbuildPath)();
|
|
349
|
+
if (!esbuildPath || !(0, fs_extra_1.pathExistsSync)(esbuildPath)) {
|
|
350
|
+
console.warn("esbuild not found, installing...");
|
|
351
|
+
(0, utils_2.installEsbuild)(constants_2.ESBUILD_VERSION);
|
|
352
|
+
esbuildPath = (0, utils_2.findEsbuildPath)();
|
|
353
|
+
if (!esbuildPath || !(0, fs_extra_1.pathExistsSync)(esbuildPath)) {
|
|
354
|
+
throw new error_1.FirebaseError("Failed to locate esbuild after installation.");
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const esbuild = require(esbuildPath);
|
|
358
|
+
if (!esbuild) {
|
|
359
|
+
throw new error_1.FirebaseError(`Failed to load esbuild from path: ${esbuildPath}`);
|
|
360
|
+
}
|
|
341
361
|
const productionDeps = await new Promise((resolve) => {
|
|
342
362
|
const dependencies = [];
|
|
343
363
|
const npmLs = (0, cross_spawn_1.spawn)("npm", ["ls", "--omit=dev", "--all", "--json=true"], {
|
|
@@ -359,21 +379,21 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
359
379
|
resolve([...new Set(dependencies)]);
|
|
360
380
|
});
|
|
361
381
|
});
|
|
362
|
-
const esbuildArgs =
|
|
363
|
-
.
|
|
364
|
-
|
|
382
|
+
const esbuildArgs = {
|
|
383
|
+
entryPoints: [(0, path_1.join)(sourceDir, configFile)],
|
|
384
|
+
outfile: (0, path_1.join)(destDir, configFile),
|
|
385
|
+
bundle: true,
|
|
386
|
+
platform: "node",
|
|
387
|
+
target: `node${constants_1.NODE_VERSION}`,
|
|
388
|
+
logLevel: "error",
|
|
389
|
+
external: productionDeps,
|
|
390
|
+
};
|
|
365
391
|
if (configFile === "next.config.mjs") {
|
|
366
|
-
esbuildArgs.
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
esbuildArgs.push(`--outfile=${(0, path_1.join)(destDir, configFile)}`);
|
|
392
|
+
esbuildArgs.format = "esm";
|
|
370
393
|
}
|
|
371
|
-
const bundle =
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
});
|
|
375
|
-
if (bundle.status !== 0) {
|
|
376
|
-
throw new error_1.FirebaseError(bundle.stderr.toString());
|
|
394
|
+
const bundle = await esbuild.build(esbuildArgs);
|
|
395
|
+
if (bundle.errors && bundle.errors.length > 0) {
|
|
396
|
+
throw new error_1.FirebaseError(bundle.errors.toString());
|
|
377
397
|
}
|
|
378
398
|
}
|
|
379
399
|
catch (e) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
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;
|
|
3
|
+
exports.installEsbuild = exports.getGlobalEsbuildVersion = exports.findEsbuildPath = 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");
|
|
@@ -11,6 +11,8 @@ const utils_1 = require("../utils");
|
|
|
11
11
|
const constants_1 = require("./constants");
|
|
12
12
|
const fsutils_1 = require("../../fsutils");
|
|
13
13
|
const utils_2 = require("../../utils");
|
|
14
|
+
const child_process_1 = require("child_process");
|
|
15
|
+
const error_1 = require("../../error");
|
|
14
16
|
exports.I18N_SOURCE = /\/:nextInternalLocale(\([^\)]+\))?/;
|
|
15
17
|
function cleanEscapedChars(path) {
|
|
16
18
|
return path.replace(/\\([(){}:+?*])/g, (a, b) => b);
|
|
@@ -241,3 +243,53 @@ async function whichNextConfigFile(dir) {
|
|
|
241
243
|
return null;
|
|
242
244
|
}
|
|
243
245
|
exports.whichNextConfigFile = whichNextConfigFile;
|
|
246
|
+
function findEsbuildPath() {
|
|
247
|
+
var _a;
|
|
248
|
+
try {
|
|
249
|
+
const esbuildBinPath = (_a = (0, child_process_1.execSync)("npx which esbuild", { encoding: "utf8" })) === null || _a === void 0 ? void 0 : _a.trim();
|
|
250
|
+
if (!esbuildBinPath) {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
const globalVersion = getGlobalEsbuildVersion(esbuildBinPath);
|
|
254
|
+
if (globalVersion && !(0, semver_1.satisfies)(globalVersion, constants_1.ESBUILD_VERSION)) {
|
|
255
|
+
console.warn(`Warning: Global esbuild version (${globalVersion}) does not match the required version (${constants_1.ESBUILD_VERSION}).`);
|
|
256
|
+
}
|
|
257
|
+
return (0, path_1.resolve)((0, path_1.dirname)(esbuildBinPath), "../esbuild");
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
console.error(`Failed to find esbuild with npx which: ${error}`);
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
exports.findEsbuildPath = findEsbuildPath;
|
|
265
|
+
function getGlobalEsbuildVersion(binPath) {
|
|
266
|
+
var _a;
|
|
267
|
+
try {
|
|
268
|
+
const versionOutput = (_a = (0, child_process_1.execSync)(`${binPath} --version`, { encoding: "utf8" })) === null || _a === void 0 ? void 0 : _a.trim();
|
|
269
|
+
if (!versionOutput) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
const versionMatch = versionOutput.match(/(\d+\.\d+\.\d+)/);
|
|
273
|
+
return versionMatch ? versionMatch[0] : null;
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
console.error(`Failed to get global esbuild version: ${error}`);
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.getGlobalEsbuildVersion = getGlobalEsbuildVersion;
|
|
281
|
+
function installEsbuild(version) {
|
|
282
|
+
const installCommand = `npm install esbuild@${version} --no-save`;
|
|
283
|
+
try {
|
|
284
|
+
(0, child_process_1.execSync)(installCommand, { stdio: "inherit" });
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
if (error instanceof error_1.FirebaseError) {
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
throw new error_1.FirebaseError(`Failed to install esbuild: ${error}`, { original: error });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
exports.installEsbuild = installEsbuild;
|