firebase-tools 14.22.0 → 14.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -5
- package/lib/apiv2.js +12 -2
- package/lib/appUtils.js +32 -13
- package/lib/appdistribution/client.js +62 -16
- package/lib/appdistribution/types.js +1 -12
- package/lib/appdistribution/yaml_helper.js +69 -0
- package/lib/commands/appdistribution-groups-list.js +3 -5
- package/lib/commands/appdistribution-testcases-export.js +32 -0
- package/lib/commands/appdistribution-testcases-import.js +34 -0
- package/lib/commands/appdistribution-testers-list.js +3 -5
- package/lib/commands/dataconnect-sdk-generate.js +3 -2
- package/lib/commands/index.js +8 -5
- package/lib/commands/init.js +5 -7
- package/lib/deploy/functions/services/dataconnect.js +14 -0
- package/lib/deploy/functions/services/index.js +11 -0
- package/lib/emulator/auth/operations.js +7 -1
- package/lib/emulator/downloadableEmulatorInfo.json +33 -25
- package/lib/emulator/downloadableEmulators.js +59 -47
- package/lib/emulator/functionsEmulatorRuntime.js +8 -0
- package/lib/emulator/taskQueue.js +5 -0
- package/lib/experiments.js +0 -6
- package/lib/firestore/api.js +22 -4
- package/lib/functions/events/v2.js +2 -1
- package/lib/init/features/dataconnect/sdk.js +18 -0
- package/lib/init/features/hosting/github.js +6 -6
- package/lib/init/features/hosting/index.js +37 -37
- package/lib/management/provisioning/errorHandler.js +54 -0
- package/lib/management/provisioning/provision.js +2 -5
- package/lib/mcp/tools/crashlytics/events.js +92 -9
- package/lib/mcp/tools/functions/index.js +2 -1
- package/lib/mcp/tools/functions/list_functions.js +48 -0
- package/lib/utils.js +4 -1
- package/package.json +2 -2
- package/schema/connector-yaml.json +30 -0
- package/schema/firebase-config.json +0 -1
|
@@ -44,38 +44,46 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"pubsub": {
|
|
47
|
-
"version": "0.8.
|
|
48
|
-
"expectedSize":
|
|
49
|
-
"expectedChecksum": "
|
|
50
|
-
"expectedChecksumSHA256": "
|
|
51
|
-
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.
|
|
52
|
-
"downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.
|
|
53
|
-
"binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.
|
|
47
|
+
"version": "0.8.17",
|
|
48
|
+
"expectedSize": 65162324,
|
|
49
|
+
"expectedChecksum": "a88ec6424e49af459b5c8a3657d69c06",
|
|
50
|
+
"expectedChecksumSHA256": "72a49d14ee6cd4c1a0fee4a46f520fe4d7465396a155c61abc0103905047edd3",
|
|
51
|
+
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.17.zip",
|
|
52
|
+
"downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.17.zip",
|
|
53
|
+
"binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.17/pubsub-emulator/bin/cloud-pubsub-emulator"
|
|
54
54
|
},
|
|
55
55
|
"dataconnect": {
|
|
56
56
|
"darwin": {
|
|
57
|
-
"version": "2.
|
|
58
|
-
"expectedSize":
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v2.
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
57
|
+
"version": "2.17.0",
|
|
58
|
+
"expectedSize": 29983584,
|
|
59
|
+
"expectedChecksum": "d9a3a5bd575dc24185ad473a440c4738",
|
|
60
|
+
"expectedChecksumSHA256": "da5485e68c7adbf86e3fb2f9ca550e4619f55ae75845009837780fcf16dd05cc",
|
|
61
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v2.17.0",
|
|
62
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0"
|
|
63
|
+
},
|
|
64
|
+
"darwin_arm64": {
|
|
65
|
+
"version": "2.17.0",
|
|
66
|
+
"expectedSize": 29459746,
|
|
67
|
+
"expectedChecksum": "8362a56419a66507b1aead4630b9033c",
|
|
68
|
+
"expectedChecksumSHA256": "cbb8a3030f69c5aba81d1ef2d64d249f18100915f9738f59b815004b27983dab",
|
|
69
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v2.17.0",
|
|
70
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0"
|
|
63
71
|
},
|
|
64
72
|
"win32": {
|
|
65
|
-
"version": "2.
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v2.
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
73
|
+
"version": "2.17.0",
|
|
74
|
+
"expectedSize": 30477824,
|
|
75
|
+
"expectedChecksum": "7d8434eee4f3d33cc8ec6c99c6056a77",
|
|
76
|
+
"expectedChecksumSHA256": "051c60be0651be4971409da7ab3a15cdfb693400e9293c89010edcb28016d061",
|
|
77
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v2.17.0",
|
|
78
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0.exe"
|
|
71
79
|
},
|
|
72
80
|
"linux": {
|
|
73
|
-
"version": "2.
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v2.
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
81
|
+
"version": "2.17.0",
|
|
82
|
+
"expectedSize": 29905080,
|
|
83
|
+
"expectedChecksum": "ca7003aaee41e3c1261f9655c5f9dd8a",
|
|
84
|
+
"expectedChecksumSHA256": "79efd09f1bd685cbfa0157b2d08e0f6eb085ed82d83b48fabb7d102db6636c6c",
|
|
85
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v2.17.0",
|
|
86
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0"
|
|
79
87
|
}
|
|
80
88
|
}
|
|
81
89
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isIncomaptibleArchError = exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName =
|
|
3
|
+
exports.isIncomaptibleArchError = exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName = void 0;
|
|
4
4
|
const lsofi = require("lsofi");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
6
|
const constants_1 = require("./constants");
|
|
@@ -20,51 +20,63 @@ const emulatorUpdateDetails = require("./downloadableEmulatorInfo.json");
|
|
|
20
20
|
const EMULATOR_INSTANCE_KILL_TIMEOUT = 4000;
|
|
21
21
|
const CACHE_DIR = process.env.FIREBASE_EMULATORS_PATH || path.join(os.homedir(), ".cache", "firebase", "emulators");
|
|
22
22
|
const EMULATOR_UPDATE_DETAILS = emulatorUpdateDetails;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
23
|
+
function generateDownloadDetails(emulator) {
|
|
24
|
+
const emulatorUiDetails = experiments.isEnabled("emulatoruisnapshot")
|
|
25
|
+
? EMULATOR_UPDATE_DETAILS.ui.snapshot
|
|
26
|
+
: EMULATOR_UPDATE_DETAILS.ui.main;
|
|
27
|
+
const dataconnectDetails = process.platform === "darwin"
|
|
28
|
+
? process.arch === "arm64"
|
|
29
|
+
? EMULATOR_UPDATE_DETAILS.dataconnect.darwin_arm64
|
|
30
|
+
: EMULATOR_UPDATE_DETAILS.dataconnect.darwin
|
|
31
|
+
: process.platform === "win32"
|
|
32
|
+
? EMULATOR_UPDATE_DETAILS.dataconnect.win32
|
|
33
|
+
: EMULATOR_UPDATE_DETAILS.dataconnect.linux;
|
|
34
|
+
switch (emulator) {
|
|
35
|
+
case "database":
|
|
36
|
+
return {
|
|
37
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.database.downloadPathRelativeToCacheDir),
|
|
38
|
+
version: EMULATOR_UPDATE_DETAILS.database.version,
|
|
39
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.database), { cacheDir: CACHE_DIR, namePrefix: "firebase-database-emulator" }),
|
|
40
|
+
};
|
|
41
|
+
case "firestore":
|
|
42
|
+
return {
|
|
43
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.firestore.downloadPathRelativeToCacheDir),
|
|
44
|
+
version: EMULATOR_UPDATE_DETAILS.firestore.version,
|
|
45
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.firestore), { cacheDir: CACHE_DIR, namePrefix: "cloud-firestore-emulator" }),
|
|
46
|
+
};
|
|
47
|
+
case "storage":
|
|
48
|
+
return {
|
|
49
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.storage.downloadPathRelativeToCacheDir),
|
|
50
|
+
version: EMULATOR_UPDATE_DETAILS.storage.version,
|
|
51
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.storage), { cacheDir: CACHE_DIR, namePrefix: "cloud-storage-rules-emulator" }),
|
|
52
|
+
};
|
|
53
|
+
case "ui":
|
|
54
|
+
return {
|
|
55
|
+
version: emulatorUiDetails.version,
|
|
56
|
+
downloadPath: path.join(CACHE_DIR, emulatorUiDetails.downloadPathRelativeToCacheDir),
|
|
57
|
+
unzipDir: path.join(CACHE_DIR, `ui-v${emulatorUiDetails.version}`),
|
|
58
|
+
binaryPath: path.join(CACHE_DIR, emulatorUiDetails.binaryPathRelativeToCacheDir),
|
|
59
|
+
opts: Object.assign(Object.assign({}, emulatorUiDetails), { cacheDir: CACHE_DIR, skipCache: experiments.isEnabled("emulatoruisnapshot"), skipChecksumAndSize: experiments.isEnabled("emulatoruisnapshot"), namePrefix: "ui" }),
|
|
60
|
+
};
|
|
61
|
+
case "pubsub":
|
|
62
|
+
return {
|
|
63
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.pubsub.downloadPathRelativeToCacheDir),
|
|
64
|
+
version: EMULATOR_UPDATE_DETAILS.pubsub.version,
|
|
65
|
+
unzipDir: path.join(CACHE_DIR, `pubsub-emulator-${EMULATOR_UPDATE_DETAILS.pubsub.version}`),
|
|
66
|
+
binaryPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.pubsub.binaryPathRelativeToCacheDir),
|
|
67
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.pubsub), { cacheDir: CACHE_DIR, namePrefix: "pubsub-emulator" }),
|
|
68
|
+
};
|
|
69
|
+
case "dataconnect":
|
|
70
|
+
return {
|
|
71
|
+
downloadPath: path.join(CACHE_DIR, dataconnectDetails.downloadPathRelativeToCacheDir),
|
|
72
|
+
version: dataconnectDetails.version,
|
|
73
|
+
binaryPath: path.join(CACHE_DIR, dataconnectDetails.downloadPathRelativeToCacheDir),
|
|
74
|
+
opts: Object.assign(Object.assign({}, dataconnectDetails), { cacheDir: CACHE_DIR, skipChecksumAndSize: false, namePrefix: "dataconnect-emulator", auth: false }),
|
|
75
|
+
};
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Invalid downloadable emulator: ${emulator}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
68
80
|
const EmulatorDetails = {
|
|
69
81
|
database: {
|
|
70
82
|
name: types_1.Emulators.DATABASE,
|
|
@@ -318,7 +330,7 @@ async function _runBinary(emulator, command, extraEnv) {
|
|
|
318
330
|
});
|
|
319
331
|
}
|
|
320
332
|
function getDownloadDetails(emulator) {
|
|
321
|
-
const details =
|
|
333
|
+
const details = generateDownloadDetails(emulator);
|
|
322
334
|
const pathOverride = process.env[`${emulator.toUpperCase()}_EMULATOR_BINARY_PATH`];
|
|
323
335
|
if (pathOverride) {
|
|
324
336
|
const logger = emulatorLogger_1.EmulatorLogger.forEmulator(emulator);
|
|
@@ -240,6 +240,10 @@ function initializeNetworkFiltering() {
|
|
|
240
240
|
}
|
|
241
241
|
async function initializeFirebaseFunctionsStubs() {
|
|
242
242
|
const firebaseFunctionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
|
|
243
|
+
if ((0, functionsEmulatorUtils_1.compareVersionStrings)(firebaseFunctionsResolution.version, "7.0.0") >= 0) {
|
|
244
|
+
logDebug("Detected firebase-functions v7+, skipping legacy stubs.");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
243
247
|
const firebaseFunctionsRoot = (0, functionsEmulatorShared_1.findModuleRoot)("firebase-functions", firebaseFunctionsResolution.resolution);
|
|
244
248
|
const httpsProviderResolution = path.join(firebaseFunctionsRoot, "lib/providers/https");
|
|
245
249
|
const httpsProviderV1Resolution = path.join(firebaseFunctionsRoot, "lib/v1/providers/https");
|
|
@@ -451,6 +455,10 @@ function warnAboutStorageProd() {
|
|
|
451
455
|
}
|
|
452
456
|
async function initializeFunctionsConfigHelper() {
|
|
453
457
|
const functionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
|
|
458
|
+
if ((0, functionsEmulatorUtils_1.compareVersionStrings)(functionsResolution.version, "7.0.0") >= 0) {
|
|
459
|
+
logDebug("Detected firebase-functions v7+, skipping config helper.");
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
454
462
|
const localFunctionsModule = require(functionsResolution.resolution);
|
|
455
463
|
logDebug("Checked functions.config()", {
|
|
456
464
|
config: localFunctionsModule.config(),
|
|
@@ -4,6 +4,7 @@ exports.TaskQueue = exports.TaskStatus = exports.Queue = void 0;
|
|
|
4
4
|
const abort_controller_1 = require("abort-controller");
|
|
5
5
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
6
6
|
const types_1 = require("./types");
|
|
7
|
+
const error_1 = require("../error");
|
|
7
8
|
const node_fetch_1 = require("node-fetch");
|
|
8
9
|
class Node {
|
|
9
10
|
constructor(data) {
|
|
@@ -198,6 +199,10 @@ class TaskQueue {
|
|
|
198
199
|
}
|
|
199
200
|
const controller = new abort_controller_1.default();
|
|
200
201
|
const signal = controller.signal;
|
|
202
|
+
signal.reason = "";
|
|
203
|
+
signal.throwIfAborted = () => {
|
|
204
|
+
throw new error_1.FirebaseError("Aborted");
|
|
205
|
+
};
|
|
201
206
|
const request = (0, node_fetch_1.default)(emulatedTask.task.httpRequest.url, {
|
|
202
207
|
method: "POST",
|
|
203
208
|
headers: headers,
|
package/lib/experiments.js
CHANGED
|
@@ -118,12 +118,6 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
118
118
|
shortDescription: "Adds experimental App Testing feature",
|
|
119
119
|
public: true,
|
|
120
120
|
},
|
|
121
|
-
ailogic: {
|
|
122
|
-
shortDescription: "Enable Firebase AI Logic feature for existing apps",
|
|
123
|
-
fullDescription: "Enables the AI Logic initialization feature that provisions AI Logic for existing Firebase apps.",
|
|
124
|
-
public: true,
|
|
125
|
-
default: false,
|
|
126
|
-
},
|
|
127
121
|
});
|
|
128
122
|
function isValidExperiment(name) {
|
|
129
123
|
return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
|
package/lib/firestore/api.js
CHANGED
|
@@ -22,16 +22,34 @@ class FirestoreApi {
|
|
|
22
22
|
this.printer = new pretty_print_1.PrettyPrint();
|
|
23
23
|
}
|
|
24
24
|
static processIndex(index) {
|
|
25
|
-
var _a
|
|
26
|
-
|
|
25
|
+
var _a;
|
|
26
|
+
let fields = index.fields;
|
|
27
|
+
const suffixOrder = FirestoreApi.lastIndexFieldOrder(fields);
|
|
28
|
+
const nameSuffix = { fieldPath: "__name__", order: suffixOrder };
|
|
27
29
|
const lastField = (_a = index.fields) === null || _a === void 0 ? void 0 : _a[index.fields.length - 1];
|
|
30
|
+
if (lastField.vectorConfig) {
|
|
31
|
+
const vectorField = lastField;
|
|
32
|
+
fields = fields.slice(0, -1);
|
|
33
|
+
if (fields.length === 0 || (fields === null || fields === void 0 ? void 0 : fields[fields.length - 1].fieldPath) !== "__name__") {
|
|
34
|
+
fields.push(nameSuffix);
|
|
35
|
+
}
|
|
36
|
+
fields.push(vectorField);
|
|
37
|
+
return Object.assign(Object.assign({}, index), { fields });
|
|
38
|
+
}
|
|
28
39
|
if ((lastField === null || lastField === void 0 ? void 0 : lastField.fieldPath) !== "__name__") {
|
|
29
|
-
const defaultDirection = (_c = (_b = index.fields) === null || _b === void 0 ? void 0 : _b[index.fields.length - 1]) === null || _c === void 0 ? void 0 : _c.order;
|
|
30
|
-
const nameSuffix = { fieldPath: "__name__", order: defaultDirection };
|
|
31
40
|
fields.push(nameSuffix);
|
|
32
41
|
}
|
|
33
42
|
return Object.assign(Object.assign({}, index), { fields });
|
|
34
43
|
}
|
|
44
|
+
static lastIndexFieldOrder(fields) {
|
|
45
|
+
let lastIndexFieldOrder = types.Order.ASCENDING;
|
|
46
|
+
for (const field of fields) {
|
|
47
|
+
if (field.order) {
|
|
48
|
+
lastIndexFieldOrder = field.order;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return lastIndexFieldOrder;
|
|
52
|
+
}
|
|
35
53
|
async deploy(options, indexes, fieldOverrides, databaseId = "(default)") {
|
|
36
54
|
var _a;
|
|
37
55
|
const spec = this.upgradeOldSpec({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONVERTABLE_EVENTS = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
3
|
+
exports.CONVERTABLE_EVENTS = exports.DATACONNECT_EVENT = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
4
4
|
exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
|
|
5
5
|
exports.STORAGE_EVENTS = [
|
|
6
6
|
"google.cloud.storage.object.v1.finalized",
|
|
@@ -28,6 +28,7 @@ exports.FIRESTORE_EVENTS = [
|
|
|
28
28
|
"google.cloud.firestore.document.v1.deleted.withAuthContext",
|
|
29
29
|
];
|
|
30
30
|
exports.FIREALERTS_EVENT = "google.firebase.firebasealerts.alerts.v1.published";
|
|
31
|
+
exports.DATACONNECT_EVENT = "google.firebase.dataconnect.connector.v1.mutationExecuted";
|
|
31
32
|
exports.CONVERTABLE_EVENTS = {
|
|
32
33
|
"google.cloud.firestore.document.v1.created": "google.cloud.firestore.document.v1.created.withAuthContext",
|
|
33
34
|
"google.cloud.firestore.document.v1.updated": "google.cloud.firestore.document.v1.updated.withAuthContext",
|
|
@@ -145,9 +145,13 @@ function initAppCounters(info) {
|
|
|
145
145
|
num_android_apps: 0,
|
|
146
146
|
num_ios_apps: 0,
|
|
147
147
|
num_flutter_apps: 0,
|
|
148
|
+
num_admin_node_apps: 0,
|
|
148
149
|
};
|
|
149
150
|
for (const app of (_a = info.apps) !== null && _a !== void 0 ? _a : []) {
|
|
150
151
|
switch (app.platform) {
|
|
152
|
+
case appUtils_1.Platform.ADMIN_NODE:
|
|
153
|
+
counts.num_admin_node_apps++;
|
|
154
|
+
break;
|
|
151
155
|
case appUtils_1.Platform.WEB:
|
|
152
156
|
counts.num_web_apps++;
|
|
153
157
|
break;
|
|
@@ -246,6 +250,20 @@ function addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app) {
|
|
|
246
250
|
}
|
|
247
251
|
const generate = connectorYaml.generate;
|
|
248
252
|
switch (app.platform) {
|
|
253
|
+
case appUtils_1.Platform.ADMIN_NODE: {
|
|
254
|
+
const adminNodeSdk = {
|
|
255
|
+
outputDir: path.relative(connectorDir, path.join(appDir, `src/dataconnect-admin-generated`)),
|
|
256
|
+
package: `@dataconnect/admin-generated`,
|
|
257
|
+
packageJsonDir: path.relative(connectorDir, appDir),
|
|
258
|
+
};
|
|
259
|
+
if (!(0, lodash_1.isArray)(generate === null || generate === void 0 ? void 0 : generate.adminNodeSdk)) {
|
|
260
|
+
generate.adminNodeSdk = generate.adminNodeSdk ? [generate.adminNodeSdk] : [];
|
|
261
|
+
}
|
|
262
|
+
if (!generate.adminNodeSdk.some((s) => s.outputDir === adminNodeSdk.outputDir)) {
|
|
263
|
+
generate.adminNodeSdk.push(adminNodeSdk);
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
249
267
|
case appUtils_1.Platform.WEB: {
|
|
250
268
|
const javascriptSdk = {
|
|
251
269
|
outputDir: path.relative(connectorDir, path.join(appDir, `src/dataconnect-generated`)),
|
|
@@ -29,11 +29,11 @@ const HOSTING_GITHUB_ACTION_NAME = "FirebaseExtended/action-hosting-deploy@v0";
|
|
|
29
29
|
const SERVICE_ACCOUNT_MAX_KEY_NUMBER = 10;
|
|
30
30
|
const githubApiClient = new apiv2_1.Client({ urlPrefix: (0, api_1.githubApiOrigin)(), auth: false });
|
|
31
31
|
async function initGitHub(setup) {
|
|
32
|
-
var _a, _b, _c, _d, _e;
|
|
32
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
33
33
|
if (!setup.projectId) {
|
|
34
34
|
return (0, utils_1.reject)("Could not determine Project ID, can't set up GitHub workflow.", { exit: 1 });
|
|
35
35
|
}
|
|
36
|
-
if (!setup.config.hosting) {
|
|
36
|
+
if (!setup.config.hosting && !((_a = setup.featureInfo) === null || _a === void 0 ? void 0 : _a.hosting)) {
|
|
37
37
|
return (0, utils_1.reject)(`Didn't find a Hosting config in firebase.json. Run ${(0, colorette_1.bold)("firebase init hosting")} instead.`);
|
|
38
38
|
}
|
|
39
39
|
logger_1.logger.info();
|
|
@@ -67,10 +67,10 @@ async function initGitHub(setup) {
|
|
|
67
67
|
(0, utils_1.logSuccess)(`Uploaded service account JSON to GitHub as secret ${(0, colorette_1.bold)(githubSecretName)}.`);
|
|
68
68
|
(0, utils_1.logBullet)(`You can manage your secrets at https://github.com/${repo}/settings/secrets.`);
|
|
69
69
|
logger_1.logger.info();
|
|
70
|
-
if (!Array.isArray(setup.config.hosting) && setup.config.hosting.predeploy) {
|
|
70
|
+
if (!Array.isArray(setup.config.hosting) && ((_b = setup.config.hosting) === null || _b === void 0 ? void 0 : _b.predeploy)) {
|
|
71
71
|
(0, utils_1.logBullet)(`You have a predeploy script configured in firebase.json.`);
|
|
72
72
|
}
|
|
73
|
-
const { script } = await promptForBuildScript((
|
|
73
|
+
const { script } = await promptForBuildScript((_c = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _c === void 0 ? void 0 : _c.useWebFrameworks);
|
|
74
74
|
const ymlDeployDoc = loadYMLDeploy();
|
|
75
75
|
let shouldWriteYMLHostingFile = true;
|
|
76
76
|
let shouldWriteYMLDeployFile = false;
|
|
@@ -81,7 +81,7 @@ async function initGitHub(setup) {
|
|
|
81
81
|
shouldWriteYMLHostingFile = overwrite;
|
|
82
82
|
}
|
|
83
83
|
if (shouldWriteYMLHostingFile) {
|
|
84
|
-
writeChannelActionYMLFile(YML_FULL_PATH_PULL_REQUEST, githubSecretName, setup.projectId, script, (
|
|
84
|
+
writeChannelActionYMLFile(YML_FULL_PATH_PULL_REQUEST, githubSecretName, setup.projectId, script, (_d = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _d === void 0 ? void 0 : _d.useWebFrameworks, (_e = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _e === void 0 ? void 0 : _e.source);
|
|
85
85
|
logger_1.logger.info();
|
|
86
86
|
(0, utils_1.logSuccess)(`Created workflow file ${(0, colorette_1.bold)(YML_FULL_PATH_PULL_REQUEST)}`);
|
|
87
87
|
}
|
|
@@ -101,7 +101,7 @@ async function initGitHub(setup) {
|
|
|
101
101
|
shouldWriteYMLDeployFile = true;
|
|
102
102
|
}
|
|
103
103
|
if (shouldWriteYMLDeployFile) {
|
|
104
|
-
writeDeployToProdActionYMLFile(YML_FULL_PATH_MERGE, branch, githubSecretName, setup.projectId, script, (
|
|
104
|
+
writeDeployToProdActionYMLFile(YML_FULL_PATH_MERGE, branch, githubSecretName, setup.projectId, script, (_f = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _f === void 0 ? void 0 : _f.useWebFrameworks, (_g = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _g === void 0 ? void 0 : _g.source);
|
|
105
105
|
logger_1.logger.info();
|
|
106
106
|
(0, utils_1.logSuccess)(`Created workflow file ${(0, colorette_1.bold)(YML_FULL_PATH_MERGE)}`);
|
|
107
107
|
}
|
|
@@ -48,10 +48,10 @@ async function askQuestions(setup, config, options) {
|
|
|
48
48
|
setup.featureInfo.hosting.newSiteId = await (0, interactive_1.pickHostingSiteName)("", createOptions);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
|
+
let discoveredFramework = experiments.isEnabled("webframeworks")
|
|
52
|
+
? await (0, frameworks_1.discover)(config.projectDir, false)
|
|
53
|
+
: undefined;
|
|
51
54
|
if (experiments.isEnabled("webframeworks")) {
|
|
52
|
-
let discoveredFramework = experiments.isEnabled("webframeworks")
|
|
53
|
-
? await (0, frameworks_1.discover)(config.projectDir, false)
|
|
54
|
-
: undefined;
|
|
55
55
|
if (discoveredFramework &&
|
|
56
56
|
(await (0, prompt_1.confirm)({
|
|
57
57
|
message: `Detected an existing ${frameworks_1.WebFrameworks[discoveredFramework.framework].name} codebase in the current directory, do you want to use this?`,
|
|
@@ -65,43 +65,43 @@ async function askQuestions(setup, config, options) {
|
|
|
65
65
|
else {
|
|
66
66
|
setup.featureInfo.hosting.useWebFrameworks = await (0, prompt_1.confirm)(`Do you want to use a web framework? (${clc.bold("experimental")})`);
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
}
|
|
69
|
+
if (setup.featureInfo.hosting.useWebFrameworks) {
|
|
70
|
+
(_a = (_g = setup.featureInfo.hosting).source) !== null && _a !== void 0 ? _a : (_g.source = await (0, prompt_1.input)({
|
|
71
|
+
message: "What folder would you like to use for your web application's root directory?",
|
|
72
|
+
default: "hosting",
|
|
73
|
+
}));
|
|
74
|
+
discoveredFramework = await (0, frameworks_1.discover)((0, path_1.join)(config.projectDir, setup.featureInfo.hosting.source));
|
|
75
|
+
if (discoveredFramework) {
|
|
76
|
+
const name = frameworks_1.WebFrameworks[discoveredFramework.framework].name;
|
|
77
|
+
(_b = (_h = setup.featureInfo.hosting).useDiscoveredFramework) !== null && _b !== void 0 ? _b : (_h.useDiscoveredFramework = await (0, prompt_1.confirm)({
|
|
78
|
+
message: `Detected an existing ${name} codebase in ${setup.featureInfo.hosting.source}, should we use this?`,
|
|
79
|
+
default: true,
|
|
72
80
|
}));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
const choices = [];
|
|
84
|
-
for (const value in frameworks_1.WebFrameworks) {
|
|
85
|
-
if (frameworks_1.WebFrameworks[value]) {
|
|
86
|
-
const { name, init } = frameworks_1.WebFrameworks[value];
|
|
87
|
-
if (init)
|
|
88
|
-
choices.push({ name, value });
|
|
89
|
-
}
|
|
81
|
+
if (setup.featureInfo.hosting.useDiscoveredFramework)
|
|
82
|
+
setup.featureInfo.hosting.webFramework = discoveredFramework.framework;
|
|
83
|
+
}
|
|
84
|
+
const choices = [];
|
|
85
|
+
for (const value in frameworks_1.WebFrameworks) {
|
|
86
|
+
if (frameworks_1.WebFrameworks[value]) {
|
|
87
|
+
const { name, init } = frameworks_1.WebFrameworks[value];
|
|
88
|
+
if (init)
|
|
89
|
+
choices.push({ name, value });
|
|
90
90
|
}
|
|
91
|
-
const defaultChoice = (_c = choices.find(({ value }) => value === (discoveredFramework === null || discoveredFramework === void 0 ? void 0 : discoveredFramework.framework))) === null || _c === void 0 ? void 0 : _c.value;
|
|
92
|
-
(_d = (_j = setup.featureInfo.hosting).webFramework) !== null && _d !== void 0 ? _d : (_j.webFramework = await (0, prompt_1.select)({
|
|
93
|
-
message: "Please choose the framework:",
|
|
94
|
-
default: defaultChoice,
|
|
95
|
-
choices,
|
|
96
|
-
}));
|
|
97
|
-
setup.featureInfo.hosting.region =
|
|
98
|
-
setup.featureInfo.hosting.region ||
|
|
99
|
-
(await (0, prompt_1.select)({
|
|
100
|
-
message: "In which region would you like to host server-side content, if applicable?",
|
|
101
|
-
default: constants_1.DEFAULT_REGION,
|
|
102
|
-
choices: constants_1.ALLOWED_SSR_REGIONS.filter((region) => region.recommended),
|
|
103
|
-
}));
|
|
104
91
|
}
|
|
92
|
+
const defaultChoice = (_c = choices.find(({ value }) => value === (discoveredFramework === null || discoveredFramework === void 0 ? void 0 : discoveredFramework.framework))) === null || _c === void 0 ? void 0 : _c.value;
|
|
93
|
+
(_d = (_j = setup.featureInfo.hosting).webFramework) !== null && _d !== void 0 ? _d : (_j.webFramework = await (0, prompt_1.select)({
|
|
94
|
+
message: "Please choose the framework:",
|
|
95
|
+
default: defaultChoice,
|
|
96
|
+
choices,
|
|
97
|
+
}));
|
|
98
|
+
setup.featureInfo.hosting.region =
|
|
99
|
+
setup.featureInfo.hosting.region ||
|
|
100
|
+
(await (0, prompt_1.select)({
|
|
101
|
+
message: "In which region would you like to host server-side content, if applicable?",
|
|
102
|
+
default: constants_1.DEFAULT_REGION,
|
|
103
|
+
choices: constants_1.ALLOWED_SSR_REGIONS.filter((region) => region.recommended),
|
|
104
|
+
}));
|
|
105
105
|
}
|
|
106
106
|
else {
|
|
107
107
|
logger_1.logger.info();
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enhanceProvisioningError = void 0;
|
|
4
|
+
const error_1 = require("../../error");
|
|
5
|
+
function isErrorInfo(detail) {
|
|
6
|
+
return detail["@type"] === "type.googleapis.com/google.rpc.ErrorInfo";
|
|
7
|
+
}
|
|
8
|
+
function isHelpLinks(detail) {
|
|
9
|
+
return detail["@type"] === "type.googleapis.com/google.rpc.Help";
|
|
10
|
+
}
|
|
11
|
+
function extractErrorDetails(err) {
|
|
12
|
+
var _a;
|
|
13
|
+
if (!(err instanceof Error)) {
|
|
14
|
+
return "";
|
|
15
|
+
}
|
|
16
|
+
if (err instanceof error_1.FirebaseError && err.context) {
|
|
17
|
+
const context = err.context;
|
|
18
|
+
const errorBody = (_a = context.body) === null || _a === void 0 ? void 0 : _a.error;
|
|
19
|
+
if ((errorBody === null || errorBody === void 0 ? void 0 : errorBody.details) && Array.isArray(errorBody.details)) {
|
|
20
|
+
const parts = [];
|
|
21
|
+
for (const detail of errorBody.details) {
|
|
22
|
+
if (isErrorInfo(detail)) {
|
|
23
|
+
parts.push(`Error details:`);
|
|
24
|
+
parts.push(` Reason: ${detail.reason}`);
|
|
25
|
+
parts.push(` Domain: ${detail.domain}`);
|
|
26
|
+
if (detail.metadata) {
|
|
27
|
+
parts.push(` Additional Info: ${JSON.stringify(detail.metadata)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else if (isHelpLinks(detail)) {
|
|
31
|
+
parts.push(`\nFor help resolving this issue:`);
|
|
32
|
+
for (const link of detail.links) {
|
|
33
|
+
parts.push(` - ${link.description}`);
|
|
34
|
+
parts.push(` ${link.url}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return parts.length > 0 ? `\n\n${parts.join("\n")}` : "";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
function enhanceProvisioningError(err, contextMessage) {
|
|
44
|
+
const originalError = (0, error_1.getError)(err);
|
|
45
|
+
const errorDetails = extractErrorDetails(err);
|
|
46
|
+
const fullMessage = errorDetails
|
|
47
|
+
? `${contextMessage}: ${originalError.message}${errorDetails}`
|
|
48
|
+
: `${contextMessage}: ${originalError.message}`;
|
|
49
|
+
return new error_1.FirebaseError(fullMessage, {
|
|
50
|
+
exit: 2,
|
|
51
|
+
original: originalError,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
exports.enhanceProvisioningError = enhanceProvisioningError;
|
|
@@ -7,6 +7,7 @@ const error_1 = require("../../error");
|
|
|
7
7
|
const logger_1 = require("../../logger");
|
|
8
8
|
const operation_poller_1 = require("../../operation-poller");
|
|
9
9
|
const apps_1 = require("../apps");
|
|
10
|
+
const errorHandler_1 = require("./errorHandler");
|
|
10
11
|
const apiClient = new apiv2_1.Client({
|
|
11
12
|
urlPrefix: (0, api_1.firebaseApiOrigin)(),
|
|
12
13
|
apiVersion: "v1alpha",
|
|
@@ -100,11 +101,7 @@ async function provisionFirebaseApp(options) {
|
|
|
100
101
|
return result;
|
|
101
102
|
}
|
|
102
103
|
catch (err) {
|
|
103
|
-
|
|
104
|
-
throw new error_1.FirebaseError(`Failed to provision Firebase app: ${errorMessage}`, {
|
|
105
|
-
exit: 2,
|
|
106
|
-
original: err instanceof Error ? err : new Error(String(err)),
|
|
107
|
-
});
|
|
104
|
+
throw (0, errorHandler_1.enhanceProvisioningError)(err, "Failed to provision Firebase app");
|
|
108
105
|
}
|
|
109
106
|
}
|
|
110
107
|
exports.provisionFirebaseApp = provisionFirebaseApp;
|