firebase-tools 13.14.2 → 13.15.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/bin/firebase.js +2 -4
- package/lib/commands/deploy.js +10 -2
- package/lib/commands/ext-configure.js +1 -6
- package/lib/commands/ext-dev-init.js +2 -4
- package/lib/commands/ext-dev-upload.js +4 -6
- package/lib/commands/ext-info.js +3 -5
- package/lib/commands/ext-install.js +0 -5
- package/lib/commands/ext-uninstall.js +0 -5
- package/lib/commands/ext-update.js +0 -5
- package/lib/commands/firestore-databases-create.js +19 -1
- package/lib/commands/functions-secrets-set.js +9 -6
- package/lib/commands/hosting-channel-create.js +1 -1
- package/lib/commands/hosting-channel-delete.js +1 -1
- package/lib/commands/hosting-channel-deploy.js +1 -1
- package/lib/commands/hosting-clone.js +1 -2
- package/lib/dataconnect/fileUtils.js +63 -1
- package/lib/dataconnect/provisionCloudSql.js +5 -1
- package/lib/dataconnect/types.js +8 -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/dataconnectEmulator.js +2 -0
- package/lib/emulator/downloadableEmulators.js +11 -12
- package/lib/emulator/functionsEmulator.js +8 -1
- package/lib/extensions/askUserForEventsConfig.js +18 -8
- package/lib/extensions/askUserForParam.js +3 -2
- package/lib/extensions/change-log.js +2 -4
- package/lib/extensions/displayExtensionInfo.js +5 -10
- package/lib/extensions/extensionsApi.js +1 -1
- package/lib/extensions/extensionsHelper.js +47 -10
- package/lib/extensions/localHelper.js +1 -1
- package/lib/extensions/provisioningHelper.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/extensions/updateHelper.js +1 -2
- package/lib/extensions/warnings.js +2 -7
- package/lib/firestore/api.js +8 -7
- package/lib/firestore/pretty-print.js +21 -1
- package/lib/firestore/pretty-print.test.js +8 -0
- package/lib/frameworks/constants.js +1 -1
- package/lib/frameworks/next/constants.js +1 -1
- package/lib/frameworks/next/index.js +26 -14
- package/lib/frameworks/next/utils.js +45 -1
- package/lib/init/features/dataconnect/index.js +29 -15
- package/lib/init/features/dataconnect/sdk.js +72 -56
- package/lib/prompt.js +22 -1
- package/lib/rulesDeploy.js +14 -12
- package/package.json +3 -3
- 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
- package/lib/extensions/billingMigrationHelper.js +0 -61
|
@@ -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");
|
|
@@ -9,11 +16,9 @@ const fs = require("fs-extra");
|
|
|
9
16
|
const node_fetch_1 = require("node-fetch");
|
|
10
17
|
const path = require("path");
|
|
11
18
|
const marked_1 = require("marked");
|
|
19
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
12
20
|
const unzip_1 = require("./../unzip");
|
|
13
|
-
|
|
14
|
-
marked_1.marked.setOptions({
|
|
15
|
-
renderer: new TerminalRenderer(),
|
|
16
|
-
});
|
|
21
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
17
22
|
const api_1 = require("../api");
|
|
18
23
|
const archiveDirectory_1 = require("../archiveDirectory");
|
|
19
24
|
const utils_1 = require("./utils");
|
|
@@ -128,6 +133,38 @@ function substituteParams(original, params) {
|
|
|
128
133
|
return JSON.parse(s);
|
|
129
134
|
}
|
|
130
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;
|
|
131
168
|
function populateDefaultParams(paramVars, paramSpecs) {
|
|
132
169
|
const newParams = paramVars;
|
|
133
170
|
for (const param of paramSpecs) {
|
|
@@ -417,12 +454,12 @@ function validateReleaseNotes(rootDirectory, newVersion, extension) {
|
|
|
417
454
|
catch (err) {
|
|
418
455
|
throw new error_1.FirebaseError("No CHANGELOG.md file found. " +
|
|
419
456
|
"Please create one and add an entry for this version. " +
|
|
420
|
-
|
|
457
|
+
"See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
|
|
421
458
|
}
|
|
422
459
|
if (!notes && !semver.prerelease(newVersion) && extension) {
|
|
423
460
|
throw new error_1.FirebaseError(`No entry for version ${newVersion} found in CHANGELOG.md. ` +
|
|
424
461
|
"Please add one so users know what has changed in this version. " +
|
|
425
|
-
|
|
462
|
+
"See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
|
|
426
463
|
}
|
|
427
464
|
return notes;
|
|
428
465
|
}
|
|
@@ -474,7 +511,7 @@ function displayExtensionHeader(extensionRef, extension, extensionRoot) {
|
|
|
474
511
|
}
|
|
475
512
|
else {
|
|
476
513
|
logger_1.logger.info(`\n${clc.bold("Extension:")} ${extensionRef}\n` +
|
|
477
|
-
`${clc.bold("State:")} ${clc.bold(clc.
|
|
514
|
+
`${clc.bold("State:")} ${clc.bold(clc.blueBright("New"))}\n`);
|
|
478
515
|
}
|
|
479
516
|
}
|
|
480
517
|
async function fetchExtensionSource(repoUri, sourceRef, extensionRoot) {
|
|
@@ -701,7 +738,7 @@ async function uploadExtensionVersionFromLocalSource(args) {
|
|
|
701
738
|
}
|
|
702
739
|
exports.uploadExtensionVersionFromLocalSource = uploadExtensionVersionFromLocalSource;
|
|
703
740
|
function getMissingPublisherError(publisherId) {
|
|
704
|
-
return new error_1.FirebaseError(
|
|
741
|
+
return new error_1.FirebaseError(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. For step-by-step instructions on getting started as a publisher, see https://firebase.google.com/docs/extensions/publishers/get-started.`);
|
|
705
742
|
}
|
|
706
743
|
exports.getMissingPublisherError = getMissingPublisherError;
|
|
707
744
|
async function createSourceFromLocation(projectId, sourceUri) {
|
|
@@ -796,7 +833,7 @@ async function instanceIdExists(projectId, instanceId) {
|
|
|
796
833
|
if (err.status === 404) {
|
|
797
834
|
return false;
|
|
798
835
|
}
|
|
799
|
-
const msg = `Unexpected error when checking if instance ID exists: ${err}`;
|
|
836
|
+
const msg = `Unexpected error when checking if instance ID exists: ${err.message}`;
|
|
800
837
|
throw new error_1.FirebaseError(msg, {
|
|
801
838
|
original: err,
|
|
802
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
|
}
|
|
@@ -64,7 +64,7 @@ async function checkProducts(projectId, usedProducts) {
|
|
|
64
64
|
"without server-side code.\n";
|
|
65
65
|
errorMessage += ` https://console.firebase.google.com/project/${projectId}/authentication/users`;
|
|
66
66
|
}
|
|
67
|
-
throw new error_1.FirebaseError((0, marked_1.marked)(errorMessage), { exit: 2 });
|
|
67
|
+
throw new error_1.FirebaseError(await (0, marked_1.marked)(errorMessage), { exit: 2 });
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
function getUsedProducts(spec) {
|
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;
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.inferUpdateSource = exports.updateFromUrlSource = exports.updateFromLocalSource = exports.update = exports.warningUpdateToOtherSource = exports.getExistingSourceOrigin = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const semver = require("semver");
|
|
6
|
-
const marked_1 = require("marked");
|
|
7
6
|
const error_1 = require("../error");
|
|
8
7
|
const logger_1 = require("../logger");
|
|
9
8
|
const extensionsApi = require("./extensionsApi");
|
|
@@ -47,7 +46,7 @@ function warningUpdateToOtherSource(sourceOrigin) {
|
|
|
47
46
|
targetText = "URL";
|
|
48
47
|
}
|
|
49
48
|
const warning = `All the instance's resources and logic will be overwritten to use the source code and files from the ${targetText}.\n`;
|
|
50
|
-
logger_1.logger.info(
|
|
49
|
+
logger_1.logger.info(warning);
|
|
51
50
|
}
|
|
52
51
|
exports.warningUpdateToOtherSource = warningUpdateToOtherSource;
|
|
53
52
|
async function update(updateOptions) {
|
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.outOfBandChangesWarning = exports.displayWarningsForDeploy = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
|
-
const TerminalRenderer = require("marked-terminal");
|
|
6
|
-
const marked_1 = require("marked");
|
|
7
|
-
marked_1.marked.setOptions({
|
|
8
|
-
renderer: new TerminalRenderer(),
|
|
9
|
-
});
|
|
10
5
|
const extensionsHelper_1 = require("./extensionsHelper");
|
|
11
6
|
const deploymentSummary_1 = require("../deploy/extensions/deploymentSummary");
|
|
12
7
|
const planner_1 = require("../deploy/extensions/planner");
|
|
@@ -29,9 +24,9 @@ async function displayWarningsForDeploy(instancesToCreate) {
|
|
|
29
24
|
const unpublishedExtensions = uploadedExtensionInstances.filter((i) => { var _a, _b; return ((_b = (_a = i.extensionVersion) === null || _a === void 0 ? void 0 : _a.listing) === null || _b === void 0 ? void 0 : _b.state) !== "APPROVED"; });
|
|
30
25
|
if (unpublishedExtensions.length) {
|
|
31
26
|
const humanReadableList = unpublishedExtensions.map(toListEntry).join("\n");
|
|
32
|
-
utils.logLabeledBullet(extensionsHelper_1.logPrefix,
|
|
27
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, `The following extension versions have not been published to the Firebase Extensions Hub:\n${humanReadableList}\n.` +
|
|
33
28
|
"Unpublished extensions have not been reviewed by " +
|
|
34
|
-
"Firebase. Please make sure you trust the extension publisher before installing this extension."
|
|
29
|
+
"Firebase. Please make sure you trust the extension publisher before installing this extension.");
|
|
35
30
|
}
|
|
36
31
|
return unpublishedExtensions.length > 0;
|
|
37
32
|
}
|
package/lib/firestore/api.js
CHANGED
|
@@ -420,15 +420,16 @@ class FirestoreApi {
|
|
|
420
420
|
}
|
|
421
421
|
return database;
|
|
422
422
|
}
|
|
423
|
-
async createDatabase(
|
|
424
|
-
const url = `/projects/${project}/databases`;
|
|
423
|
+
async createDatabase(req) {
|
|
424
|
+
const url = `/projects/${req.project}/databases`;
|
|
425
425
|
const payload = {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
deleteProtectionState,
|
|
429
|
-
pointInTimeRecoveryEnablement,
|
|
426
|
+
locationId: req.locationId,
|
|
427
|
+
type: req.type,
|
|
428
|
+
deleteProtectionState: req.deleteProtectionState,
|
|
429
|
+
pointInTimeRecoveryEnablement: req.pointInTimeRecoveryEnablement,
|
|
430
|
+
cmekConfig: req.cmekConfig,
|
|
430
431
|
};
|
|
431
|
-
const options = { queryParams: { databaseId: databaseId } };
|
|
432
|
+
const options = { queryParams: { databaseId: req.databaseId } };
|
|
432
433
|
const res = await this.apiClient.post(url, payload, options);
|
|
433
434
|
const database = res.body.response;
|
|
434
435
|
if (!database) {
|
|
@@ -33,13 +33,33 @@ class PrettyPrint {
|
|
|
33
33
|
logger_1.logger.info(table.toString());
|
|
34
34
|
}
|
|
35
35
|
prettyPrintDatabase(database) {
|
|
36
|
+
let colValueWidth = Math.max(50, 5 + database.name.length);
|
|
37
|
+
if (database.cmekConfig) {
|
|
38
|
+
colValueWidth = Math.max(140, 20 + database.cmekConfig.kmsKeyName.length);
|
|
39
|
+
}
|
|
36
40
|
const table = new Table({
|
|
37
41
|
head: ["Field", "Value"],
|
|
38
|
-
colWidths: [
|
|
42
|
+
colWidths: [30, colValueWidth],
|
|
39
43
|
});
|
|
40
44
|
table.push(["Name", clc.yellow(database.name)], ["Create Time", clc.yellow(database.createTime)], ["Last Update Time", clc.yellow(database.updateTime)], ["Type", clc.yellow(database.type)], ["Location", clc.yellow(database.locationId)], ["Delete Protection State", clc.yellow(database.deleteProtectionState)], ["Point In Time Recovery", clc.yellow(database.pointInTimeRecoveryEnablement)], ["Earliest Version Time", clc.yellow(database.earliestVersionTime)], ["Version Retention Period", clc.yellow(database.versionRetentionPeriod)]);
|
|
45
|
+
if (database.cmekConfig) {
|
|
46
|
+
table.push(["KMS Key Name", clc.yellow(database.cmekConfig.kmsKeyName)]);
|
|
47
|
+
if (database.cmekConfig.activeKeyVersion) {
|
|
48
|
+
table.push([
|
|
49
|
+
"Active Key Versions",
|
|
50
|
+
clc.yellow(this.prettyStringArray(database.cmekConfig.activeKeyVersion)),
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
41
54
|
logger_1.logger.info(table.toString());
|
|
42
55
|
}
|
|
56
|
+
prettyStringArray(stringArray) {
|
|
57
|
+
let result = "";
|
|
58
|
+
stringArray.forEach((str) => {
|
|
59
|
+
result += `${str}\n`;
|
|
60
|
+
});
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
43
63
|
prettyPrintBackups(backups) {
|
|
44
64
|
if (backups.length === 0) {
|
|
45
65
|
logger_1.logger.info("No backups found.");
|
|
@@ -51,3 +51,11 @@ describe("firebaseConsoleDatabaseUrl", () => {
|
|
|
51
51
|
(0, chai_1.expect)(printer.firebaseConsoleDatabaseUrl("example-project", "(default)")).to.equal("https://console.firebase.google.com/project/example-project/firestore/databases/-default-/data");
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
|
+
describe("prettyStringArray", () => {
|
|
55
|
+
it("should correctly print an array of strings", () => {
|
|
56
|
+
(0, chai_1.expect)(printer.prettyStringArray(["kms-key-1", "kms-key-2"])).to.equal("kms-key-1\nkms-key-2\n");
|
|
57
|
+
});
|
|
58
|
+
it("should print nothing if the array is empty", () => {
|
|
59
|
+
(0, chai_1.expect)(printer.prettyStringArray([])).to.equal("");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -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",
|
|
@@ -29,7 +29,6 @@ exports.name = "Next.js";
|
|
|
29
29
|
exports.support = "preview";
|
|
30
30
|
exports.type = 2;
|
|
31
31
|
exports.docsUrl = "https://firebase.google.com/docs/hosting/frameworks/nextjs";
|
|
32
|
-
const BUNDLE_NEXT_CONFIG_TIMEOUT = 60000;
|
|
33
32
|
const DEFAULT_NUMBER_OF_REASONS_TO_LIST = 5;
|
|
34
33
|
function getReactVersion(cwd) {
|
|
35
34
|
var _a;
|
|
@@ -338,6 +337,19 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
338
337
|
const configFile = await (0, utils_2.whichNextConfigFile)(sourceDir);
|
|
339
338
|
if (configFile) {
|
|
340
339
|
try {
|
|
340
|
+
let esbuildPath = (0, utils_2.findEsbuildPath)();
|
|
341
|
+
if (!esbuildPath || !(0, fs_extra_1.pathExistsSync)(esbuildPath)) {
|
|
342
|
+
console.warn("esbuild not found, installing...");
|
|
343
|
+
(0, utils_2.installEsbuild)(constants_2.ESBUILD_VERSION);
|
|
344
|
+
esbuildPath = (0, utils_2.findEsbuildPath)();
|
|
345
|
+
if (!esbuildPath || !(0, fs_extra_1.pathExistsSync)(esbuildPath)) {
|
|
346
|
+
throw new error_1.FirebaseError("Failed to locate esbuild after installation.");
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const esbuild = require(esbuildPath);
|
|
350
|
+
if (!esbuild) {
|
|
351
|
+
throw new error_1.FirebaseError(`Failed to load esbuild from path: ${esbuildPath}`);
|
|
352
|
+
}
|
|
341
353
|
const productionDeps = await new Promise((resolve) => {
|
|
342
354
|
const dependencies = [];
|
|
343
355
|
const npmLs = (0, cross_spawn_1.spawn)("npm", ["ls", "--omit=dev", "--all", "--json=true"], {
|
|
@@ -359,21 +371,21 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, target, context)
|
|
|
359
371
|
resolve([...new Set(dependencies)]);
|
|
360
372
|
});
|
|
361
373
|
});
|
|
362
|
-
const esbuildArgs =
|
|
363
|
-
.
|
|
364
|
-
|
|
374
|
+
const esbuildArgs = {
|
|
375
|
+
entryPoints: [(0, path_1.join)(sourceDir, configFile)],
|
|
376
|
+
outfile: (0, path_1.join)(destDir, configFile),
|
|
377
|
+
bundle: true,
|
|
378
|
+
platform: "node",
|
|
379
|
+
target: `node${constants_1.NODE_VERSION}`,
|
|
380
|
+
logLevel: "error",
|
|
381
|
+
external: productionDeps,
|
|
382
|
+
};
|
|
365
383
|
if (configFile === "next.config.mjs") {
|
|
366
|
-
esbuildArgs.
|
|
384
|
+
esbuildArgs.format = "esm";
|
|
367
385
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
const bundle = (0, cross_spawn_1.sync)("npx", ["--yes", `esbuild@${constants_2.ESBUILD_VERSION}`, configFile, ...esbuildArgs], {
|
|
372
|
-
cwd: sourceDir,
|
|
373
|
-
timeout: BUNDLE_NEXT_CONFIG_TIMEOUT,
|
|
374
|
-
});
|
|
375
|
-
if (bundle.status !== 0) {
|
|
376
|
-
throw new error_1.FirebaseError(bundle.stderr.toString());
|
|
386
|
+
const bundle = await esbuild.build(esbuildArgs);
|
|
387
|
+
if (bundle.errors && bundle.errors.length > 0) {
|
|
388
|
+
throw new error_1.FirebaseError(bundle.errors.toString());
|
|
377
389
|
}
|
|
378
390
|
}
|
|
379
391
|
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,45 @@ async function whichNextConfigFile(dir) {
|
|
|
241
243
|
return null;
|
|
242
244
|
}
|
|
243
245
|
exports.whichNextConfigFile = whichNextConfigFile;
|
|
246
|
+
function findEsbuildPath() {
|
|
247
|
+
try {
|
|
248
|
+
const esbuildBinPath = (0, child_process_1.execSync)("npx which esbuild", { encoding: "utf8" }).trim();
|
|
249
|
+
const globalVersion = getGlobalEsbuildVersion();
|
|
250
|
+
if (globalVersion && !(0, semver_1.satisfies)(globalVersion, constants_1.ESBUILD_VERSION)) {
|
|
251
|
+
console.warn(`Warning: Global esbuild version (${globalVersion}) does not match the required version (${constants_1.ESBUILD_VERSION}).`);
|
|
252
|
+
}
|
|
253
|
+
return (0, path_1.resolve)((0, path_1.dirname)(esbuildBinPath), "../esbuild");
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.error(`Failed to find esbuild with npx which: ${error}`);
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
exports.findEsbuildPath = findEsbuildPath;
|
|
261
|
+
function getGlobalEsbuildVersion() {
|
|
262
|
+
try {
|
|
263
|
+
const versionOutput = (0, child_process_1.execSync)("esbuild --version", { encoding: "utf8" }).trim();
|
|
264
|
+
const versionMatch = versionOutput.match(/(\d+\.\d+\.\d+)/);
|
|
265
|
+
return versionMatch ? versionMatch[0] : null;
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
console.error(`Failed to get global esbuild version: ${error}`);
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
exports.getGlobalEsbuildVersion = getGlobalEsbuildVersion;
|
|
273
|
+
function installEsbuild(version) {
|
|
274
|
+
const installCommand = `npm install esbuild@${version} --no-save`;
|
|
275
|
+
try {
|
|
276
|
+
(0, child_process_1.execSync)(installCommand, { stdio: "inherit" });
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (error instanceof error_1.FirebaseError) {
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
throw new error_1.FirebaseError(`Failed to install esbuild: ${error}`, { original: error });
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
exports.installEsbuild = installEsbuild;
|