From 49ee786f2b022e65aef45693e1a8b546d889ec10 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Wed, 18 Jan 2023 11:56:34 -0800 Subject: [PATCH 1/7] Prevented hostname from being changed when using BrowserPollConnection w/ emulator (#6912) --- .changeset/fresh-experts-mix.md | 6 ++++++ packages/database-compat/test/database.test.ts | 10 +++++++++- packages/database/src/api/Database.ts | 3 ++- packages/database/src/core/RepoInfo.ts | 3 ++- packages/database/src/realtime/Connection.ts | 13 +++++++++---- 5 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 .changeset/fresh-experts-mix.md diff --git a/.changeset/fresh-experts-mix.md b/.changeset/fresh-experts-mix.md new file mode 100644 index 00000000000..00a6bb1c16d --- /dev/null +++ b/.changeset/fresh-experts-mix.md @@ -0,0 +1,6 @@ +--- +"@firebase/database-compat": patch +"@firebase/database": patch +--- + +Fixed issue where hostname set by `connectDatabaseEmulator` was being overridden by longpolling response diff --git a/packages/database-compat/test/database.test.ts b/packages/database-compat/test/database.test.ts index e72d7e53c34..8e984e211a6 100644 --- a/packages/database-compat/test/database.test.ts +++ b/packages/database-compat/test/database.test.ts @@ -272,6 +272,7 @@ describe('Database Tests', () => { }); it('refFromURL() validates argument', () => { + // TODO: Remove all any references const db = (firebase as any).database(); expect(() => { const ref = (db as any).refFromURL(); @@ -279,11 +280,18 @@ describe('Database Tests', () => { }); it('can call useEmulator before use', () => { - const db = (firebase as any).database(); + const db = firebase.database(); db.useEmulator('localhost', 1234); + // Cast as any as _delegate isn't a public property + expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.true; expect(db.ref().toString()).to.equal('http://localhost:1234/'); }); + it('initializes usingEmulator to false before use', () => { + const db = firebase.database(); + expect((db as any)._delegate._repo.repoInfo_.isUsingEmulator).to.be.false; + }); + it('cannot call useEmulator after use', () => { const db = (firebase as any).database(); diff --git a/packages/database/src/api/Database.ts b/packages/database/src/api/Database.ts index f1a27492442..6cf60d5fbd6 100644 --- a/packages/database/src/api/Database.ts +++ b/packages/database/src/api/Database.ts @@ -95,7 +95,8 @@ function repoManagerApplyEmulatorSettings( repo.repoInfo_.webSocketOnly, repo.repoInfo_.nodeAdmin, repo.repoInfo_.persistenceKey, - repo.repoInfo_.includeNamespaceInQueryParams + repo.repoInfo_.includeNamespaceInQueryParams, + /*isUsingEmulator=*/ true ); if (tokenProvider) { diff --git a/packages/database/src/core/RepoInfo.ts b/packages/database/src/core/RepoInfo.ts index de0e4603be1..9d4c1abe36b 100644 --- a/packages/database/src/core/RepoInfo.ts +++ b/packages/database/src/core/RepoInfo.ts @@ -45,7 +45,8 @@ export class RepoInfo { public readonly webSocketOnly: boolean, public readonly nodeAdmin: boolean = false, public readonly persistenceKey: string = '', - public readonly includeNamespaceInQueryParams: boolean = false + public readonly includeNamespaceInQueryParams: boolean = false, + public readonly isUsingEmulator: boolean = false ) { this._host = host.toLowerCase(); this._domain = this._host.substr(this._host.indexOf('.') + 1); diff --git a/packages/database/src/realtime/Connection.ts b/packages/database/src/realtime/Connection.ts index 430d68ec9b0..80fb9520fb1 100644 --- a/packages/database/src/realtime/Connection.ts +++ b/packages/database/src/realtime/Connection.ts @@ -337,14 +337,19 @@ export class Connection { if (MESSAGE_DATA in controlData) { const payload = controlData[MESSAGE_DATA]; if (cmd === SERVER_HELLO) { - this.onHandshake_( - payload as { + const handshakePayload = { + ...(payload as { ts: number; v: string; h: string; s: string; - } - ); + }) + }; + if (this.repoInfo_.isUsingEmulator) { + // Upon connecting, the emulator will pass the hostname that it's aware of, but we prefer the user's set hostname via `connectDatabaseEmulator` over what the emulator passes. + handshakePayload.h = this.repoInfo_.host; + } + this.onHandshake_(handshakePayload); } else if (cmd === END_TRANSMISSION) { this.log_('recvd end transmission on primary'); this.rx_ = this.secondaryConn_; From 4604b3cb7adbb3b8aa970f4a7bdd1e50a7755fa7 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 24 Jan 2023 09:37:54 -0800 Subject: [PATCH 2/7] update link (#6959) --- packages/analytics-types/index.d.ts | 2 +- packages/analytics/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/analytics-types/index.d.ts b/packages/analytics-types/index.d.ts index c9c38e7c3d7..b502af099bd 100644 --- a/packages/analytics-types/index.d.ts +++ b/packages/analytics-types/index.d.ts @@ -651,7 +651,7 @@ export interface Promotion { /** * Dynamic configuration fetched from server. - * See https://firebase.google.com/docs/projects/api/reference/rest/v1beta1/projects.webApps/getConfig + * See https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.webApps/getConfig */ interface DynamicConfig { projectId: string; diff --git a/packages/analytics/src/types.ts b/packages/analytics/src/types.ts index 3b615c1c011..9ec0a9e79ab 100644 --- a/packages/analytics/src/types.ts +++ b/packages/analytics/src/types.ts @@ -34,7 +34,7 @@ export interface ThrottleMetadata { /** * Dynamic configuration fetched from server. - * See https://firebase.google.com/docs/projects/api/reference/rest/v1beta1/projects.webApps/getConfig + * See https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.webApps/getConfig */ export interface DynamicConfig { projectId: string; From 6439f1173353f3857ab820675d572ea676340924 Mon Sep 17 00:00:00 2001 From: prameshj Date: Tue, 24 Jan 2023 14:06:44 -0800 Subject: [PATCH 3/7] Expose TOKEN_EXPIRED error upon mfa unenroll. (#6973) * Expose TOKEN_EXPIRED error upon mfa unenroll. This can be thrown if the MFA option that was most recently enrolled into, was unenrolled. The user will be logged out to prove the posession of the other second factor. This error can be handled by reauthenticating the user. This change also updates the demo app to store the lastUser in case mfa unenroll logs out the user. From here, the lastUser can be reauthenticated. * Changeset --- .changeset/chilled-boats-report.md | 5 +++ packages/auth/demo/public/index.html | 4 ++ packages/auth/demo/src/index.js | 44 ++++++++++++++++++- .../auth/src/core/strategies/credential.ts | 3 +- packages/auth/src/mfa/mfa_user.test.ts | 6 ++- packages/auth/src/mfa/mfa_user.ts | 41 ++++++++--------- 6 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 .changeset/chilled-boats-report.md diff --git a/.changeset/chilled-boats-report.md b/.changeset/chilled-boats-report.md new file mode 100644 index 00000000000..1bdf195b85a --- /dev/null +++ b/.changeset/chilled-boats-report.md @@ -0,0 +1,5 @@ +--- +'@firebase/auth': patch +--- + +Expose TOKEN_EXPIRED error when mfa unenroll logs out the user. diff --git a/packages/auth/demo/public/index.html b/packages/auth/demo/public/index.html index aa32e144ed5..624b6e3c0e7 100644 --- a/packages/auth/demo/public/index.html +++ b/packages/auth/demo/public/index.html @@ -252,6 +252,10 @@ id="sign-in-with-email-and-password"> Sign In with Email and Password +
{ refreshUserData(); alertSuccess('Multi-factor successfully unenrolled.'); @@ -278,6 +282,9 @@ function onAuthError(error) { handleMultiFactorSignIn(getMultiFactorResolver(auth, error)); } else { alertError('Error: ' + error.code); + if (error.code === 'auth/user-token-expired') { + alertError('Token expired, please reauthenticate.'); + } } } @@ -403,13 +410,41 @@ function onLinkWithEmailLink() { * Re-authenticate a user with email link credential. */ function onReauthenticateWithEmailLink() { + if (!activeUser()) { + alertError( + 'No user logged in. Select the "Last User" tab to reauth the previous user.' + ); + return; + } const email = $('#link-with-email-link-email').val(); const link = $('#link-with-email-link-link').val() || undefined; const credential = EmailAuthProvider.credentialWithLink(email, link); + // This will not set auth.currentUser to lastUser if the lastUser is reauthenticated. reauthenticateWithCredential(activeUser(), credential).then(result => { logAdditionalUserInfo(result); refreshUserData(); - alertSuccess('User reauthenticated!'); + alertSuccess('User reauthenticated with email link!'); + }, onAuthError); +} + +/** + * Re-authenticate a user with email and password. + */ +function onReauthenticateWithEmailAndPassword() { + if (!activeUser()) { + alertError( + 'No user logged in. Select the "Last User" tab to reauth the previous user.' + ); + return; + } + const email = $('#signin-email').val(); + const password = $('#signin-password').val(); + const credential = EmailAuthProvider.credential(email, password); + // This will not set auth.currentUser to lastUser if the lastUser is reauthenticated. + reauthenticateWithCredential(activeUser(), credential).then(result => { + logAdditionalUserInfo(result); + refreshUserData(); + alertSuccess('User reauthenticated with email/password!'); }, onAuthError); } @@ -1264,7 +1299,9 @@ function signInWithPopupRedirect(provider) { break; case 'reauthenticate': if (!activeUser()) { - alertError('No user logged in.'); + alertError( + 'No user logged in. Select the "Last User" tab to reauth the previous user.' + ); return; } inst = activeUser(); @@ -1860,6 +1897,9 @@ function initApp() { // Actions listeners. $('#sign-up-with-email-and-password').click(onSignUp); $('#sign-in-with-email-and-password').click(onSignInWithEmailAndPassword); + $('#reauth-with-email-and-password').click( + onReauthenticateWithEmailAndPassword + ); $('.sign-in-with-custom-token').click(onSignInWithCustomToken); $('#sign-in-anonymously').click(onSignInAnonymously); $('#sign-in-with-generic-idp-credential').click( diff --git a/packages/auth/src/core/strategies/credential.ts b/packages/auth/src/core/strategies/credential.ts index 4d24c758fb9..00aa919f047 100644 --- a/packages/auth/src/core/strategies/credential.ts +++ b/packages/auth/src/core/strategies/credential.ts @@ -96,7 +96,8 @@ export async function linkWithCredential( * * @remarks * Use before operations such as {@link updatePassword} that require tokens from recent sign-in - * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error. + * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error + * or a `TOKEN_EXPIRED` error. * * @param user - The user. * @param credential - The auth credential. diff --git a/packages/auth/src/mfa/mfa_user.test.ts b/packages/auth/src/mfa/mfa_user.test.ts index 2c0da80a11a..c152c1384a5 100644 --- a/packages/auth/src/mfa/mfa_user.test.ts +++ b/packages/auth/src/mfa/mfa_user.test.ts @@ -235,8 +235,10 @@ describe('core/mfa/mfa_user/MultiFactorUser', () => { ); }); - it('should swallow the error', async () => { - await mfaUser.unenroll(mfaInfo); + it('should throw TOKEN_EXPIRED error', async () => { + await expect(mfaUser.unenroll(mfaInfo)).to.be.rejectedWith( + 'auth/user-token-expired' + ); }); }); }); diff --git a/packages/auth/src/mfa/mfa_user.ts b/packages/auth/src/mfa/mfa_user.ts index 535de17310d..51e3433cc44 100644 --- a/packages/auth/src/mfa/mfa_user.ts +++ b/packages/auth/src/mfa/mfa_user.ts @@ -23,13 +23,12 @@ import { } from '../model/public_types'; import { withdrawMfa } from '../api/account_management/mfa'; -import { AuthErrorCode } from '../core/errors'; import { _logoutIfInvalidated } from '../core/user/invalidation'; import { UserInternal } from '../model/user'; import { MultiFactorAssertionImpl } from './mfa_assertion'; import { MultiFactorInfoImpl } from './mfa_info'; import { MultiFactorSessionImpl } from './mfa_session'; -import { FirebaseError, getModularInstance } from '@firebase/util'; +import { getModularInstance } from '@firebase/util'; export class MultiFactorUserImpl implements MultiFactorUser { enrolledFactors: MultiFactorInfo[] = []; @@ -78,30 +77,26 @@ export class MultiFactorUserImpl implements MultiFactorUser { const mfaEnrollmentId = typeof infoOrUid === 'string' ? infoOrUid : infoOrUid.uid; const idToken = await this.user.getIdToken(); - const idTokenResponse = await _logoutIfInvalidated( - this.user, - withdrawMfa(this.user.auth, { - idToken, - mfaEnrollmentId - }) - ); - // Remove the second factor from the user's list. - this.enrolledFactors = this.enrolledFactors.filter( - ({ uid }) => uid !== mfaEnrollmentId - ); - // Depending on whether the backend decided to revoke the user's session, - // the tokenResponse may be empty. If the tokens were not updated (and they - // are now invalid), reloading the user will discover this and invalidate - // the user's state accordingly. - await this.user._updateTokensIfNecessary(idTokenResponse); try { + const idTokenResponse = await _logoutIfInvalidated( + this.user, + withdrawMfa(this.user.auth, { + idToken, + mfaEnrollmentId + }) + ); + // Remove the second factor from the user's list. + this.enrolledFactors = this.enrolledFactors.filter( + ({ uid }) => uid !== mfaEnrollmentId + ); + // Depending on whether the backend decided to revoke the user's session, + // the tokenResponse may be empty. If the tokens were not updated (and they + // are now invalid), reloading the user will discover this and invalidate + // the user's state accordingly. + await this.user._updateTokensIfNecessary(idTokenResponse); await this.user.reload(); } catch (e) { - if ( - (e as FirebaseError)?.code !== `auth/${AuthErrorCode.TOKEN_EXPIRED}` - ) { - throw e; - } + throw e; } } } From f8ddadba94c2a7ae947e70c0322d1c4bba8388ab Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Thu, 26 Jan 2023 10:29:33 -0800 Subject: [PATCH 4/7] Fix link format in auth doc comment (#6980) --- .../auth/src/platform_browser/strategies/redirect.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/auth/src/platform_browser/strategies/redirect.ts b/packages/auth/src/platform_browser/strategies/redirect.ts index 791bc2ea2cd..f85a0d3d8df 100644 --- a/packages/auth/src/platform_browser/strategies/redirect.ts +++ b/packages/auth/src/platform_browser/strategies/redirect.ts @@ -42,7 +42,8 @@ import { getModularInstance } from '@firebase/util'; * * @remarks * To handle the results and errors for this operation, refer to {@link getRedirectResult}. - * Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using {@link signInWithRedirect}. + * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices + * | best practices} when using {@link signInWithRedirect}. * * @example * ```javascript @@ -110,7 +111,8 @@ export async function _signInWithRedirect( * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow. * @remarks * To handle the results and errors for this operation, refer to {@link getRedirectResult}. - * Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using {@link reauthenticateWithRedirect}. + * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices + * | best practices} when using {@link reauthenticateWithRedirect}. * * @example * ```javascript @@ -176,7 +178,8 @@ export async function _reauthenticateWithRedirect( * Links the {@link OAuthProvider} to the user account using a full-page redirect flow. * @remarks * To handle the results and errors for this operation, refer to {@link getRedirectResult}. - * Follow the [best practices](https://firebase.google.com/docs/auth/web/redirect-best-practices) when using {@link linkWithRedirect}. + * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices + * | best practices} when using {@link linkWithRedirect}. * * @example * ```javascript From 825e648b81ca63c7bc64f8700f7a46eb320b2106 Mon Sep 17 00:00:00 2001 From: Maneesh Tewani Date: Fri, 27 Jan 2023 09:26:47 -0800 Subject: [PATCH 5/7] Export StorageError class instead of interface (#6974) --- .changeset/hungry-glasses-impress.md | 8 ++ common/api-review/storage.api.md | 79 +++++++++++++++++--- packages/firebase/compat/index.d.ts | 52 ++++++++++++- packages/storage-compat/src/task.ts | 2 +- packages/storage-types/index.d.ts | 52 ++++++++++++- packages/storage/src/api.ts | 2 + packages/storage/src/implementation/error.ts | 2 +- packages/storage/src/public-types.ts | 20 +---- 8 files changed, 182 insertions(+), 35 deletions(-) create mode 100644 .changeset/hungry-glasses-impress.md diff --git a/.changeset/hungry-glasses-impress.md b/.changeset/hungry-glasses-impress.md new file mode 100644 index 00000000000..90f5840d28e --- /dev/null +++ b/.changeset/hungry-glasses-impress.md @@ -0,0 +1,8 @@ +--- +"firebase": minor +"@firebase/storage": minor +"@firebase/storage-types": minor +"@firebase/storage-compat": minor +--- + +Fixed issue where users were unable to check if an Error was an instance of `StorageError`. diff --git a/common/api-review/storage.api.md b/common/api-review/storage.api.md index 04df972b727..84173245c95 100644 --- a/common/api-review/storage.api.md +++ b/common/api-review/storage.api.md @@ -134,13 +134,11 @@ export function getStorage(app?: FirebaseApp, bucketUrl?: string): FirebaseStora // @public export function getStream(ref: StorageReference, maxDownloadSizeBytes?: number): NodeJS.ReadableStream; -// Warning: (ae-forgotten-export) The symbol "StorageError" needs to be exported by the entry point index.d.ts -// // @internal (undocumented) -export function _invalidArgument(message: string): StorageError_2; +export function _invalidArgument(message: string): StorageError; // @internal (undocumented) -export function _invalidRootOperation(name: string): StorageError_2; +export function _invalidRootOperation(name: string): StorageError; // @public export function list(ref: StorageReference, options?: ListOptions): Promise; @@ -217,8 +215,71 @@ export interface SettableMetadata { } // @public -export interface StorageError extends FirebaseError { - serverResponse: string | null; +export class StorageError extends FirebaseError { + constructor(code: StorageErrorCode, message: string, status_?: number); + _codeEquals(code: StorageErrorCode): boolean; + customData: { + serverResponse: string | null; + }; + get serverResponse(): null | string; + set serverResponse(serverResponse: string | null); + // (undocumented) + get status(): number; + set status(status: number); + } + +// @public +export enum StorageErrorCode { + // (undocumented) + APP_DELETED = "app-deleted", + // (undocumented) + BUCKET_NOT_FOUND = "bucket-not-found", + // (undocumented) + CANCELED = "canceled", + // (undocumented) + CANNOT_SLICE_BLOB = "cannot-slice-blob", + // (undocumented) + INTERNAL_ERROR = "internal-error", + // (undocumented) + INVALID_ARGUMENT = "invalid-argument", + // (undocumented) + INVALID_ARGUMENT_COUNT = "invalid-argument-count", + // (undocumented) + INVALID_CHECKSUM = "invalid-checksum", + // (undocumented) + INVALID_DEFAULT_BUCKET = "invalid-default-bucket", + // (undocumented) + INVALID_EVENT_NAME = "invalid-event-name", + // (undocumented) + INVALID_FORMAT = "invalid-format", + // (undocumented) + INVALID_ROOT_OPERATION = "invalid-root-operation", + // (undocumented) + INVALID_URL = "invalid-url", + // (undocumented) + NO_DEFAULT_BUCKET = "no-default-bucket", + // (undocumented) + NO_DOWNLOAD_URL = "no-download-url", + // (undocumented) + OBJECT_NOT_FOUND = "object-not-found", + // (undocumented) + PROJECT_NOT_FOUND = "project-not-found", + // (undocumented) + QUOTA_EXCEEDED = "quota-exceeded", + // (undocumented) + RETRY_LIMIT_EXCEEDED = "retry-limit-exceeded", + // (undocumented) + SERVER_FILE_WRONG_SIZE = "server-file-wrong-size", + // (undocumented) + UNAUTHENTICATED = "unauthenticated", + // (undocumented) + UNAUTHORIZED = "unauthorized", + // (undocumented) + UNAUTHORIZED_APP = "unauthorized-app", + // (undocumented) + UNKNOWN = "unknown", + // (undocumented) + UNSUPPORTED_ENVIRONMENT = "unsupported-environment" } // @public @@ -318,20 +379,20 @@ export class _UploadTask { constructor(ref: _Reference, blob: _FbsBlob, metadata?: Metadata | null); _blob: _FbsBlob; cancel(): boolean; - catch(onRejected: (p1: StorageError_2) => T | Promise): Promise; + catch(onRejected: (p1: StorageError) => T | Promise): Promise; // (undocumented) isExponentialBackoffExpired(): boolean; // Warning: (ae-forgotten-export) The symbol "Metadata" needs to be exported by the entry point index.d.ts _metadata: Metadata | null; // Warning: (ae-forgotten-export) The symbol "Unsubscribe" needs to be exported by the entry point index.d.ts // Warning: (ae-forgotten-export) The symbol "Subscribe" needs to be exported by the entry point index.d.ts - on(type: _TaskEvent, nextOrObserver?: StorageObserver | null | ((snapshot: UploadTaskSnapshot) => unknown), error?: ((a: StorageError_2) => unknown) | null, completed?: CompleteFn | null): Unsubscribe_2 | Subscribe_2; + on(type: _TaskEvent, nextOrObserver?: StorageObserver | null | ((snapshot: UploadTaskSnapshot) => unknown), error?: ((a: StorageError) => unknown) | null, completed?: CompleteFn | null): Unsubscribe_2 | Subscribe_2; pause(): boolean; resume(): boolean; get snapshot(): UploadTaskSnapshot; // Warning: (ae-forgotten-export) The symbol "InternalTaskState" needs to be exported by the entry point index.d.ts _state: InternalTaskState; - then(onFulfilled?: ((value: UploadTaskSnapshot) => U | Promise) | null, onRejected?: ((error: StorageError_2) => U | Promise) | null): Promise; + then(onFulfilled?: ((value: UploadTaskSnapshot) => U | Promise) | null, onRejected?: ((error: StorageError) => U | Promise) | null): Promise; _transferred: number; } diff --git a/packages/firebase/compat/index.d.ts b/packages/firebase/compat/index.d.ts index aa9281fc588..773c240c379 100644 --- a/packages/firebase/compat/index.d.ts +++ b/packages/firebase/compat/index.d.ts @@ -8017,11 +8017,59 @@ declare namespace firebase.storage { md5Hash?: string | null; } + /** + * Error codes that can be attached to `StorageError`s. + */ + export enum StorageErrorCode { + UNKNOWN = 'unknown', + OBJECT_NOT_FOUND = 'object-not-found', + BUCKET_NOT_FOUND = 'bucket-not-found', + PROJECT_NOT_FOUND = 'project-not-found', + QUOTA_EXCEEDED = 'quota-exceeded', + UNAUTHENTICATED = 'unauthenticated', + UNAUTHORIZED = 'unauthorized', + UNAUTHORIZED_APP = 'unauthorized-app', + RETRY_LIMIT_EXCEEDED = 'retry-limit-exceeded', + INVALID_CHECKSUM = 'invalid-checksum', + CANCELED = 'canceled', + INVALID_EVENT_NAME = 'invalid-event-name', + INVALID_URL = 'invalid-url', + INVALID_DEFAULT_BUCKET = 'invalid-default-bucket', + NO_DEFAULT_BUCKET = 'no-default-bucket', + CANNOT_SLICE_BLOB = 'cannot-slice-blob', + SERVER_FILE_WRONG_SIZE = 'server-file-wrong-size', + NO_DOWNLOAD_URL = 'no-download-url', + INVALID_ARGUMENT = 'invalid-argument', + INVALID_ARGUMENT_COUNT = 'invalid-argument-count', + APP_DELETED = 'app-deleted', + INVALID_ROOT_OPERATION = 'invalid-root-operation', + INVALID_FORMAT = 'invalid-format', + INTERNAL_ERROR = 'internal-error', + UNSUPPORTED_ENVIRONMENT = 'unsupported-environment' + } + /** * An error returned by the Firebase Storage SDK. */ - interface FirebaseStorageError extends FirebaseError { - serverResponse: string | null; + export interface FirebaseStorageError extends FirebaseError { + /** + * Stores custom error data unque to StorageError. + */ + customData: { + serverResponse: string | null; + }; + + get status(): number; + set status(status: number); + /** + * Compares a StorageErrorCode against this error's code, filtering out the prefix. + */ + _codeEquals(code: StorageErrorCode): boolean; + /** + * Optional response message that was added by the server. + */ + get serverResponse(): null | string; + set serverResponse(serverResponse: string | null); } interface StorageObserver { diff --git a/packages/storage-compat/src/task.ts b/packages/storage-compat/src/task.ts index 66a4dd9262e..7cc6f7ba9bd 100644 --- a/packages/storage-compat/src/task.ts +++ b/packages/storage-compat/src/task.ts @@ -65,7 +65,7 @@ export class UploadTaskCompat implements types.UploadTask, Compat { | types.StorageObserver | null | ((a: UploadTaskSnapshotCompat) => unknown), - error?: (error: StorageError) => void | null, + error?: ((error: StorageError) => void) | null, completed?: () => void | null ): Unsubscribe | Subscribe { let wrappedNextOrObserver: diff --git a/packages/storage-types/index.d.ts b/packages/storage-types/index.d.ts index c6a8fc7178d..e42c32bbb96 100644 --- a/packages/storage-types/index.d.ts +++ b/packages/storage-types/index.d.ts @@ -91,16 +91,60 @@ export interface UploadMetadata extends SettableMetadata { md5Hash?: string | null; } -interface FirebaseStorageError extends FirebaseError { - serverResponse: string | null; -} - export interface StorageObserver { next?: NextFn | null; error?: (error: FirebaseStorageError) => void | null; complete?: CompleteFn | null; } +export enum StorageErrorCode { + UNKNOWN = 'unknown', + OBJECT_NOT_FOUND = 'object-not-found', + BUCKET_NOT_FOUND = 'bucket-not-found', + PROJECT_NOT_FOUND = 'project-not-found', + QUOTA_EXCEEDED = 'quota-exceeded', + UNAUTHENTICATED = 'unauthenticated', + UNAUTHORIZED = 'unauthorized', + UNAUTHORIZED_APP = 'unauthorized-app', + RETRY_LIMIT_EXCEEDED = 'retry-limit-exceeded', + INVALID_CHECKSUM = 'invalid-checksum', + CANCELED = 'canceled', + INVALID_EVENT_NAME = 'invalid-event-name', + INVALID_URL = 'invalid-url', + INVALID_DEFAULT_BUCKET = 'invalid-default-bucket', + NO_DEFAULT_BUCKET = 'no-default-bucket', + CANNOT_SLICE_BLOB = 'cannot-slice-blob', + SERVER_FILE_WRONG_SIZE = 'server-file-wrong-size', + NO_DOWNLOAD_URL = 'no-download-url', + INVALID_ARGUMENT = 'invalid-argument', + INVALID_ARGUMENT_COUNT = 'invalid-argument-count', + APP_DELETED = 'app-deleted', + INVALID_ROOT_OPERATION = 'invalid-root-operation', + INVALID_FORMAT = 'invalid-format', + INTERNAL_ERROR = 'internal-error', + UNSUPPORTED_ENVIRONMENT = 'unsupported-environment' +} + +export interface FirebaseStorageError extends FirebaseError { + /** + * Stores custom error data unque to StorageError. + */ + customData: { + serverResponse: string | null; + }; + + get status(): number; + set status(status: number); + /** + * Compares a StorageErrorCode against this error's code, filtering out the prefix. + */ + _codeEquals(code: StorageErrorCode): boolean; + /** + * Optional response message that was added by the server. + */ + get serverResponse(): null | string; + set serverResponse(serverResponse: string | null); +} export interface UploadTask { cancel(): boolean; catch(onRejected: (error: FirebaseStorageError) => any): Promise; diff --git a/packages/storage/src/api.ts b/packages/storage/src/api.ts index 301ca6cab98..b629c5d5b59 100644 --- a/packages/storage/src/api.ts +++ b/packages/storage/src/api.ts @@ -59,6 +59,8 @@ import { StringFormat } from './implementation/string'; export { EmulatorMockTokenOptions } from '@firebase/util'; +export { StorageError, StorageErrorCode } from './implementation/error'; + /** * Public types. */ diff --git a/packages/storage/src/implementation/error.ts b/packages/storage/src/implementation/error.ts index da90e3900ee..2d8fe7705fb 100644 --- a/packages/storage/src/implementation/error.ts +++ b/packages/storage/src/implementation/error.ts @@ -85,7 +85,7 @@ export const errors = {}; * @public * Error codes that can be attached to `StorageError`s. */ -export const enum StorageErrorCode { +export enum StorageErrorCode { // Shared between all platforms UNKNOWN = 'unknown', OBJECT_NOT_FOUND = 'object-not-found', diff --git a/packages/storage/src/public-types.ts b/packages/storage/src/public-types.ts index 8aeb3c4e5f0..879b7058354 100644 --- a/packages/storage/src/public-types.ts +++ b/packages/storage/src/public-types.ts @@ -17,13 +17,8 @@ // eslint-disable-next-line import/no-extraneous-dependencies import { FirebaseApp, _FirebaseService } from '@firebase/app'; -import { - CompleteFn, - FirebaseError, - NextFn, - Subscribe, - Unsubscribe -} from '@firebase/util'; +import { CompleteFn, NextFn, Subscribe, Unsubscribe } from '@firebase/util'; +import { StorageError } from './implementation/error'; /** * A Firebase Storage instance. @@ -249,17 +244,6 @@ export type TaskEvent = 'state_changed'; */ export type TaskState = 'running' | 'paused' | 'success' | 'canceled' | 'error'; -/** - * An error returned by the Firebase Storage SDK. - * @public - */ -export interface StorageError extends FirebaseError { - /** - * A server response message for the error, if applicable. - */ - serverResponse: string | null; -} - /** * A stream observer for Firebase Storage. * @public From 27b5e7d7081688599fc518b329a43db4319cdd1f Mon Sep 17 00:00:00 2001 From: wu-hui <53845758+wu-hui@users.noreply.github.com> Date: Tue, 31 Jan 2023 12:48:26 -0500 Subject: [PATCH 6/7] Reduce memory usage by applying query check sooner (#6989) * Rename * First commit * Create slimy-elephants-hear.md --- .changeset/slimy-elephants-hear.md | 5 ++ .../local/indexeddb_remote_document_cache.ts | 20 +++-- .../src/local/local_documents_view.ts | 19 +++-- .../src/local/memory_remote_document_cache.ts | 18 ++-- .../src/local/remote_document_cache.ts | 19 +++-- .../test/unit/local/counting_query_engine.ts | 14 +++- .../test/unit/local/local_store.test.ts | 4 +- .../unit/local/remote_document_cache.test.ts | 84 +++++++++++++++---- .../unit/local/test_remote_document_cache.ts | 15 ++-- 9 files changed, 147 insertions(+), 51 deletions(-) create mode 100644 .changeset/slimy-elephants-hear.md diff --git a/.changeset/slimy-elephants-hear.md b/.changeset/slimy-elephants-hear.md new file mode 100644 index 00000000000..cd1d8d2df4e --- /dev/null +++ b/.changeset/slimy-elephants-hear.md @@ -0,0 +1,5 @@ +--- +"@firebase/firestore": patch +--- + +Reduce memory usage by applying query check sooner in remote document cache. diff --git a/packages/firestore/src/local/indexeddb_remote_document_cache.ts b/packages/firestore/src/local/indexeddb_remote_document_cache.ts index 19b7c566322..c3af0655cc4 100644 --- a/packages/firestore/src/local/indexeddb_remote_document_cache.ts +++ b/packages/firestore/src/local/indexeddb_remote_document_cache.ts @@ -15,12 +15,14 @@ * limitations under the License. */ +import { Query, queryMatches } from '../core/query'; import { SnapshotVersion } from '../core/snapshot_version'; import { DocumentKeySet, DocumentSizeEntries, MutableDocumentMap, - mutableDocumentMap + mutableDocumentMap, + OverlayMap } from '../model/collections'; import { MutableDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; @@ -273,11 +275,13 @@ class IndexedDbRemoteDocumentCacheImpl implements IndexedDbRemoteDocumentCache { }); } - getAllFromCollection( + getDocumentsMatchingQuery( transaction: PersistenceTransaction, - collection: ResourcePath, - offset: IndexOffset + query: Query, + offset: IndexOffset, + mutatedDocs: OverlayMap ): PersistencePromise { + const collection = query.path; const startKey = [ collection.popLast().toArray(), collection.lastSegment(), @@ -307,7 +311,13 @@ class IndexedDbRemoteDocumentCacheImpl implements IndexedDbRemoteDocumentCache { ), dbRemoteDoc ); - results = results.insert(document.key, document); + if ( + document.isFoundDocument() && + (queryMatches(query, document) || mutatedDocs.has(document.key)) + ) { + // Either the document matches the given query, or it is mutated. + results = results.insert(document.key, document); + } } return results; }); diff --git a/packages/firestore/src/local/local_documents_view.ts b/packages/firestore/src/local/local_documents_view.ts index 2572646655f..78802e443bf 100644 --- a/packages/firestore/src/local/local_documents_view.ts +++ b/packages/firestore/src/local/local_documents_view.ts @@ -509,18 +509,19 @@ export class LocalDocumentsView { offset: IndexOffset ): PersistencePromise { // Query the remote documents and overlay mutations. - let remoteDocuments: MutableDocumentMap; - return this.remoteDocumentCache - .getAllFromCollection(transaction, query.path, offset) - .next(queryResults => { - remoteDocuments = queryResults; - return this.documentOverlayCache.getOverlaysForCollection( + let overlays: OverlayMap; + return this.documentOverlayCache + .getOverlaysForCollection(transaction, query.path, offset.largestBatchId) + .next(result => { + overlays = result; + return this.remoteDocumentCache.getDocumentsMatchingQuery( transaction, - query.path, - offset.largestBatchId + query, + offset, + overlays ); }) - .next(overlays => { + .next(remoteDocuments => { // As documents might match the query because of their overlay we need to // include documents for all overlays in the initial document set. overlays.forEach((_, overlay) => { diff --git a/packages/firestore/src/local/memory_remote_document_cache.ts b/packages/firestore/src/local/memory_remote_document_cache.ts index 796e461295d..1f598ba6cf9 100644 --- a/packages/firestore/src/local/memory_remote_document_cache.ts +++ b/packages/firestore/src/local/memory_remote_document_cache.ts @@ -15,11 +15,13 @@ * limitations under the License. */ +import { Query, queryMatches } from '../core/query'; import { SnapshotVersion } from '../core/snapshot_version'; import { DocumentKeySet, MutableDocumentMap, - mutableDocumentMap + mutableDocumentMap, + OverlayMap } from '../model/collections'; import { Document, MutableDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; @@ -28,7 +30,6 @@ import { indexOffsetComparator, newIndexOffsetFromDocument } from '../model/field_index'; -import { ResourcePath } from '../model/path'; import { debugAssert, fail } from '../util/assert'; import { SortedMap } from '../util/sorted_map'; @@ -159,15 +160,17 @@ class MemoryRemoteDocumentCacheImpl implements MemoryRemoteDocumentCache { return PersistencePromise.resolve(results); } - getAllFromCollection( + getDocumentsMatchingQuery( transaction: PersistenceTransaction, - collectionPath: ResourcePath, - offset: IndexOffset + query: Query, + offset: IndexOffset, + mutatedDocs: OverlayMap ): PersistencePromise { let results = mutableDocumentMap(); // Documents are ordered by key, so we can use a prefix scan to narrow down // the documents we need to match the query against. + const collectionPath = query.path; const prefix = new DocumentKey(collectionPath.child('')); const iterator = this.docs.getIteratorFrom(prefix); while (iterator.hasNext()) { @@ -188,6 +191,11 @@ class MemoryRemoteDocumentCacheImpl implements MemoryRemoteDocumentCache { // The document sorts before the offset. continue; } + if (!mutatedDocs.has(document.key) && !queryMatches(query, document)) { + // The document cannot possibly match the query. + continue; + } + results = results.insert(document.key, document.mutableCopy()); } return PersistencePromise.resolve(results); diff --git a/packages/firestore/src/local/remote_document_cache.ts b/packages/firestore/src/local/remote_document_cache.ts index 55c15826d3a..a66f1b4a253 100644 --- a/packages/firestore/src/local/remote_document_cache.ts +++ b/packages/firestore/src/local/remote_document_cache.ts @@ -15,11 +15,15 @@ * limitations under the License. */ -import { DocumentKeySet, MutableDocumentMap } from '../model/collections'; +import { Query } from '../core/query'; +import { + DocumentKeySet, + MutableDocumentMap, + OverlayMap +} from '../model/collections'; import { MutableDocument } from '../model/document'; import { DocumentKey } from '../model/document_key'; import { IndexOffset } from '../model/field_index'; -import { ResourcePath } from '../model/path'; import { IndexManager } from './index_manager'; import { PersistencePromise } from './persistence_promise'; @@ -62,16 +66,17 @@ export interface RemoteDocumentCache { ): PersistencePromise; /** - * Returns the documents from the provided collection. + * Returns the documents matching the given query * - * @param collection - The collection to read. + * @param query - The query to match documents against. * @param offset - The offset to start the scan at (exclusive). * @returns The set of matching documents. */ - getAllFromCollection( + getDocumentsMatchingQuery( transaction: PersistenceTransaction, - collection: ResourcePath, - offset: IndexOffset + query: Query, + offset: IndexOffset, + mutatedDocs: OverlayMap ): PersistencePromise; /** diff --git a/packages/firestore/test/unit/local/counting_query_engine.ts b/packages/firestore/test/unit/local/counting_query_engine.ts index a8a89a590b6..d407abfd60a 100644 --- a/packages/firestore/test/unit/local/counting_query_engine.ts +++ b/packages/firestore/test/unit/local/counting_query_engine.ts @@ -101,9 +101,19 @@ export class CountingQueryEngine extends QueryEngine { setIndexManager: (indexManager: IndexManager) => { subject.setIndexManager(indexManager); }, - getAllFromCollection: (transaction, collection, sinceReadTime) => { + getDocumentsMatchingQuery: ( + transaction, + query, + sinceReadTime, + overlays + ) => { return subject - .getAllFromCollection(transaction, collection, sinceReadTime) + .getDocumentsMatchingQuery( + transaction, + query, + sinceReadTime, + overlays + ) .next(result => { this.documentsReadByCollection += result.size; return result; diff --git a/packages/firestore/test/unit/local/local_store.test.ts b/packages/firestore/test/unit/local/local_store.test.ts index c25d337dc13..204f714a486 100644 --- a/packages/firestore/test/unit/local/local_store.test.ts +++ b/packages/firestore/test/unit/local/local_store.test.ts @@ -2288,10 +2288,10 @@ function genericLocalStoreTests( .afterAcknowledgingMutation({ documentVersion: 10 }) .afterAcknowledgingMutation({ documentVersion: 10 }) .afterExecutingQuery(query1) - // Execute the query, but note that we read all existing documents + // Execute the query, but note that we read matching documents // from the RemoteDocumentCache since we do not yet have target // mapping. - .toHaveRead({ documentsByCollection: 3 }) + .toHaveRead({ documentsByCollection: 2 }) .after( docAddedRemoteEvent( [ diff --git a/packages/firestore/test/unit/local/remote_document_cache.test.ts b/packages/firestore/test/unit/local/remote_document_cache.test.ts index 0bed7c4dade..7090394a9c8 100644 --- a/packages/firestore/test/unit/local/remote_document_cache.test.ts +++ b/packages/firestore/test/unit/local/remote_document_cache.test.ts @@ -19,7 +19,11 @@ import { expect } from 'chai'; import { User } from '../../../src/auth/user'; import { IndexedDbPersistence } from '../../../src/local/indexeddb_persistence'; -import { documentKeySet, DocumentMap } from '../../../src/model/collections'; +import { + documentKeySet, + DocumentMap, + newOverlayMap +} from '../../../src/model/collections'; import { MutableDocument, Document } from '../../../src/model/document'; import { IndexOffset, @@ -27,13 +31,15 @@ import { newIndexOffsetFromDocument, newIndexOffsetSuccessorFromReadTime } from '../../../src/model/field_index'; +import { Overlay } from '../../../src/model/overlay'; import { deletedDoc, doc, expectEqual, field, + filter, key, - path, + query, version, wrap } from '../../util/helpers'; @@ -464,9 +470,10 @@ function genericRemoteDocumentCacheTests( doc('c/1', VERSION, DOC_DATA) ]); - const matchingDocs = await cache.getAllFromCollection( - path('b'), - IndexOffset.min() + const matchingDocs = await cache.getDocumentsMatchingQuery( + query('b'), + IndexOffset.min(), + newOverlayMap() ); assertMatches( [doc('b/1', VERSION, DOC_DATA), doc('b/2', VERSION, DOC_DATA)], @@ -480,9 +487,10 @@ function genericRemoteDocumentCacheTests( doc('a/1/b/1', VERSION, DOC_DATA) ]); - const matchingDocs = await cache.getAllFromCollection( - path('a'), - IndexOffset.min() + const matchingDocs = await cache.getDocumentsMatchingQuery( + query('a'), + IndexOffset.min(), + newOverlayMap() ); assertMatches([doc('a/1', VERSION, DOC_DATA)], matchingDocs); }); @@ -498,20 +506,62 @@ function genericRemoteDocumentCacheTests( doc('b/new', 3, DOC_DATA).setReadTime(version(13)) ]); - const matchingDocs = await cache.getAllFromCollection( - path('b'), - newIndexOffsetSuccessorFromReadTime(version(12), INITIAL_LARGEST_BATCH_ID) + const matchingDocs = await cache.getDocumentsMatchingQuery( + query('b'), + newIndexOffsetSuccessorFromReadTime( + version(12), + INITIAL_LARGEST_BATCH_ID + ), + newOverlayMap() ); assertMatches([doc('b/new', 3, DOC_DATA)], matchingDocs); }); + it('getDocumentsMatchingQuery() applies query check', async () => { + await cache.addEntries([ + doc('a/1', 1, { matches: true }).setReadTime(version(1)) + ]); + await cache.addEntries([ + doc('a/2', 1, { matches: true }).setReadTime(version(2)) + ]); + await cache.addEntries([ + doc('a/3', 1, { matches: false }).setReadTime(version(3)) + ]); + + const matchingDocs = await cache.getDocumentsMatchingQuery( + query('a', filter('matches', '==', true)), + newIndexOffsetSuccessorFromReadTime(version(1), INITIAL_LARGEST_BATCH_ID), + newOverlayMap() + ); + assertMatches([doc('a/2', 1, { matches: true })], matchingDocs); + }); + + it('getDocumentsMatchingQuery() respects mutated documents', async () => { + await cache.addEntries([ + doc('a/1', 1, { matches: true }).setReadTime(version(1)) + ]); + await cache.addEntries([ + doc('a/2', 1, { matches: false }).setReadTime(version(2)) + ]); + + const mutatedDocs = newOverlayMap(); + mutatedDocs.set(key('a/2'), {} as Overlay); + const matchingDocs = await cache.getDocumentsMatchingQuery( + query('a', filter('matches', '==', true)), + newIndexOffsetSuccessorFromReadTime(version(1), INITIAL_LARGEST_BATCH_ID), + mutatedDocs + ); + assertMatches([doc('a/2', 1, { matches: false })], matchingDocs); + }); + it('getAll() uses read time rather than update time', async () => { await cache.addEntries([doc('b/old', 1, DOC_DATA).setReadTime(version(2))]); await cache.addEntries([doc('b/new', 2, DOC_DATA).setReadTime(version(1))]); - const matchingDocs = await cache.getAllFromCollection( - path('b'), - newIndexOffsetSuccessorFromReadTime(version(1), INITIAL_LARGEST_BATCH_ID) + const matchingDocs = await cache.getDocumentsMatchingQuery( + query('b'), + newIndexOffsetSuccessorFromReadTime(version(1), INITIAL_LARGEST_BATCH_ID), + newOverlayMap() ); assertMatches([doc('b/old', 1, DOC_DATA)], matchingDocs); }); @@ -545,7 +595,11 @@ function genericRemoteDocumentCacheTests( document.data.set(field('state'), wrap('new')); document = await cache - .getAllFromCollection(path('coll'), IndexOffset.min()) + .getDocumentsMatchingQuery( + query('coll'), + IndexOffset.min(), + newOverlayMap() + ) .then(m => m.get(key('coll/doc'))!); verifyOldValue(document); diff --git a/packages/firestore/test/unit/local/test_remote_document_cache.ts b/packages/firestore/test/unit/local/test_remote_document_cache.ts index 62344dd4b41..16037e4ea90 100644 --- a/packages/firestore/test/unit/local/test_remote_document_cache.ts +++ b/packages/firestore/test/unit/local/test_remote_document_cache.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { Query } from '../../../src/core/query'; import { SnapshotVersion } from '../../../src/core/snapshot_version'; import { IndexManager } from '../../../src/local/index_manager'; import { Persistence } from '../../../src/local/persistence'; @@ -23,12 +24,12 @@ import { RemoteDocumentCache } from '../../../src/local/remote_document_cache'; import { RemoteDocumentChangeBuffer } from '../../../src/local/remote_document_change_buffer'; import { DocumentKeySet, - MutableDocumentMap + MutableDocumentMap, + OverlayMap } from '../../../src/model/collections'; import { Document, MutableDocument } from '../../../src/model/document'; import { DocumentKey } from '../../../src/model/document_key'; import { IndexOffset } from '../../../src/model/field_index'; -import { ResourcePath } from '../../../src/model/path'; /** * A wrapper around a RemoteDocumentCache that automatically creates a @@ -109,14 +110,16 @@ export class TestRemoteDocumentCache { }); } - getAllFromCollection( - collection: ResourcePath, - offset: IndexOffset + getDocumentsMatchingQuery( + query: Query, + offset: IndexOffset, + mutatedDocs: OverlayMap ): Promise { return this.persistence.runTransaction( 'getAllFromCollection', 'readonly', - txn => this.cache.getAllFromCollection(txn, collection, offset) + txn => + this.cache.getDocumentsMatchingQuery(txn, query, offset, mutatedDocs) ); } From 0bab0b7a786d1563bf665904c7097d1fe06efce5 Mon Sep 17 00:00:00 2001 From: Christina Holland Date: Tue, 31 Jan 2023 12:02:30 -0800 Subject: [PATCH 7/7] Add CJS browser entry points for all packages (#6981) --- .changeset/ninety-taxis-study.md | 19 +++ packages/auth-compat/package.json | 6 +- packages/auth-compat/rollup.config.js | 13 ++ packages/auth/package.json | 12 +- packages/auth/rollup.config.js | 12 ++ packages/database-compat/package.json | 8 +- packages/database/package.json | 6 +- packages/database/rollup.config.js | 19 +++ packages/firebase/package.json | 170 +++++++++++++++++---- packages/firestore-compat/package.json | 6 +- packages/firestore-compat/rollup.config.js | 12 ++ packages/firestore/package.json | 12 +- packages/firestore/rollup.config.js | 24 ++- packages/firestore/rollup.config.lite.js | 16 ++ packages/functions-compat/package.json | 6 +- packages/functions-compat/rollup.config.js | 10 ++ packages/functions/package.json | 6 +- packages/functions/rollup.config.js | 13 ++ packages/messaging-compat/package.json | 2 +- packages/messaging/package.json | 11 +- packages/messaging/sw/package.json | 2 +- packages/rules-unit-testing/package.json | 6 +- packages/storage/package.json | 6 +- packages/storage/rollup.config.js | 20 +++ packages/template/package.json | 6 +- packages/template/rollup.config.js | 10 ++ packages/util/package.json | 6 +- packages/util/rollup.config.js | 10 ++ 28 files changed, 393 insertions(+), 56 deletions(-) create mode 100644 .changeset/ninety-taxis-study.md diff --git a/.changeset/ninety-taxis-study.md b/.changeset/ninety-taxis-study.md new file mode 100644 index 00000000000..05a7cf02cf6 --- /dev/null +++ b/.changeset/ninety-taxis-study.md @@ -0,0 +1,19 @@ +--- +'@firebase/auth': patch +'@firebase/auth-compat': patch +'@firebase/database': patch +'@firebase/database-compat': patch +'firebase': patch +'@firebase/firestore': patch +'@firebase/firestore-compat': patch +'@firebase/functions': patch +'@firebase/functions-compat': patch +'@firebase/messaging': patch +'@firebase/messaging-compat': patch +'@firebase/rules-unit-testing': patch +'@firebase/storage': patch +'@firebase/template': patch +'@firebase/util': patch +--- + +Added browser CJS entry points (expected by Jest when using JSDOM mode). diff --git a/packages/auth-compat/package.json b/packages/auth-compat/package.json index da5829e7e0a..507b6f1dbb0 100644 --- a/packages/auth-compat/package.json +++ b/packages/auth-compat/package.json @@ -16,7 +16,11 @@ "require": "./dist/index.node.cjs.js" }, "esm5": "./dist/index.esm.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/auth-compat/rollup.config.js b/packages/auth-compat/rollup.config.js index 5b767355657..cb3491541c4 100644 --- a/packages/auth-compat/rollup.config.js +++ b/packages/auth-compat/rollup.config.js @@ -73,6 +73,19 @@ const browserBuilds = [ treeshake: { moduleSideEffects: false } + }, + { + input: 'index.ts', + output: { + file: 'dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + plugins: es2017BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + treeshake: { + moduleSideEffects: false + } } ]; diff --git a/packages/auth/package.json b/packages/auth/package.json index b3b7d5c537f..70900487fdd 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -31,7 +31,11 @@ "default": "./dist/index.webworker.esm5.js" }, "esm5": "./dist/esm5/index.js", - "default": "./dist/esm2017/index.js" + "default": "./dist/esm2017/index.js", + "browser": { + "require": "./dist/browser-cjs/index.js", + "import": "./dist/esm2017/index.js" + } }, "./cordova": { "types": "./dist/cordova/index.cordova.d.ts", @@ -57,7 +61,11 @@ "default": "./dist/cordova/internal.js" }, "esm5": "./dist/esm5/internal.js", - "default": "./dist/esm2017/internal.js" + "default": "./dist/esm2017/internal.js", + "browser": { + "require": "./dist/browser-cjs/internal.js", + "import": "./dist/esm2017/internal.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/auth/rollup.config.js b/packages/auth/rollup.config.js index bea0d0d7135..01e358a9aff 100644 --- a/packages/auth/rollup.config.js +++ b/packages/auth/rollup.config.js @@ -97,6 +97,18 @@ const browserBuilds = [ replace(generateBuildTargetReplaceConfig('esm', 2017)) ], external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: { + index: 'index.ts', + internal: 'internal/index.ts' + }, + output: [{ dir: 'dist/browser-cjs', format: 'cjs', sourcemap: true }], + plugins: [ + ...es2017BuildPlugins, + replace(generateBuildTargetReplaceConfig('cjs', 2017)) + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) } ]; diff --git a/packages/database-compat/package.json b/packages/database-compat/package.json index 9262c1a2ced..6850d3581bf 100644 --- a/packages/database-compat/package.json +++ b/packages/database-compat/package.json @@ -22,7 +22,11 @@ "require": "./dist/index.js" }, "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.js", + "import": "./dist/index.esm2017.js" + } }, "./standalone": { "types": "./dist/database-compat/src/index.standalone.d.ts", @@ -64,4 +68,4 @@ "bugs": { "url": "https://github.com/firebase/firebase-js-sdk/issues" } -} \ No newline at end of file +} diff --git a/packages/database/package.json b/packages/database/package.json index af93208a9e5..d8cc37c497e 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -17,7 +17,11 @@ }, "esm5": "./dist/index.esm5.js", "standalone": "./dist/index.standalone.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/database/rollup.config.js b/packages/database/rollup.config.js index d1ba71f14da..886a177e4d9 100644 --- a/packages/database/rollup.config.js +++ b/packages/database/rollup.config.js @@ -94,6 +94,25 @@ const browserBuilds = [ }, external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), onwarn: onWarn + }, + { + input: 'src/index.ts', + output: [ + { + file: 'dist/index.cjs.js', + format: 'cjs', + sourcemap: true + } + ], + plugins: [ + ...es2017BuildPlugins, + replace(generateBuildTargetReplaceConfig('cjs', 2017)) + ], + treeshake: { + moduleSideEffects: false + }, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + onwarn: onWarn } ]; diff --git a/packages/firebase/package.json b/packages/firebase/package.json index 00bda033db5..6d982103ad8 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -29,7 +29,11 @@ "require": "./analytics/dist/index.cjs.js", "import": "./analytics/dist/index.mjs" }, - "default": "./analytics/dist/esm/index.esm.js" + "default": "./analytics/dist/esm/index.esm.js", + "browser": { + "require": "./analytics/dist/index.cjs.js", + "import": "./analytics/dist/esm/index.esm.js" + } }, "./app": { "types": "./app/dist/app/index.d.ts", @@ -37,7 +41,11 @@ "require": "./app/dist/index.cjs.js", "import": "./app/dist/index.mjs" }, - "default": "./app/dist/esm/index.esm.js" + "default": "./app/dist/esm/index.esm.js", + "browser": { + "require": "./app/dist/index.cjs.js", + "import": "./app/dist/esm/index.esm.js" + } }, "./app-check": { "types": "./app-check/dist/app-check/index.d.ts", @@ -45,7 +53,11 @@ "require": "./app-check/dist/index.cjs.js", "import": "./app-check/dist/index.mjs" }, - "default": "./app-check/dist/esm/index.esm.js" + "default": "./app-check/dist/esm/index.esm.js", + "browser": { + "require": "./app-check/dist/index.cjs.js", + "import": "./app-check/dist/esm/index.esm.js" + } }, "./auth": { "types": "./auth/dist/auth/index.d.ts", @@ -53,7 +65,11 @@ "require": "./auth/dist/index.cjs.js", "import": "./auth/dist/index.mjs" }, - "default": "./auth/dist/esm/index.esm.js" + "default": "./auth/dist/esm/index.esm.js", + "browser": { + "require": "./auth/dist/index.cjs.js", + "import": "./auth/dist/esm/index.esm.js" + } }, "./auth/cordova": { "types": "./auth/cordova/dist/auth/cordova/index.d.ts", @@ -61,7 +77,11 @@ "require": "./auth/cordova/dist/index.cjs.js", "import": "./auth/cordova/dist/index.mjs" }, - "default": "./auth/cordova/dist/esm/index.esm.js" + "default": "./auth/cordova/dist/esm/index.esm.js", + "browser": { + "require": "./auth/cordova/dist/index.cjs.js", + "import": "./auth/cordova/dist/esm/index.esm.js" + } }, "./auth/react-native": { "types": "./auth/react-native/dist/auth/react-native/index.d.ts", @@ -69,7 +89,11 @@ "require": "./auth/react-native/dist/index.cjs.js", "import": "./auth/react-native/dist/index.mjs" }, - "default": "./auth/react-native/dist/esm/index.esm.js" + "default": "./auth/react-native/dist/esm/index.esm.js", + "browser": { + "require": "./auth/react-native/dist/index.cjs.js", + "import": "./auth/react-native/dist/esm/index.esm.js" + } }, "./database": { "types": "./database/dist/database/index.d.ts", @@ -77,7 +101,11 @@ "require": "./database/dist/index.cjs.js", "import": "./database/dist/index.mjs" }, - "default": "./database/dist/esm/index.esm.js" + "default": "./database/dist/esm/index.esm.js", + "browser": { + "require": "./database/dist/index.cjs.js", + "import": "./database/dist/esm/index.esm.js" + } }, "./firestore": { "types": "./firestore/dist/firestore/index.d.ts", @@ -85,7 +113,11 @@ "require": "./firestore/dist/index.cjs.js", "import": "./firestore/dist/index.mjs" }, - "default": "./firestore/dist/esm/index.esm.js" + "default": "./firestore/dist/esm/index.esm.js", + "browser": { + "require": "./firestore/dist/index.cjs.js", + "import": "./firestore/dist/esm/index.esm.js" + } }, "./firestore/lite": { "types": "./firestore/lite/dist/firestore/lite/index.d.ts", @@ -93,7 +125,11 @@ "require": "./firestore/lite/dist/index.cjs.js", "import": "./firestore/lite/dist/index.mjs" }, - "default": "./firestore/lite/dist/esm/index.esm.js" + "default": "./firestore/lite/dist/esm/index.esm.js", + "browser": { + "require": "./firestore/lite/dist/index.cjs.js", + "import": "./firestore/lite/dist/esm/index.esm.js" + } }, "./functions": { "types": "./functions/dist/functions/index.d.ts", @@ -101,7 +137,11 @@ "require": "./functions/dist/index.cjs.js", "import": "./functions/dist/index.mjs" }, - "default": "./functions/dist/esm/index.esm.js" + "default": "./functions/dist/esm/index.esm.js", + "browser": { + "require": "./functions/dist/index.cjs.js", + "import": "./functions/dist/esm/index.esm.js" + } }, "./installations": { "types": "./installations/dist/installations/index.d.ts", @@ -109,7 +149,11 @@ "require": "./installations/dist/index.cjs.js", "import": "./installations/dist/index.mjs" }, - "default": "./installations/dist/esm/index.esm.js" + "default": "./installations/dist/esm/index.esm.js", + "browser": { + "require": "./installations/dist/index.cjs.js", + "import": "./installations/dist/esm/index.esm.js" + } }, "./messaging": { "types": "./messaging/dist/messaging/index.d.ts", @@ -117,7 +161,11 @@ "require": "./messaging/dist/index.cjs.js", "import": "./messaging/dist/index.mjs" }, - "default": "./messaging/dist/esm/index.esm.js" + "default": "./messaging/dist/esm/index.esm.js", + "browser": { + "require": "./messaging/dist/index.cjs.js", + "import": "./messaging/dist/esm/index.esm.js" + } }, "./messaging/sw": { "types": "./messaging/sw/dist/messaging/sw/index.d.ts", @@ -125,7 +173,11 @@ "require": "./messaging/sw/dist/index.cjs.js", "import": "./messaging/sw/dist/index.mjs" }, - "default": "./messaging/sw/dist/esm/index.esm.js" + "default": "./messaging/sw/dist/esm/index.esm.js", + "browser": { + "require": "./messaging/sw/dist/index.cjs.js", + "import": "./messaging/sw/dist/esm/index.esm.js" + } }, "./performance": { "types": "./performance/dist/performance/index.d.ts", @@ -133,7 +185,11 @@ "require": "./performance/dist/index.cjs.js", "import": "./performance/dist/index.mjs" }, - "default": "./performance/dist/esm/index.esm.js" + "default": "./performance/dist/esm/index.esm.js", + "browser": { + "require": "./performance/dist/index.cjs.js", + "import": "./performance/dist/esm/index.esm.js" + } }, "./remote-config": { "types": "./remote-config/dist/remote-config/index.d.ts", @@ -141,7 +197,11 @@ "require": "./remote-config/dist/index.cjs.js", "import": "./remote-config/dist/index.mjs" }, - "default": "./remote-config/dist/esm/index.esm.js" + "default": "./remote-config/dist/esm/index.esm.js", + "browser": { + "require": "./remote-config/dist/index.cjs.js", + "import": "./remote-config/dist/esm/index.esm.js" + } }, "./storage": { "types": "./storage/dist/storage/index.d.ts", @@ -149,7 +209,11 @@ "require": "./storage/dist/index.cjs.js", "import": "./storage/dist/index.mjs" }, - "default": "./storage/dist/esm/index.esm.js" + "default": "./storage/dist/esm/index.esm.js", + "browser": { + "require": "./storage/dist/index.cjs.js", + "import": "./storage/dist/esm/index.esm.js" + } }, "./compat/analytics": { "types": "./compat/analytics/dist/compat/analytics/index.d.ts", @@ -157,7 +221,11 @@ "require": "./compat/analytics/dist/index.cjs.js", "import": "./compat/analytics/dist/index.mjs" }, - "default": "./compat/analytics/dist/esm/index.esm.js" + "default": "./compat/analytics/dist/esm/index.esm.js", + "browser": { + "require": "./compat/analytics/dist/index.cjs.js", + "import": "./compat/analytics/dist/esm/index.esm.js" + } }, "./compat/app": { "types": "./compat/app/dist/compat/app/index.d.ts", @@ -165,7 +233,11 @@ "require": "./compat/app/dist/index.cjs.js", "import": "./compat/app/dist/index.mjs" }, - "default": "./compat/app/dist/esm/index.esm.js" + "default": "./compat/app/dist/esm/index.esm.js", + "browser": { + "require": "./compat/app/dist/index.cjs.js", + "import": "./compat/app/dist/esm/index.esm.js" + } }, "./compat/app-check": { "types": "./compat/app-check/dist/compat/app-check/index.d.ts", @@ -173,7 +245,11 @@ "require": "./compat/app-check/dist/index.cjs.js", "import": "./compat/app-check/dist/index.mjs" }, - "default": "./compat/app-check/dist/esm/index.esm.js" + "default": "./compat/app-check/dist/esm/index.esm.js", + "browser": { + "require": "./compat/app-check/dist/index.cjs.js", + "import": "./compat/app-check/dist/esm/index.esm.js" + } }, "./compat/auth": { "types": "./compat/auth/dist/compat/auth/index.d.ts", @@ -181,7 +257,11 @@ "require": "./compat/auth/dist/index.cjs.js", "import": "./compat/auth/dist/index.mjs" }, - "default": "./compat/auth/dist/esm/index.esm.js" + "default": "./compat/auth/dist/esm/index.esm.js", + "browser": { + "require": "./compat/auth/dist/index.cjs.js", + "import": "./compat/auth/dist/esm/index.esm.js" + } }, "./compat/database": { "types": "./compat/database/dist/compat/database/index.d.ts", @@ -189,7 +269,11 @@ "require": "./compat/database/dist/index.cjs.js", "import": "./compat/database/dist/index.mjs" }, - "default": "./compat/database/dist/esm/index.esm.js" + "default": "./compat/database/dist/esm/index.esm.js", + "browser": { + "require": "./compat/database/dist/index.cjs.js", + "import": "./compat/database/dist/esm/index.esm.js" + } }, "./compat/firestore": { "types": "./compat/firestore/dist/compat/firestore/index.d.ts", @@ -197,7 +281,11 @@ "require": "./compat/firestore/dist/index.cjs.js", "import": "./compat/firestore/dist/index.mjs" }, - "default": "./compat/firestore/dist/esm/index.esm.js" + "default": "./compat/firestore/dist/esm/index.esm.js", + "browser": { + "require": "./compat/firestore/dist/index.cjs.js", + "import": "./compat/firestore/dist/esm/index.esm.js" + } }, "./compat/functions": { "types": "./compat/functions/dist/compat/functions/index.d.ts", @@ -205,7 +293,11 @@ "require": "./compat/functions/dist/index.cjs.js", "import": "./compat/functions/dist/index.mjs" }, - "default": "./compat/functions/dist/esm/index.esm.js" + "default": "./compat/functions/dist/esm/index.esm.js", + "browser": { + "require": "./compat/functions/dist/index.cjs.js", + "import": "./compat/functions/dist/esm/index.esm.js" + } }, "./compat/installations": { "types": "./compat/installations/dist/compat/installations/index.d.ts", @@ -213,7 +305,11 @@ "require": "./compat/installations/dist/index.cjs.js", "import": "./compat/installations/dist/index.mjs" }, - "default": "./compat/installations/dist/esm/index.esm.js" + "default": "./compat/installations/dist/esm/index.esm.js", + "browser": { + "require": "./compat/installations/dist/index.cjs.js", + "import": "./compat/installations/dist/esm/index.esm.js" + } }, "./compat/messaging": { "types": "./compat/messaging/dist/compat/messaging/index.d.ts", @@ -221,7 +317,11 @@ "require": "./compat/messaging/dist/index.cjs.js", "import": "./compat/messaging/dist/index.mjs" }, - "default": "./compat/messaging/dist/esm/index.esm.js" + "default": "./compat/messaging/dist/esm/index.esm.js", + "browser": { + "require": "./compat/messaging/dist/index.cjs.js", + "import": "./compat/messaging/dist/esm/index.esm.js" + } }, "./compat/performance": { "types": "./compat/performance/dist/compat/performance/index.d.ts", @@ -229,7 +329,11 @@ "require": "./compat/performance/dist/index.cjs.js", "import": "./compat/performance/dist/index.mjs" }, - "default": "./compat/performance/dist/esm/index.esm.js" + "default": "./compat/performance/dist/esm/index.esm.js", + "browser": { + "require": "./compat/performance/dist/index.cjs.js", + "import": "./compat/performance/dist/esm/index.esm.js" + } }, "./compat/remote-config": { "types": "./compat/remote-config/dist/compat/remote-config/index.d.ts", @@ -237,7 +341,11 @@ "require": "./compat/remote-config/dist/index.cjs.js", "import": "./compat/remote-config/dist/index.mjs" }, - "default": "./compat/remote-config/dist/esm/index.esm.js" + "default": "./compat/remote-config/dist/esm/index.esm.js", + "browser": { + "require": "./compat/remote-config/dist/index.cjs.js", + "import": "./compat/remote-config/dist/esm/index.esm.js" + } }, "./compat/storage": { "types": "./compat/storage/dist/compat/storage/index.d.ts", @@ -245,7 +353,11 @@ "require": "./compat/storage/dist/index.cjs.js", "import": "./compat/storage/dist/index.mjs" }, - "default": "./compat/storage/dist/esm/index.esm.js" + "default": "./compat/storage/dist/esm/index.esm.js", + "browser": { + "require": "./compat/storage/dist/index.cjs.js", + "import": "./compat/storage/dist/esm/index.esm.js" + } }, "./package.json": "./package.json" }, @@ -321,4 +433,4 @@ "database" ], "typings": "empty.d.ts" -} \ No newline at end of file +} diff --git a/packages/firestore-compat/package.json b/packages/firestore-compat/package.json index 483a7e557c7..2321b49048b 100644 --- a/packages/firestore-compat/package.json +++ b/packages/firestore-compat/package.json @@ -17,7 +17,11 @@ }, "react-native": "./dist/index.rn.js", "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/firestore-compat/rollup.config.js b/packages/firestore-compat/rollup.config.js index ebf87c79e15..ecf6d42ca91 100644 --- a/packages/firestore-compat/rollup.config.js +++ b/packages/firestore-compat/rollup.config.js @@ -68,6 +68,18 @@ const browserBuilds = [ ], plugins: es5Plugins, external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: './src/index.ts', + output: [ + { + file: 'dist/index.cjs.js', + format: 'cjs', + sourcemap: true + } + ], + plugins: es2017Plugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) } ]; diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 800ecf7db6b..b3931e38840 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -56,7 +56,11 @@ }, "react-native": "./dist/index.rn.js", "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./lite": { "types": "./dist/lite/index.d.ts", @@ -66,7 +70,11 @@ }, "react-native": "./dist/lite/index.rn.esm2017.js", "esm5": "./dist/lite/index.browser.esm5.js", - "default": "./dist/lite/index.browser.esm2017.js" + "default": "./dist/lite/index.browser.esm2017.js", + "browser": { + "require": "./dist/lite/index.cjs.js", + "import": "./dist/lite/index.browser.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/firestore/rollup.config.js b/packages/firestore/rollup.config.js index cdde1fd83ab..21b984ab929 100644 --- a/packages/firestore/rollup.config.js +++ b/packages/firestore/rollup.config.js @@ -69,8 +69,8 @@ const browserPlugins = function () { }; const allBuilds = [ - // Intermidiate Node ESM build without build target reporting - // this is an intermidiate build used to generate the actual esm and cjs builds + // Intermediate Node ESM build without build target reporting + // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting { input: './src/index.node.ts', @@ -117,8 +117,8 @@ const allBuilds = [ moduleSideEffects: false } }, - // Intermidiate browser build without build target reporting - // this is an intermidiate build used to generate the actual esm and cjs builds + // Intermediate browser build without build target reporting + // this is an intermediate build used to generate the actual esm and cjs builds // which add build target reporting { input: './src/index.ts', @@ -152,6 +152,22 @@ const allBuilds = [ moduleSideEffects: false } }, + // Convert es2017 build to cjs + { + input: pkg['browser'], + output: [ + { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + } + ], + plugins: [replace(generateBuildTargetReplaceConfig('cjs', 2017))], + external: util.resolveBrowserExterns, + treeshake: { + moduleSideEffects: false + } + }, // es2017 build with build target reporting { input: pkg['browser'], diff --git a/packages/firestore/rollup.config.lite.js b/packages/firestore/rollup.config.lite.js index af2f510838f..ed11e40f6b8 100644 --- a/packages/firestore/rollup.config.lite.js +++ b/packages/firestore/rollup.config.lite.js @@ -171,6 +171,22 @@ const allBuilds = [ moduleSideEffects: false } }, + // Convert es2017 build to CJS + { + input: path.resolve('./lite', pkg.browser), + output: [ + { + file: './dist/lite/index.cjs.js', + format: 'es', + sourcemap: true + } + ], + plugins: [replace(generateBuildTargetReplaceConfig('cjs', 2017))], + external: util.resolveBrowserExterns, + treeshake: { + moduleSideEffects: false + } + }, // Browser es2017 build { input: path.resolve('./lite', pkg.browser), diff --git a/packages/functions-compat/package.json b/packages/functions-compat/package.json index 85ac2bed069..7aef9212356 100644 --- a/packages/functions-compat/package.json +++ b/packages/functions-compat/package.json @@ -15,7 +15,11 @@ "require": "./dist/index.node.cjs.js" }, "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/functions-compat/rollup.config.js b/packages/functions-compat/rollup.config.js index 74a738a1c92..949aeebd513 100644 --- a/packages/functions-compat/rollup.config.js +++ b/packages/functions-compat/rollup.config.js @@ -60,6 +60,16 @@ const browserBuilds = [ }, plugins: es2017BuildPlugins, external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: 'src/index.ts', + output: { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + plugins: es2017BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) } ]; diff --git a/packages/functions/package.json b/packages/functions/package.json index ab044778319..111c399cd5d 100644 --- a/packages/functions/package.json +++ b/packages/functions/package.json @@ -15,7 +15,11 @@ "require": "./dist/index.node.cjs.js" }, "esm5": "./dist/index.esm.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/functions/rollup.config.js b/packages/functions/rollup.config.js index f535171ee9e..bb5506ea9b5 100644 --- a/packages/functions/rollup.config.js +++ b/packages/functions/rollup.config.js @@ -68,6 +68,19 @@ const browserBuilds = [ ...es2017BuildPlugins, replace(generateBuildTargetReplaceConfig('esm', 2017)) ] + }, + { + input: 'src/index.ts', + output: { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + plugins: [ + ...es2017BuildPlugins, + replace(generateBuildTargetReplaceConfig('cjs', 2017)) + ] } ]; diff --git a/packages/messaging-compat/package.json b/packages/messaging-compat/package.json index 68a6ec867be..d7e16e813fd 100644 --- a/packages/messaging-compat/package.json +++ b/packages/messaging-compat/package.json @@ -11,7 +11,7 @@ "exports": { ".": { "types": "./dist/src/index.d.ts", - "node": "./dist/index.cjs.js", + "require": "./dist/index.cjs.js", "esm5": "./dist/esm/index.esm.js", "default": "./dist/esm/index.esm2017.js" }, diff --git a/packages/messaging/package.json b/packages/messaging/package.json index 5f09f0d1f78..aeee75a58fb 100644 --- a/packages/messaging/package.json +++ b/packages/messaging/package.json @@ -6,22 +6,21 @@ "main": "dist/index.cjs.js", "browser": "dist/esm/index.esm2017.js", "module": "dist/esm/index.esm2017.js", - "sw": "dist/index.sw.esm2017.js", + "sw": "dist/esm/index.sw.esm2017.js", "sw-main": "dist/index.sw.cjs", "esm5": "dist/esm/index.esm.js", "exports": { ".": { "types": "./dist/index-public.d.ts", - "node": "./dist/index.cjs.js", - "browser": "./dist/esm/index.esm2017.js", + "require": "./dist/index.cjs.js", "module": "./dist/esm/index.esm2017.js", "esm5": "./dist/esm/index.esm.js", - "default": "./dist/index.cjs.js" + "default": "./dist/esm/index.esm2017.js" }, "./sw": { "types": "./dist/sw/index-public.d.ts", - "node": "./dist/index.sw.cjs", - "default": "./dist/index.sw.esm2017.js" + "require": "./dist/index.sw.cjs", + "default": "./dist/esm/index.sw.esm2017.js" }, "./package.json": "./package.json" }, diff --git a/packages/messaging/sw/package.json b/packages/messaging/sw/package.json index 98f4f9711b6..472e37684bc 100644 --- a/packages/messaging/sw/package.json +++ b/packages/messaging/sw/package.json @@ -3,6 +3,6 @@ "description": "", "author": "Firebase (https://firebase.google.com/)", "main": "../dist/index.sw.cjs", - "module": "../dist/index.sw.esm2017.js", + "module": "../dist/esm/index.sw.esm2017.js", "typings": "../dist/src/index.sw.d.ts" } diff --git a/packages/rules-unit-testing/package.json b/packages/rules-unit-testing/package.json index c796541fa3c..f2a838736b2 100644 --- a/packages/rules-unit-testing/package.json +++ b/packages/rules-unit-testing/package.json @@ -11,7 +11,11 @@ "import": "./dist/esm/index.esm.js", "require": "./dist/index.cjs.js" }, - "default": "./dist/index.cjs.js" + "default": "./dist/index.cjs.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/esm/index.esm.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/storage/package.json b/packages/storage/package.json index 6ecf2e42a0c..cb77dbc746a 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -15,7 +15,11 @@ "default": "./dist/index.node.cjs.js" }, "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/storage/rollup.config.js b/packages/storage/rollup.config.js index 4bcb603de3a..73c9d7561aa 100644 --- a/packages/storage/rollup.config.js +++ b/packages/storage/rollup.config.js @@ -99,6 +99,26 @@ const browserBuilds = [ moduleSideEffects: false } }, + { + input: './src/index.ts', + output: { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + plugins: [ + alias(generateAliasConfig('browser')), + ...es2017Plugins, + replace({ + ...generateBuildTargetReplaceConfig('cjs', 2017), + '__RUNTIME_ENV__': '' + }) + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)), + treeshake: { + moduleSideEffects: false + } + }, { // needed by Emulator UI input: './src/index.ts', diff --git a/packages/template/package.json b/packages/template/package.json index 892332529a4..1bab48a2749 100644 --- a/packages/template/package.json +++ b/packages/template/package.json @@ -16,7 +16,11 @@ "require": "./dist/index.node.cjs.js" }, "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/template/rollup.config.js b/packages/template/rollup.config.js index 5c95031f734..0417ac2a28d 100644 --- a/packages/template/rollup.config.js +++ b/packages/template/rollup.config.js @@ -57,6 +57,16 @@ const browserBuilds = [ }, plugins: es2017BuildPlugins, external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: 'index.ts', + output: { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + plugins: es2017BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) } ]; diff --git a/packages/util/package.json b/packages/util/package.json index 518b71c6cd3..42b766c8513 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -15,7 +15,11 @@ "require": "./dist/index.node.cjs.js" }, "esm5": "./dist/index.esm5.js", - "default": "./dist/index.esm2017.js" + "default": "./dist/index.esm2017.js", + "browser": { + "require": "./dist/index.cjs.js", + "import": "./dist/index.esm2017.js" + } }, "./package.json": "./package.json" }, diff --git a/packages/util/rollup.config.js b/packages/util/rollup.config.js index 4bd11731821..8f0d1312bfa 100644 --- a/packages/util/rollup.config.js +++ b/packages/util/rollup.config.js @@ -57,6 +57,16 @@ const browserBuilds = [ }, plugins: es2017BuildPlugins, external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + }, + { + input: 'index.ts', + output: { + file: './dist/index.cjs.js', + format: 'cjs', + sourcemap: true + }, + plugins: es2017BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) } ];