@firebase/installations
Advanced tools
Comparing version 0.1.6-0 to 0.1.6-canary.5856b9d
@@ -12,3 +12,3 @@ 'use strict'; | ||
var version = "0.1.6-0"; | ||
var version = "0.1.6-canary.5856b9d"; | ||
@@ -352,2 +352,3 @@ /** | ||
// that correspond to those versions to run, not only the last one. | ||
// eslint-disable-next-line default-case | ||
switch (upgradeDB.oldVersion) { | ||
@@ -370,6 +371,8 @@ case 0: | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).put(value, key); | ||
return [4 /*yield*/, tx.complete]; | ||
return [4 /*yield*/, tx.objectStore(OBJECT_STORE_NAME).put(value, key)]; | ||
case 2: | ||
_a.sent(); | ||
return [4 /*yield*/, tx.complete]; | ||
case 3: | ||
_a.sent(); | ||
return [2 /*return*/, value]; | ||
@@ -392,4 +395,9 @@ } | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
return [2 /*return*/, tx.complete]; | ||
return [4 /*yield*/, tx.objectStore(OBJECT_STORE_NAME).delete(key)]; | ||
case 2: | ||
_a.sent(); | ||
return [4 /*yield*/, tx.complete]; | ||
case 3: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
@@ -424,11 +432,14 @@ }); | ||
} | ||
if (newValue === undefined) { | ||
store.delete(key); | ||
} | ||
else { | ||
store.put(newValue, key); | ||
} | ||
return [4 /*yield*/, tx.complete]; | ||
if (!(newValue === undefined)) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, store.delete(key)]; | ||
case 3: | ||
_a.sent(); | ||
return [3 /*break*/, 6]; | ||
case 4: return [4 /*yield*/, store.put(newValue, key)]; | ||
case 5: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: return [4 /*yield*/, tx.complete]; | ||
case 7: | ||
_a.sent(); | ||
return [2 /*return*/, newValue]; | ||
@@ -644,38 +655,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) { | ||
@@ -735,47 +710,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; | ||
@@ -961,2 +899,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) { | ||
@@ -963,0 +1002,0 @@ return tslib_1.__awaiter(this, void 0, void 0, function () { |
@@ -7,3 +7,3 @@ import firebase from '@firebase/app'; | ||
var version = "0.1.6-0"; | ||
var version = "0.1.6-canary.5856b9d"; | ||
@@ -347,2 +347,3 @@ /** | ||
// that correspond to those versions to run, not only the last one. | ||
// eslint-disable-next-line default-case | ||
switch (upgradeDB.oldVersion) { | ||
@@ -365,6 +366,8 @@ case 0: | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).put(value, key); | ||
return [4 /*yield*/, tx.complete]; | ||
return [4 /*yield*/, tx.objectStore(OBJECT_STORE_NAME).put(value, key)]; | ||
case 2: | ||
_a.sent(); | ||
return [4 /*yield*/, tx.complete]; | ||
case 3: | ||
_a.sent(); | ||
return [2 /*return*/, value]; | ||
@@ -387,4 +390,9 @@ } | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
return [2 /*return*/, tx.complete]; | ||
return [4 /*yield*/, tx.objectStore(OBJECT_STORE_NAME).delete(key)]; | ||
case 2: | ||
_a.sent(); | ||
return [4 /*yield*/, tx.complete]; | ||
case 3: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
@@ -419,11 +427,14 @@ }); | ||
} | ||
if (newValue === undefined) { | ||
store.delete(key); | ||
} | ||
else { | ||
store.put(newValue, key); | ||
} | ||
return [4 /*yield*/, tx.complete]; | ||
if (!(newValue === undefined)) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, store.delete(key)]; | ||
case 3: | ||
_a.sent(); | ||
return [3 /*break*/, 6]; | ||
case 4: return [4 /*yield*/, store.put(newValue, key)]; | ||
case 5: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: return [4 /*yield*/, tx.complete]; | ||
case 7: | ||
_a.sent(); | ||
return [2 /*return*/, newValue]; | ||
@@ -639,38 +650,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) { | ||
@@ -730,47 +705,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; | ||
@@ -956,2 +894,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) { | ||
@@ -958,0 +997,0 @@ return __awaiter(this, void 0, void 0, function () { |
@@ -5,3 +5,3 @@ import firebase from '@firebase/app'; | ||
const version = "0.1.6-0"; | ||
const version = "0.1.6-canary.5856b9d"; | ||
@@ -312,2 +312,3 @@ /** | ||
// that correspond to those versions to run, not only the last one. | ||
// eslint-disable-next-line default-case | ||
switch (upgradeDB.oldVersion) { | ||
@@ -323,3 +324,3 @@ case 0: | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).put(value, key); | ||
await tx.objectStore(OBJECT_STORE_NAME).put(value, key); | ||
await tx.complete; | ||
@@ -333,4 +334,4 @@ return value; | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
return tx.complete; | ||
await tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
await tx.complete; | ||
} | ||
@@ -354,6 +355,6 @@ /** | ||
if (newValue === undefined) { | ||
store.delete(key); | ||
await store.delete(key); | ||
} | ||
else { | ||
store.put(newValue, key); | ||
await store.put(newValue, key); | ||
} | ||
@@ -525,28 +526,2 @@ await tx.complete; | ||
*/ | ||
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) { | ||
@@ -595,21 +570,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; | ||
@@ -748,2 +711,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) { | ||
@@ -750,0 +779,0 @@ const endpoint = getDeleteEndpoint(appConfig, installationEntry); |
{ | ||
"name": "@firebase/installations", | ||
"version": "0.1.6-0", | ||
"version": "0.1.6-canary.5856b9d", | ||
"main": "dist/index.cjs.js", | ||
@@ -11,2 +11,4 @@ "module": "dist/index.esm.js", | ||
"scripts": { | ||
"lint": "eslint -c .eslintrc.json '**/*.ts' --ignore-path '../../.gitignore'", | ||
"lint:fix": "eslint --fix -c .eslintrc.json '**/*.ts'", | ||
"build": "rollup -c", | ||
@@ -17,4 +19,2 @@ "test": "yarn type-check && yarn test:karma && yarn lint", | ||
"type-check": "tsc -p . --noEmit", | ||
"lint": "tslint --project .", | ||
"lint:fix": "yarn lint --fix && prettier --write 'src/**/*.ts'", | ||
"serve": "yarn serve:build && yarn serve:host", | ||
@@ -44,14 +44,16 @@ "serve:build": "rollup -c test-app/rollup.config.js", | ||
"tslint": "5.16.0", | ||
"tslint-config-prettier": "1.18.0", | ||
"tslint-no-unused-expression-chai": "0.1.4", | ||
"tslint-plugin-prettier": "2.0.1", | ||
"typescript": "3.4.5" | ||
"typescript": "3.4.5", | ||
"eslint": "5.16.0", | ||
"@typescript-eslint/parser": "1.10.2", | ||
"@typescript-eslint/eslint-plugin": "1.10.2", | ||
"@typescript-eslint/eslint-plugin-tslint": "1.10.2", | ||
"eslint-plugin-import": "2.17.3" | ||
}, | ||
"peerDependencies": { | ||
"@firebase/app": "0.x", | ||
"@firebase/app-types": "0.x" | ||
"@firebase/app": "0.4.5-canary.5856b9d", | ||
"@firebase/app-types": "0.4.0-canary.5856b9d" | ||
}, | ||
"dependencies": { | ||
"@firebase/installations-types": "0.1.1", | ||
"@firebase/util": "0.2.19-0", | ||
"@firebase/installations-types": "0.1.1-canary.5856b9d", | ||
"@firebase/util": "0.2.19-canary.5856b9d", | ||
"idb": "3.0.2", | ||
@@ -58,0 +60,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; | ||
} |
@@ -102,2 +102,3 @@ /** | ||
// Finish pending request after 500 ms | ||
// tslint:disable-next-line:no-floating-promises | ||
sleep(500).then(async () => { | ||
@@ -113,3 +114,3 @@ const updatedEntry: RegisteredInstallationEntry = { | ||
}; | ||
set(appConfig, updatedEntry); | ||
await set(appConfig, updatedEntry); | ||
}); | ||
@@ -144,2 +145,3 @@ } | ||
// Finish pending request after 500 ms | ||
// tslint:disable-next-line:no-floating-promises | ||
sleep(500).then(async () => { | ||
@@ -157,3 +159,3 @@ const updatedEntry: RegisteredInstallationEntry = { | ||
}; | ||
set(appConfig, updatedEntry); | ||
await set(appConfig, updatedEntry); | ||
}); | ||
@@ -301,3 +303,3 @@ } | ||
it('does not call generateAuthToken on subsequent calls', async () => { | ||
it('does not call generateAuthToken twice on subsequent calls', async () => { | ||
await getToken(app); | ||
@@ -308,2 +310,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 () => { | ||
@@ -310,0 +317,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() | ||
); | ||
} |
@@ -38,3 +38,2 @@ /** | ||
it('throws if a necessary value is missing', () => { | ||
// tslint:disable-next-line:no-any | ||
expect(() => extractAppConfig(undefined as any)).to.throw(FirebaseError); | ||
@@ -41,0 +40,0 @@ |
@@ -38,3 +38,3 @@ /** | ||
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], | ||
] | ||
]; | ||
@@ -41,0 +41,0 @@ /** The FIDs that should be generated based on MOCK_RANDOM_VALUES. */ |
@@ -33,2 +33,3 @@ /** | ||
// that correspond to those versions to run, not only the last one. | ||
// eslint-disable-next-line default-case | ||
switch (upgradeDB.oldVersion) { | ||
@@ -59,3 +60,3 @@ case 0: | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).put(value, key); | ||
await tx.objectStore(OBJECT_STORE_NAME).put(value, key); | ||
await tx.complete; | ||
@@ -70,4 +71,4 @@ return value; | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
return tx.complete; | ||
await tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
await tx.complete; | ||
} | ||
@@ -97,5 +98,5 @@ | ||
if (newValue === undefined) { | ||
store.delete(key); | ||
await store.delete(key); | ||
} else { | ||
store.put(newValue, key); | ||
await store.put(newValue, key); | ||
} | ||
@@ -110,4 +111,4 @@ | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
tx.objectStore(OBJECT_STORE_NAME).clear(); | ||
return tx.complete; | ||
await tx.objectStore(OBJECT_STORE_NAME).clear(); | ||
await tx.complete; | ||
} | ||
@@ -114,0 +115,0 @@ |
@@ -37,3 +37,3 @@ /** | ||
// This won't be used in tests. | ||
// tslint:disable-next-line:no-any | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
installations: null as any | ||
@@ -40,0 +40,0 @@ }; |
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
669134
24
267
38
7470
+ Added@firebase/app@0.4.5-canary.5856b9d(transitive)
+ Added@firebase/app-types@0.4.0-canary.5856b9d(transitive)
+ Added@firebase/installations-types@0.1.1-canary.5856b9d(transitive)
+ Added@firebase/logger@0.1.16-canary.5856b9d(transitive)
+ Added@firebase/util@0.2.19-canary.5856b9d(transitive)
+ Addeddom-storage@2.1.0(transitive)
+ Addedxmlhttprequest@1.8.0(transitive)
- Removed@firebase/app@0.10.17(transitive)
- Removed@firebase/app-types@0.9.3(transitive)
- Removed@firebase/component@0.6.11(transitive)
- Removed@firebase/installations-types@0.1.1(transitive)
- Removed@firebase/logger@0.4.4(transitive)
- Removed@firebase/util@0.2.19-01.10.2(transitive)
- Removedidb@7.1.1(transitive)
- Removedtslib@2.8.1(transitive)