From 3a465b40496cb18747e540f569f8340097009b04 Mon Sep 17 00:00:00 2001 From: Kai Wu Date: Tue, 16 Mar 2021 14:21:23 -0700 Subject: [PATCH] Create messaging-compat (#4544) * Create messaging-compat Using the modular sdk to recreate legacy API surface * Modify based on review - Update licenses date to 2020 (from 2017, 2018) - Declare Module in `registerMessagingCompat.ts` - Update build rule (package.json): -- add `app-comapt` as a dev dependency * Fix build based on Christina's input Thanks Christina for the input here. Changes are - Add entry in changeset file - Add eslintrc.js to `messaging-compat` * Resolve lint issue surfaced from test - return type in `onMessage` * Add unit tests * Improve based on Fei's comments/feedbacks - Updated dependencies versions - Remove redundant namespace declarations --- .changeset/config.json | 1 + packages-exp/messaging-compat/.eslintrc.js | 28 ++++++ packages-exp/messaging-compat/README.md | 5 ++ packages-exp/messaging-compat/karma.conf.js | 32 +++++++ packages-exp/messaging-compat/package.json | 54 +++++++++++ .../messaging-compat/rollup.config.js | 77 ++++++++++++++++ .../messaging-compat/rollup.config.release.js | 90 +++++++++++++++++++ packages-exp/messaging-compat/src/index.ts | 24 +++++ .../messaging-compat/src/messaging-compat.ts | 74 +++++++++++++++ .../src/registerMessagingCompat.ts | 51 +++++++++++ packages-exp/messaging-compat/test/fakes.ts | 40 +++++++++ .../test/messaging-compat.test.ts | 61 +++++++++++++ packages-exp/messaging-compat/tsconfig.json | 15 ++++ 13 files changed, 552 insertions(+) create mode 100644 packages-exp/messaging-compat/.eslintrc.js create mode 100644 packages-exp/messaging-compat/README.md create mode 100644 packages-exp/messaging-compat/karma.conf.js create mode 100644 packages-exp/messaging-compat/package.json create mode 100644 packages-exp/messaging-compat/rollup.config.js create mode 100644 packages-exp/messaging-compat/rollup.config.release.js create mode 100644 packages-exp/messaging-compat/src/index.ts create mode 100644 packages-exp/messaging-compat/src/messaging-compat.ts create mode 100644 packages-exp/messaging-compat/src/registerMessagingCompat.ts create mode 100644 packages-exp/messaging-compat/test/fakes.ts create mode 100644 packages-exp/messaging-compat/test/messaging-compat.test.ts create mode 100644 packages-exp/messaging-compat/tsconfig.json diff --git a/.changeset/config.json b/.changeset/config.json index 038541fb90b..e9e62f8edbd 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -23,6 +23,7 @@ "@firebase/installations-exp", "@firebase/installations-compat", "@firebase/messaging-exp", + "@firebase/messaging-compat", "@firebase/performance-exp", "@firebase/performance-compat", "@firebase/remote-config-exp", diff --git a/packages-exp/messaging-compat/.eslintrc.js b/packages-exp/messaging-compat/.eslintrc.js new file mode 100644 index 00000000000..67f0cbcecbf --- /dev/null +++ b/packages-exp/messaging-compat/.eslintrc.js @@ -0,0 +1,28 @@ +/* eslint-disable @typescript-eslint/no-require-imports */ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const path = require('path'); + +module.exports = { + extends: '../../config/.eslintrc.js', + parserOptions: { + project: 'tsconfig.json', + // to make vscode-eslint work with monorepo + // https://github.com/typescript-eslint/typescript-eslint/issues/251#issuecomment-463943250 + tsconfigRootDir: __dirname + } +}; diff --git a/packages-exp/messaging-compat/README.md b/packages-exp/messaging-compat/README.md new file mode 100644 index 00000000000..9e7d29db35d --- /dev/null +++ b/packages-exp/messaging-compat/README.md @@ -0,0 +1,5 @@ +# @firebase/messaging-compat + +This is the compat package that recreates the v8 APIs. + +**This package is not intended for direct usage, and should only be used via the officially supported [firebase](https://www.npmjs.com/package/firebase) package.** diff --git a/packages-exp/messaging-compat/karma.conf.js b/packages-exp/messaging-compat/karma.conf.js new file mode 100644 index 00000000000..322599066d1 --- /dev/null +++ b/packages-exp/messaging-compat/karma.conf.js @@ -0,0 +1,32 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const karmaBase = require('../../config/karma.base'); + +const files = ['test/**/*']; + +module.exports = function (config) { + const karmaConfig = { + ...karmaBase, + files, + frameworks: ['mocha'] + }; + + config.set(karmaConfig); +}; + +module.exports.files = files; diff --git a/packages-exp/messaging-compat/package.json b/packages-exp/messaging-compat/package.json new file mode 100644 index 00000000000..186886f1aff --- /dev/null +++ b/packages-exp/messaging-compat/package.json @@ -0,0 +1,54 @@ +{ + "name": "@firebase/messaging-compat", + "version": "0.0.900", + "license": "Apache-2.0", + "description": "", + "private": true, + "author": "Firebase (https://firebase.google.com/)", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "esm2017": "dist/index.esm2017.js", + "typings": "dist/index.d.ts", + "sw": "dist/index.sw.esm2017.js", + "files": [ + "dist" + ], + "scripts": { + "lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", + "lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'", + "build": "rollup -c", + "build:deps": "lerna run --scope @firebase/'messaging-compat' --include-dependencies build", + "build:release": "rollup -c rollup.config.release.js", + "dev": "rollup -c -w", + "test": "run-p test:karma", + "test:ci": "node ../../scripts/run_tests_in_ci.js", + "test:karma": "karma start --single-run", + "test:debug": "karma start --browsers=Chrome --auto-watch", + "type-check": "tsc --noEmit" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + }, + "dependencies": { + "@firebase/messaging-exp": "0.0.900", + "@firebase/component": "0.2.1", + "@firebase/installations-exp": "0.0.900", + "@firebase/util": "0.4.0", + "tslib": "^2.0.0" + }, + "devDependencies": { + "@firebase/app-compat": "0.0.900", + "@rollup/plugin-json": "4.1.0", + "rollup-plugin-typescript2": "0.29.0", + "ts-essentials": "7.0.1", + "typescript": "4.2.2" + }, + "repository": { + "directory": "packages/messaging", + "type": "git", + "url": "https://github.com/firebase/firebase-js-sdk.git" + }, + "bugs": { + "url": "https://github.com/firebase/firebase-js-sdk/issues" + } +} diff --git a/packages-exp/messaging-compat/rollup.config.js b/packages-exp/messaging-compat/rollup.config.js new file mode 100644 index 00000000000..49de83b926c --- /dev/null +++ b/packages-exp/messaging-compat/rollup.config.js @@ -0,0 +1,77 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import json from '@rollup/plugin-json'; +import pkg from './package.json'; +import typescript from 'typescript'; +import typescriptPlugin from 'rollup-plugin-typescript2'; + +const deps = Object.keys( + Object.assign({}, pkg.peerDependencies, pkg.dependencies) +); + +/** + * ES5 Builds + */ +const es5BuildPlugins = [ + typescriptPlugin({ + typescript + }), + json() +]; + +const es5Builds = [ + { + input: 'src/index.ts', + output: [ + { file: pkg.main, format: 'cjs', sourcemap: true }, + { file: pkg.module, format: 'es', sourcemap: true } + ], + plugins: es5BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +/** + * ES2017 Builds + */ +const es2017BuildPlugins = [ + typescriptPlugin({ + typescript, + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + } + }), + json({ preferConst: true }) +]; + +const es2017Builds = [ + { + input: 'src/index.ts', + output: { + file: pkg.esm2017, + format: 'es', + sourcemap: true + }, + plugins: es2017BuildPlugins, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +export default [...es5Builds, ...es2017Builds]; diff --git a/packages-exp/messaging-compat/rollup.config.release.js b/packages-exp/messaging-compat/rollup.config.release.js new file mode 100644 index 00000000000..6756098f379 --- /dev/null +++ b/packages-exp/messaging-compat/rollup.config.release.js @@ -0,0 +1,90 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { importPathTransformer } from '../../scripts/exp/ts-transform-import-path'; +import json from '@rollup/plugin-json'; +import pkg from './package.json'; +import typescript from 'typescript'; +import typescriptPlugin from 'rollup-plugin-typescript2'; + +const deps = Object.keys( + Object.assign({}, pkg.peerDependencies, pkg.dependencies) +); + +/** + * ES5 Builds + */ +const es5BuildPlugins = [ + typescriptPlugin({ + typescript, + clean: true, + abortOnError: false, + transformers: [importPathTransformer] + }), + json() +]; + +const es5Builds = [ + { + input: 'src/index.ts', + output: [ + { file: pkg.main, format: 'cjs', sourcemap: true }, + { file: pkg.module, format: 'es', sourcemap: true } + ], + plugins: es5BuildPlugins, + treeshake: { + moduleSideEffects: false + }, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +/** + * ES2017 Builds + */ +const es2017BuildPlugins = [ + typescriptPlugin({ + typescript, + abortOnError: false, + clean: true, + transformers: [importPathTransformer], + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + } + }), + json({ preferConst: true }) +]; + +const es2017Builds = [ + { + input: 'src/index.ts', + output: { + file: pkg.esm2017, + format: 'es', + sourcemap: true + }, + plugins: es2017BuildPlugins, + treeshake: { + moduleSideEffects: false + }, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +export default [...es5Builds, ...es2017Builds]; diff --git a/packages-exp/messaging-compat/src/index.ts b/packages-exp/messaging-compat/src/index.ts new file mode 100644 index 00000000000..f9dc0996ed7 --- /dev/null +++ b/packages-exp/messaging-compat/src/index.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { name, version } from '../package.json'; + +import { firebase } from '@firebase/app-compat'; +import { registerMessagingCompat } from './registerMessagingCompat'; + +registerMessagingCompat(); +firebase.registerVersion(name, version); diff --git a/packages-exp/messaging-compat/src/messaging-compat.ts b/packages-exp/messaging-compat/src/messaging-compat.ts new file mode 100644 index 00000000000..16b871be12f --- /dev/null +++ b/packages-exp/messaging-compat/src/messaging-compat.ts @@ -0,0 +1,74 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + FirebaseApp as AppCompat, + _FirebaseService +} from '@firebase/app-compat'; +import { + FirebaseMessaging, + MessagePayload, + deleteToken, + getToken, + onMessage +} from '@firebase/messaging-exp'; +import { NextFn, Observer, Unsubscribe } from '@firebase/util'; + +import { onBackgroundMessage } from '@firebase/messaging-exp/sw'; + +export class MessagingCompat implements _FirebaseService { + swRegistration?: ServiceWorkerRegistration; + vapidKey?: string; + + onBackgroundMessageHandler: + | NextFn + | Observer + | null = null; + + onMessageHandler: + | NextFn + | Observer + | null = null; + + constructor(readonly app: AppCompat, readonly messaging: FirebaseMessaging) { + this.app = app; + this.messaging = messaging; + } + + async getToken(options?: { + vapidKey?: string; + serviceWorkerRegistration?: ServiceWorkerRegistration; + }): Promise { + return getToken(this.messaging, options); + } + + async deleteToken(): Promise { + return deleteToken(this.messaging); + } + + onMessage( + nextOrObserver: NextFn | Observer + ): Unsubscribe { + return onMessage(this.messaging, nextOrObserver); + } + + onBackgroundMessage( + nextOrObserver: NextFn | Observer + ): Unsubscribe { + return onBackgroundMessage(this.messaging, nextOrObserver); + } +} diff --git a/packages-exp/messaging-compat/src/registerMessagingCompat.ts b/packages-exp/messaging-compat/src/registerMessagingCompat.ts new file mode 100644 index 00000000000..9e116a37bef --- /dev/null +++ b/packages-exp/messaging-compat/src/registerMessagingCompat.ts @@ -0,0 +1,51 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Component, + ComponentContainer, + ComponentType, + InstanceFactory +} from '@firebase/component'; + +import { MessagingCompat } from './messaging-compat'; +import { _registerComponent } from '@firebase/app-exp'; + +declare module '@firebase/component' { + interface NameServiceMapping { + 'messaging-compat': MessagingCompat; + } +} + +const messagingCompatFactory: InstanceFactory<'messaging-compat'> = ( + container: ComponentContainer +) => { + return new MessagingCompat( + container.getProvider('app-compat').getImmediate(), + container.getProvider('messaging-exp').getImmediate() + ); +}; + +export function registerMessagingCompat(): void { + _registerComponent( + new Component( + 'messaging-compat', + messagingCompatFactory, + ComponentType.PUBLIC + ) + ); +} diff --git a/packages-exp/messaging-compat/test/fakes.ts b/packages-exp/messaging-compat/test/fakes.ts new file mode 100644 index 00000000000..d8e218e147a --- /dev/null +++ b/packages-exp/messaging-compat/test/fakes.ts @@ -0,0 +1,40 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FirebaseApp } from '@firebase/app-compat'; +import { FirebaseMessaging } from '@firebase/messaging-exp'; + +export function getFakeApp(): FirebaseApp { + return { + name: 'appName', + options: { + apiKey: 'apiKey', + projectId: 'projectId', + authDomain: 'authDomain', + messagingSenderId: 'messagingSenderId', + databaseURL: 'databaseUrl', + storageBucket: 'storageBucket', + appId: '1:777777777777:web:d93b5ca1475efe57' + }, + automaticDataCollectionEnabled: true, + delete: async () => {} + }; +} + +export function getFakeModularMessaging(): FirebaseMessaging { + return {}; +} diff --git a/packages-exp/messaging-compat/test/messaging-compat.test.ts b/packages-exp/messaging-compat/test/messaging-compat.test.ts new file mode 100644 index 00000000000..e5d7a0dc2ae --- /dev/null +++ b/packages-exp/messaging-compat/test/messaging-compat.test.ts @@ -0,0 +1,61 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as messagingModule from '@firebase/messaging-exp'; +import * as messagingModuleSwComponent from '@firebase/messaging-exp/sw'; + +import { getFakeApp, getFakeModularMessaging } from './fakes'; + +import { MessagingCompat } from '../src/messaging-compat'; +import { expect } from 'chai'; +import { stub } from 'sinon'; + +describe('messagingCompat', () => { + const messagingCompat = new MessagingCompat( + getFakeApp(), + getFakeModularMessaging() + ); + + //Stubs + const getTokenStub = stub(messagingModule, 'getToken'); + const deleteTokenStub = stub(messagingModule, 'deleteToken'); + const onMessageStub = stub(messagingModule, 'onMessage'); + const onBackgroundMessageStub = stub( + messagingModuleSwComponent, + 'onBackgroundMessage' + ); + + it('routes messagingCompat.getToken to modular SDK', () => { + void messagingCompat.getToken(); + expect(getTokenStub.called).to.be.true; + }); + + it('routes messagingCompat.deleteToken to modular SDK', () => { + void messagingCompat.deleteToken(); + expect(deleteTokenStub.called).to.be.true; + }); + + it('routes messagingCompat.onMessage to modular SDK', () => { + messagingCompat.onMessage(_ => {}); + expect(onMessageStub.called).to.be.true; + }); + + it('routes messagingCompat.onBackgroundMessage to modular SDK', () => { + messagingCompat.onBackgroundMessage(_ => {}); + expect(onBackgroundMessageStub.called).to.be.true; + }); +}); diff --git a/packages-exp/messaging-compat/tsconfig.json b/packages-exp/messaging-compat/tsconfig.json new file mode 100644 index 00000000000..4b63b47c5b5 --- /dev/null +++ b/packages-exp/messaging-compat/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../config/tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "noUnusedLocals": true, + "lib": [ + "dom", + "es2017" + ], + "downlevelIteration": true + }, + "exclude": [ + "dist/**/*" + ] +}