@prmichaelsen/firebase-admin-sdk-v8 2.7.0 → 2.8.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/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.8.0] - 2026-03-12
9
+
10
+ ### Added
11
+ - **Firestore Batch Get by Paths (`getAllByPaths`)**: Fetch multiple documents from different collections in a single REST API call
12
+ - `getAllByPaths([{ collection, id }])` - Batch get up to 100 documents from arbitrary paths via `documents:batchGet` endpoint
13
+ - Returns results in the same order as input refs
14
+ - Missing documents return `null` (no throw)
15
+ - Supports subcollection paths (e.g., `users/uid1/profile`)
16
+ - 7 unit tests + 3 e2e tests
17
+
8
18
  ## [2.7.0] - 2026-03-12
9
19
 
10
20
  ### Added
@@ -16,6 +26,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
26
  - Supports subcollection paths
17
27
  - 8 unit tests + 5 e2e tests
18
28
 
29
+ ### Fixed
30
+ - **FCM**: `sendMessage` now uses `getProjectId()` instead of `getConfig().projectId`, fixing silent failure when `initializeApp()` hasn't been called (falls back to `FIREBASE_PROJECT_ID` env var)
31
+
19
32
  ### Changed
20
33
  - Total unit tests increased from 498 to 506 (+8 tests)
21
34
 
package/dist/index.d.mts CHANGED
@@ -656,6 +656,26 @@ declare function queryDocuments(collectionPath: string, options?: QueryOptions):
656
656
  * ```
657
657
  */
658
658
  declare function getAll(collectionPath: string, documentIds: string[]): Promise<(DataObject | null)[]>;
659
+ /**
660
+ * Batch get multiple documents from different collections by their full paths
661
+ * Uses the documents:batchGet REST API endpoint
662
+ *
663
+ * @param documentRefs - Array of { collection, id } tuples pointing to documents (max 100)
664
+ * @returns Array of results in the same order as documentRefs. Missing documents return null.
665
+ * @throws {Error} If the operation fails or more than 100 documents requested
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * const docs = await getAllByPaths([
670
+ * { collection: 'users/uid1/profile', id: 'default' },
671
+ * { collection: 'users/uid2/profile', id: 'default' },
672
+ * ]);
673
+ * ```
674
+ */
675
+ declare function getAllByPaths(documentRefs: Array<{
676
+ collection: string;
677
+ id: string;
678
+ }>): Promise<(DataObject | null)[]>;
659
679
  /**
660
680
  * Perform batch write operations (set, update, delete)
661
681
  *
@@ -1266,4 +1286,4 @@ declare function getAdminAccessToken(): Promise<string>;
1266
1286
  */
1267
1287
  declare function clearTokenCache(): void;
1268
1288
 
1269
- export { type AndroidConfig, type AndroidNotification, type ApnsConfig, type BatchWrite, type BatchWriteResult, type CreateUserRequest, type CustomClaims, type CustomTokenSignInResponse, type DataObject, type DecodedIdToken, type DocumentReference, type DownloadOptions, type Notification as FcmNotification, type FcmOptions, FieldValue, type FieldValue$1 as FieldValueSentinel, FieldValueType, type FileMetadata, type FirestoreDocument, type FirestoreValue, type ListFilesResult, type ListOptions, type ListUsersResult, type Message, type QueryFilter, type QueryOptions, type QueryOrder, type ResumableUploadOptions, type SendResponse, type ServiceAccount, type SessionCookieOptions, type SetOptions, type SignedUrlOptions, type TokenResponse, type TopicManagementError, type TopicManagementResponse, type UpdateOptions, type UpdateUserRequest, type UploadOptions, type UserInfo, type UserRecord, type WebpushConfig, type WhereFilterOp, addDocument, batchWrite, clearConfig, clearTokenCache, countDocuments, createCustomToken, createSessionCookie, createUser, deleteDocument, deleteFile, deleteUser, downloadFile, fileExists, generateSignedUrl, getAdminAccessToken, getAll, getAuth, getConfig, getDocument, getFileMetadata, getProjectId, getServiceAccount, getUserByEmail, getUserByUid, getUserFromToken, initializeApp, iterateCollection, listDocuments, listFiles, listUsers, queryDocuments, sendMessage, setCustomUserClaims, setDocument, signInWithCustomToken, subscribeToTopic, unsubscribeFromTopic, updateDocument, updateUser, uploadFile, uploadFileResumable, verifyIdToken, verifySessionCookie };
1289
+ export { type AndroidConfig, type AndroidNotification, type ApnsConfig, type BatchWrite, type BatchWriteResult, type CreateUserRequest, type CustomClaims, type CustomTokenSignInResponse, type DataObject, type DecodedIdToken, type DocumentReference, type DownloadOptions, type Notification as FcmNotification, type FcmOptions, FieldValue, type FieldValue$1 as FieldValueSentinel, FieldValueType, type FileMetadata, type FirestoreDocument, type FirestoreValue, type ListFilesResult, type ListOptions, type ListUsersResult, type Message, type QueryFilter, type QueryOptions, type QueryOrder, type ResumableUploadOptions, type SendResponse, type ServiceAccount, type SessionCookieOptions, type SetOptions, type SignedUrlOptions, type TokenResponse, type TopicManagementError, type TopicManagementResponse, type UpdateOptions, type UpdateUserRequest, type UploadOptions, type UserInfo, type UserRecord, type WebpushConfig, type WhereFilterOp, addDocument, batchWrite, clearConfig, clearTokenCache, countDocuments, createCustomToken, createSessionCookie, createUser, deleteDocument, deleteFile, deleteUser, downloadFile, fileExists, generateSignedUrl, getAdminAccessToken, getAll, getAllByPaths, getAuth, getConfig, getDocument, getFileMetadata, getProjectId, getServiceAccount, getUserByEmail, getUserByUid, getUserFromToken, initializeApp, iterateCollection, listDocuments, listFiles, listUsers, queryDocuments, sendMessage, setCustomUserClaims, setDocument, signInWithCustomToken, subscribeToTopic, unsubscribeFromTopic, updateDocument, updateUser, uploadFile, uploadFileResumable, verifyIdToken, verifySessionCookie };
package/dist/index.d.ts CHANGED
@@ -656,6 +656,26 @@ declare function queryDocuments(collectionPath: string, options?: QueryOptions):
656
656
  * ```
657
657
  */
658
658
  declare function getAll(collectionPath: string, documentIds: string[]): Promise<(DataObject | null)[]>;
659
+ /**
660
+ * Batch get multiple documents from different collections by their full paths
661
+ * Uses the documents:batchGet REST API endpoint
662
+ *
663
+ * @param documentRefs - Array of { collection, id } tuples pointing to documents (max 100)
664
+ * @returns Array of results in the same order as documentRefs. Missing documents return null.
665
+ * @throws {Error} If the operation fails or more than 100 documents requested
666
+ *
667
+ * @example
668
+ * ```typescript
669
+ * const docs = await getAllByPaths([
670
+ * { collection: 'users/uid1/profile', id: 'default' },
671
+ * { collection: 'users/uid2/profile', id: 'default' },
672
+ * ]);
673
+ * ```
674
+ */
675
+ declare function getAllByPaths(documentRefs: Array<{
676
+ collection: string;
677
+ id: string;
678
+ }>): Promise<(DataObject | null)[]>;
659
679
  /**
660
680
  * Perform batch write operations (set, update, delete)
661
681
  *
@@ -1266,4 +1286,4 @@ declare function getAdminAccessToken(): Promise<string>;
1266
1286
  */
1267
1287
  declare function clearTokenCache(): void;
1268
1288
 
1269
- export { type AndroidConfig, type AndroidNotification, type ApnsConfig, type BatchWrite, type BatchWriteResult, type CreateUserRequest, type CustomClaims, type CustomTokenSignInResponse, type DataObject, type DecodedIdToken, type DocumentReference, type DownloadOptions, type Notification as FcmNotification, type FcmOptions, FieldValue, type FieldValue$1 as FieldValueSentinel, FieldValueType, type FileMetadata, type FirestoreDocument, type FirestoreValue, type ListFilesResult, type ListOptions, type ListUsersResult, type Message, type QueryFilter, type QueryOptions, type QueryOrder, type ResumableUploadOptions, type SendResponse, type ServiceAccount, type SessionCookieOptions, type SetOptions, type SignedUrlOptions, type TokenResponse, type TopicManagementError, type TopicManagementResponse, type UpdateOptions, type UpdateUserRequest, type UploadOptions, type UserInfo, type UserRecord, type WebpushConfig, type WhereFilterOp, addDocument, batchWrite, clearConfig, clearTokenCache, countDocuments, createCustomToken, createSessionCookie, createUser, deleteDocument, deleteFile, deleteUser, downloadFile, fileExists, generateSignedUrl, getAdminAccessToken, getAll, getAuth, getConfig, getDocument, getFileMetadata, getProjectId, getServiceAccount, getUserByEmail, getUserByUid, getUserFromToken, initializeApp, iterateCollection, listDocuments, listFiles, listUsers, queryDocuments, sendMessage, setCustomUserClaims, setDocument, signInWithCustomToken, subscribeToTopic, unsubscribeFromTopic, updateDocument, updateUser, uploadFile, uploadFileResumable, verifyIdToken, verifySessionCookie };
1289
+ export { type AndroidConfig, type AndroidNotification, type ApnsConfig, type BatchWrite, type BatchWriteResult, type CreateUserRequest, type CustomClaims, type CustomTokenSignInResponse, type DataObject, type DecodedIdToken, type DocumentReference, type DownloadOptions, type Notification as FcmNotification, type FcmOptions, FieldValue, type FieldValue$1 as FieldValueSentinel, FieldValueType, type FileMetadata, type FirestoreDocument, type FirestoreValue, type ListFilesResult, type ListOptions, type ListUsersResult, type Message, type QueryFilter, type QueryOptions, type QueryOrder, type ResumableUploadOptions, type SendResponse, type ServiceAccount, type SessionCookieOptions, type SetOptions, type SignedUrlOptions, type TokenResponse, type TopicManagementError, type TopicManagementResponse, type UpdateOptions, type UpdateUserRequest, type UploadOptions, type UserInfo, type UserRecord, type WebpushConfig, type WhereFilterOp, addDocument, batchWrite, clearConfig, clearTokenCache, countDocuments, createCustomToken, createSessionCookie, createUser, deleteDocument, deleteFile, deleteUser, downloadFile, fileExists, generateSignedUrl, getAdminAccessToken, getAll, getAllByPaths, getAuth, getConfig, getDocument, getFileMetadata, getProjectId, getServiceAccount, getUserByEmail, getUserByUid, getUserFromToken, initializeApp, iterateCollection, listDocuments, listFiles, listUsers, queryDocuments, sendMessage, setCustomUserClaims, setDocument, signInWithCustomToken, subscribeToTopic, unsubscribeFromTopic, updateDocument, updateUser, uploadFile, uploadFileResumable, verifyIdToken, verifySessionCookie };
package/dist/index.js CHANGED
@@ -217,6 +217,7 @@ __export(index_exports, {
217
217
  generateSignedUrl: () => generateSignedUrl,
218
218
  getAdminAccessToken: () => getAdminAccessToken,
219
219
  getAll: () => getAll,
220
+ getAllByPaths: () => getAllByPaths,
220
221
  getAuth: () => getAuth,
221
222
  getConfig: () => getConfig,
222
223
  getDocument: () => getDocument,
@@ -1553,6 +1554,44 @@ async function getAll(collectionPath, documentIds) {
1553
1554
  }
1554
1555
  return documents.map((docPath) => resultMap.get(docPath) ?? null);
1555
1556
  }
1557
+ async function getAllByPaths(documentRefs) {
1558
+ if (documentRefs.length === 0) return [];
1559
+ if (documentRefs.length > 100) {
1560
+ throw new Error("getAllByPaths supports a maximum of 100 documents per request");
1561
+ }
1562
+ for (const ref of documentRefs) {
1563
+ validateDocumentPath("collection", ref.collection, ref.id);
1564
+ }
1565
+ const accessToken = await getAdminAccessToken();
1566
+ const projectId = getProjectId();
1567
+ const basePath = `projects/${projectId}/databases/(default)/documents`;
1568
+ const documents = documentRefs.map((ref) => `${basePath}/${ref.collection}/${ref.id}`);
1569
+ const url = `${FIRESTORE_API}/${basePath}:batchGet`;
1570
+ const response = await fetch(url, {
1571
+ method: "POST",
1572
+ headers: {
1573
+ "Authorization": `Bearer ${accessToken}`,
1574
+ "Content-Type": "application/json"
1575
+ },
1576
+ body: JSON.stringify({ documents })
1577
+ });
1578
+ if (!response.ok) {
1579
+ const errorText = await response.text();
1580
+ throw new Error(`Failed to batch get documents: ${errorText}`);
1581
+ }
1582
+ const results = await response.json();
1583
+ const resultMap = /* @__PURE__ */ new Map();
1584
+ for (const result of results) {
1585
+ if (result.found) {
1586
+ const name = result.found.name;
1587
+ const data = convertFromFirestoreFormat(result.found.fields);
1588
+ resultMap.set(name, data);
1589
+ } else if (result.missing) {
1590
+ resultMap.set(result.missing, null);
1591
+ }
1592
+ }
1593
+ return documents.map((docPath) => resultMap.get(docPath) ?? null);
1594
+ }
1556
1595
  async function batchWrite(operations) {
1557
1596
  const accessToken = await getAdminAccessToken();
1558
1597
  const projectId = getProjectId();
@@ -2296,6 +2335,7 @@ init_service_account();
2296
2335
  generateSignedUrl,
2297
2336
  getAdminAccessToken,
2298
2337
  getAll,
2338
+ getAllByPaths,
2299
2339
  getAuth,
2300
2340
  getConfig,
2301
2341
  getDocument,
package/dist/index.mjs CHANGED
@@ -1304,6 +1304,44 @@ async function getAll(collectionPath, documentIds) {
1304
1304
  }
1305
1305
  return documents.map((docPath) => resultMap.get(docPath) ?? null);
1306
1306
  }
1307
+ async function getAllByPaths(documentRefs) {
1308
+ if (documentRefs.length === 0) return [];
1309
+ if (documentRefs.length > 100) {
1310
+ throw new Error("getAllByPaths supports a maximum of 100 documents per request");
1311
+ }
1312
+ for (const ref of documentRefs) {
1313
+ validateDocumentPath("collection", ref.collection, ref.id);
1314
+ }
1315
+ const accessToken = await getAdminAccessToken();
1316
+ const projectId = getProjectId();
1317
+ const basePath = `projects/${projectId}/databases/(default)/documents`;
1318
+ const documents = documentRefs.map((ref) => `${basePath}/${ref.collection}/${ref.id}`);
1319
+ const url = `${FIRESTORE_API}/${basePath}:batchGet`;
1320
+ const response = await fetch(url, {
1321
+ method: "POST",
1322
+ headers: {
1323
+ "Authorization": `Bearer ${accessToken}`,
1324
+ "Content-Type": "application/json"
1325
+ },
1326
+ body: JSON.stringify({ documents })
1327
+ });
1328
+ if (!response.ok) {
1329
+ const errorText = await response.text();
1330
+ throw new Error(`Failed to batch get documents: ${errorText}`);
1331
+ }
1332
+ const results = await response.json();
1333
+ const resultMap = /* @__PURE__ */ new Map();
1334
+ for (const result of results) {
1335
+ if (result.found) {
1336
+ const name = result.found.name;
1337
+ const data = convertFromFirestoreFormat(result.found.fields);
1338
+ resultMap.set(name, data);
1339
+ } else if (result.missing) {
1340
+ resultMap.set(result.missing, null);
1341
+ }
1342
+ }
1343
+ return documents.map((docPath) => resultMap.get(docPath) ?? null);
1344
+ }
1307
1345
  async function batchWrite(operations) {
1308
1346
  const accessToken = await getAdminAccessToken();
1309
1347
  const projectId = getProjectId();
@@ -2035,6 +2073,7 @@ export {
2035
2073
  generateSignedUrl,
2036
2074
  getAdminAccessToken,
2037
2075
  getAll,
2076
+ getAllByPaths,
2038
2077
  getAuth,
2039
2078
  getConfig,
2040
2079
  getDocument,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/firebase-admin-sdk-v8",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Firebase Admin SDK for Cloudflare Workers and edge runtimes using REST APIs",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",