@firebase/installations
Advanced tools
Comparing version 0.1.5-canary.d164cac to 0.1.5-canary.dd098c6
@@ -12,3 +12,3 @@ 'use strict'; | ||
var version = "0.1.5-canary.d164cac"; | ||
var version = "0.1.5-canary.dd098c6"; | ||
@@ -640,38 +640,2 @@ /** | ||
*/ | ||
function getId(app) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var appConfig, _a, installationEntry, registrationPromise; | ||
return tslib_1.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (registrationPromise) { | ||
// Suppress registration errors as they are not a problem for getId. | ||
registrationPromise.catch(function () { }); | ||
} | ||
return [2 /*return*/, installationEntry.fid]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
function generateAuthToken(appConfig, installationEntry) { | ||
@@ -731,47 +695,10 @@ return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
*/ | ||
function getToken(app) { | ||
/** | ||
* Returns a valid authentication token for the installation. Generates a new | ||
* token if one doesn't exist, is expired or about to expire. | ||
* | ||
* Should only be called if the Firebase Installation is registered. | ||
*/ | ||
function refreshAuthToken(appConfig) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var appConfig; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, completeInstallationRegistration(appConfig)]; | ||
case 1: | ||
_a.sent(); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
return [2 /*return*/, fetchAuthToken(appConfig)]; | ||
} | ||
}); | ||
}); | ||
} | ||
function completeInstallationRegistration(appConfig) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var _a, installationEntry, registrationPromise; | ||
return tslib_1.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (!registrationPromise) return [3 /*break*/, 3]; | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
return [4 /*yield*/, registrationPromise]; | ||
case 2: | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
_b.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
if (installationEntry.registrationStatus !== 2 /* COMPLETED */) { | ||
// Installation ID can't be registered. | ||
throw ERROR_FACTORY.create("create-installation-failed" /* CREATE_INSTALLATION_FAILED */); | ||
} | ||
_b.label = 4; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
function fetchAuthToken(appConfig) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var tokenPromise, entry, authToken, _a; | ||
@@ -957,2 +884,103 @@ return tslib_1.__generator(this, function (_b) { | ||
*/ | ||
function getId(app) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var appConfig, _a, installationEntry, registrationPromise; | ||
return tslib_1.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (registrationPromise) { | ||
// Suppress registration errors as they are not a problem for getId. | ||
registrationPromise.catch(function () { }); | ||
} | ||
if (installationEntry.registrationStatus === 2 /* COMPLETED */) { | ||
// If the installation is already registered, update the authentication | ||
// token if needed. Suppress errors as they are not relevant to getId. | ||
refreshAuthToken(appConfig).catch(function () { }); | ||
} | ||
return [2 /*return*/, installationEntry.fid]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
function getToken(app) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var appConfig; | ||
return tslib_1.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, completeInstallationRegistration(appConfig)]; | ||
case 1: | ||
_a.sent(); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
return [2 /*return*/, refreshAuthToken(appConfig)]; | ||
} | ||
}); | ||
}); | ||
} | ||
function completeInstallationRegistration(appConfig) { | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var _a, installationEntry, registrationPromise; | ||
return tslib_1.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (!registrationPromise) return [3 /*break*/, 3]; | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
return [4 /*yield*/, registrationPromise]; | ||
case 2: | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
_b.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
if (installationEntry.registrationStatus !== 2 /* COMPLETED */) { | ||
// Installation ID can't be registered. | ||
throw ERROR_FACTORY.create("create-installation-failed" /* CREATE_INSTALLATION_FAILED */); | ||
} | ||
_b.label = 4; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
function deleteInstallation(appConfig, installationEntry) { | ||
@@ -959,0 +987,0 @@ return tslib_1.__awaiter(this, void 0, void 0, function () { |
@@ -7,3 +7,3 @@ import firebase from '@firebase/app'; | ||
var version = "0.1.5-canary.d164cac"; | ||
var version = "0.1.5-canary.dd098c6"; | ||
@@ -635,38 +635,2 @@ /** | ||
*/ | ||
function getId(app) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var appConfig, _a, installationEntry, registrationPromise; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (registrationPromise) { | ||
// Suppress registration errors as they are not a problem for getId. | ||
registrationPromise.catch(function () { }); | ||
} | ||
return [2 /*return*/, installationEntry.fid]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
function generateAuthToken(appConfig, installationEntry) { | ||
@@ -726,47 +690,10 @@ return __awaiter(this, void 0, void 0, function () { | ||
*/ | ||
function getToken(app) { | ||
/** | ||
* Returns a valid authentication token for the installation. Generates a new | ||
* token if one doesn't exist, is expired or about to expire. | ||
* | ||
* Should only be called if the Firebase Installation is registered. | ||
*/ | ||
function refreshAuthToken(appConfig) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var appConfig; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, completeInstallationRegistration(appConfig)]; | ||
case 1: | ||
_a.sent(); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
return [2 /*return*/, fetchAuthToken(appConfig)]; | ||
} | ||
}); | ||
}); | ||
} | ||
function completeInstallationRegistration(appConfig) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, installationEntry, registrationPromise; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (!registrationPromise) return [3 /*break*/, 3]; | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
return [4 /*yield*/, registrationPromise]; | ||
case 2: | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
_b.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
if (installationEntry.registrationStatus !== 2 /* COMPLETED */) { | ||
// Installation ID can't be registered. | ||
throw ERROR_FACTORY.create("create-installation-failed" /* CREATE_INSTALLATION_FAILED */); | ||
} | ||
_b.label = 4; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
function fetchAuthToken(appConfig) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var tokenPromise, entry, authToken, _a; | ||
@@ -952,2 +879,103 @@ return __generator(this, function (_b) { | ||
*/ | ||
function getId(app) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var appConfig, _a, installationEntry, registrationPromise; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (registrationPromise) { | ||
// Suppress registration errors as they are not a problem for getId. | ||
registrationPromise.catch(function () { }); | ||
} | ||
if (installationEntry.registrationStatus === 2 /* COMPLETED */) { | ||
// If the installation is already registered, update the authentication | ||
// token if needed. Suppress errors as they are not relevant to getId. | ||
refreshAuthToken(appConfig).catch(function () { }); | ||
} | ||
return [2 /*return*/, installationEntry.fid]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
function getToken(app) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var appConfig; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
appConfig = extractAppConfig(app); | ||
return [4 /*yield*/, completeInstallationRegistration(appConfig)]; | ||
case 1: | ||
_a.sent(); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
return [2 /*return*/, refreshAuthToken(appConfig)]; | ||
} | ||
}); | ||
}); | ||
} | ||
function completeInstallationRegistration(appConfig) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, installationEntry, registrationPromise; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, getInstallationEntry(appConfig)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (!registrationPromise) return [3 /*break*/, 3]; | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
return [4 /*yield*/, registrationPromise]; | ||
case 2: | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
_b.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
if (installationEntry.registrationStatus !== 2 /* COMPLETED */) { | ||
// Installation ID can't be registered. | ||
throw ERROR_FACTORY.create("create-installation-failed" /* CREATE_INSTALLATION_FAILED */); | ||
} | ||
_b.label = 4; | ||
case 4: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
function deleteInstallation(appConfig, installationEntry) { | ||
@@ -954,0 +982,0 @@ return __awaiter(this, void 0, void 0, function () { |
@@ -5,3 +5,3 @@ import firebase from '@firebase/app'; | ||
const version = "0.1.5-canary.d164cac"; | ||
const version = "0.1.5-canary.dd098c6"; | ||
@@ -521,28 +521,2 @@ /** | ||
*/ | ||
async function getId(app) { | ||
const appConfig = extractAppConfig(app); | ||
const { installationEntry, registrationPromise } = await getInstallationEntry(appConfig); | ||
if (registrationPromise) { | ||
// Suppress registration errors as they are not a problem for getId. | ||
registrationPromise.catch(() => { }); | ||
} | ||
return installationEntry.fid; | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
async function generateAuthToken(appConfig, installationEntry) { | ||
@@ -591,21 +565,9 @@ const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry); | ||
*/ | ||
async function getToken(app) { | ||
const appConfig = extractAppConfig(app); | ||
await completeInstallationRegistration(appConfig); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
return fetchAuthToken(appConfig); | ||
} | ||
async function completeInstallationRegistration(appConfig) { | ||
const { installationEntry, registrationPromise } = await getInstallationEntry(appConfig); | ||
if (registrationPromise) { | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
await registrationPromise; | ||
} | ||
else if (installationEntry.registrationStatus !== 2 /* COMPLETED */) { | ||
// Installation ID can't be registered. | ||
throw ERROR_FACTORY.create("create-installation-failed" /* CREATE_INSTALLATION_FAILED */); | ||
} | ||
} | ||
async function fetchAuthToken(appConfig) { | ||
/** | ||
* Returns a valid authentication token for the installation. Generates a new | ||
* token if one doesn't exist, is expired or about to expire. | ||
* | ||
* Should only be called if the Firebase Installation is registered. | ||
*/ | ||
async function refreshAuthToken(appConfig) { | ||
let tokenPromise; | ||
@@ -744,2 +706,68 @@ const entry = await update(appConfig, (oldEntry) => { | ||
*/ | ||
async function getId(app) { | ||
const appConfig = extractAppConfig(app); | ||
const { installationEntry, registrationPromise } = await getInstallationEntry(appConfig); | ||
if (registrationPromise) { | ||
// Suppress registration errors as they are not a problem for getId. | ||
registrationPromise.catch(() => { }); | ||
} | ||
if (installationEntry.registrationStatus === 2 /* COMPLETED */) { | ||
// If the installation is already registered, update the authentication | ||
// token if needed. Suppress errors as they are not relevant to getId. | ||
refreshAuthToken(appConfig).catch(() => { }); | ||
} | ||
return installationEntry.fid; | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
async function getToken(app) { | ||
const appConfig = extractAppConfig(app); | ||
await completeInstallationRegistration(appConfig); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
return refreshAuthToken(appConfig); | ||
} | ||
async function completeInstallationRegistration(appConfig) { | ||
const { installationEntry, registrationPromise } = await getInstallationEntry(appConfig); | ||
if (registrationPromise) { | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
await registrationPromise; | ||
} | ||
else if (installationEntry.registrationStatus !== 2 /* COMPLETED */) { | ||
// Installation ID can't be registered. | ||
throw ERROR_FACTORY.create("create-installation-failed" /* CREATE_INSTALLATION_FAILED */); | ||
} | ||
} | ||
/** | ||
* @license | ||
* Copyright 2019 Google Inc. | ||
* | ||
* 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. | ||
*/ | ||
async function deleteInstallation(appConfig, installationEntry) { | ||
@@ -746,0 +774,0 @@ const endpoint = getDeleteEndpoint(appConfig, installationEntry); |
{ | ||
"name": "@firebase/installations", | ||
"version": "0.1.5-canary.d164cac", | ||
"version": "0.1.5-canary.dd098c6", | ||
"main": "dist/index.cjs.js", | ||
@@ -48,8 +48,8 @@ "module": "dist/index.esm.js", | ||
"peerDependencies": { | ||
"@firebase/app": "0.4.4-canary.d164cac", | ||
"@firebase/app-types": "0.4.0-canary.d164cac" | ||
"@firebase/app": "0.4.4-canary.dd098c6", | ||
"@firebase/app-types": "0.4.0-canary.dd098c6" | ||
}, | ||
"dependencies": { | ||
"@firebase/installations-types": "0.1.1-canary.d164cac", | ||
"@firebase/util": "0.2.18-canary.d164cac", | ||
"@firebase/installations-types": "0.1.1-canary.dd098c6", | ||
"@firebase/util": "0.2.18-canary.dd098c6", | ||
"idb": "3.0.2", | ||
@@ -56,0 +56,0 @@ "tslib": "1.9.3" |
@@ -21,2 +21,3 @@ /** | ||
import * as getInstallationEntryModule from '../helpers/get-installation-entry'; | ||
import * as refreshAuthTokenModule from '../helpers/refresh-auth-token'; | ||
import { AppConfig } from '../interfaces/app-config'; | ||
@@ -40,3 +41,7 @@ import { RequestStatus } from '../interfaces/installation-entry'; | ||
'getInstallationEntry' | ||
).resolves({ | ||
); | ||
}); | ||
it('returns the FID in InstallationEntry returned by getInstallationEntry', async () => { | ||
getInstallationEntrySpy.resolves({ | ||
installationEntry: { | ||
@@ -47,5 +52,3 @@ fid: FID, | ||
}); | ||
}); | ||
it('returns the FID in InstallationEntry returned by getInstallationEntry', async () => { | ||
const firebaseApp = getFakeApp(); | ||
@@ -56,2 +59,24 @@ const fid = await getId(firebaseApp); | ||
}); | ||
it('calls refreshAuthToken if the installation is registered', async () => { | ||
getInstallationEntrySpy.resolves({ | ||
installationEntry: { | ||
fid: FID, | ||
registrationStatus: RequestStatus.COMPLETED, | ||
refreshToken: 'refreshToken', | ||
authToken: { | ||
requestStatus: RequestStatus.NOT_STARTED | ||
} | ||
} | ||
}); | ||
const refreshAuthTokenSpy = stub( | ||
refreshAuthTokenModule, | ||
'refreshAuthToken' | ||
).resolves('authToken'); | ||
const firebaseApp = getFakeApp(); | ||
await getId(firebaseApp); | ||
expect(refreshAuthTokenSpy).to.be.calledOnce; | ||
}); | ||
}); |
@@ -21,2 +21,4 @@ /** | ||
import { getInstallationEntry } from '../helpers/get-installation-entry'; | ||
import { refreshAuthToken } from '../helpers/refresh-auth-token'; | ||
import { RequestStatus } from '../interfaces/installation-entry'; | ||
@@ -28,2 +30,3 @@ export async function getId(app: FirebaseApp): Promise<string> { | ||
); | ||
if (registrationPromise) { | ||
@@ -33,3 +36,10 @@ // Suppress registration errors as they are not a problem for getId. | ||
} | ||
if (installationEntry.registrationStatus === RequestStatus.COMPLETED) { | ||
// If the installation is already registered, update the authentication | ||
// token if needed. Suppress errors as they are not relevant to getId. | ||
refreshAuthToken(appConfig).catch(() => {}); | ||
} | ||
return installationEntry.fid; | ||
} |
@@ -297,3 +297,3 @@ /** | ||
it('does not call generateAuthToken on subsequent calls', async () => { | ||
it('does not call generateAuthToken twice on subsequent calls', async () => { | ||
await getToken(app); | ||
@@ -304,2 +304,7 @@ await getToken(app); | ||
it('does not call generateAuthToken twice on simultaneous calls', async () => { | ||
await Promise.all([getToken(app), getToken(app)]); | ||
expect(generateAuthTokenSpy).to.be.calledOnce; | ||
}); | ||
it('throws if the app is offline', async () => { | ||
@@ -306,0 +311,0 @@ stub(navigator, 'onLine').value(false); |
@@ -19,18 +19,8 @@ /** | ||
import { FirebaseApp } from '@firebase/app-types'; | ||
import { generateAuthToken } from '../api/generate-auth-token'; | ||
import { extractAppConfig } from '../helpers/extract-app-config'; | ||
import { getInstallationEntry } from '../helpers/get-installation-entry'; | ||
import { remove, set, update } from '../helpers/idb-manager'; | ||
import { refreshAuthToken } from '../helpers/refresh-auth-token'; | ||
import { AppConfig } from '../interfaces/app-config'; | ||
import { | ||
AuthToken, | ||
CompletedAuthToken, | ||
InProgressAuthToken, | ||
InstallationEntry, | ||
RegisteredInstallationEntry, | ||
RequestStatus | ||
} from '../interfaces/installation-entry'; | ||
import { PENDING_TIMEOUT_MS, TOKEN_EXPIRATION_BUFFER } from '../util/constants'; | ||
import { ERROR_FACTORY, ErrorCode, isServerError } from '../util/errors'; | ||
import { sleep } from '../util/sleep'; | ||
import { RequestStatus } from '../interfaces/installation-entry'; | ||
import { ERROR_FACTORY, ErrorCode } from '../util/errors'; | ||
@@ -44,3 +34,3 @@ export async function getToken(app: FirebaseApp): Promise<string> { | ||
// already thrown an error. | ||
return fetchAuthToken(appConfig); | ||
return refreshAuthToken(appConfig); | ||
} | ||
@@ -63,167 +53,1 @@ | ||
} | ||
async function fetchAuthToken(appConfig: AppConfig): Promise<string> { | ||
let tokenPromise: Promise<CompletedAuthToken> | undefined; | ||
const entry = await update( | ||
appConfig, | ||
(oldEntry?: InstallationEntry): RegisteredInstallationEntry => { | ||
if (!isEntryRegistered(oldEntry)) { | ||
throw ERROR_FACTORY.create(ErrorCode.NOT_REGISTERED); | ||
} | ||
const oldAuthToken = oldEntry.authToken; | ||
if (isAuthTokenValid(oldAuthToken)) { | ||
// There is a valid token in the DB. | ||
return oldEntry; | ||
} else if (oldAuthToken.requestStatus === RequestStatus.IN_PROGRESS) { | ||
// There already is a token request in progress. | ||
tokenPromise = waitUntilAuthTokenRequest(appConfig); | ||
return oldEntry; | ||
} else { | ||
// No token or token expired. | ||
if (!navigator.onLine) { | ||
throw ERROR_FACTORY.create(ErrorCode.APP_OFFLINE); | ||
} | ||
const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry); | ||
tokenPromise = fetchAuthTokenFromServer(appConfig, inProgressEntry); | ||
return inProgressEntry; | ||
} | ||
} | ||
); | ||
const authToken: CompletedAuthToken = tokenPromise | ||
? await tokenPromise | ||
: (entry.authToken as CompletedAuthToken); | ||
return authToken.token; | ||
} | ||
/** | ||
* Call only if FID is registered and Auth Token request is in progress. | ||
*/ | ||
async function waitUntilAuthTokenRequest( | ||
appConfig: AppConfig | ||
): Promise<CompletedAuthToken> { | ||
// Unfortunately, there is no way of reliably observing when a value in | ||
// IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers), | ||
// so we need to poll. | ||
let entry = await updateAuthTokenRequest(appConfig); | ||
while (entry.authToken.requestStatus === RequestStatus.IN_PROGRESS) { | ||
// generateAuthToken still in progress. | ||
await sleep(100); | ||
entry = await updateAuthTokenRequest(appConfig); | ||
} | ||
const authToken = entry.authToken; | ||
if (authToken.requestStatus === RequestStatus.NOT_STARTED) { | ||
throw ERROR_FACTORY.create(ErrorCode.GENERATE_TOKEN_FAILED); | ||
} else { | ||
return authToken; | ||
} | ||
} | ||
/** | ||
* Called only if there is a GenerateAuthToken request in progress. | ||
* | ||
* Updates the InstallationEntry in the DB based on the status of the | ||
* GenerateAuthToken request. | ||
* | ||
* Returns the updated InstallationEntry. | ||
*/ | ||
function updateAuthTokenRequest( | ||
appConfig: AppConfig | ||
): Promise<RegisteredInstallationEntry> { | ||
return update( | ||
appConfig, | ||
(oldEntry?: InstallationEntry): RegisteredInstallationEntry => { | ||
if (!isEntryRegistered(oldEntry)) { | ||
throw ERROR_FACTORY.create(ErrorCode.NOT_REGISTERED); | ||
} | ||
const oldAuthToken = oldEntry.authToken; | ||
if (hasAuthTokenRequestTimedOut(oldAuthToken)) { | ||
return { | ||
...oldEntry, | ||
authToken: { requestStatus: RequestStatus.NOT_STARTED } | ||
}; | ||
} | ||
return oldEntry; | ||
} | ||
); | ||
} | ||
async function fetchAuthTokenFromServer( | ||
appConfig: AppConfig, | ||
installationEntry: RegisteredInstallationEntry | ||
): Promise<CompletedAuthToken> { | ||
try { | ||
const authToken = await generateAuthToken(appConfig, installationEntry); | ||
const updatedInstallationEntry: RegisteredInstallationEntry = { | ||
...installationEntry, | ||
authToken | ||
}; | ||
await set(appConfig, updatedInstallationEntry); | ||
return authToken; | ||
} catch (e) { | ||
if (isServerError(e) && (e.serverCode === 401 || e.serverCode === 404)) { | ||
// Server returned a "FID not found" or a "Invalid authentication" error. | ||
// Generate a new ID next time. | ||
await remove(appConfig); | ||
} else { | ||
const updatedInstallationEntry: RegisteredInstallationEntry = { | ||
...installationEntry, | ||
authToken: { requestStatus: RequestStatus.NOT_STARTED } | ||
}; | ||
await set(appConfig, updatedInstallationEntry); | ||
} | ||
throw e; | ||
} | ||
} | ||
function isEntryRegistered( | ||
installationEntry: InstallationEntry | undefined | ||
): installationEntry is RegisteredInstallationEntry { | ||
return ( | ||
installationEntry !== undefined && | ||
installationEntry.registrationStatus === RequestStatus.COMPLETED | ||
); | ||
} | ||
function isAuthTokenValid(authToken: AuthToken): boolean { | ||
return ( | ||
authToken.requestStatus === RequestStatus.COMPLETED && | ||
!isAuthTokenExpired(authToken) | ||
); | ||
} | ||
function isAuthTokenExpired(authToken: CompletedAuthToken): boolean { | ||
const now = Date.now(); | ||
return ( | ||
now < authToken.creationTime || | ||
authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER | ||
); | ||
} | ||
/** Returns an updated InstallationEntry with an InProgressAuthToken. */ | ||
function makeAuthTokenRequestInProgressEntry( | ||
oldEntry: RegisteredInstallationEntry | ||
): RegisteredInstallationEntry { | ||
const inProgressAuthToken: InProgressAuthToken = { | ||
requestStatus: RequestStatus.IN_PROGRESS, | ||
requestTime: Date.now() | ||
}; | ||
return { | ||
...oldEntry, | ||
authToken: inProgressAuthToken | ||
}; | ||
} | ||
function hasAuthTokenRequestTimedOut(authToken: AuthToken): boolean { | ||
return ( | ||
authToken.requestStatus === RequestStatus.IN_PROGRESS && | ||
authToken.requestTime + PENDING_TIMEOUT_MS < Date.now() | ||
); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 35 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 33 instances in 1 package
666977
267
7467
38
+ Added@firebase/app@0.4.4-canary.dd098c6(transitive)
+ Added@firebase/app-types@0.4.0-canary.dd098c6(transitive)
+ Added@firebase/installations-types@0.1.1-canary.dd098c6(transitive)
+ Added@firebase/logger@0.1.15-canary.dd098c6(transitive)
+ Added@firebase/util@0.2.18-canary.dd098c6(transitive)
- Removed@firebase/app@0.4.4-canary.d164cac(transitive)
- Removed@firebase/app-types@0.4.0-canary.d164cac(transitive)
- Removed@firebase/installations-types@0.1.1-canary.d164cac(transitive)
- Removed@firebase/logger@0.1.15-canary.d164cac(transitive)
- Removed@firebase/util@0.2.18-canary.d164cac(transitive)