firebase-tools 15.20.0 → 15.22.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/lib/appdistribution/yaml_helper.js +2 -2
- package/lib/apphosting/constants.js +2 -1
- package/lib/apphosting/localbuilds.js +4 -2
- package/lib/apphosting/secrets/index.js +77 -0
- package/lib/archiveDirectory.js +2 -2
- package/lib/auth.js +2 -3
- package/lib/bin/cli.js +26 -18
- package/lib/commands/apphosting-secrets-revokeaccess.js +56 -0
- package/lib/commands/apptesting.js +11 -2
- package/lib/commands/crashlytics-symbols-upload.js +2 -2
- package/lib/commands/index.js +1 -0
- package/lib/crashlytics/sourcemap.js +2 -3
- package/lib/database/import.js +2 -2
- package/lib/dataconnect/build.js +6 -6
- package/lib/deploy/apphosting/util.js +9 -1
- package/lib/deploy/functions/prepare.js +39 -3
- package/lib/deploy/functions/prepareFunctionsUpload.js +1 -2
- package/lib/deploy/functions/release/index.js +0 -5
- package/lib/emulator/auth/apiSpec.js +307 -33
- package/lib/emulator/auth/cloudFunctions.js +2 -2
- package/lib/emulator/auth/operations.js +99 -9
- package/lib/emulator/auth/state.js +27 -0
- package/lib/emulator/downloadableEmulatorInfo.json +31 -31
- package/lib/emulator/functionsEmulatorShell.js +4 -4
- package/lib/emulator/functionsRuntimeWorker.js +2 -2
- package/lib/emulator/pubsubEmulator.js +3 -3
- package/lib/emulator/storage/apis/firebase.js +2 -2
- package/lib/emulator/storage/cloudFunctions.js +2 -2
- package/lib/emulator/storage/metadata.js +1 -2
- package/lib/emulator/storage/persistence.js +2 -2
- package/lib/emulator/storage/upload.js +3 -3
- package/lib/env.js +20 -4
- package/lib/experiments.js +1 -2
- package/lib/frameworks/angular/index.js +3 -2
- package/lib/frameworks/angular/utils.js +100 -2
- package/lib/frameworks/astro/index.js +1 -1
- package/lib/frameworks/astro/utils.js +1 -1
- package/lib/functions/python.js +4 -4
- package/lib/hosting/cloudRunProxy.js +8 -0
- package/lib/index.js +2 -2
- package/lib/init/features/apphosting.js +8 -1
- package/lib/init/features/functions/python.js +32 -20
- package/lib/localFunction.js +4 -2
- package/lib/track.js +2 -2
- package/lib/tsconfig.compile.tsbuildinfo +1 -1
- package/lib/tsconfig.publish.tsbuildinfo +1 -1
- package/lib/utils.js +70 -0
- package/package.json +3 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AuthCloudFunction = void 0;
|
|
4
|
-
const
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
5
|
const types_1 = require("../types");
|
|
6
6
|
const emulatorLogger_1 = require("../emulatorLogger");
|
|
7
7
|
const registry_1 = require("../registry");
|
|
@@ -32,7 +32,7 @@ class AuthCloudFunction {
|
|
|
32
32
|
}
|
|
33
33
|
createEventRequestBody(action, userInfoPayload) {
|
|
34
34
|
return {
|
|
35
|
-
eventId:
|
|
35
|
+
eventId: (0, crypto_1.randomUUID)(),
|
|
36
36
|
eventType: `providers/firebase.auth/eventTypes/user.${action}`,
|
|
37
37
|
resource: {
|
|
38
38
|
name: `projects/${this.projectId}`,
|
|
@@ -41,6 +41,14 @@ exports.authOperations = {
|
|
|
41
41
|
start: mfaSignInStart,
|
|
42
42
|
finalize: mfaSignInFinalize,
|
|
43
43
|
},
|
|
44
|
+
passkeyEnrollment: {
|
|
45
|
+
start: passkeyEnrollmentStart,
|
|
46
|
+
finalize: passkeyEnrollmentFinalize,
|
|
47
|
+
},
|
|
48
|
+
passkeySignIn: {
|
|
49
|
+
start: passkeySignInStart,
|
|
50
|
+
finalize: passkeySignInFinalize,
|
|
51
|
+
},
|
|
44
52
|
},
|
|
45
53
|
projects: {
|
|
46
54
|
createSessionCookie,
|
|
@@ -914,6 +922,10 @@ function setAccountInfoImpl(state, reqBody, { privileged = false, emulatorUrl =
|
|
|
914
922
|
if (reqBody.deleteProvider?.includes(state_1.PROVIDER_PHONE)) {
|
|
915
923
|
updates.phoneNumber = undefined;
|
|
916
924
|
}
|
|
925
|
+
if (reqBody.deletePasskey) {
|
|
926
|
+
const deletePasskey = reqBody.deletePasskey;
|
|
927
|
+
updates.passkeyInfo = (user.passkeyInfo || []).filter((pk) => pk.credentialId && !deletePasskey.includes(pk.credentialId));
|
|
928
|
+
}
|
|
917
929
|
}
|
|
918
930
|
if (reqBody.linkProviderUserInfo) {
|
|
919
931
|
(0, errors_1.assert)(reqBody.linkProviderUserInfo.providerId, "MISSING_PROVIDER_ID");
|
|
@@ -1574,16 +1586,90 @@ async function mfaSignInFinalize(state, reqBody) {
|
|
|
1574
1586
|
refreshToken,
|
|
1575
1587
|
};
|
|
1576
1588
|
}
|
|
1589
|
+
function passkeyEnrollmentStart(state, reqBody) {
|
|
1590
|
+
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1591
|
+
(0, errors_1.assert)(reqBody.idToken, "MISSING_ID_TOKEN");
|
|
1592
|
+
const { user } = parseIdToken(state, reqBody.idToken);
|
|
1593
|
+
return {
|
|
1594
|
+
credentialCreationOptions: {
|
|
1595
|
+
rp: { name: "localhost", id: "localhost" },
|
|
1596
|
+
user: {
|
|
1597
|
+
id: Buffer.from(user.localId).toString("base64"),
|
|
1598
|
+
name: user.email || "user@example.com",
|
|
1599
|
+
displayName: user.displayName || "User",
|
|
1600
|
+
},
|
|
1601
|
+
challenge: Buffer.from(newRandomId(32)).toString("base64"),
|
|
1602
|
+
pubKeyCredParams: [
|
|
1603
|
+
{ type: "public-key", alg: -7 },
|
|
1604
|
+
{ type: "public-key", alg: -257 },
|
|
1605
|
+
],
|
|
1606
|
+
timeout: 60000,
|
|
1607
|
+
attestation: "none",
|
|
1608
|
+
},
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
function passkeyEnrollmentFinalize(state, reqBody) {
|
|
1612
|
+
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1613
|
+
(0, errors_1.assert)(reqBody.idToken, "MISSING_ID_TOKEN");
|
|
1614
|
+
(0, errors_1.assert)(reqBody.authenticatorRegistrationResponse, "MISSING_AUTHENTICATOR_RESPONSE");
|
|
1615
|
+
let { user } = parseIdToken(state, reqBody.idToken);
|
|
1616
|
+
const credentialId = reqBody.authenticatorRegistrationResponse.id;
|
|
1617
|
+
(0, errors_1.assert)(credentialId, "INVALID_CREDENTIAL_ID");
|
|
1618
|
+
const isDuplicate = !!state.getUserByPasskeyCredentialId(credentialId);
|
|
1619
|
+
(0, errors_1.assert)(!isDuplicate, "CREDENTIAL_ALREADY_IN_USE");
|
|
1620
|
+
const newPasskey = {
|
|
1621
|
+
credentialId,
|
|
1622
|
+
name: reqBody.name || reqBody.displayName || "Unnamed Passkey",
|
|
1623
|
+
};
|
|
1624
|
+
const existing = user.passkeyInfo || [];
|
|
1625
|
+
user = state.updateUserByLocalId(user.localId, {
|
|
1626
|
+
passkeyInfo: [...existing, newPasskey],
|
|
1627
|
+
});
|
|
1628
|
+
const { idToken, refreshToken } = issueTokens(state, user, "passkey");
|
|
1629
|
+
return {
|
|
1630
|
+
localId: user.localId,
|
|
1631
|
+
idToken,
|
|
1632
|
+
refreshToken,
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1635
|
+
function passkeySignInStart(state) {
|
|
1636
|
+
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1637
|
+
return {
|
|
1638
|
+
credentialRequestOptions: {
|
|
1639
|
+
challenge: Buffer.from(newRandomId(32)).toString("base64"),
|
|
1640
|
+
rpId: "localhost",
|
|
1641
|
+
userVerification: "required",
|
|
1642
|
+
},
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
function passkeySignInFinalize(state, reqBody) {
|
|
1646
|
+
(0, errors_1.assert)(!state.disableAuth, "PROJECT_DISABLED");
|
|
1647
|
+
(0, errors_1.assert)(reqBody.authenticatorAuthenticationResponse, "MISSING_AUTHENTICATOR_RESPONSE");
|
|
1648
|
+
const credentialId = reqBody.authenticatorAuthenticationResponse.id;
|
|
1649
|
+
(0, errors_1.assert)(credentialId, "INVALID_CREDENTIAL_ID");
|
|
1650
|
+
let matchedUser = state.getUserByPasskeyCredentialId(credentialId);
|
|
1651
|
+
(0, errors_1.assert)(matchedUser, "PASSKEY_CREDENTIAL_NOT_FOUND");
|
|
1652
|
+
(0, errors_1.assert)(!matchedUser.disabled, "USER_DISABLED");
|
|
1653
|
+
matchedUser = state.updateUserByLocalId(matchedUser.localId, {
|
|
1654
|
+
lastLoginAt: Date.now().toString(),
|
|
1655
|
+
});
|
|
1656
|
+
const { idToken, refreshToken } = issueTokens(state, matchedUser, "passkey");
|
|
1657
|
+
return {
|
|
1658
|
+
idToken,
|
|
1659
|
+
refreshToken,
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1577
1662
|
function getConfig(state) {
|
|
1578
1663
|
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "((Can only get top-level configurations on agent projects.))");
|
|
1579
1664
|
return state.config;
|
|
1580
1665
|
}
|
|
1581
1666
|
function updateConfig(state, reqBody, ctx) {
|
|
1582
1667
|
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "((Can only update top-level configurations on agent projects.))");
|
|
1583
|
-
|
|
1584
|
-
|
|
1668
|
+
const triggers = reqBody.blockingFunctions?.triggers ?? {};
|
|
1669
|
+
for (const event in triggers) {
|
|
1670
|
+
if (Object.prototype.hasOwnProperty.call(triggers, event)) {
|
|
1585
1671
|
(0, errors_1.assert)(Object.values(state_1.BlockingFunctionEvents).includes(event), "INVALID_BLOCKING_FUNCTION : ((Event type is invalid.))");
|
|
1586
|
-
(0, errors_1.assert)((0, utils_1.parseAbsoluteUri)(
|
|
1672
|
+
(0, errors_1.assert)((0, utils_1.parseAbsoluteUri)(triggers[event].functionUri), "INVALID_BLOCKING_FUNCTION : ((Expected an absolute URI with valid scheme and host.))");
|
|
1587
1673
|
}
|
|
1588
1674
|
}
|
|
1589
1675
|
return state.updateConfig(reqBody, ctx.params.query.updateMask);
|
|
@@ -1870,13 +1956,13 @@ function fakeFetchUserInfoFromIdp(providerId, claims, samlResponse) {
|
|
|
1870
1956
|
});
|
|
1871
1957
|
break;
|
|
1872
1958
|
}
|
|
1873
|
-
case
|
|
1959
|
+
case /^saml\./.exec(providerId)?.input:
|
|
1874
1960
|
const nameId = samlResponse?.assertion?.subject?.nameId;
|
|
1875
1961
|
response.email = nameId && (0, utils_1.isValidEmailAddress)(nameId) ? nameId : response.email;
|
|
1876
1962
|
response.emailVerified = true;
|
|
1877
1963
|
response.rawUserInfo = JSON.stringify(samlResponse?.assertion?.attributeStatements);
|
|
1878
1964
|
break;
|
|
1879
|
-
case
|
|
1965
|
+
case /^oidc\./.exec(providerId)?.input:
|
|
1880
1966
|
default:
|
|
1881
1967
|
response.rawUserInfo = JSON.stringify(claims);
|
|
1882
1968
|
break;
|
|
@@ -2271,11 +2357,15 @@ function generateBlockingFunctionJwt(state, event, url, timeoutMs, user, options
|
|
|
2271
2357
|
});
|
|
2272
2358
|
return jwtStr;
|
|
2273
2359
|
}
|
|
2360
|
+
function assertBlockingFunctionsJwtPayload(payload) {
|
|
2361
|
+
(0, errors_1.assert)(payload !== null && typeof payload === "object", "((Invalid blocking function jwt.))");
|
|
2362
|
+
const p = payload;
|
|
2363
|
+
(0, errors_1.assert)(typeof p.iss === "string", "((Invalid blocking function jwt, missing `iss` claim.))");
|
|
2364
|
+
(0, errors_1.assert)(typeof p.aud === "string", "((Invalid blocking function jwt, missing `aud` claim.))");
|
|
2365
|
+
(0, errors_1.assert)(p.user_record !== undefined, "((Invalid blocking function jwt, missing `user_record` claim.))");
|
|
2366
|
+
}
|
|
2274
2367
|
function parseBlockingFunctionJwt(jwt) {
|
|
2275
2368
|
const decoded = (0, jsonwebtoken_1.decode)(jwt, { json: true });
|
|
2276
|
-
(
|
|
2277
|
-
(0, errors_1.assert)(decoded.iss, "((Invalid blocking function jwt, missing `iss` claim.))");
|
|
2278
|
-
(0, errors_1.assert)(decoded.aud, "((Invalid blocking function jwt, missing `aud` claim.))");
|
|
2279
|
-
(0, errors_1.assert)(decoded.user_record, "((Invalid blocking function jwt, missing `user_record` claim.))");
|
|
2369
|
+
assertBlockingFunctionsJwtPayload(decoded);
|
|
2280
2370
|
return decoded;
|
|
2281
2371
|
}
|
|
@@ -21,6 +21,7 @@ class ProjectState {
|
|
|
21
21
|
this.localIdForPhoneNumber = new Map();
|
|
22
22
|
this.localIdsForProviderEmail = new Map();
|
|
23
23
|
this.userIdForProviderRawId = new Map();
|
|
24
|
+
this.localIdForPasskeyCredentialId = new Map();
|
|
24
25
|
this.oobs = new Map();
|
|
25
26
|
this.verificationCodes = new Map();
|
|
26
27
|
this.temporaryProofs = new Map();
|
|
@@ -83,9 +84,22 @@ class ProjectState {
|
|
|
83
84
|
}
|
|
84
85
|
const oldEmail = user.email;
|
|
85
86
|
const oldPhoneNumber = user.phoneNumber;
|
|
87
|
+
const oldPasskeyInfo = user.passkeyInfo;
|
|
86
88
|
for (const field of Object.keys(fields)) {
|
|
87
89
|
(0, utils_1.mirrorFieldTo)(user, field, fields);
|
|
88
90
|
}
|
|
91
|
+
if (fields.passkeyInfo) {
|
|
92
|
+
for (const pk of oldPasskeyInfo ?? []) {
|
|
93
|
+
if (pk.credentialId) {
|
|
94
|
+
this.localIdForPasskeyCredentialId.delete(pk.credentialId);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const pk of fields.passkeyInfo) {
|
|
98
|
+
if (pk.credentialId) {
|
|
99
|
+
this.localIdForPasskeyCredentialId.set(pk.credentialId, user.localId);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
89
103
|
if (oldEmail && oldEmail !== user.email) {
|
|
90
104
|
this.localIdForEmail.delete(oldEmail);
|
|
91
105
|
}
|
|
@@ -267,6 +281,13 @@ class ProjectState {
|
|
|
267
281
|
getUserByLocalId(localId) {
|
|
268
282
|
return this.users.get(localId);
|
|
269
283
|
}
|
|
284
|
+
getUserByPasskeyCredentialId(credentialId) {
|
|
285
|
+
const localId = this.localIdForPasskeyCredentialId.get(credentialId);
|
|
286
|
+
if (!localId) {
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
return this.getUserByLocalIdAssertingExists(localId);
|
|
290
|
+
}
|
|
270
291
|
createRefreshTokenFor(userInfo, provider, { extraClaims = {}, secondFactor, } = {}) {
|
|
271
292
|
const localId = userInfo.localId;
|
|
272
293
|
const refreshTokenRecord = {
|
|
@@ -343,6 +364,7 @@ class ProjectState {
|
|
|
343
364
|
this.localIdForPhoneNumber.clear();
|
|
344
365
|
this.localIdsForProviderEmail.clear();
|
|
345
366
|
this.userIdForProviderRawId.clear();
|
|
367
|
+
this.localIdForPasskeyCredentialId.clear();
|
|
346
368
|
}
|
|
347
369
|
getUserCount() {
|
|
348
370
|
return this.users.size;
|
|
@@ -400,6 +422,11 @@ class ProjectState {
|
|
|
400
422
|
this.removeProviderEmailForUser(info.email, user.localId);
|
|
401
423
|
}
|
|
402
424
|
}
|
|
425
|
+
for (const pk of user.passkeyInfo ?? []) {
|
|
426
|
+
if (pk.credentialId) {
|
|
427
|
+
this.localIdForPasskeyCredentialId.delete(pk.credentialId);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
403
430
|
}
|
|
404
431
|
}
|
|
405
432
|
exports.ProjectState = ProjectState;
|
|
@@ -44,46 +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.33",
|
|
48
|
+
"expectedSize": 52948835,
|
|
49
|
+
"expectedChecksum": "7dc33e0c8bb37948228e49a18375d53b",
|
|
50
|
+
"expectedChecksumSHA256": "93768f8763d85c37f7f6e0f64d10195abaa088f4ff559b7d9fb8a2fc5520848d",
|
|
51
|
+
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.33.zip",
|
|
52
|
+
"downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.33.zip",
|
|
53
|
+
"binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.33/pubsub-emulator/bin/cloud-pubsub-emulator"
|
|
54
54
|
},
|
|
55
55
|
"dataconnect": {
|
|
56
56
|
"darwin": {
|
|
57
|
-
"version": "3.4.
|
|
58
|
-
"expectedSize":
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.4.
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.
|
|
57
|
+
"version": "3.4.12",
|
|
58
|
+
"expectedSize": 29963104,
|
|
59
|
+
"expectedChecksum": "ee4d81abfba3576c7c6c8082313acfd0",
|
|
60
|
+
"expectedChecksumSHA256": "8aed1dc6cc8c35ab23fdf10e519e9cf3d93c8a0ccb0ff7d5af3ddc41a4847e3e",
|
|
61
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.4.12",
|
|
62
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.12"
|
|
63
63
|
},
|
|
64
64
|
"darwin_arm64": {
|
|
65
|
-
"version": "3.4.
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.4.
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.
|
|
65
|
+
"version": "3.4.12",
|
|
66
|
+
"expectedSize": 29442946,
|
|
67
|
+
"expectedChecksum": "15a6ee63f48021197df5395455666f29",
|
|
68
|
+
"expectedChecksumSHA256": "4a3933f55db380f20c478cd1a3cc4da8742da75bdcea589fc6e1f52b18943f48",
|
|
69
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.4.12",
|
|
70
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.12"
|
|
71
71
|
},
|
|
72
72
|
"win32": {
|
|
73
|
-
"version": "3.4.
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.4.
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.
|
|
73
|
+
"version": "3.4.12",
|
|
74
|
+
"expectedSize": 30456320,
|
|
75
|
+
"expectedChecksum": "546019a713be28620a3b43d49fc9d4b0",
|
|
76
|
+
"expectedChecksumSHA256": "ec1de720e173f0a613fbbb51767c0288121aa2f80e45e6bad0f3d2aff12689ec",
|
|
77
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.4.12",
|
|
78
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.12.exe"
|
|
79
79
|
},
|
|
80
80
|
"linux": {
|
|
81
|
-
"version": "3.4.
|
|
82
|
-
"expectedSize":
|
|
83
|
-
"expectedChecksum": "
|
|
84
|
-
"expectedChecksumSHA256": "
|
|
85
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.4.
|
|
86
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.
|
|
81
|
+
"version": "3.4.12",
|
|
82
|
+
"expectedSize": 29888696,
|
|
83
|
+
"expectedChecksum": "5ab8da956043a48b43199f07b94ac48c",
|
|
84
|
+
"expectedChecksumSHA256": "1a420f3d2672627eae2d9b0b6747b833517cfc08f7e80ae3a79389788691b67a",
|
|
85
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.4.12",
|
|
86
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.12"
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FunctionsEmulatorShell = void 0;
|
|
4
|
-
const
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
5
|
const utils = require("../utils");
|
|
6
6
|
const functionsEmulator_1 = require("./functionsEmulator");
|
|
7
7
|
const logger_1 = require("../logger");
|
|
@@ -26,7 +26,7 @@ class FunctionsEmulatorShell {
|
|
|
26
26
|
resource = resource.name;
|
|
27
27
|
}
|
|
28
28
|
return {
|
|
29
|
-
eventId:
|
|
29
|
+
eventId: (0, crypto_1.randomUUID)(),
|
|
30
30
|
timestamp: new Date().toISOString(),
|
|
31
31
|
eventType: eventTrigger.eventType,
|
|
32
32
|
resource: resource,
|
|
@@ -39,7 +39,7 @@ class FunctionsEmulatorShell {
|
|
|
39
39
|
const ce = {
|
|
40
40
|
specversion: "1.0",
|
|
41
41
|
datacontenttype: "application/json",
|
|
42
|
-
id:
|
|
42
|
+
id: (0, crypto_1.randomUUID)(),
|
|
43
43
|
type: eventTrigger.eventType,
|
|
44
44
|
time: new Date().toISOString(),
|
|
45
45
|
source: "",
|
|
@@ -50,7 +50,7 @@ class FunctionsEmulatorShell {
|
|
|
50
50
|
}
|
|
51
51
|
else if (eventTrigger.eventType.startsWith("google.cloud.pubsub")) {
|
|
52
52
|
ce.source = eventTrigger.eventFilters.topic;
|
|
53
|
-
data = { ...data, messageId:
|
|
53
|
+
data = { ...data, messageId: (0, crypto_1.randomUUID)() };
|
|
54
54
|
}
|
|
55
55
|
else if (eventTrigger.eventType.startsWith("google.cloud.firestore")) {
|
|
56
56
|
ce.source = `projects/_/databases/(default)`;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RuntimeWorkerPool = exports.RuntimeWorker = exports.RuntimeWorkerState = void 0;
|
|
4
4
|
const http = require("http");
|
|
5
|
-
const
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
6
|
const types_1 = require("./types");
|
|
7
7
|
const events_1 = require("events");
|
|
8
8
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
@@ -26,7 +26,7 @@ class RuntimeWorker {
|
|
|
26
26
|
this.stateEvents = new events_1.EventEmitter();
|
|
27
27
|
this.logListeners = [];
|
|
28
28
|
this._state = RuntimeWorkerState.CREATED;
|
|
29
|
-
this.id =
|
|
29
|
+
this.id = (0, crypto_1.randomUUID)();
|
|
30
30
|
this.triggerKey = triggerId || FREE_WORKER_KEY;
|
|
31
31
|
this.runtime = runtime;
|
|
32
32
|
const childProc = this.runtime.process;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PubsubEmulator = void 0;
|
|
4
|
-
const
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
5
|
const pubsub_1 = require("@google-cloud/pubsub");
|
|
6
6
|
const downloadableEmulators = require("./downloadableEmulators");
|
|
7
7
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
@@ -117,7 +117,7 @@ class PubsubEmulator {
|
|
|
117
117
|
createLegacyEventRequestBody(topic, message) {
|
|
118
118
|
return {
|
|
119
119
|
context: {
|
|
120
|
-
eventId:
|
|
120
|
+
eventId: (0, crypto_1.randomUUID)(),
|
|
121
121
|
resource: {
|
|
122
122
|
service: "pubsub.googleapis.com",
|
|
123
123
|
name: `projects/${this.args.projectId}/topics/${topic}`,
|
|
@@ -147,7 +147,7 @@ class PubsubEmulator {
|
|
|
147
147
|
};
|
|
148
148
|
return {
|
|
149
149
|
specversion: "1.0",
|
|
150
|
-
id:
|
|
150
|
+
id: (0, crypto_1.randomUUID)(),
|
|
151
151
|
time: truncatedPublishTime,
|
|
152
152
|
type: "google.cloud.pubsub.topic.v1.messagePublished",
|
|
153
153
|
source: `//pubsub.googleapis.com/projects/${this.args.projectId}/topics/${topic}`,
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createFirebaseEndpoints = createFirebaseEndpoints;
|
|
4
4
|
const emulatorLogger_1 = require("../../emulatorLogger");
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
|
-
const
|
|
6
|
+
const crypto_1 = require("crypto");
|
|
7
7
|
const metadata_1 = require("../metadata");
|
|
8
8
|
const express_1 = require("express");
|
|
9
9
|
const shared_1 = require("./shared");
|
|
@@ -157,7 +157,7 @@ function createFirebaseEndpoints(emulator) {
|
|
|
157
157
|
if (!upload.metadata?.metadata?.firebaseStorageDownloadTokens) {
|
|
158
158
|
const customMetadata = {
|
|
159
159
|
...(upload.metadata?.metadata || {}),
|
|
160
|
-
firebaseStorageDownloadTokens:
|
|
160
|
+
firebaseStorageDownloadTokens: (0, crypto_1.randomUUID)(),
|
|
161
161
|
};
|
|
162
162
|
upload.metadata = { ...(upload.metadata || {}), metadata: customMetadata };
|
|
163
163
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StorageCloudFunctions = void 0;
|
|
4
|
-
const
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
5
|
const registry_1 = require("../registry");
|
|
6
6
|
const types_1 = require("../types");
|
|
7
7
|
const emulatorLogger_1 = require("../emulatorLogger");
|
|
@@ -77,7 +77,7 @@ class StorageCloudFunctions {
|
|
|
77
77
|
}
|
|
78
78
|
return {
|
|
79
79
|
specversion: "1.0",
|
|
80
|
-
id:
|
|
80
|
+
id: (0, crypto_1.randomUUID)(),
|
|
81
81
|
type: `google.cloud.storage.object.v1.${ceAction}`,
|
|
82
82
|
source: `//storage.googleapis.com/projects/_/buckets/${objectMetadataPayload.bucket}/objects/${objectMetadataPayload.name}`,
|
|
83
83
|
time,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CloudStorageObjectMetadata = exports.CloudStorageObjectAccessControlMetadata = exports.CloudStorageBucketMetadata = exports.OutgoingFirebaseMetadata = exports.StoredFileMetadata = void 0;
|
|
4
4
|
exports.toSerializedDate = toSerializedDate;
|
|
5
|
-
const uuid = require("uuid");
|
|
6
5
|
const crypto = require("crypto");
|
|
7
6
|
const registry_1 = require("../registry");
|
|
8
7
|
const types_1 = require("../types");
|
|
@@ -185,7 +184,7 @@ class StoredFileMetadata {
|
|
|
185
184
|
}
|
|
186
185
|
}
|
|
187
186
|
addDownloadToken(shouldTrigger = true) {
|
|
188
|
-
this.downloadTokens = [...(this.downloadTokens || []),
|
|
187
|
+
this.downloadTokens = [...(this.downloadTokens || []), crypto.randomUUID()];
|
|
189
188
|
this.update({}, shouldTrigger);
|
|
190
189
|
}
|
|
191
190
|
deleteDownloadToken(token) {
|
|
@@ -6,7 +6,7 @@ const promises_1 = require("node:fs/promises");
|
|
|
6
6
|
const fs = require("fs");
|
|
7
7
|
const fse = require("fs-extra");
|
|
8
8
|
const path = require("path");
|
|
9
|
-
const
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
10
|
class Persistence {
|
|
11
11
|
constructor(dirPath) {
|
|
12
12
|
this._diskPathMap = new Map();
|
|
@@ -78,7 +78,7 @@ class Persistence {
|
|
|
78
78
|
fse.copyFileSync(sourcePath, this.getDiskPath(newName));
|
|
79
79
|
}
|
|
80
80
|
generateNewDiskName() {
|
|
81
|
-
return
|
|
81
|
+
return (0, crypto_1.randomUUID)();
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
exports.Persistence = Persistence;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.UploadService = exports.NotCancellableError = exports.UploadPreviouslyFinalizedError = exports.UploadNotActiveError = exports.UploadStatus = exports.UploadType = void 0;
|
|
4
|
-
const
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
5
|
const errors_1 = require("./errors");
|
|
6
6
|
var UploadType;
|
|
7
7
|
(function (UploadType) {
|
|
@@ -58,7 +58,7 @@ class UploadService {
|
|
|
58
58
|
return upload;
|
|
59
59
|
}
|
|
60
60
|
startOneShotUpload(request) {
|
|
61
|
-
const id = (0,
|
|
61
|
+
const id = (0, crypto_1.randomUUID)();
|
|
62
62
|
const upload = {
|
|
63
63
|
id,
|
|
64
64
|
bucketId: request.bucketId,
|
|
@@ -74,7 +74,7 @@ class UploadService {
|
|
|
74
74
|
return upload;
|
|
75
75
|
}
|
|
76
76
|
startResumableUpload(request) {
|
|
77
|
-
const id = (0,
|
|
77
|
+
const id = (0, crypto_1.randomUUID)();
|
|
78
78
|
const upload = {
|
|
79
79
|
id: id,
|
|
80
80
|
bucketId: request.bucketId,
|
package/lib/env.js
CHANGED
|
@@ -22,23 +22,39 @@ function setFirebaseMcp(value) {
|
|
|
22
22
|
isFirebaseMcpFlag = value;
|
|
23
23
|
}
|
|
24
24
|
function detectAIAgent() {
|
|
25
|
+
if (process.env.AI_AGENT) {
|
|
26
|
+
return process.env.AI_AGENT.trim();
|
|
27
|
+
}
|
|
25
28
|
if (process.env.ANTIGRAVITY_AGENT)
|
|
26
29
|
return "antigravity";
|
|
27
|
-
if (process.env.CLAUDECODE)
|
|
30
|
+
if (process.env.CLAUDECODE || process.env.CLAUDE_CODE)
|
|
28
31
|
return "claude_code";
|
|
29
32
|
if (process.env.CLINE_ACTIVE)
|
|
30
33
|
return "cline";
|
|
31
|
-
if (process.env.CODEX_SANDBOX)
|
|
34
|
+
if (process.env.CODEX_SANDBOX || process.env.CODEX_CI || process.env.CODEX_THREAD_ID) {
|
|
32
35
|
return "codex_cli";
|
|
33
|
-
|
|
36
|
+
}
|
|
37
|
+
if (process.env.CURSOR_AGENT ||
|
|
38
|
+
process.env.CURSOR_TRACE_ID ||
|
|
39
|
+
process.env.CURSOR_EXTENSION_HOST_ROLE === "agent-exec") {
|
|
34
40
|
return "cursor";
|
|
41
|
+
}
|
|
35
42
|
if (process.env.GEMINI_CLI)
|
|
36
43
|
return "gemini_cli";
|
|
37
|
-
if (process.env.OPENCODE)
|
|
44
|
+
if (process.env.OPENCODE || process.env.OPENCODE_CLIENT)
|
|
38
45
|
return "open_code";
|
|
39
46
|
if (process.env.ANDROID_STUDIO_AGENT)
|
|
40
47
|
return "android_studio_agent";
|
|
41
48
|
if (process.env.KIRO_AGENT_PATH)
|
|
42
49
|
return "kiro";
|
|
50
|
+
if (process.env.COPILOT_MODEL ||
|
|
51
|
+
process.env.COPILOT_ALLOW_ALL ||
|
|
52
|
+
process.env.COPILOT_GITHUB_TOKEN) {
|
|
53
|
+
return "github_copilot";
|
|
54
|
+
}
|
|
55
|
+
if (process.env.REPL_ID)
|
|
56
|
+
return "replit";
|
|
57
|
+
if (process.env.AUGMENT_AGENT)
|
|
58
|
+
return "augment";
|
|
43
59
|
return "unknown";
|
|
44
60
|
}
|
package/lib/experiments.js
CHANGED
|
@@ -9,7 +9,6 @@ exports.enableExperimentsFromCliEnvVariable = enableExperimentsFromCliEnvVariabl
|
|
|
9
9
|
exports.assertEnabled = assertEnabled;
|
|
10
10
|
exports.flushToDisk = flushToDisk;
|
|
11
11
|
const colorette_1 = require("colorette");
|
|
12
|
-
const leven = require("leven");
|
|
13
12
|
const path_1 = require("path");
|
|
14
13
|
const configstore_1 = require("./configstore");
|
|
15
14
|
const error_1 = require("./error");
|
|
@@ -195,7 +194,7 @@ function experimentNameAutocorrect(malformed) {
|
|
|
195
194
|
if (isValidExperiment(malformed)) {
|
|
196
195
|
throw new error_1.FirebaseError("Assertion failed: experimentNameAutocorrect given actual experiment name", { exit: 2 });
|
|
197
196
|
}
|
|
198
|
-
return Object.keys(exports.ALL_EXPERIMENTS).filter((name) =>
|
|
197
|
+
return Object.keys(exports.ALL_EXPERIMENTS).filter((name) => (0, utils_1.stringDistance)(name, malformed) < malformed.length * 0.4);
|
|
199
198
|
}
|
|
200
199
|
let localPreferencesCache = undefined;
|
|
201
200
|
function localPreferences() {
|
|
@@ -45,8 +45,9 @@ function init(setup, config) {
|
|
|
45
45
|
return Promise.resolve();
|
|
46
46
|
}
|
|
47
47
|
async function build(dir, configuration) {
|
|
48
|
-
const { targets, serveOptimizedImages, locales, baseHref: baseUrl, ssr, } = await (0, utils_2.getBuildConfig)(dir, configuration);
|
|
48
|
+
const { targets, serveOptimizedImages, locales, baseHref: baseUrl, ssr, buildTargetOptions, } = await (0, utils_2.getBuildConfig)(dir, configuration);
|
|
49
49
|
await (0, utils_1.warnIfCustomBuildScript)(dir, exports.name, DEFAULT_BUILD_SCRIPT);
|
|
50
|
+
await (0, utils_2.maybeWarnAngular22SsrSecurity)(dir, { ssr, buildTargetOptions });
|
|
50
51
|
for (const target of targets) {
|
|
51
52
|
const cli = (0, utils_1.getNodeModuleBin)("ng", dir);
|
|
52
53
|
const result = (0, cross_spawn_1.sync)(cli, ["run", target], {
|
|
@@ -145,7 +146,7 @@ async function ɵcodegenFunctionsDirectory(sourceDir, destDir, configuration) {
|
|
|
145
146
|
if (bundleDependencies) {
|
|
146
147
|
const dependencies = {};
|
|
147
148
|
for (const externalDependency of externalDependencies) {
|
|
148
|
-
const packageVersion = (0, utils_1.findDependency)(externalDependency)?.version;
|
|
149
|
+
const packageVersion = (0, utils_1.findDependency)(externalDependency, { cwd: sourceDir })?.version;
|
|
149
150
|
if (packageVersion) {
|
|
150
151
|
dependencies[externalDependency] = packageVersion;
|
|
151
152
|
}
|