diff --git a/.changeset/config.json b/.changeset/config.json index c59a15f4d7f..dbc6b9042c1 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,6 +1,9 @@ { "$schema": "https://unpkg.com/@changesets/config@1.1.0/schema.json", - "changelog": ["../repo-scripts/changelog-generator", { "repo": "firebase/firebase-js-sdk"}], + "changelog": [ + "../repo-scripts/changelog-generator", + { "repo": "firebase/firebase-js-sdk" } + ], "commit": false, "linked": [], "access": "public", @@ -20,6 +23,7 @@ "@firebase/functions-types-exp", "@firebase/installations-exp", "@firebase/installations-types-exp", + "@firebase/installations-compat", "@firebase/messaging-exp", "@firebase/messaging-types-exp", "@firebase/performance-exp", diff --git a/packages-exp/installations-compat/.eslintrc.js b/packages-exp/installations-compat/.eslintrc.js new file mode 100644 index 00000000000..ca80aa0f69a --- /dev/null +++ b/packages-exp/installations-compat/.eslintrc.js @@ -0,0 +1,26 @@ +/** + * @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. + */ + +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/installations-compat/karma.conf.js b/packages-exp/installations-compat/karma.conf.js new file mode 100644 index 00000000000..1699a0681ec --- /dev/null +++ b/packages-exp/installations-compat/karma.conf.js @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2019 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 = [`src/**/*.test.ts`]; + +module.exports = function (config) { + const karmaConfig = { + ...karmaBase, + // files to load into karma + files, + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'] + }; + + config.set(karmaConfig); +}; + +module.exports.files = files; diff --git a/packages-exp/installations-compat/package.json b/packages-exp/installations-compat/package.json new file mode 100644 index 00000000000..7423f473af5 --- /dev/null +++ b/packages-exp/installations-compat/package.json @@ -0,0 +1,63 @@ +{ + "name": "@firebase/installations-compat", + "version": "0.0.900", + "private": true, + "author": "Firebase (https://firebase.google.com/)", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", + "browser": "dist/index.esm.js", + "esm2017": "dist/index.esm2017.js", + "typings": "dist/installations-compat.d.ts", + "license": "Apache-2.0", + "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/installations-compat --include-dependencies build", + "build:release": "rollup -c rollup.config.release.js", + "dev": "rollup -c -w", + "test": "yarn type-check && yarn test:karma && yarn lint", + "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 -p . --noEmit", + "serve": "yarn serve:build && yarn serve:host", + "serve:build": "rollup -c test-app/rollup.config.js", + "serve:host": "http-server -c-1 test-app", + "prepare": "yarn build:release", + "api-report": "api-extractor run --local --verbose", + "predoc": "node ../../scripts/exp/remove-exp.js temp", + "doc": "api-documenter markdown --input temp --output docs", + "build:doc": "yarn build && yarn doc" + }, + "repository": { + "directory": "packages-exp/installations-compat", + "type": "git", + "url": "https://github.com/firebase/firebase-js-sdk.git" + }, + "bugs": { + "url": "https://github.com/firebase/firebase-js-sdk/issues" + }, + "devDependencies": { + "@firebase/app-compat": "0.0.900", + "rollup": "2.33.2", + "@rollup/plugin-commonjs": "15.1.0", + "@rollup/plugin-json": "4.1.0", + "@rollup/plugin-node-resolve": "9.0.0", + "rollup-plugin-typescript2": "0.29.0", + "rollup-plugin-uglify": "6.0.4", + "typescript": "4.0.5" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + }, + "dependencies": { + "@firebase/installations-exp": "0.0.900", + "@firebase/installations-types-exp": "0.0.900", + "@firebase/util": "0.3.4", + "@firebase/component": "0.1.21", + "idb": "3.0.2", + "tslib": "^1.11.1" + } +} diff --git a/packages-exp/installations-compat/rollup.config.js b/packages-exp/installations-compat/rollup.config.js new file mode 100644 index 00000000000..d66e464f546 --- /dev/null +++ b/packages-exp/installations-compat/rollup.config.js @@ -0,0 +1,53 @@ +/** + * @license + * Copyright 2019 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 typescriptPlugin from 'rollup-plugin-typescript2'; +import typescript from 'typescript'; +import { es2017BuildsNoPlugin, es5BuildsNoPlugin } from './rollup.shared'; + +/** + * ES5 Builds + */ +const es5BuildPlugins = [typescriptPlugin({ typescript }), json()]; + +const es5Builds = es5BuildsNoPlugin.map(build => ({ + ...build, + plugins: es5BuildPlugins +})); + +/** + * ES2017 Builds + */ +const es2017BuildPlugins = [ + typescriptPlugin({ + typescript, + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + } + }), + json({ preferConst: true }) +]; + +const es2017Builds = es2017BuildsNoPlugin.map(build => ({ + ...build, + plugins: es2017BuildPlugins +})); + +export default [...es5Builds, ...es2017Builds]; diff --git a/packages-exp/installations-compat/rollup.config.release.js b/packages-exp/installations-compat/rollup.config.release.js new file mode 100644 index 00000000000..5050932f4a4 --- /dev/null +++ b/packages-exp/installations-compat/rollup.config.release.js @@ -0,0 +1,71 @@ +/** + * @license + * Copyright 2019 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 typescriptPlugin from 'rollup-plugin-typescript2'; +import typescript from 'typescript'; +import { importPathTransformer } from '../../scripts/exp/ts-transform-import-path'; +import { es2017BuildsNoPlugin, es5BuildsNoPlugin } from './rollup.shared'; + +/** + * ES5 Builds + */ +const es5BuildPlugins = [ + typescriptPlugin({ + typescript, + clean: true, + abortOnError: false, + transformers: [importPathTransformer] + }), + json() +]; + +const es5Builds = es5BuildsNoPlugin.map(build => ({ + ...build, + plugins: es5BuildPlugins, + treeshake: { + moduleSideEffects: false + } +})); + +/** + * ES2017 Builds + */ +const es2017BuildPlugins = [ + typescriptPlugin({ + typescript, + tsconfigOverride: { + compilerOptions: { + target: 'es2017' + } + }, + abortOnError: false, + clean: true, + transformers: [importPathTransformer] + }), + json({ preferConst: true }) +]; + +const es2017Builds = es2017BuildsNoPlugin.map(build => ({ + ...build, + plugins: es2017BuildPlugins, + treeshake: { + moduleSideEffects: false + } +})); + +export default [...es5Builds, ...es2017Builds]; diff --git a/packages-exp/installations-compat/rollup.shared.js b/packages-exp/installations-compat/rollup.shared.js new file mode 100644 index 00000000000..ca79f888314 --- /dev/null +++ b/packages-exp/installations-compat/rollup.shared.js @@ -0,0 +1,48 @@ +/** + * @license + * Copyright 2019 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 pkg from './package.json'; + +const deps = Object.keys({ ...pkg.peerDependencies, ...pkg.dependencies }); + +/** + * ES5 Builds + */ +export const es5BuildsNoPlugin = [ + { + input: 'src/index.ts', + output: [ + { file: pkg.main, format: 'cjs', sourcemap: true }, + { file: pkg.module, format: 'es', sourcemap: true } + ], + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; + +/** + * ES2017 Builds + */ +export const es2017BuildsNoPlugin = [ + { + input: 'src/index.ts', + output: { + file: pkg.esm2017, + format: 'es', + sourcemap: true + }, + external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`)) + } +]; diff --git a/packages-exp/installations-compat/src/index.ts b/packages-exp/installations-compat/src/index.ts new file mode 100644 index 00000000000..dab8ad4607d --- /dev/null +++ b/packages-exp/installations-compat/src/index.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 { firebase } from '@firebase/app-compat'; +import { name, version } from '../package.json'; +import { _FirebaseNamespace } from '@firebase/app-types/private'; +import { Component, ComponentType } from '@firebase/component'; +import { FirebaseInstallations as FirebaseInstallationsCompat } from '@firebase/installations-types'; +import { FirebaseApp } from '@firebase/app-types'; +import { InstallationsCompat } from './installationsCompat'; + +declare module '@firebase/component' { + interface NameServiceMapping { + 'app-compat': FirebaseApp; + 'installations-compat': FirebaseInstallationsCompat; + } +} + +function registerInstallations(instance: _FirebaseNamespace): void { + instance.INTERNAL.registerComponent( + new Component( + 'installations-compat', + container => { + const app = container.getProvider('app-compat').getImmediate()!; + const installations = container + .getProvider('installations-exp') + .getImmediate()!; + return new InstallationsCompat(app, installations); + }, + ComponentType.PUBLIC + ) + ); + + instance.registerVersion(name, version); +} + +registerInstallations(firebase as _FirebaseNamespace); diff --git a/packages-exp/installations-compat/src/installationsCompat.test.ts b/packages-exp/installations-compat/src/installationsCompat.test.ts new file mode 100644 index 00000000000..1f3442c4d86 --- /dev/null +++ b/packages-exp/installations-compat/src/installationsCompat.test.ts @@ -0,0 +1,85 @@ +/** + * @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 './testing/setup'; +import { getFakeApp, getFakeInstallations } from './testing/util'; +import { InstallationsCompat } from './installationsCompat'; +import * as modularApi from '@firebase/installations-exp'; +import { expect } from 'chai'; +import { stub } from 'sinon'; + +describe('Installations Compat', () => { + let installationsCompat!: InstallationsCompat; + const installations = getFakeInstallations(); + before(() => { + installationsCompat = new InstallationsCompat(getFakeApp(), installations); + }); + + it('getId calls modular getId()', async () => { + const fakeFid = 'fake-fid'; + const modularGetIdStub = stub(modularApi, 'getId').callsFake(() => + Promise.resolve(fakeFid) + ); + + const res = await installationsCompat.getId(); + + expect(res).to.equal(fakeFid); + expect(modularGetIdStub).to.have.been.calledWithExactly(installations); + }); + + it('getToken calls modular getToken()', async () => { + const fakeToken = 'fake-token'; + const modularGetTokenStub = stub(modularApi, 'getToken').callsFake(() => + Promise.resolve(fakeToken) + ); + + const res = await installationsCompat.getToken(); + + expect(res).to.equal(fakeToken); + expect(modularGetTokenStub).to.have.been.calledWithExactly( + installations, + undefined + ); + }); + + it('delete calls modular deleteInstallations()', async () => { + const modularDeleteStub = stub( + modularApi, + 'deleteInstallations' + ).callsFake(() => Promise.resolve()); + + await installationsCompat.delete(); + + expect(modularDeleteStub).to.have.been.calledWithExactly(installations); + }); + + it('onIdChange calls modular onIdChange()', () => { + const fakeIdChangeCallbackFn = stub(); + const fakeIdChangeUnsubscribeFn = stub(); + const modularOnIdChangeStub = stub(modularApi, 'onIdChange').callsFake( + () => fakeIdChangeUnsubscribeFn + ); + + const res = installationsCompat.onIdChange(fakeIdChangeCallbackFn); + + expect(res).to.equal(fakeIdChangeUnsubscribeFn); + expect(modularOnIdChangeStub).to.have.been.calledWith( + installations, + fakeIdChangeCallbackFn + ); + }); +}); diff --git a/packages-exp/installations-compat/src/installationsCompat.ts b/packages-exp/installations-compat/src/installationsCompat.ts new file mode 100644 index 00000000000..467a9cae4f2 --- /dev/null +++ b/packages-exp/installations-compat/src/installationsCompat.ts @@ -0,0 +1,50 @@ +/** + * @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 { FirebaseInstallations } from '@firebase/installations-types-exp'; +import { FirebaseInstallations as FirebaseInstallationsCompat } from '@firebase/installations-types'; +import { FirebaseApp } from '@firebase/app-types'; +import { FirebaseService } from '@firebase/app-types/private'; +import { + deleteInstallations, + getId, + getToken, + IdChangeCallbackFn, + IdChangeUnsubscribeFn, + onIdChange +} from '@firebase/installations-exp'; + +export class InstallationsCompat + implements FirebaseInstallationsCompat, FirebaseService { + constructor( + public app: FirebaseApp, + private _installations: FirebaseInstallations + ) {} + + getId(): Promise { + return getId(this._installations); + } + getToken(forceRefresh?: boolean): Promise { + return getToken(this._installations, forceRefresh); + } + delete(): Promise { + return deleteInstallations(this._installations); + } + onIdChange(callback: IdChangeCallbackFn): IdChangeUnsubscribeFn { + return onIdChange(this._installations, callback); + } +} diff --git a/packages-exp/installations-compat/src/testing/setup.ts b/packages-exp/installations-compat/src/testing/setup.ts new file mode 100644 index 00000000000..463089fa69b --- /dev/null +++ b/packages-exp/installations-compat/src/testing/setup.ts @@ -0,0 +1,26 @@ +/** + * @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 { use } from 'chai'; +import { restore } from 'sinon'; +import * as sinonChai from 'sinon-chai'; + +use(sinonChai); + +afterEach(async () => { + restore(); +}); diff --git a/packages-exp/installations-compat/src/testing/util.ts b/packages-exp/installations-compat/src/testing/util.ts new file mode 100644 index 00000000000..ad124e13236 --- /dev/null +++ b/packages-exp/installations-compat/src/testing/util.ts @@ -0,0 +1,55 @@ +/** + * @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-types'; +import { FirebaseInstallations } from '@firebase/installations-types-exp'; + +const appName = 'testApp'; +const apiKey = 'AIzaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaA'; +const projectId = 'fis-test-app'; +const appId = '1:777777777777:web:aaaaaaaaaaaaaaaa'; + +export function getFakeApp(): FirebaseApp { + return { + name: appName, + options: { + apiKey, + projectId, + authDomain: 'authDomain', + messagingSenderId: 'messagingSenderId', + databaseURL: 'databaseUrl', + storageBucket: 'storageBucket', + appId + }, + automaticDataCollectionEnabled: true, + delete: async () => {} + }; +} + +export function getFakeInstallations(): FirebaseInstallations { + return { + app: getFakeApp(), + appConfig: { + appName, + projectId, + apiKey, + appId + }, + platformLoggerProvider: null, + _delete: () => Promise.resolve() + }; +} diff --git a/packages-exp/installations-compat/tsconfig.json b/packages-exp/installations-compat/tsconfig.json new file mode 100644 index 00000000000..420eda97a1d --- /dev/null +++ b/packages-exp/installations-compat/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../config/tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "downlevelIteration": true, + "resolveJsonModule": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "exclude": ["dist/**/*"] +}