@firebase/installations
Advanced tools
Comparing version 0.6.9-canary.2e2804139 to 0.6.9-canary.479226bf3
@@ -7,3 +7,3 @@ import { _getProvider, getApp, _registerComponent, registerVersion } from '@firebase/app'; | ||
const name = "@firebase/installations"; | ||
const version = "0.6.9-canary.2e2804139"; | ||
const version = "0.6.9-canary.479226bf3"; | ||
@@ -1152,3 +1152,3 @@ /** | ||
registerVersion(name, version); | ||
// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation | ||
// BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation | ||
registerVersion(name, version, 'esm2017'); | ||
@@ -1155,0 +1155,0 @@ |
@@ -7,8 +7,7 @@ 'use strict'; | ||
var component = require('@firebase/component'); | ||
var tslib = require('tslib'); | ||
var util = require('@firebase/util'); | ||
var idb = require('idb'); | ||
var name = "@firebase/installations"; | ||
var version = "0.6.9-canary.2e2804139"; | ||
const name = "@firebase/installations"; | ||
const version = "0.6.9-canary.479226bf3"; | ||
@@ -31,9 +30,9 @@ /** | ||
*/ | ||
var PENDING_TIMEOUT_MS = 10000; | ||
var PACKAGE_VERSION = "w:".concat(version); | ||
var INTERNAL_AUTH_VERSION = 'FIS_v2'; | ||
var INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1'; | ||
var TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour | ||
var SERVICE = 'installations'; | ||
var SERVICE_NAME = 'Installations'; | ||
const PENDING_TIMEOUT_MS = 10000; | ||
const PACKAGE_VERSION = `w:${version}`; | ||
const INTERNAL_AUTH_VERSION = 'FIS_v2'; | ||
const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1'; | ||
const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour | ||
const SERVICE = 'installations'; | ||
const SERVICE_NAME = 'Installations'; | ||
@@ -56,12 +55,11 @@ /** | ||
*/ | ||
var _a; | ||
var ERROR_DESCRIPTION_MAP = (_a = {}, | ||
_a["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */] = 'Missing App configuration value: "{$valueName}"', | ||
_a["not-registered" /* ErrorCode.NOT_REGISTERED */] = 'Firebase Installation is not registered.', | ||
_a["installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */] = 'Firebase Installation not found.', | ||
_a["request-failed" /* ErrorCode.REQUEST_FAILED */] = '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"', | ||
_a["app-offline" /* ErrorCode.APP_OFFLINE */] = 'Could not process request. Application offline.', | ||
_a["delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */] = "Can't delete installation while there is a pending registration request.", | ||
_a); | ||
var ERROR_FACTORY = new util.ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP); | ||
const ERROR_DESCRIPTION_MAP = { | ||
["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"', | ||
["not-registered" /* ErrorCode.NOT_REGISTERED */]: 'Firebase Installation is not registered.', | ||
["installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.', | ||
["request-failed" /* ErrorCode.REQUEST_FAILED */]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"', | ||
["app-offline" /* ErrorCode.APP_OFFLINE */]: 'Could not process request. Application offline.', | ||
["delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */]: "Can't delete installation while there is a pending registration request." | ||
}; | ||
const ERROR_FACTORY = new util.ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP); | ||
/** Returns true if error is a FirebaseError that is based on an error from the server. */ | ||
@@ -89,5 +87,4 @@ function isServerError(error) { | ||
*/ | ||
function getInstallationsEndpoint(_a) { | ||
var projectId = _a.projectId; | ||
return "".concat(INSTALLATIONS_API_URL, "/projects/").concat(projectId, "/installations"); | ||
function getInstallationsEndpoint({ projectId }) { | ||
return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`; | ||
} | ||
@@ -102,23 +99,13 @@ function extractAuthTokenInfoFromResponse(response) { | ||
} | ||
function getErrorFromResponse(requestName, response) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var responseJson, errorData; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, response.json()]; | ||
case 1: | ||
responseJson = _a.sent(); | ||
errorData = responseJson.error; | ||
return [2 /*return*/, ERROR_FACTORY.create("request-failed" /* ErrorCode.REQUEST_FAILED */, { | ||
requestName: requestName, | ||
serverCode: errorData.code, | ||
serverMessage: errorData.message, | ||
serverStatus: errorData.status | ||
})]; | ||
} | ||
}); | ||
async function getErrorFromResponse(requestName, response) { | ||
const responseJson = await response.json(); | ||
const errorData = responseJson.error; | ||
return ERROR_FACTORY.create("request-failed" /* ErrorCode.REQUEST_FAILED */, { | ||
requestName, | ||
serverCode: errorData.code, | ||
serverMessage: errorData.message, | ||
serverStatus: errorData.status | ||
}); | ||
} | ||
function getHeaders(_a) { | ||
var apiKey = _a.apiKey; | ||
function getHeaders({ apiKey }) { | ||
return new Headers({ | ||
@@ -130,5 +117,4 @@ 'Content-Type': 'application/json', | ||
} | ||
function getHeadersWithAuth(appConfig, _a) { | ||
var refreshToken = _a.refreshToken; | ||
var headers = getHeaders(appConfig); | ||
function getHeadersWithAuth(appConfig, { refreshToken }) { | ||
const headers = getHeaders(appConfig); | ||
headers.append('Authorization', getAuthorizationHeader(refreshToken)); | ||
@@ -142,18 +128,9 @@ return headers; | ||
*/ | ||
function retryIfServerError(fn) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var result; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, fn()]; | ||
case 1: | ||
result = _a.sent(); | ||
if (result.status >= 500 && result.status < 600) { | ||
// Internal Server Error. Retry request. | ||
return [2 /*return*/, fn()]; | ||
} | ||
return [2 /*return*/, result]; | ||
} | ||
}); | ||
}); | ||
async function retryIfServerError(fn) { | ||
const result = await fn(); | ||
if (result.status >= 500 && result.status < 600) { | ||
// Internal Server Error. Retry request. | ||
return fn(); | ||
} | ||
return result; | ||
} | ||
@@ -165,3 +142,3 @@ function getExpiresInFromResponseExpiresIn(responseExpiresIn) { | ||
function getAuthorizationHeader(refreshToken) { | ||
return "".concat(INTERNAL_AUTH_VERSION, " ").concat(refreshToken); | ||
return `${INTERNAL_AUTH_VERSION} ${refreshToken}`; | ||
} | ||
@@ -185,54 +162,40 @@ | ||
*/ | ||
function createInstallationRequest(_a, _b) { | ||
var appConfig = _a.appConfig, heartbeatServiceProvider = _a.heartbeatServiceProvider; | ||
var fid = _b.fid; | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var endpoint, headers, heartbeatService, heartbeatsHeader, body, request, response, responseValue, registeredInstallationEntry; | ||
return tslib.__generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
endpoint = getInstallationsEndpoint(appConfig); | ||
headers = getHeaders(appConfig); | ||
heartbeatService = heartbeatServiceProvider.getImmediate({ | ||
optional: true | ||
}); | ||
if (!heartbeatService) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, heartbeatService.getHeartbeatsHeader()]; | ||
case 1: | ||
heartbeatsHeader = _c.sent(); | ||
if (heartbeatsHeader) { | ||
headers.append('x-firebase-client', heartbeatsHeader); | ||
} | ||
_c.label = 2; | ||
case 2: | ||
body = { | ||
fid: fid, | ||
authVersion: INTERNAL_AUTH_VERSION, | ||
appId: appConfig.appId, | ||
sdkVersion: PACKAGE_VERSION | ||
}; | ||
request = { | ||
method: 'POST', | ||
headers: headers, | ||
body: JSON.stringify(body) | ||
}; | ||
return [4 /*yield*/, retryIfServerError(function () { return fetch(endpoint, request); })]; | ||
case 3: | ||
response = _c.sent(); | ||
if (!response.ok) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, response.json()]; | ||
case 4: | ||
responseValue = _c.sent(); | ||
registeredInstallationEntry = { | ||
fid: responseValue.fid || fid, | ||
registrationStatus: 2 /* RequestStatus.COMPLETED */, | ||
refreshToken: responseValue.refreshToken, | ||
authToken: extractAuthTokenInfoFromResponse(responseValue.authToken) | ||
}; | ||
return [2 /*return*/, registeredInstallationEntry]; | ||
case 5: return [4 /*yield*/, getErrorFromResponse('Create Installation', response)]; | ||
case 6: throw _c.sent(); | ||
} | ||
}); | ||
async function createInstallationRequest({ appConfig, heartbeatServiceProvider }, { fid }) { | ||
const endpoint = getInstallationsEndpoint(appConfig); | ||
const headers = getHeaders(appConfig); | ||
// If heartbeat service exists, add the heartbeat string to the header. | ||
const heartbeatService = heartbeatServiceProvider.getImmediate({ | ||
optional: true | ||
}); | ||
if (heartbeatService) { | ||
const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader(); | ||
if (heartbeatsHeader) { | ||
headers.append('x-firebase-client', heartbeatsHeader); | ||
} | ||
} | ||
const body = { | ||
fid, | ||
authVersion: INTERNAL_AUTH_VERSION, | ||
appId: appConfig.appId, | ||
sdkVersion: PACKAGE_VERSION | ||
}; | ||
const request = { | ||
method: 'POST', | ||
headers, | ||
body: JSON.stringify(body) | ||
}; | ||
const response = await retryIfServerError(() => fetch(endpoint, request)); | ||
if (response.ok) { | ||
const responseValue = await response.json(); | ||
const registeredInstallationEntry = { | ||
fid: responseValue.fid || fid, | ||
registrationStatus: 2 /* RequestStatus.COMPLETED */, | ||
refreshToken: responseValue.refreshToken, | ||
authToken: extractAuthTokenInfoFromResponse(responseValue.authToken) | ||
}; | ||
return registeredInstallationEntry; | ||
} | ||
else { | ||
throw await getErrorFromResponse('Create Installation', response); | ||
} | ||
} | ||
@@ -258,3 +221,3 @@ | ||
function sleep(ms) { | ||
return new Promise(function (resolve) { | ||
return new Promise(resolve => { | ||
setTimeout(resolve, ms); | ||
@@ -281,3 +244,3 @@ }); | ||
function bufferToBase64UrlSafe(array) { | ||
var b64 = btoa(String.fromCharCode.apply(String, tslib.__spreadArray([], tslib.__read(array), false))); | ||
const b64 = btoa(String.fromCharCode(...array)); | ||
return b64.replace(/\+/g, '-').replace(/\//g, '_'); | ||
@@ -302,4 +265,4 @@ } | ||
*/ | ||
var VALID_FID_PATTERN = /^[cdef][\w-]{21}$/; | ||
var INVALID_FID = ''; | ||
const VALID_FID_PATTERN = /^[cdef][\w-]{21}$/; | ||
const INVALID_FID = ''; | ||
/** | ||
@@ -313,8 +276,8 @@ * Generates a new FID using random values from Web Crypto API. | ||
// bytes. our implementation generates a 17 byte array instead. | ||
var fidByteArray = new Uint8Array(17); | ||
var crypto_1 = self.crypto || self.msCrypto; | ||
crypto_1.getRandomValues(fidByteArray); | ||
const fidByteArray = new Uint8Array(17); | ||
const crypto = self.crypto || self.msCrypto; | ||
crypto.getRandomValues(fidByteArray); | ||
// Replace the first 4 random bits with the constant FID header of 0b0111. | ||
fidByteArray[0] = 112 + (fidByteArray[0] % 16); | ||
var fid = encode(fidByteArray); | ||
fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000); | ||
const fid = encode(fidByteArray); | ||
return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID; | ||
@@ -329,3 +292,3 @@ } | ||
function encode(fidByteArray) { | ||
var b64String = bufferToBase64UrlSafe(fidByteArray); | ||
const b64String = bufferToBase64UrlSafe(fidByteArray); | ||
// Remove the 23rd character that was added because of the extra 4 bits at the | ||
@@ -354,3 +317,3 @@ // end of our 17 byte array, and the '=' padding. | ||
function getKey(appConfig) { | ||
return "".concat(appConfig.appName, "!").concat(appConfig.appId); | ||
return `${appConfig.appName}!${appConfig.appId}`; | ||
} | ||
@@ -374,3 +337,3 @@ | ||
*/ | ||
var fidChangeCallbacks = new Map(); | ||
const fidChangeCallbacks = new Map(); | ||
/** | ||
@@ -381,3 +344,3 @@ * Calls the onIdChange callbacks with the new FID value, and broadcasts the | ||
function fidChanged(appConfig, fid) { | ||
var key = getKey(appConfig); | ||
const key = getKey(appConfig); | ||
callFidChangeCallbacks(key, fid); | ||
@@ -390,4 +353,4 @@ broadcastFidChange(key, fid); | ||
getBroadcastChannel(); | ||
var key = getKey(appConfig); | ||
var callbackSet = fidChangeCallbacks.get(key); | ||
const key = getKey(appConfig); | ||
let callbackSet = fidChangeCallbacks.get(key); | ||
if (!callbackSet) { | ||
@@ -400,4 +363,4 @@ callbackSet = new Set(); | ||
function removeCallback(appConfig, callback) { | ||
var key = getKey(appConfig); | ||
var callbackSet = fidChangeCallbacks.get(key); | ||
const key = getKey(appConfig); | ||
const callbackSet = fidChangeCallbacks.get(key); | ||
if (!callbackSet) { | ||
@@ -414,29 +377,18 @@ return; | ||
function callFidChangeCallbacks(key, fid) { | ||
var e_1, _a; | ||
var callbacks = fidChangeCallbacks.get(key); | ||
const callbacks = fidChangeCallbacks.get(key); | ||
if (!callbacks) { | ||
return; | ||
} | ||
try { | ||
for (var callbacks_1 = tslib.__values(callbacks), callbacks_1_1 = callbacks_1.next(); !callbacks_1_1.done; callbacks_1_1 = callbacks_1.next()) { | ||
var callback = callbacks_1_1.value; | ||
callback(fid); | ||
} | ||
for (const callback of callbacks) { | ||
callback(fid); | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (callbacks_1_1 && !callbacks_1_1.done && (_a = callbacks_1.return)) _a.call(callbacks_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
function broadcastFidChange(key, fid) { | ||
var channel = getBroadcastChannel(); | ||
const channel = getBroadcastChannel(); | ||
if (channel) { | ||
channel.postMessage({ key: key, fid: fid }); | ||
channel.postMessage({ key, fid }); | ||
} | ||
closeBroadcastChannel(); | ||
} | ||
var broadcastChannel = null; | ||
let broadcastChannel = null; | ||
/** Opens and returns a BroadcastChannel if it is supported by the browser. */ | ||
@@ -446,3 +398,3 @@ function getBroadcastChannel() { | ||
broadcastChannel = new BroadcastChannel('[Firebase] FID Change'); | ||
broadcastChannel.onmessage = function (e) { | ||
broadcastChannel.onmessage = e => { | ||
callFidChangeCallbacks(e.data.key, e.data.fid); | ||
@@ -476,10 +428,10 @@ }; | ||
*/ | ||
var DATABASE_NAME = 'firebase-installations-database'; | ||
var DATABASE_VERSION = 1; | ||
var OBJECT_STORE_NAME = 'firebase-installations-store'; | ||
var dbPromise = null; | ||
const DATABASE_NAME = 'firebase-installations-database'; | ||
const DATABASE_VERSION = 1; | ||
const OBJECT_STORE_NAME = 'firebase-installations-store'; | ||
let dbPromise = null; | ||
function getDbPromise() { | ||
if (!dbPromise) { | ||
dbPromise = idb.openDB(DATABASE_NAME, DATABASE_VERSION, { | ||
upgrade: function (db, oldVersion) { | ||
upgrade: (db, oldVersion) => { | ||
// We don't use 'break' in this switch statement, the fall-through | ||
@@ -500,53 +452,22 @@ // behavior is what we want, because if there are multiple versions between | ||
/** Assigns or overwrites the record for the given key with the given value. */ | ||
function set(appConfig, value) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var key, db, tx, objectStore, oldValue; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
key = getKey(appConfig); | ||
return [4 /*yield*/, getDbPromise()]; | ||
case 1: | ||
db = _a.sent(); | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
objectStore = tx.objectStore(OBJECT_STORE_NAME); | ||
return [4 /*yield*/, objectStore.get(key)]; | ||
case 2: | ||
oldValue = (_a.sent()); | ||
return [4 /*yield*/, objectStore.put(value, key)]; | ||
case 3: | ||
_a.sent(); | ||
return [4 /*yield*/, tx.done]; | ||
case 4: | ||
_a.sent(); | ||
if (!oldValue || oldValue.fid !== value.fid) { | ||
fidChanged(appConfig, value.fid); | ||
} | ||
return [2 /*return*/, value]; | ||
} | ||
}); | ||
}); | ||
async function set(appConfig, value) { | ||
const key = getKey(appConfig); | ||
const db = await getDbPromise(); | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
const objectStore = tx.objectStore(OBJECT_STORE_NAME); | ||
const oldValue = (await objectStore.get(key)); | ||
await objectStore.put(value, key); | ||
await tx.done; | ||
if (!oldValue || oldValue.fid !== value.fid) { | ||
fidChanged(appConfig, value.fid); | ||
} | ||
return value; | ||
} | ||
/** Removes record(s) from the objectStore that match the given key. */ | ||
function remove(appConfig) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var key, db, tx; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
key = getKey(appConfig); | ||
return [4 /*yield*/, getDbPromise()]; | ||
case 1: | ||
db = _a.sent(); | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
return [4 /*yield*/, tx.objectStore(OBJECT_STORE_NAME).delete(key)]; | ||
case 2: | ||
_a.sent(); | ||
return [4 /*yield*/, tx.done]; | ||
case 3: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function remove(appConfig) { | ||
const key = getKey(appConfig); | ||
const db = await getDbPromise(); | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
await tx.objectStore(OBJECT_STORE_NAME).delete(key); | ||
await tx.done; | ||
} | ||
@@ -559,37 +480,20 @@ /** | ||
*/ | ||
function update(appConfig, updateFn) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var key, db, tx, store, oldValue, newValue; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
key = getKey(appConfig); | ||
return [4 /*yield*/, getDbPromise()]; | ||
case 1: | ||
db = _a.sent(); | ||
tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
store = tx.objectStore(OBJECT_STORE_NAME); | ||
return [4 /*yield*/, store.get(key)]; | ||
case 2: | ||
oldValue = (_a.sent()); | ||
newValue = updateFn(oldValue); | ||
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.done]; | ||
case 7: | ||
_a.sent(); | ||
if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) { | ||
fidChanged(appConfig, newValue.fid); | ||
} | ||
return [2 /*return*/, newValue]; | ||
} | ||
}); | ||
}); | ||
async function update(appConfig, updateFn) { | ||
const key = getKey(appConfig); | ||
const db = await getDbPromise(); | ||
const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite'); | ||
const store = tx.objectStore(OBJECT_STORE_NAME); | ||
const oldValue = (await store.get(key)); | ||
const newValue = updateFn(oldValue); | ||
if (newValue === undefined) { | ||
await store.delete(key); | ||
} | ||
else { | ||
await store.put(newValue, key); | ||
} | ||
await tx.done; | ||
if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) { | ||
fidChanged(appConfig, newValue.fid); | ||
} | ||
return newValue; | ||
} | ||
@@ -617,29 +521,18 @@ | ||
*/ | ||
function getInstallationEntry(installations) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var registrationPromise, installationEntry; | ||
var _a; | ||
return tslib.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, update(installations.appConfig, function (oldEntry) { | ||
var installationEntry = updateOrCreateInstallationEntry(oldEntry); | ||
var entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry); | ||
registrationPromise = entryWithPromise.registrationPromise; | ||
return entryWithPromise.installationEntry; | ||
})]; | ||
case 1: | ||
installationEntry = _b.sent(); | ||
if (!(installationEntry.fid === INVALID_FID)) return [3 /*break*/, 3]; | ||
_a = {}; | ||
return [4 /*yield*/, registrationPromise]; | ||
case 2: | ||
// FID generation failed. Waiting for the FID from the server. | ||
return [2 /*return*/, (_a.installationEntry = _b.sent(), _a)]; | ||
case 3: return [2 /*return*/, { | ||
installationEntry: installationEntry, | ||
registrationPromise: registrationPromise | ||
}]; | ||
} | ||
}); | ||
async function getInstallationEntry(installations) { | ||
let registrationPromise; | ||
const installationEntry = await update(installations.appConfig, oldEntry => { | ||
const installationEntry = updateOrCreateInstallationEntry(oldEntry); | ||
const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry); | ||
registrationPromise = entryWithPromise.registrationPromise; | ||
return entryWithPromise.installationEntry; | ||
}); | ||
if (installationEntry.fid === INVALID_FID) { | ||
// FID generation failed. Waiting for the FID from the server. | ||
return { installationEntry: await registrationPromise }; | ||
} | ||
return { | ||
installationEntry, | ||
registrationPromise | ||
}; | ||
} | ||
@@ -651,3 +544,3 @@ /** | ||
function updateOrCreateInstallationEntry(oldEntry) { | ||
var entry = oldEntry || { | ||
const entry = oldEntry || { | ||
fid: generateFid(), | ||
@@ -669,5 +562,5 @@ registrationStatus: 0 /* RequestStatus.NOT_STARTED */ | ||
// Registration required but app is offline. | ||
var registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */)); | ||
const registrationPromiseWithError = Promise.reject(ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */)); | ||
return { | ||
installationEntry: installationEntry, | ||
installationEntry, | ||
registrationPromise: registrationPromiseWithError | ||
@@ -677,3 +570,3 @@ }; | ||
// Try registering. Change status to IN_PROGRESS. | ||
var inProgressEntry = { | ||
const inProgressEntry = { | ||
fid: installationEntry.fid, | ||
@@ -683,8 +576,8 @@ registrationStatus: 1 /* RequestStatus.IN_PROGRESS */, | ||
}; | ||
var registrationPromise = registerInstallation(installations, inProgressEntry); | ||
return { installationEntry: inProgressEntry, registrationPromise: registrationPromise }; | ||
const registrationPromise = registerInstallation(installations, inProgressEntry); | ||
return { installationEntry: inProgressEntry, registrationPromise }; | ||
} | ||
else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) { | ||
return { | ||
installationEntry: installationEntry, | ||
installationEntry, | ||
registrationPromise: waitUntilFidRegistration(installations) | ||
@@ -694,81 +587,50 @@ }; | ||
else { | ||
return { installationEntry: installationEntry }; | ||
return { installationEntry }; | ||
} | ||
} | ||
/** This will be executed only once for each new Firebase Installation. */ | ||
function registerInstallation(installations, installationEntry) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var registeredInstallationEntry, e_1; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 2, , 7]); | ||
return [4 /*yield*/, createInstallationRequest(installations, installationEntry)]; | ||
case 1: | ||
registeredInstallationEntry = _a.sent(); | ||
return [2 /*return*/, set(installations.appConfig, registeredInstallationEntry)]; | ||
case 2: | ||
e_1 = _a.sent(); | ||
if (!(isServerError(e_1) && e_1.customData.serverCode === 409)) return [3 /*break*/, 4]; | ||
// Server returned a "FID cannot be used" error. | ||
// Generate a new ID next time. | ||
return [4 /*yield*/, remove(installations.appConfig)]; | ||
case 3: | ||
// Server returned a "FID cannot be used" error. | ||
// Generate a new ID next time. | ||
_a.sent(); | ||
return [3 /*break*/, 6]; | ||
case 4: | ||
// Registration failed. Set FID as not registered. | ||
return [4 /*yield*/, set(installations.appConfig, { | ||
fid: installationEntry.fid, | ||
registrationStatus: 0 /* RequestStatus.NOT_STARTED */ | ||
})]; | ||
case 5: | ||
// Registration failed. Set FID as not registered. | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: throw e_1; | ||
case 7: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function registerInstallation(installations, installationEntry) { | ||
try { | ||
const registeredInstallationEntry = await createInstallationRequest(installations, installationEntry); | ||
return set(installations.appConfig, registeredInstallationEntry); | ||
} | ||
catch (e) { | ||
if (isServerError(e) && e.customData.serverCode === 409) { | ||
// Server returned a "FID cannot be used" error. | ||
// Generate a new ID next time. | ||
await remove(installations.appConfig); | ||
} | ||
else { | ||
// Registration failed. Set FID as not registered. | ||
await set(installations.appConfig, { | ||
fid: installationEntry.fid, | ||
registrationStatus: 0 /* RequestStatus.NOT_STARTED */ | ||
}); | ||
} | ||
throw e; | ||
} | ||
} | ||
/** Call if FID registration is pending in another request. */ | ||
function waitUntilFidRegistration(installations) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var entry, _a, installationEntry, registrationPromise; | ||
return tslib.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, updateInstallationRequest(installations.appConfig)]; | ||
case 1: | ||
entry = _b.sent(); | ||
_b.label = 2; | ||
case 2: | ||
if (!(entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */)) return [3 /*break*/, 5]; | ||
// createInstallation request still in progress. | ||
return [4 /*yield*/, sleep(100)]; | ||
case 3: | ||
// createInstallation request still in progress. | ||
_b.sent(); | ||
return [4 /*yield*/, updateInstallationRequest(installations.appConfig)]; | ||
case 4: | ||
entry = _b.sent(); | ||
return [3 /*break*/, 2]; | ||
case 5: | ||
if (!(entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */)) return [3 /*break*/, 7]; | ||
return [4 /*yield*/, getInstallationEntry(installations)]; | ||
case 6: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (registrationPromise) { | ||
return [2 /*return*/, registrationPromise]; | ||
} | ||
else { | ||
// if there is no registrationPromise, entry is registered. | ||
return [2 /*return*/, installationEntry]; | ||
} | ||
case 7: return [2 /*return*/, entry]; | ||
} | ||
}); | ||
}); | ||
async function waitUntilFidRegistration(installations) { | ||
// 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 updateInstallationRequest(installations.appConfig); | ||
while (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) { | ||
// createInstallation request still in progress. | ||
await sleep(100); | ||
entry = await updateInstallationRequest(installations.appConfig); | ||
} | ||
if (entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) { | ||
// The request timed out or failed in a different call. Try again. | ||
const { installationEntry, registrationPromise } = await getInstallationEntry(installations); | ||
if (registrationPromise) { | ||
return registrationPromise; | ||
} | ||
else { | ||
// if there is no registrationPromise, entry is registered. | ||
return installationEntry; | ||
} | ||
} | ||
return entry; | ||
} | ||
@@ -784,3 +646,3 @@ /** | ||
function updateInstallationRequest(appConfig) { | ||
return update(appConfig, function (oldEntry) { | ||
return update(appConfig, oldEntry => { | ||
if (!oldEntry) { | ||
@@ -822,52 +684,38 @@ throw ERROR_FACTORY.create("installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */); | ||
*/ | ||
function generateAuthTokenRequest(_a, installationEntry) { | ||
var appConfig = _a.appConfig, heartbeatServiceProvider = _a.heartbeatServiceProvider; | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var endpoint, headers, heartbeatService, heartbeatsHeader, body, request, response, responseValue, completedAuthToken; | ||
return tslib.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry); | ||
headers = getHeadersWithAuth(appConfig, installationEntry); | ||
heartbeatService = heartbeatServiceProvider.getImmediate({ | ||
optional: true | ||
}); | ||
if (!heartbeatService) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, heartbeatService.getHeartbeatsHeader()]; | ||
case 1: | ||
heartbeatsHeader = _b.sent(); | ||
if (heartbeatsHeader) { | ||
headers.append('x-firebase-client', heartbeatsHeader); | ||
} | ||
_b.label = 2; | ||
case 2: | ||
body = { | ||
installation: { | ||
sdkVersion: PACKAGE_VERSION, | ||
appId: appConfig.appId | ||
} | ||
}; | ||
request = { | ||
method: 'POST', | ||
headers: headers, | ||
body: JSON.stringify(body) | ||
}; | ||
return [4 /*yield*/, retryIfServerError(function () { return fetch(endpoint, request); })]; | ||
case 3: | ||
response = _b.sent(); | ||
if (!response.ok) return [3 /*break*/, 5]; | ||
return [4 /*yield*/, response.json()]; | ||
case 4: | ||
responseValue = _b.sent(); | ||
completedAuthToken = extractAuthTokenInfoFromResponse(responseValue); | ||
return [2 /*return*/, completedAuthToken]; | ||
case 5: return [4 /*yield*/, getErrorFromResponse('Generate Auth Token', response)]; | ||
case 6: throw _b.sent(); | ||
} | ||
}); | ||
async function generateAuthTokenRequest({ appConfig, heartbeatServiceProvider }, installationEntry) { | ||
const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry); | ||
const headers = getHeadersWithAuth(appConfig, installationEntry); | ||
// If heartbeat service exists, add the heartbeat string to the header. | ||
const heartbeatService = heartbeatServiceProvider.getImmediate({ | ||
optional: true | ||
}); | ||
if (heartbeatService) { | ||
const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader(); | ||
if (heartbeatsHeader) { | ||
headers.append('x-firebase-client', heartbeatsHeader); | ||
} | ||
} | ||
const body = { | ||
installation: { | ||
sdkVersion: PACKAGE_VERSION, | ||
appId: appConfig.appId | ||
} | ||
}; | ||
const request = { | ||
method: 'POST', | ||
headers, | ||
body: JSON.stringify(body) | ||
}; | ||
const response = await retryIfServerError(() => fetch(endpoint, request)); | ||
if (response.ok) { | ||
const responseValue = await response.json(); | ||
const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue); | ||
return completedAuthToken; | ||
} | ||
else { | ||
throw await getErrorFromResponse('Generate Auth Token', response); | ||
} | ||
} | ||
function getGenerateAuthTokenEndpoint(appConfig, _a) { | ||
var fid = _a.fid; | ||
return "".concat(getInstallationsEndpoint(appConfig), "/").concat(fid, "/authTokens:generate"); | ||
function getGenerateAuthTokenEndpoint(appConfig, { fid }) { | ||
return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`; | ||
} | ||
@@ -897,48 +745,32 @@ | ||
*/ | ||
function refreshAuthToken(installations, forceRefresh) { | ||
if (forceRefresh === void 0) { forceRefresh = false; } | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var tokenPromise, entry, authToken, _a; | ||
return tslib.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4 /*yield*/, update(installations.appConfig, function (oldEntry) { | ||
if (!isEntryRegistered(oldEntry)) { | ||
throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */); | ||
} | ||
var oldAuthToken = oldEntry.authToken; | ||
if (!forceRefresh && isAuthTokenValid(oldAuthToken)) { | ||
// There is a valid token in the DB. | ||
return oldEntry; | ||
} | ||
else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) { | ||
// There already is a token request in progress. | ||
tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh); | ||
return oldEntry; | ||
} | ||
else { | ||
// No token or token expired. | ||
if (!navigator.onLine) { | ||
throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */); | ||
} | ||
var inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry); | ||
tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry); | ||
return inProgressEntry; | ||
} | ||
})]; | ||
case 1: | ||
entry = _b.sent(); | ||
if (!tokenPromise) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, tokenPromise]; | ||
case 2: | ||
_a = _b.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
_a = entry.authToken; | ||
_b.label = 4; | ||
case 4: | ||
authToken = _a; | ||
return [2 /*return*/, authToken]; | ||
async function refreshAuthToken(installations, forceRefresh = false) { | ||
let tokenPromise; | ||
const entry = await update(installations.appConfig, oldEntry => { | ||
if (!isEntryRegistered(oldEntry)) { | ||
throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */); | ||
} | ||
const oldAuthToken = oldEntry.authToken; | ||
if (!forceRefresh && isAuthTokenValid(oldAuthToken)) { | ||
// There is a valid token in the DB. | ||
return oldEntry; | ||
} | ||
else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) { | ||
// There already is a token request in progress. | ||
tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh); | ||
return oldEntry; | ||
} | ||
else { | ||
// No token or token expired. | ||
if (!navigator.onLine) { | ||
throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */); | ||
} | ||
}); | ||
const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry); | ||
tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry); | ||
return inProgressEntry; | ||
} | ||
}); | ||
const authToken = tokenPromise | ||
? await tokenPromise | ||
: entry.authToken; | ||
return authToken; | ||
} | ||
@@ -951,34 +783,20 @@ /** | ||
*/ | ||
function waitUntilAuthTokenRequest(installations, forceRefresh) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var entry, authToken; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, updateAuthTokenRequest(installations.appConfig)]; | ||
case 1: | ||
entry = _a.sent(); | ||
_a.label = 2; | ||
case 2: | ||
if (!(entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */)) return [3 /*break*/, 5]; | ||
// generateAuthToken still in progress. | ||
return [4 /*yield*/, sleep(100)]; | ||
case 3: | ||
// generateAuthToken still in progress. | ||
_a.sent(); | ||
return [4 /*yield*/, updateAuthTokenRequest(installations.appConfig)]; | ||
case 4: | ||
entry = _a.sent(); | ||
return [3 /*break*/, 2]; | ||
case 5: | ||
authToken = entry.authToken; | ||
if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) { | ||
// The request timed out or failed in a different call. Try again. | ||
return [2 /*return*/, refreshAuthToken(installations, forceRefresh)]; | ||
} | ||
else { | ||
return [2 /*return*/, authToken]; | ||
} | ||
} | ||
}); | ||
}); | ||
async function waitUntilAuthTokenRequest(installations, forceRefresh) { | ||
// 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(installations.appConfig); | ||
while (entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) { | ||
// generateAuthToken still in progress. | ||
await sleep(100); | ||
entry = await updateAuthTokenRequest(installations.appConfig); | ||
} | ||
const authToken = entry.authToken; | ||
if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) { | ||
// The request timed out or failed in a different call. Try again. | ||
return refreshAuthToken(installations, forceRefresh); | ||
} | ||
else { | ||
return authToken; | ||
} | ||
} | ||
@@ -994,9 +812,9 @@ /** | ||
function updateAuthTokenRequest(appConfig) { | ||
return update(appConfig, function (oldEntry) { | ||
return update(appConfig, oldEntry => { | ||
if (!isEntryRegistered(oldEntry)) { | ||
throw ERROR_FACTORY.create("not-registered" /* ErrorCode.NOT_REGISTERED */); | ||
} | ||
var oldAuthToken = oldEntry.authToken; | ||
const oldAuthToken = oldEntry.authToken; | ||
if (hasAuthTokenRequestTimedOut(oldAuthToken)) { | ||
return tslib.__assign(tslib.__assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } }); | ||
return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } }); | ||
} | ||
@@ -1006,40 +824,22 @@ return oldEntry; | ||
} | ||
function fetchAuthTokenFromServer(installations, installationEntry) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var authToken, updatedInstallationEntry, e_1, updatedInstallationEntry; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
_a.trys.push([0, 3, , 8]); | ||
return [4 /*yield*/, generateAuthTokenRequest(installations, installationEntry)]; | ||
case 1: | ||
authToken = _a.sent(); | ||
updatedInstallationEntry = tslib.__assign(tslib.__assign({}, installationEntry), { authToken: authToken }); | ||
return [4 /*yield*/, set(installations.appConfig, updatedInstallationEntry)]; | ||
case 2: | ||
_a.sent(); | ||
return [2 /*return*/, authToken]; | ||
case 3: | ||
e_1 = _a.sent(); | ||
if (!(isServerError(e_1) && | ||
(e_1.customData.serverCode === 401 || e_1.customData.serverCode === 404))) return [3 /*break*/, 5]; | ||
// Server returned a "FID not found" or a "Invalid authentication" error. | ||
// Generate a new ID next time. | ||
return [4 /*yield*/, remove(installations.appConfig)]; | ||
case 4: | ||
// Server returned a "FID not found" or a "Invalid authentication" error. | ||
// Generate a new ID next time. | ||
_a.sent(); | ||
return [3 /*break*/, 7]; | ||
case 5: | ||
updatedInstallationEntry = tslib.__assign(tslib.__assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } }); | ||
return [4 /*yield*/, set(installations.appConfig, updatedInstallationEntry)]; | ||
case 6: | ||
_a.sent(); | ||
_a.label = 7; | ||
case 7: throw e_1; | ||
case 8: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function fetchAuthTokenFromServer(installations, installationEntry) { | ||
try { | ||
const authToken = await generateAuthTokenRequest(installations, installationEntry); | ||
const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken }); | ||
await set(installations.appConfig, updatedInstallationEntry); | ||
return authToken; | ||
} | ||
catch (e) { | ||
if (isServerError(e) && | ||
(e.customData.serverCode === 401 || e.customData.serverCode === 404)) { | ||
// Server returned a "FID not found" or a "Invalid authentication" error. | ||
// Generate a new ID next time. | ||
await remove(installations.appConfig); | ||
} | ||
else { | ||
const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } }); | ||
await set(installations.appConfig, updatedInstallationEntry); | ||
} | ||
throw e; | ||
} | ||
} | ||
@@ -1055,3 +855,3 @@ function isEntryRegistered(installationEntry) { | ||
function isAuthTokenExpired(authToken) { | ||
var now = Date.now(); | ||
const now = Date.now(); | ||
return (now < authToken.creationTime || | ||
@@ -1062,7 +862,7 @@ authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER); | ||
function makeAuthTokenRequestInProgressEntry(oldEntry) { | ||
var inProgressAuthToken = { | ||
const inProgressAuthToken = { | ||
requestStatus: 1 /* RequestStatus.IN_PROGRESS */, | ||
requestTime: Date.now() | ||
}; | ||
return tslib.__assign(tslib.__assign({}, oldEntry), { authToken: inProgressAuthToken }); | ||
return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken }); | ||
} | ||
@@ -1097,24 +897,14 @@ function hasAuthTokenRequestTimedOut(authToken) { | ||
*/ | ||
function getId(installations) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var installationsImpl, _a, installationEntry, registrationPromise; | ||
return tslib.__generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: | ||
installationsImpl = installations; | ||
return [4 /*yield*/, getInstallationEntry(installationsImpl)]; | ||
case 1: | ||
_a = _b.sent(), installationEntry = _a.installationEntry, registrationPromise = _a.registrationPromise; | ||
if (registrationPromise) { | ||
registrationPromise.catch(console.error); | ||
} | ||
else { | ||
// If the installation is already registered, update the authentication | ||
// token if needed. | ||
refreshAuthToken(installationsImpl).catch(console.error); | ||
} | ||
return [2 /*return*/, installationEntry.fid]; | ||
} | ||
}); | ||
}); | ||
async function getId(installations) { | ||
const installationsImpl = installations; | ||
const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl); | ||
if (registrationPromise) { | ||
registrationPromise.catch(console.error); | ||
} | ||
else { | ||
// If the installation is already registered, update the authentication | ||
// token if needed. | ||
refreshAuthToken(installationsImpl).catch(console.error); | ||
} | ||
return installationEntry.fid; | ||
} | ||
@@ -1146,40 +936,16 @@ | ||
*/ | ||
function getToken(installations, forceRefresh) { | ||
if (forceRefresh === void 0) { forceRefresh = false; } | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var installationsImpl, authToken; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
installationsImpl = installations; | ||
return [4 /*yield*/, completeInstallationRegistration(installationsImpl)]; | ||
case 1: | ||
_a.sent(); | ||
return [4 /*yield*/, refreshAuthToken(installationsImpl, forceRefresh)]; | ||
case 2: | ||
authToken = _a.sent(); | ||
return [2 /*return*/, authToken.token]; | ||
} | ||
}); | ||
}); | ||
async function getToken(installations, forceRefresh = false) { | ||
const installationsImpl = installations; | ||
await completeInstallationRegistration(installationsImpl); | ||
// At this point we either have a Registered Installation in the DB, or we've | ||
// already thrown an error. | ||
const authToken = await refreshAuthToken(installationsImpl, forceRefresh); | ||
return authToken.token; | ||
} | ||
function completeInstallationRegistration(installations) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var registrationPromise; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, getInstallationEntry(installations)]; | ||
case 1: | ||
registrationPromise = (_a.sent()).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. | ||
_a.sent(); | ||
_a.label = 3; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function completeInstallationRegistration(installations) { | ||
const { registrationPromise } = await getInstallationEntry(installations); | ||
if (registrationPromise) { | ||
// A createInstallation request is in progress. Wait until it finishes. | ||
await registrationPromise; | ||
} | ||
} | ||
@@ -1203,28 +969,16 @@ | ||
*/ | ||
function deleteInstallationRequest(appConfig, installationEntry) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var endpoint, headers, request, response; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
endpoint = getDeleteEndpoint(appConfig, installationEntry); | ||
headers = getHeadersWithAuth(appConfig, installationEntry); | ||
request = { | ||
method: 'DELETE', | ||
headers: headers | ||
}; | ||
return [4 /*yield*/, retryIfServerError(function () { return fetch(endpoint, request); })]; | ||
case 1: | ||
response = _a.sent(); | ||
if (!!response.ok) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, getErrorFromResponse('Delete Installation', response)]; | ||
case 2: throw _a.sent(); | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
async function deleteInstallationRequest(appConfig, installationEntry) { | ||
const endpoint = getDeleteEndpoint(appConfig, installationEntry); | ||
const headers = getHeadersWithAuth(appConfig, installationEntry); | ||
const request = { | ||
method: 'DELETE', | ||
headers | ||
}; | ||
const response = await retryIfServerError(() => fetch(endpoint, request)); | ||
if (!response.ok) { | ||
throw await getErrorFromResponse('Delete Installation', response); | ||
} | ||
} | ||
function getDeleteEndpoint(appConfig, _a) { | ||
var fid = _a.fid; | ||
return "".concat(getInstallationsEndpoint(appConfig), "/").concat(fid); | ||
function getDeleteEndpoint(appConfig, { fid }) { | ||
return `${getInstallationsEndpoint(appConfig)}/${fid}`; | ||
} | ||
@@ -1254,37 +1008,26 @@ | ||
*/ | ||
function deleteInstallations(installations) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var appConfig, entry; | ||
return tslib.__generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
appConfig = installations.appConfig; | ||
return [4 /*yield*/, update(appConfig, function (oldEntry) { | ||
if (oldEntry && oldEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) { | ||
// Delete the unregistered entry without sending a deleteInstallation request. | ||
return undefined; | ||
} | ||
return oldEntry; | ||
})]; | ||
case 1: | ||
entry = _a.sent(); | ||
if (!entry) return [3 /*break*/, 6]; | ||
if (!(entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */)) return [3 /*break*/, 2]; | ||
// Can't delete while trying to register. | ||
throw ERROR_FACTORY.create("delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */); | ||
case 2: | ||
if (!(entry.registrationStatus === 2 /* RequestStatus.COMPLETED */)) return [3 /*break*/, 6]; | ||
if (!!navigator.onLine) return [3 /*break*/, 3]; | ||
throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */); | ||
case 3: return [4 /*yield*/, deleteInstallationRequest(appConfig, entry)]; | ||
case 4: | ||
_a.sent(); | ||
return [4 /*yield*/, remove(appConfig)]; | ||
case 5: | ||
_a.sent(); | ||
_a.label = 6; | ||
case 6: return [2 /*return*/]; | ||
async function deleteInstallations(installations) { | ||
const { appConfig } = installations; | ||
const entry = await update(appConfig, oldEntry => { | ||
if (oldEntry && oldEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) { | ||
// Delete the unregistered entry without sending a deleteInstallation request. | ||
return undefined; | ||
} | ||
return oldEntry; | ||
}); | ||
if (entry) { | ||
if (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) { | ||
// Can't delete while trying to register. | ||
throw ERROR_FACTORY.create("delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */); | ||
} | ||
else if (entry.registrationStatus === 2 /* RequestStatus.COMPLETED */) { | ||
if (!navigator.onLine) { | ||
throw ERROR_FACTORY.create("app-offline" /* ErrorCode.APP_OFFLINE */); | ||
} | ||
}); | ||
}); | ||
else { | ||
await deleteInstallationRequest(appConfig, entry); | ||
await remove(appConfig); | ||
} | ||
} | ||
} | ||
} | ||
@@ -1318,5 +1061,5 @@ | ||
function onIdChange(installations, callback) { | ||
var appConfig = installations.appConfig; | ||
const { appConfig } = installations; | ||
addCallback(appConfig, callback); | ||
return function () { | ||
return () => { | ||
removeCallback(appConfig, callback); | ||
@@ -1349,5 +1092,4 @@ }; | ||
*/ | ||
function getInstallations(app$1) { | ||
if (app$1 === void 0) { app$1 = app.getApp(); } | ||
var installationsImpl = app._getProvider(app$1, 'installations').getImmediate(); | ||
function getInstallations(app$1 = app.getApp()) { | ||
const installationsImpl = app._getProvider(app$1, 'installations').getImmediate(); | ||
return installationsImpl; | ||
@@ -1373,3 +1115,2 @@ } | ||
function extractAppConfig(app) { | ||
var e_1, _a; | ||
if (!app || !app.options) { | ||
@@ -1382,3 +1123,3 @@ throw getMissingValueError('App Configuration'); | ||
// Required app config keys | ||
var configKeys = [ | ||
const configKeys = [ | ||
'projectId', | ||
@@ -1388,17 +1129,7 @@ 'apiKey', | ||
]; | ||
try { | ||
for (var configKeys_1 = tslib.__values(configKeys), configKeys_1_1 = configKeys_1.next(); !configKeys_1_1.done; configKeys_1_1 = configKeys_1.next()) { | ||
var keyName = configKeys_1_1.value; | ||
if (!app.options[keyName]) { | ||
throw getMissingValueError(keyName); | ||
} | ||
for (const keyName of configKeys) { | ||
if (!app.options[keyName]) { | ||
throw getMissingValueError(keyName); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (configKeys_1_1 && !configKeys_1_1.done && (_a = configKeys_1.return)) _a.call(configKeys_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
return { | ||
@@ -1413,3 +1144,3 @@ appName: app.name, | ||
return ERROR_FACTORY.create("missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, { | ||
valueName: valueName | ||
valueName | ||
}); | ||
@@ -1434,24 +1165,24 @@ } | ||
*/ | ||
var INSTALLATIONS_NAME = 'installations'; | ||
var INSTALLATIONS_NAME_INTERNAL = 'installations-internal'; | ||
var publicFactory = function (container) { | ||
var app$1 = container.getProvider('app').getImmediate(); | ||
const INSTALLATIONS_NAME = 'installations'; | ||
const INSTALLATIONS_NAME_INTERNAL = 'installations-internal'; | ||
const publicFactory = (container) => { | ||
const app$1 = container.getProvider('app').getImmediate(); | ||
// Throws if app isn't configured properly. | ||
var appConfig = extractAppConfig(app$1); | ||
var heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat'); | ||
var installationsImpl = { | ||
const appConfig = extractAppConfig(app$1); | ||
const heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat'); | ||
const installationsImpl = { | ||
app: app$1, | ||
appConfig: appConfig, | ||
heartbeatServiceProvider: heartbeatServiceProvider, | ||
_delete: function () { return Promise.resolve(); } | ||
appConfig, | ||
heartbeatServiceProvider, | ||
_delete: () => Promise.resolve() | ||
}; | ||
return installationsImpl; | ||
}; | ||
var internalFactory = function (container) { | ||
var app$1 = container.getProvider('app').getImmediate(); | ||
const internalFactory = (container) => { | ||
const app$1 = container.getProvider('app').getImmediate(); | ||
// Internal FIS instance relies on public FIS instance. | ||
var installations = app._getProvider(app$1, INSTALLATIONS_NAME).getImmediate(); | ||
var installationsInternal = { | ||
getId: function () { return getId(installations); }, | ||
getToken: function (forceRefresh) { return getToken(installations, forceRefresh); } | ||
const installations = app._getProvider(app$1, INSTALLATIONS_NAME).getImmediate(); | ||
const installationsInternal = { | ||
getId: () => getId(installations), | ||
getToken: (forceRefresh) => getToken(installations, forceRefresh) | ||
}; | ||
@@ -1473,4 +1204,4 @@ return installationsInternal; | ||
app.registerVersion(name, version); | ||
// BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation | ||
app.registerVersion(name, version, 'cjs5'); | ||
// BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation | ||
app.registerVersion(name, version, 'cjs2017'); | ||
@@ -1477,0 +1208,0 @@ exports.deleteInstallations = deleteInstallations; |
{ | ||
"name": "@firebase/installations", | ||
"version": "0.6.9-canary.2e2804139", | ||
"version": "0.6.9-canary.479226bf3", | ||
"author": "Firebase <firebase-support@google.com> (https://firebase.google.com/)", | ||
@@ -8,3 +8,2 @@ "main": "dist/index.cjs.js", | ||
"browser": "dist/esm/index.esm2017.js", | ||
"esm5": "dist/esm/index.esm.js", | ||
"exports": { | ||
@@ -14,3 +13,2 @@ ".": { | ||
"require": "./dist/index.cjs.js", | ||
"esm5": "./dist/esm/index.esm.js", | ||
"default": "./dist/esm/index.esm2017.js" | ||
@@ -56,3 +54,3 @@ }, | ||
"devDependencies": { | ||
"@firebase/app": "0.10.13-canary.2e2804139", | ||
"@firebase/app": "0.10.13-canary.479226bf3", | ||
"rollup": "2.79.1", | ||
@@ -67,7 +65,7 @@ "@rollup/plugin-commonjs": "21.1.0", | ||
"peerDependencies": { | ||
"@firebase/app": "0.10.13-canary.2e2804139" | ||
"@firebase/app": "0.10.13-canary.479226bf3" | ||
}, | ||
"dependencies": { | ||
"@firebase/util": "1.10.0-canary.2e2804139", | ||
"@firebase/component": "0.6.9-canary.2e2804139", | ||
"@firebase/util": "1.10.0-canary.479226bf3", | ||
"@firebase/component": "0.6.9-canary.479226bf3", | ||
"idb": "7.1.1", | ||
@@ -74,0 +72,0 @@ "tslib": "^2.1.0" |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
2
6
342698
103
4640
+ Added@firebase/app@0.10.13-canary.479226bf3(transitive)
+ Added@firebase/component@0.6.9-canary.479226bf3(transitive)
+ Added@firebase/logger@0.4.2-canary.479226bf3(transitive)
+ Added@firebase/util@1.10.0-canary.479226bf3(transitive)
- Removed@firebase/app@0.10.13-canary.2e2804139(transitive)
- Removed@firebase/component@0.6.9-canary.2e2804139(transitive)
- Removed@firebase/logger@0.4.2-canary.2e2804139(transitive)
- Removed@firebase/util@1.10.0-canary.2e2804139(transitive)