Skip to content

Commit 1bd1c08

Browse files
authored
Merge 9570f71 into 57739ae
2 parents 57739ae + 9570f71 commit 1bd1c08

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+4855
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* @license
3+
* Copyright 2020 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
module.exports = {
19+
extends: '../../config/.eslintrc.js',
20+
parserOptions: {
21+
project: 'tsconfig.json',
22+
// to make vscode-eslint work with monorepo
23+
// https://github.com/typescript-eslint/typescript-eslint/issues/251#issuecomment-463943250
24+
tsconfigRootDir: __dirname
25+
}
26+
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
const karmaBase = require('../../config/karma.base');
19+
20+
const files = [`src/**/*.test.ts`];
21+
22+
module.exports = function (config) {
23+
const karmaConfig = {
24+
...karmaBase,
25+
// files to load into karma
26+
files,
27+
// frameworks to use
28+
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
29+
frameworks: ['mocha']
30+
};
31+
32+
config.set(karmaConfig);
33+
};
34+
35+
module.exports.files = files;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"name": "@firebase/installations-exp",
3+
"version": "0.0.800",
4+
"private": true,
5+
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
6+
"main": "dist/index.cjs.js",
7+
"module": "dist/index.esm.js",
8+
"esm2017": "dist/index.esm2017.js",
9+
"types": "dist/src/index.d.ts",
10+
"license": "Apache-2.0",
11+
"files": [
12+
"dist"
13+
],
14+
"scripts": {
15+
"lint": "eslint -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'",
16+
"lint:fix": "eslint --fix -c .eslintrc.js '**/*.ts' --ignore-path '../../.gitignore'",
17+
"build": "rollup -c",
18+
"build:deps": "lerna run --scope @firebase/installations-exp --include-dependencies build",
19+
"dev": "rollup -c -w",
20+
"test": "yarn type-check && yarn test:karma && yarn lint",
21+
"test:ci": "node ../../scripts/run_tests_in_ci.js",
22+
"test:karma": "karma start --single-run",
23+
"test:debug": "karma start --browsers=Chrome --auto-watch",
24+
"type-check": "tsc -p . --noEmit",
25+
"serve": "yarn serve:build && yarn serve:host",
26+
"serve:build": "rollup -c test-app/rollup.config.js",
27+
"serve:host": "http-server -c-1 test-app",
28+
"prepare": "yarn build"
29+
},
30+
"repository": {
31+
"directory": "packages-exp/installations-exp",
32+
"type": "git",
33+
"url": "https://github.com/firebase/firebase-js-sdk.git"
34+
},
35+
"bugs": {
36+
"url": "https://github.com/firebase/firebase-js-sdk/issues"
37+
},
38+
"devDependencies": {
39+
"@firebase/app-exp": "0.0.800",
40+
"rollup": "2.26.5",
41+
"rollup-plugin-commonjs": "10.1.0",
42+
"rollup-plugin-json": "4.0.0",
43+
"rollup-plugin-node-resolve": "5.2.0",
44+
"rollup-plugin-typescript2": "0.27.1",
45+
"rollup-plugin-uglify": "6.0.4",
46+
"typescript": "4.0.2"
47+
},
48+
"peerDependencies": {
49+
"@firebase/app-exp": "0.x",
50+
"@firebase/app-types-exp": "0.x"
51+
},
52+
"dependencies": {
53+
"@firebase/installations-types-exp": "0.0.800",
54+
"@firebase/util": "0.3.1",
55+
"@firebase/component": "0.1.18",
56+
"idb": "3.0.2",
57+
"tslib": "^1.11.1"
58+
}
59+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import json from 'rollup-plugin-json';
19+
import typescriptPlugin from 'rollup-plugin-typescript2';
20+
import pkg from './package.json';
21+
import typescript from 'typescript';
22+
23+
const deps = Object.keys({ ...pkg.peerDependencies, ...pkg.dependencies });
24+
25+
/**
26+
* ES5 Builds
27+
*/
28+
const es5BuildPlugins = [typescriptPlugin({ typescript }), json()];
29+
30+
const es5Builds = [
31+
{
32+
input: 'src/index.ts',
33+
output: [
34+
{ file: pkg.main, format: 'cjs', sourcemap: true },
35+
{ file: pkg.module, format: 'es', sourcemap: true }
36+
],
37+
plugins: es5BuildPlugins,
38+
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
39+
}
40+
];
41+
42+
/**
43+
* ES2017 Builds
44+
*/
45+
const es2017BuildPlugins = [
46+
typescriptPlugin({
47+
typescript,
48+
tsconfigOverride: {
49+
compilerOptions: {
50+
target: 'es2017'
51+
}
52+
}
53+
}),
54+
json({ preferConst: true })
55+
];
56+
57+
const es2017Builds = [
58+
{
59+
input: 'src/index.ts',
60+
output: {
61+
file: pkg.esm2017,
62+
format: 'es',
63+
sourcemap: true
64+
},
65+
plugins: es2017BuildPlugins,
66+
external: id => deps.some(dep => id === dep || id.startsWith(`${dep}/`))
67+
}
68+
];
69+
70+
export default [...es5Builds, ...es2017Builds];
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { expect } from 'chai';
19+
import { SinonStub, stub } from 'sinon';
20+
import * as deleteInstallationRequestModule from '../functions/delete-installation-request';
21+
import { get, set } from '../helpers/idb-manager';
22+
import {
23+
FirebaseInstallations,
24+
AppConfig
25+
} from '@firebase/installations-types-exp';
26+
import {
27+
InProgressInstallationEntry,
28+
RegisteredInstallationEntry,
29+
RequestStatus,
30+
UnregisteredInstallationEntry
31+
} from '../interfaces/installation-entry';
32+
import { getFakeInstallations } from '../testing/fake-generators';
33+
import '../testing/setup';
34+
import { ErrorCode } from '../util/errors';
35+
import { sleep } from '../util/sleep';
36+
import { deleteInstallation } from './delete-installation';
37+
38+
const FID = 'children-of-the-damned';
39+
40+
describe('deleteInstallation', () => {
41+
let installations: FirebaseInstallations;
42+
let deleteInstallationRequestSpy: SinonStub<
43+
[AppConfig, RegisteredInstallationEntry],
44+
Promise<void>
45+
>;
46+
47+
beforeEach(() => {
48+
installations = getFakeInstallations();
49+
50+
deleteInstallationRequestSpy = stub(
51+
deleteInstallationRequestModule,
52+
'deleteInstallationRequest'
53+
).callsFake(
54+
() => sleep(100) // Request would take some time
55+
);
56+
});
57+
58+
it('resolves without calling server API if there is no installation', async () => {
59+
await expect(deleteInstallation(installations)).to.be.fulfilled;
60+
expect(deleteInstallationRequestSpy).not.to.have.been.called;
61+
});
62+
63+
it('deletes and resolves without calling server API if the installation is unregistered', async () => {
64+
const entry: UnregisteredInstallationEntry = {
65+
registrationStatus: RequestStatus.NOT_STARTED,
66+
fid: FID
67+
};
68+
await set(installations.appConfig, entry);
69+
70+
await expect(deleteInstallation(installations)).to.be.fulfilled;
71+
expect(deleteInstallationRequestSpy).not.to.have.been.called;
72+
await expect(get(installations.appConfig)).to.eventually.be.undefined;
73+
});
74+
75+
it('rejects without calling server API if the installation is pending', async () => {
76+
const entry: InProgressInstallationEntry = {
77+
fid: FID,
78+
registrationStatus: RequestStatus.IN_PROGRESS,
79+
registrationTime: Date.now() - 3 * 1000
80+
};
81+
await set(installations.appConfig, entry);
82+
83+
await expect(deleteInstallation(installations)).to.be.rejectedWith(
84+
ErrorCode.DELETE_PENDING_REGISTRATION
85+
);
86+
expect(deleteInstallationRequestSpy).not.to.have.been.called;
87+
});
88+
89+
it('rejects without calling server API if the installation is registered and app is offline', async () => {
90+
const entry: RegisteredInstallationEntry = {
91+
fid: FID,
92+
registrationStatus: RequestStatus.COMPLETED,
93+
refreshToken: 'refreshToken',
94+
authToken: {
95+
token: 'authToken',
96+
expiresIn: 123456,
97+
requestStatus: RequestStatus.COMPLETED,
98+
creationTime: Date.now()
99+
}
100+
};
101+
await set(installations.appConfig, entry);
102+
stub(navigator, 'onLine').value(false);
103+
104+
await expect(deleteInstallation(installations)).to.be.rejectedWith(
105+
ErrorCode.APP_OFFLINE
106+
);
107+
expect(deleteInstallationRequestSpy).not.to.have.been.called;
108+
});
109+
110+
it('deletes and resolves after calling server API if the installation is registered', async () => {
111+
const entry: RegisteredInstallationEntry = {
112+
fid: FID,
113+
registrationStatus: RequestStatus.COMPLETED,
114+
refreshToken: 'refreshToken',
115+
authToken: {
116+
token: 'authToken',
117+
expiresIn: 123456,
118+
requestStatus: RequestStatus.COMPLETED,
119+
creationTime: Date.now()
120+
}
121+
};
122+
await set(installations.appConfig, entry);
123+
124+
await expect(deleteInstallation(installations)).to.be.fulfilled;
125+
expect(deleteInstallationRequestSpy).to.have.been.calledOnceWith(
126+
installations.appConfig,
127+
entry
128+
);
129+
await expect(get(installations.appConfig)).to.eventually.be.undefined;
130+
});
131+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google LLC
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { deleteInstallationRequest } from '../functions/delete-installation-request';
19+
import { remove, update } from '../helpers/idb-manager';
20+
import { RequestStatus } from '../interfaces/installation-entry';
21+
import { ERROR_FACTORY, ErrorCode } from '../util/errors';
22+
import { FirebaseInstallations } from '@firebase/installations-types-exp';
23+
24+
export async function deleteInstallation(
25+
installations: FirebaseInstallations
26+
): Promise<void> {
27+
const { appConfig } = installations;
28+
29+
const entry = await update(appConfig, oldEntry => {
30+
if (oldEntry && oldEntry.registrationStatus === RequestStatus.NOT_STARTED) {
31+
// Delete the unregistered entry without sending a deleteInstallation request.
32+
return undefined;
33+
}
34+
return oldEntry;
35+
});
36+
37+
if (entry) {
38+
if (entry.registrationStatus === RequestStatus.IN_PROGRESS) {
39+
// Can't delete while trying to register.
40+
throw ERROR_FACTORY.create(ErrorCode.DELETE_PENDING_REGISTRATION);
41+
} else if (entry.registrationStatus === RequestStatus.COMPLETED) {
42+
if (!navigator.onLine) {
43+
throw ERROR_FACTORY.create(ErrorCode.APP_OFFLINE);
44+
} else {
45+
await deleteInstallationRequest(appConfig, entry);
46+
await remove(appConfig);
47+
}
48+
}
49+
}
50+
}

0 commit comments

Comments
 (0)