@firebase/app-check
Advanced tools
Comparing version 0.1.4 to 0.2.0-202153001032
# @firebase/app-check | ||
## 0.2.0-202153001032 | ||
### Minor Changes | ||
- [`870dd5e35`](https://github.com/firebase/firebase-js-sdk/commit/870dd5e3594f5b588bdc2801c60c6d984d1d08cc) [#5033](https://github.com/firebase/firebase-js-sdk/pull/5033) - Added `getToken()` and `onTokenChanged` methods to App Check. | ||
### Patch Changes | ||
- [`5d31e2192`](https://github.com/firebase/firebase-js-sdk/commit/5d31e2192d0ea68a768bc7826ad5aa830c2bc36c) [#5055](https://github.com/firebase/firebase-js-sdk/pull/5055) (fixes [#5052](https://github.com/firebase/firebase-js-sdk/issues/5052)) - Fix an error causing App Check to log `HTTP status 429` errors in debug mode. | ||
- Updated dependencies [[`870dd5e35`](https://github.com/firebase/firebase-js-sdk/commit/870dd5e3594f5b588bdc2801c60c6d984d1d08cc), [`56a6a9d4a`](https://github.com/firebase/firebase-js-sdk/commit/56a6a9d4af2766154584a0f66d3c4d8024d74ba5)]: | ||
- @firebase/app-check-types@0.2.0-202153001032 | ||
- @firebase/component@0.5.4-202153001032 | ||
- @firebase/app@0.6.28-202153001032 | ||
## 0.1.4 | ||
@@ -4,0 +19,0 @@ |
@@ -67,3 +67,3 @@ 'use strict'; | ||
activated: false, | ||
tokenListeners: [] | ||
tokenObservers: [] | ||
}; | ||
@@ -168,3 +168,3 @@ var DEBUG_STATE = { | ||
} | ||
function getToken(app) { | ||
function getToken$2(app) { | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
@@ -232,70 +232,2 @@ var reCAPTCHAState, recaptcha; | ||
*/ | ||
/** | ||
* | ||
* @param app | ||
* @param siteKeyOrProvider - optional custom attestation provider | ||
* or reCAPTCHA siteKey | ||
* @param isTokenAutoRefreshEnabled - if true, enables auto refresh | ||
* of appCheck token. | ||
*/ | ||
function activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
if (state.activated) { | ||
throw ERROR_FACTORY.create("already-activated" /* ALREADY_ACTIVATED */, { | ||
appName: app.name | ||
}); | ||
} | ||
var newState = tslib.__assign(tslib.__assign({}, state), { activated: true }); | ||
if (typeof siteKeyOrProvider === 'string') { | ||
newState.siteKey = siteKeyOrProvider; | ||
} | ||
else { | ||
newState.customProvider = siteKeyOrProvider; | ||
} | ||
// Use value of global `automaticDataCollectionEnabled` (which | ||
// itself defaults to false if not specified in config) if | ||
// `isTokenAutoRefreshEnabled` param was not provided by user. | ||
newState.isTokenAutoRefreshEnabled = | ||
isTokenAutoRefreshEnabled === undefined | ||
? app.automaticDataCollectionEnabled | ||
: isTokenAutoRefreshEnabled; | ||
setState(app, newState); | ||
// initialize reCAPTCHA if siteKey is provided | ||
if (newState.siteKey) { | ||
initialize(app, newState.siteKey).catch(function () { | ||
/* we don't care about the initialization result in activate() */ | ||
}); | ||
} | ||
} | ||
function setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
// This will exist if any product libraries have called | ||
// `addTokenListener()` | ||
if (state.tokenRefresher) { | ||
if (isTokenAutoRefreshEnabled === true) { | ||
state.tokenRefresher.start(); | ||
} | ||
else { | ||
state.tokenRefresher.stop(); | ||
} | ||
} | ||
setState(app, tslib.__assign(tslib.__assign({}, state), { isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabled })); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
var BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1beta'; | ||
@@ -772,3 +704,3 @@ var EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaToken'; | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var existingDebugToken, _e_1, newToken; | ||
var existingDebugToken, newToken; | ||
return tslib.__generator(this, function (_a) { | ||
@@ -786,3 +718,3 @@ switch (_a.label) { | ||
case 3: | ||
_e_1 = _a.sent(); | ||
_a.sent(); | ||
return [3 /*break*/, 4]; | ||
@@ -901,3 +833,3 @@ case 4: | ||
return tslib.__awaiter(this, void 0, void 0, function () { | ||
var tokenFromDebugExchange, _a, _b, _c, state, token, error, cachedToken, customToken, issuedAtTimeSeconds, issuedAtTimeMillis, attestedClaimsToken, e_1, interopTokenResult; | ||
var state, token, error, cachedToken, tokenFromDebugExchange, _a, _b, _c, customToken, issuedAtTimeSeconds, issuedAtTimeMillis, attestedClaimsToken, e_1, interopTokenResult; | ||
return tslib.__generator(this, function (_d) { | ||
@@ -907,18 +839,8 @@ switch (_d.label) { | ||
ensureActivated(app); | ||
if (!isDebugMode()) return [3 /*break*/, 3]; | ||
_a = exchangeToken; | ||
_b = getExchangeDebugTokenRequest; | ||
_c = [app]; | ||
return [4 /*yield*/, getDebugToken()]; | ||
case 1: return [4 /*yield*/, _a.apply(void 0, [_b.apply(void 0, _c.concat([_d.sent()])), platformLoggerProvider])]; | ||
case 2: | ||
tokenFromDebugExchange = _d.sent(); | ||
return [2 /*return*/, { token: tokenFromDebugExchange.token }]; | ||
case 3: | ||
state = getState(app); | ||
token = state.token; | ||
error = undefined; | ||
if (!!token) return [3 /*break*/, 5]; | ||
if (!!token) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, readTokenFromStorage(app)]; | ||
case 4: | ||
case 1: | ||
cachedToken = _d.sent(); | ||
@@ -931,5 +853,5 @@ if (cachedToken && isValid(cachedToken)) { | ||
} | ||
_d.label = 5; | ||
case 5: | ||
// return the cached token if it's valid | ||
_d.label = 2; | ||
case 2: | ||
// Return the cached token (from either memory or indexedDB) if it's valid | ||
if (!forceRefresh && token && isValid(token)) { | ||
@@ -940,3 +862,18 @@ return [2 /*return*/, { | ||
} | ||
_d.label = 6; | ||
if (!isDebugMode()) return [3 /*break*/, 6]; | ||
_a = exchangeToken; | ||
_b = getExchangeDebugTokenRequest; | ||
_c = [app]; | ||
return [4 /*yield*/, getDebugToken()]; | ||
case 3: return [4 /*yield*/, _a.apply(void 0, [_b.apply(void 0, _c.concat([_d.sent()])), platformLoggerProvider])]; | ||
case 4: | ||
tokenFromDebugExchange = _d.sent(); | ||
// Write debug token to indexedDB. | ||
return [4 /*yield*/, writeTokenToStorage(app, tokenFromDebugExchange)]; | ||
case 5: | ||
// Write debug token to indexedDB. | ||
_d.sent(); | ||
// Write debug token to state. | ||
setState(app, tslib.__assign(tslib.__assign({}, state), { token: tokenFromDebugExchange })); | ||
return [2 /*return*/, { token: tokenFromDebugExchange.token }]; | ||
case 6: | ||
@@ -956,3 +893,3 @@ _d.trys.push([6, 12, , 13]); | ||
return [3 /*break*/, 11]; | ||
case 8: return [4 /*yield*/, getToken(app).catch(function (_e) { | ||
case 8: return [4 /*yield*/, getToken$2(app).catch(function (_e) { | ||
// reCaptcha.execute() throws null which is not very descriptive. | ||
@@ -984,3 +921,3 @@ throw ERROR_FACTORY.create("recaptcha-error" /* RECAPTCHA_ERROR */); | ||
}; | ||
// write the new token to the memory state as well ashe persistent storage. | ||
// write the new token to the memory state as well as the persistent storage. | ||
// Only do it if we got a valid new token | ||
@@ -999,46 +936,31 @@ setState(app, tslib.__assign(tslib.__assign({}, state), { token: token })); | ||
} | ||
function addTokenListener(app, platformLoggerProvider, listener) { | ||
function addTokenListener(app, platformLoggerProvider, listener, onError) { | ||
var state = getState(app); | ||
var newState = tslib.__assign(tslib.__assign({}, state), { tokenListeners: tslib.__spreadArray(tslib.__spreadArray([], state.tokenListeners), [listener]) }); | ||
var tokenListener = { | ||
next: listener, | ||
error: onError | ||
}; | ||
var newState = tslib.__assign(tslib.__assign({}, state), { tokenObservers: tslib.__spreadArray(tslib.__spreadArray([], state.tokenObservers), [tokenListener]) }); | ||
/** | ||
* DEBUG MODE | ||
* | ||
* invoke the listener once with the debug token. | ||
* Invoke the listener with the valid token, then start the token refresher | ||
*/ | ||
if (isDebugMode()) { | ||
var debugState = getDebugState(); | ||
if (debugState.enabled && debugState.token) { | ||
debugState.token.promise | ||
.then(function (token) { return listener({ token: token }); }) | ||
.catch(function () { | ||
/* we don't care about exceptions thrown in listeners */ | ||
}); | ||
} | ||
if (!newState.tokenRefresher) { | ||
var tokenRefresher = createTokenRefresher(app, platformLoggerProvider); | ||
newState.tokenRefresher = tokenRefresher; | ||
} | ||
else { | ||
/** | ||
* PROD MODE | ||
* | ||
* invoke the listener with the valid token, then start the token refresher | ||
*/ | ||
if (!newState.tokenRefresher) { | ||
var tokenRefresher = createTokenRefresher(app, platformLoggerProvider); | ||
newState.tokenRefresher = tokenRefresher; | ||
} | ||
// Create the refresher but don't start it if `isTokenAutoRefreshEnabled` | ||
// is not true. | ||
if (!newState.tokenRefresher.isRunning() && | ||
state.isTokenAutoRefreshEnabled === true) { | ||
newState.tokenRefresher.start(); | ||
} | ||
// invoke the listener async immediately if there is a valid token | ||
if (state.token && isValid(state.token)) { | ||
var validToken_1 = state.token; | ||
Promise.resolve() | ||
.then(function () { return listener({ token: validToken_1.token }); }) | ||
.catch(function () { | ||
/* we don't care about exceptions thrown in listeners */ | ||
}); | ||
} | ||
// Create the refresher but don't start it if `isTokenAutoRefreshEnabled` | ||
// is not true. | ||
if (!newState.tokenRefresher.isRunning() && | ||
state.isTokenAutoRefreshEnabled === true) { | ||
newState.tokenRefresher.start(); | ||
} | ||
// invoke the listener async immediately if there is a valid token | ||
if (state.token && isValid(state.token)) { | ||
var validToken_1 = state.token; | ||
Promise.resolve() | ||
.then(function () { return listener({ token: validToken_1.token }); }) | ||
.catch(function () { | ||
/** Ignore errors in listeners. */ | ||
}); | ||
} | ||
setState(app, newState); | ||
@@ -1048,4 +970,4 @@ } | ||
var state = getState(app); | ||
var newListeners = state.tokenListeners.filter(function (l) { return l !== listener; }); | ||
if (newListeners.length === 0 && | ||
var newObservers = state.tokenObservers.filter(function (tokenObserver) { return tokenObserver.next !== listener; }); | ||
if (newObservers.length === 0 && | ||
state.tokenRefresher && | ||
@@ -1055,3 +977,3 @@ state.tokenRefresher.isRunning()) { | ||
} | ||
setState(app, tslib.__assign(tslib.__assign({}, state), { tokenListeners: newListeners })); | ||
setState(app, tslib.__assign(tslib.__assign({}, state), { tokenObservers: newObservers })); | ||
} | ||
@@ -1108,9 +1030,22 @@ function createTokenRefresher(app, platformLoggerProvider) { | ||
function notifyTokenListeners(app, token) { | ||
var listeners = getState(app).tokenListeners; | ||
for (var _i = 0, listeners_1 = listeners; _i < listeners_1.length; _i++) { | ||
var listener = listeners_1[_i]; | ||
var observers = getState(app).tokenObservers; | ||
for (var _i = 0, observers_1 = observers; _i < observers_1.length; _i++) { | ||
var observer = observers_1[_i]; | ||
try { | ||
listener(token); | ||
if (observer.error) { | ||
// If this listener has an error handler, handle errors differently | ||
// from successes. | ||
if (token.error) { | ||
observer.error(token.error); | ||
} | ||
else { | ||
observer.next(token); | ||
} | ||
} | ||
else { | ||
// Otherwise return the token, whether or not it has an error field. | ||
observer.next(token); | ||
} | ||
} | ||
catch (e) { | ||
catch (ignored) { | ||
// If any handler fails, ignore and run next handler. | ||
@@ -1146,7 +1081,143 @@ } | ||
*/ | ||
function factory(app) { | ||
/** | ||
* | ||
* @param app | ||
* @param siteKeyOrProvider - optional custom attestation provider | ||
* or reCAPTCHA siteKey | ||
* @param isTokenAutoRefreshEnabled - if true, enables auto refresh | ||
* of appCheck token. | ||
*/ | ||
function activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
if (state.activated) { | ||
throw ERROR_FACTORY.create("already-activated" /* ALREADY_ACTIVATED */, { | ||
appName: app.name | ||
}); | ||
} | ||
var newState = tslib.__assign(tslib.__assign({}, state), { activated: true }); | ||
if (typeof siteKeyOrProvider === 'string') { | ||
newState.siteKey = siteKeyOrProvider; | ||
} | ||
else { | ||
newState.customProvider = siteKeyOrProvider; | ||
} | ||
// Use value of global `automaticDataCollectionEnabled` (which | ||
// itself defaults to false if not specified in config) if | ||
// `isTokenAutoRefreshEnabled` param was not provided by user. | ||
newState.isTokenAutoRefreshEnabled = | ||
isTokenAutoRefreshEnabled === undefined | ||
? app.automaticDataCollectionEnabled | ||
: isTokenAutoRefreshEnabled; | ||
setState(app, newState); | ||
// initialize reCAPTCHA if siteKey is provided | ||
if (newState.siteKey) { | ||
initialize(app, newState.siteKey).catch(function () { | ||
/* we don't care about the initialization result in activate() */ | ||
}); | ||
} | ||
} | ||
function setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
// This will exist if any product libraries have called | ||
// `addTokenListener()` | ||
if (state.tokenRefresher) { | ||
if (isTokenAutoRefreshEnabled === true) { | ||
state.tokenRefresher.start(); | ||
} | ||
else { | ||
state.tokenRefresher.stop(); | ||
} | ||
} | ||
setState(app, tslib.__assign(tslib.__assign({}, state), { isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabled })); | ||
} | ||
/** | ||
* Differs from internal getToken in that it throws the error. | ||
*/ | ||
function getToken(app, platformLoggerProvider, forceRefresh) { | ||
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*/, getToken$1(app, platformLoggerProvider, forceRefresh)]; | ||
case 1: | ||
result = _a.sent(); | ||
if (result.error) { | ||
throw result.error; | ||
} | ||
return [2 /*return*/, { token: result.token }]; | ||
} | ||
}); | ||
}); | ||
} | ||
function onTokenChanged(app, platformLoggerProvider, onNextOrObserver, onError, | ||
/** | ||
* NOTE: Although an `onCompletion` callback can be provided, it will | ||
* never be called because the token stream is never-ending. | ||
* It is added only for API consistency with the observer pattern, which | ||
* we follow in JS APIs. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
onCompletion) { | ||
var nextFn = function () { }; | ||
var errorFn = function () { }; | ||
if (onNextOrObserver.next != null) { | ||
nextFn = onNextOrObserver.next.bind(onNextOrObserver); | ||
} | ||
else { | ||
nextFn = onNextOrObserver; | ||
} | ||
if (onNextOrObserver.error != null) { | ||
errorFn = onNextOrObserver.error.bind(onNextOrObserver); | ||
} | ||
else if (onError) { | ||
errorFn = onError; | ||
} | ||
addTokenListener(app, platformLoggerProvider, nextFn, errorFn); | ||
return function () { return removeTokenListener(app, nextFn); }; | ||
} | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
function factory(app, platformLoggerProvider) { | ||
return { | ||
app: app, | ||
activate: function (siteKeyOrProvider, isTokenAutoRefreshEnabled) { return activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled); }, | ||
setTokenAutoRefreshEnabled: function (isTokenAutoRefreshEnabled) { | ||
return setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled); | ||
}, | ||
getToken: function (forceRefresh) { | ||
return getToken(app, platformLoggerProvider, forceRefresh); | ||
}, | ||
onTokenChanged: function (onNextOrObserver, onError, onCompletion) { | ||
return onTokenChanged(app, platformLoggerProvider, | ||
/** | ||
* This can still be an observer. Need to do this casting because | ||
* according to Typescript: "Implementation signatures of overloads | ||
* are not externally visible" | ||
*/ | ||
onNextOrObserver, onError); | ||
}, | ||
INTERNAL: { | ||
delete: function () { | ||
var tokenObservers = getState(app).tokenObservers; | ||
for (var _i = 0, tokenObservers_1 = tokenObservers; _i < tokenObservers_1.length; _i++) { | ||
var tokenObserver = tokenObservers_1[_i]; | ||
removeTokenListener(app, tokenObserver.next); | ||
} | ||
return Promise.resolve(); | ||
} | ||
} | ||
@@ -1168,3 +1239,3 @@ }; | ||
var name = "@firebase/app-check"; | ||
var version = "0.1.4"; | ||
var version = "0.2.0-202153001032"; | ||
@@ -1194,3 +1265,4 @@ /** | ||
var app = container.getProvider('app').getImmediate(); | ||
return factory(app); | ||
var platformLoggerProvider = container.getProvider('platform-logger'); | ||
return factory(app, platformLoggerProvider); | ||
}, "PUBLIC" /* PUBLIC */) | ||
@@ -1197,0 +1269,0 @@ /** |
@@ -61,3 +61,3 @@ import firebase from '@firebase/app'; | ||
activated: false, | ||
tokenListeners: [] | ||
tokenObservers: [] | ||
}; | ||
@@ -162,3 +162,3 @@ var DEBUG_STATE = { | ||
} | ||
function getToken(app) { | ||
function getToken$2(app) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -226,70 +226,2 @@ var reCAPTCHAState, recaptcha; | ||
*/ | ||
/** | ||
* | ||
* @param app | ||
* @param siteKeyOrProvider - optional custom attestation provider | ||
* or reCAPTCHA siteKey | ||
* @param isTokenAutoRefreshEnabled - if true, enables auto refresh | ||
* of appCheck token. | ||
*/ | ||
function activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
if (state.activated) { | ||
throw ERROR_FACTORY.create("already-activated" /* ALREADY_ACTIVATED */, { | ||
appName: app.name | ||
}); | ||
} | ||
var newState = __assign(__assign({}, state), { activated: true }); | ||
if (typeof siteKeyOrProvider === 'string') { | ||
newState.siteKey = siteKeyOrProvider; | ||
} | ||
else { | ||
newState.customProvider = siteKeyOrProvider; | ||
} | ||
// Use value of global `automaticDataCollectionEnabled` (which | ||
// itself defaults to false if not specified in config) if | ||
// `isTokenAutoRefreshEnabled` param was not provided by user. | ||
newState.isTokenAutoRefreshEnabled = | ||
isTokenAutoRefreshEnabled === undefined | ||
? app.automaticDataCollectionEnabled | ||
: isTokenAutoRefreshEnabled; | ||
setState(app, newState); | ||
// initialize reCAPTCHA if siteKey is provided | ||
if (newState.siteKey) { | ||
initialize(app, newState.siteKey).catch(function () { | ||
/* we don't care about the initialization result in activate() */ | ||
}); | ||
} | ||
} | ||
function setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
// This will exist if any product libraries have called | ||
// `addTokenListener()` | ||
if (state.tokenRefresher) { | ||
if (isTokenAutoRefreshEnabled === true) { | ||
state.tokenRefresher.start(); | ||
} | ||
else { | ||
state.tokenRefresher.stop(); | ||
} | ||
} | ||
setState(app, __assign(__assign({}, state), { isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabled })); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
var BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1beta'; | ||
@@ -766,3 +698,3 @@ var EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaToken'; | ||
return __awaiter(this, void 0, void 0, function () { | ||
var existingDebugToken, _e_1, newToken; | ||
var existingDebugToken, newToken; | ||
return __generator(this, function (_a) { | ||
@@ -780,3 +712,3 @@ switch (_a.label) { | ||
case 3: | ||
_e_1 = _a.sent(); | ||
_a.sent(); | ||
return [3 /*break*/, 4]; | ||
@@ -895,3 +827,3 @@ case 4: | ||
return __awaiter(this, void 0, void 0, function () { | ||
var tokenFromDebugExchange, _a, _b, _c, state, token, error, cachedToken, customToken, issuedAtTimeSeconds, issuedAtTimeMillis, attestedClaimsToken, e_1, interopTokenResult; | ||
var state, token, error, cachedToken, tokenFromDebugExchange, _a, _b, _c, customToken, issuedAtTimeSeconds, issuedAtTimeMillis, attestedClaimsToken, e_1, interopTokenResult; | ||
return __generator(this, function (_d) { | ||
@@ -901,18 +833,8 @@ switch (_d.label) { | ||
ensureActivated(app); | ||
if (!isDebugMode()) return [3 /*break*/, 3]; | ||
_a = exchangeToken; | ||
_b = getExchangeDebugTokenRequest; | ||
_c = [app]; | ||
return [4 /*yield*/, getDebugToken()]; | ||
case 1: return [4 /*yield*/, _a.apply(void 0, [_b.apply(void 0, _c.concat([_d.sent()])), platformLoggerProvider])]; | ||
case 2: | ||
tokenFromDebugExchange = _d.sent(); | ||
return [2 /*return*/, { token: tokenFromDebugExchange.token }]; | ||
case 3: | ||
state = getState(app); | ||
token = state.token; | ||
error = undefined; | ||
if (!!token) return [3 /*break*/, 5]; | ||
if (!!token) return [3 /*break*/, 2]; | ||
return [4 /*yield*/, readTokenFromStorage(app)]; | ||
case 4: | ||
case 1: | ||
cachedToken = _d.sent(); | ||
@@ -925,5 +847,5 @@ if (cachedToken && isValid(cachedToken)) { | ||
} | ||
_d.label = 5; | ||
case 5: | ||
// return the cached token if it's valid | ||
_d.label = 2; | ||
case 2: | ||
// Return the cached token (from either memory or indexedDB) if it's valid | ||
if (!forceRefresh && token && isValid(token)) { | ||
@@ -934,3 +856,18 @@ return [2 /*return*/, { | ||
} | ||
_d.label = 6; | ||
if (!isDebugMode()) return [3 /*break*/, 6]; | ||
_a = exchangeToken; | ||
_b = getExchangeDebugTokenRequest; | ||
_c = [app]; | ||
return [4 /*yield*/, getDebugToken()]; | ||
case 3: return [4 /*yield*/, _a.apply(void 0, [_b.apply(void 0, _c.concat([_d.sent()])), platformLoggerProvider])]; | ||
case 4: | ||
tokenFromDebugExchange = _d.sent(); | ||
// Write debug token to indexedDB. | ||
return [4 /*yield*/, writeTokenToStorage(app, tokenFromDebugExchange)]; | ||
case 5: | ||
// Write debug token to indexedDB. | ||
_d.sent(); | ||
// Write debug token to state. | ||
setState(app, __assign(__assign({}, state), { token: tokenFromDebugExchange })); | ||
return [2 /*return*/, { token: tokenFromDebugExchange.token }]; | ||
case 6: | ||
@@ -950,3 +887,3 @@ _d.trys.push([6, 12, , 13]); | ||
return [3 /*break*/, 11]; | ||
case 8: return [4 /*yield*/, getToken(app).catch(function (_e) { | ||
case 8: return [4 /*yield*/, getToken$2(app).catch(function (_e) { | ||
// reCaptcha.execute() throws null which is not very descriptive. | ||
@@ -978,3 +915,3 @@ throw ERROR_FACTORY.create("recaptcha-error" /* RECAPTCHA_ERROR */); | ||
}; | ||
// write the new token to the memory state as well ashe persistent storage. | ||
// write the new token to the memory state as well as the persistent storage. | ||
// Only do it if we got a valid new token | ||
@@ -993,46 +930,31 @@ setState(app, __assign(__assign({}, state), { token: token })); | ||
} | ||
function addTokenListener(app, platformLoggerProvider, listener) { | ||
function addTokenListener(app, platformLoggerProvider, listener, onError) { | ||
var state = getState(app); | ||
var newState = __assign(__assign({}, state), { tokenListeners: __spreadArray(__spreadArray([], state.tokenListeners), [listener]) }); | ||
var tokenListener = { | ||
next: listener, | ||
error: onError | ||
}; | ||
var newState = __assign(__assign({}, state), { tokenObservers: __spreadArray(__spreadArray([], state.tokenObservers), [tokenListener]) }); | ||
/** | ||
* DEBUG MODE | ||
* | ||
* invoke the listener once with the debug token. | ||
* Invoke the listener with the valid token, then start the token refresher | ||
*/ | ||
if (isDebugMode()) { | ||
var debugState = getDebugState(); | ||
if (debugState.enabled && debugState.token) { | ||
debugState.token.promise | ||
.then(function (token) { return listener({ token: token }); }) | ||
.catch(function () { | ||
/* we don't care about exceptions thrown in listeners */ | ||
}); | ||
} | ||
if (!newState.tokenRefresher) { | ||
var tokenRefresher = createTokenRefresher(app, platformLoggerProvider); | ||
newState.tokenRefresher = tokenRefresher; | ||
} | ||
else { | ||
/** | ||
* PROD MODE | ||
* | ||
* invoke the listener with the valid token, then start the token refresher | ||
*/ | ||
if (!newState.tokenRefresher) { | ||
var tokenRefresher = createTokenRefresher(app, platformLoggerProvider); | ||
newState.tokenRefresher = tokenRefresher; | ||
} | ||
// Create the refresher but don't start it if `isTokenAutoRefreshEnabled` | ||
// is not true. | ||
if (!newState.tokenRefresher.isRunning() && | ||
state.isTokenAutoRefreshEnabled === true) { | ||
newState.tokenRefresher.start(); | ||
} | ||
// invoke the listener async immediately if there is a valid token | ||
if (state.token && isValid(state.token)) { | ||
var validToken_1 = state.token; | ||
Promise.resolve() | ||
.then(function () { return listener({ token: validToken_1.token }); }) | ||
.catch(function () { | ||
/* we don't care about exceptions thrown in listeners */ | ||
}); | ||
} | ||
// Create the refresher but don't start it if `isTokenAutoRefreshEnabled` | ||
// is not true. | ||
if (!newState.tokenRefresher.isRunning() && | ||
state.isTokenAutoRefreshEnabled === true) { | ||
newState.tokenRefresher.start(); | ||
} | ||
// invoke the listener async immediately if there is a valid token | ||
if (state.token && isValid(state.token)) { | ||
var validToken_1 = state.token; | ||
Promise.resolve() | ||
.then(function () { return listener({ token: validToken_1.token }); }) | ||
.catch(function () { | ||
/** Ignore errors in listeners. */ | ||
}); | ||
} | ||
setState(app, newState); | ||
@@ -1042,4 +964,4 @@ } | ||
var state = getState(app); | ||
var newListeners = state.tokenListeners.filter(function (l) { return l !== listener; }); | ||
if (newListeners.length === 0 && | ||
var newObservers = state.tokenObservers.filter(function (tokenObserver) { return tokenObserver.next !== listener; }); | ||
if (newObservers.length === 0 && | ||
state.tokenRefresher && | ||
@@ -1049,3 +971,3 @@ state.tokenRefresher.isRunning()) { | ||
} | ||
setState(app, __assign(__assign({}, state), { tokenListeners: newListeners })); | ||
setState(app, __assign(__assign({}, state), { tokenObservers: newObservers })); | ||
} | ||
@@ -1102,9 +1024,22 @@ function createTokenRefresher(app, platformLoggerProvider) { | ||
function notifyTokenListeners(app, token) { | ||
var listeners = getState(app).tokenListeners; | ||
for (var _i = 0, listeners_1 = listeners; _i < listeners_1.length; _i++) { | ||
var listener = listeners_1[_i]; | ||
var observers = getState(app).tokenObservers; | ||
for (var _i = 0, observers_1 = observers; _i < observers_1.length; _i++) { | ||
var observer = observers_1[_i]; | ||
try { | ||
listener(token); | ||
if (observer.error) { | ||
// If this listener has an error handler, handle errors differently | ||
// from successes. | ||
if (token.error) { | ||
observer.error(token.error); | ||
} | ||
else { | ||
observer.next(token); | ||
} | ||
} | ||
else { | ||
// Otherwise return the token, whether or not it has an error field. | ||
observer.next(token); | ||
} | ||
} | ||
catch (e) { | ||
catch (ignored) { | ||
// If any handler fails, ignore and run next handler. | ||
@@ -1140,7 +1075,143 @@ } | ||
*/ | ||
function factory(app) { | ||
/** | ||
* | ||
* @param app | ||
* @param siteKeyOrProvider - optional custom attestation provider | ||
* or reCAPTCHA siteKey | ||
* @param isTokenAutoRefreshEnabled - if true, enables auto refresh | ||
* of appCheck token. | ||
*/ | ||
function activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
if (state.activated) { | ||
throw ERROR_FACTORY.create("already-activated" /* ALREADY_ACTIVATED */, { | ||
appName: app.name | ||
}); | ||
} | ||
var newState = __assign(__assign({}, state), { activated: true }); | ||
if (typeof siteKeyOrProvider === 'string') { | ||
newState.siteKey = siteKeyOrProvider; | ||
} | ||
else { | ||
newState.customProvider = siteKeyOrProvider; | ||
} | ||
// Use value of global `automaticDataCollectionEnabled` (which | ||
// itself defaults to false if not specified in config) if | ||
// `isTokenAutoRefreshEnabled` param was not provided by user. | ||
newState.isTokenAutoRefreshEnabled = | ||
isTokenAutoRefreshEnabled === undefined | ||
? app.automaticDataCollectionEnabled | ||
: isTokenAutoRefreshEnabled; | ||
setState(app, newState); | ||
// initialize reCAPTCHA if siteKey is provided | ||
if (newState.siteKey) { | ||
initialize(app, newState.siteKey).catch(function () { | ||
/* we don't care about the initialization result in activate() */ | ||
}); | ||
} | ||
} | ||
function setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) { | ||
var state = getState(app); | ||
// This will exist if any product libraries have called | ||
// `addTokenListener()` | ||
if (state.tokenRefresher) { | ||
if (isTokenAutoRefreshEnabled === true) { | ||
state.tokenRefresher.start(); | ||
} | ||
else { | ||
state.tokenRefresher.stop(); | ||
} | ||
} | ||
setState(app, __assign(__assign({}, state), { isTokenAutoRefreshEnabled: isTokenAutoRefreshEnabled })); | ||
} | ||
/** | ||
* Differs from internal getToken in that it throws the error. | ||
*/ | ||
function getToken(app, platformLoggerProvider, forceRefresh) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var result; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, getToken$1(app, platformLoggerProvider, forceRefresh)]; | ||
case 1: | ||
result = _a.sent(); | ||
if (result.error) { | ||
throw result.error; | ||
} | ||
return [2 /*return*/, { token: result.token }]; | ||
} | ||
}); | ||
}); | ||
} | ||
function onTokenChanged(app, platformLoggerProvider, onNextOrObserver, onError, | ||
/** | ||
* NOTE: Although an `onCompletion` callback can be provided, it will | ||
* never be called because the token stream is never-ending. | ||
* It is added only for API consistency with the observer pattern, which | ||
* we follow in JS APIs. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
onCompletion) { | ||
var nextFn = function () { }; | ||
var errorFn = function () { }; | ||
if (onNextOrObserver.next != null) { | ||
nextFn = onNextOrObserver.next.bind(onNextOrObserver); | ||
} | ||
else { | ||
nextFn = onNextOrObserver; | ||
} | ||
if (onNextOrObserver.error != null) { | ||
errorFn = onNextOrObserver.error.bind(onNextOrObserver); | ||
} | ||
else if (onError) { | ||
errorFn = onError; | ||
} | ||
addTokenListener(app, platformLoggerProvider, nextFn, errorFn); | ||
return function () { return removeTokenListener(app, nextFn); }; | ||
} | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
function factory(app, platformLoggerProvider) { | ||
return { | ||
app: app, | ||
activate: function (siteKeyOrProvider, isTokenAutoRefreshEnabled) { return activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled); }, | ||
setTokenAutoRefreshEnabled: function (isTokenAutoRefreshEnabled) { | ||
return setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled); | ||
}, | ||
getToken: function (forceRefresh) { | ||
return getToken(app, platformLoggerProvider, forceRefresh); | ||
}, | ||
onTokenChanged: function (onNextOrObserver, onError, onCompletion) { | ||
return onTokenChanged(app, platformLoggerProvider, | ||
/** | ||
* This can still be an observer. Need to do this casting because | ||
* according to Typescript: "Implementation signatures of overloads | ||
* are not externally visible" | ||
*/ | ||
onNextOrObserver, onError); | ||
}, | ||
INTERNAL: { | ||
delete: function () { | ||
var tokenObservers = getState(app).tokenObservers; | ||
for (var _i = 0, tokenObservers_1 = tokenObservers; _i < tokenObservers_1.length; _i++) { | ||
var tokenObserver = tokenObservers_1[_i]; | ||
removeTokenListener(app, tokenObserver.next); | ||
} | ||
return Promise.resolve(); | ||
} | ||
} | ||
@@ -1162,3 +1233,3 @@ }; | ||
var name = "@firebase/app-check"; | ||
var version = "0.1.4"; | ||
var version = "0.2.0-202153001032"; | ||
@@ -1188,3 +1259,4 @@ /** | ||
var app = container.getProvider('app').getImmediate(); | ||
return factory(app); | ||
var platformLoggerProvider = container.getProvider('platform-logger'); | ||
return factory(app, platformLoggerProvider); | ||
}, "PUBLIC" /* PUBLIC */) | ||
@@ -1191,0 +1263,0 @@ /** |
@@ -59,3 +59,3 @@ import firebase from '@firebase/app'; | ||
activated: false, | ||
tokenListeners: [] | ||
tokenObservers: [] | ||
}; | ||
@@ -160,3 +160,3 @@ const DEBUG_STATE = { | ||
} | ||
async function getToken(app) { | ||
async function getToken$2(app) { | ||
ensureActivated(app); | ||
@@ -215,70 +215,2 @@ // ensureActivated() guarantees that reCAPTCHAState is set | ||
*/ | ||
/** | ||
* | ||
* @param app | ||
* @param siteKeyOrProvider - optional custom attestation provider | ||
* or reCAPTCHA siteKey | ||
* @param isTokenAutoRefreshEnabled - if true, enables auto refresh | ||
* of appCheck token. | ||
*/ | ||
function activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled) { | ||
const state = getState(app); | ||
if (state.activated) { | ||
throw ERROR_FACTORY.create("already-activated" /* ALREADY_ACTIVATED */, { | ||
appName: app.name | ||
}); | ||
} | ||
const newState = Object.assign(Object.assign({}, state), { activated: true }); | ||
if (typeof siteKeyOrProvider === 'string') { | ||
newState.siteKey = siteKeyOrProvider; | ||
} | ||
else { | ||
newState.customProvider = siteKeyOrProvider; | ||
} | ||
// Use value of global `automaticDataCollectionEnabled` (which | ||
// itself defaults to false if not specified in config) if | ||
// `isTokenAutoRefreshEnabled` param was not provided by user. | ||
newState.isTokenAutoRefreshEnabled = | ||
isTokenAutoRefreshEnabled === undefined | ||
? app.automaticDataCollectionEnabled | ||
: isTokenAutoRefreshEnabled; | ||
setState(app, newState); | ||
// initialize reCAPTCHA if siteKey is provided | ||
if (newState.siteKey) { | ||
initialize(app, newState.siteKey).catch(() => { | ||
/* we don't care about the initialization result in activate() */ | ||
}); | ||
} | ||
} | ||
function setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) { | ||
const state = getState(app); | ||
// This will exist if any product libraries have called | ||
// `addTokenListener()` | ||
if (state.tokenRefresher) { | ||
if (isTokenAutoRefreshEnabled === true) { | ||
state.tokenRefresher.start(); | ||
} | ||
else { | ||
state.tokenRefresher.stop(); | ||
} | ||
} | ||
setState(app, Object.assign(Object.assign({}, state), { isTokenAutoRefreshEnabled })); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
const BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1beta'; | ||
@@ -803,15 +735,10 @@ const EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaToken'; | ||
ensureActivated(app); | ||
const state = getState(app); | ||
/** | ||
* DEBUG MODE | ||
* return the debug token directly | ||
* First check if there is a token in memory from a previous `getToken()` call. | ||
*/ | ||
if (isDebugMode()) { | ||
const tokenFromDebugExchange = await exchangeToken(getExchangeDebugTokenRequest(app, await getDebugToken()), platformLoggerProvider); | ||
return { token: tokenFromDebugExchange.token }; | ||
} | ||
const state = getState(app); | ||
let token = state.token; | ||
let error = undefined; | ||
/** | ||
* try to load token from indexedDB if it's the first time this function is called | ||
* If there is no token in memory, try to load token from indexedDB. | ||
*/ | ||
@@ -828,3 +755,3 @@ if (!token) { | ||
} | ||
// return the cached token if it's valid | ||
// Return the cached token (from either memory or indexedDB) if it's valid | ||
if (!forceRefresh && token && isValid(token)) { | ||
@@ -836,2 +763,15 @@ return { | ||
/** | ||
* DEBUG MODE | ||
* If debug mode is set, and there is no cached token, fetch a new App | ||
* Check token using the debug token, and return it directly. | ||
*/ | ||
if (isDebugMode()) { | ||
const tokenFromDebugExchange = await exchangeToken(getExchangeDebugTokenRequest(app, await getDebugToken()), platformLoggerProvider); | ||
// Write debug token to indexedDB. | ||
await writeTokenToStorage(app, tokenFromDebugExchange); | ||
// Write debug token to state. | ||
setState(app, Object.assign(Object.assign({}, state), { token: tokenFromDebugExchange })); | ||
return { token: tokenFromDebugExchange.token }; | ||
} | ||
/** | ||
* request a new token | ||
@@ -855,3 +795,3 @@ */ | ||
else { | ||
const attestedClaimsToken = await getToken(app).catch(_e => { | ||
const attestedClaimsToken = await getToken$2(app).catch(_e => { | ||
// reCaptcha.execute() throws null which is not very descriptive. | ||
@@ -878,3 +818,3 @@ throw ERROR_FACTORY.create("recaptcha-error" /* RECAPTCHA_ERROR */); | ||
}; | ||
// write the new token to the memory state as well ashe persistent storage. | ||
// write the new token to the memory state as well as the persistent storage. | ||
// Only do it if we got a valid new token | ||
@@ -887,46 +827,31 @@ setState(app, Object.assign(Object.assign({}, state), { token })); | ||
} | ||
function addTokenListener(app, platformLoggerProvider, listener) { | ||
function addTokenListener(app, platformLoggerProvider, listener, onError) { | ||
const state = getState(app); | ||
const newState = Object.assign(Object.assign({}, state), { tokenListeners: [...state.tokenListeners, listener] }); | ||
const tokenListener = { | ||
next: listener, | ||
error: onError | ||
}; | ||
const newState = Object.assign(Object.assign({}, state), { tokenObservers: [...state.tokenObservers, tokenListener] }); | ||
/** | ||
* DEBUG MODE | ||
* | ||
* invoke the listener once with the debug token. | ||
* Invoke the listener with the valid token, then start the token refresher | ||
*/ | ||
if (isDebugMode()) { | ||
const debugState = getDebugState(); | ||
if (debugState.enabled && debugState.token) { | ||
debugState.token.promise | ||
.then(token => listener({ token })) | ||
.catch(() => { | ||
/* we don't care about exceptions thrown in listeners */ | ||
}); | ||
} | ||
if (!newState.tokenRefresher) { | ||
const tokenRefresher = createTokenRefresher(app, platformLoggerProvider); | ||
newState.tokenRefresher = tokenRefresher; | ||
} | ||
else { | ||
/** | ||
* PROD MODE | ||
* | ||
* invoke the listener with the valid token, then start the token refresher | ||
*/ | ||
if (!newState.tokenRefresher) { | ||
const tokenRefresher = createTokenRefresher(app, platformLoggerProvider); | ||
newState.tokenRefresher = tokenRefresher; | ||
} | ||
// Create the refresher but don't start it if `isTokenAutoRefreshEnabled` | ||
// is not true. | ||
if (!newState.tokenRefresher.isRunning() && | ||
state.isTokenAutoRefreshEnabled === true) { | ||
newState.tokenRefresher.start(); | ||
} | ||
// invoke the listener async immediately if there is a valid token | ||
if (state.token && isValid(state.token)) { | ||
const validToken = state.token; | ||
Promise.resolve() | ||
.then(() => listener({ token: validToken.token })) | ||
.catch(() => { | ||
/* we don't care about exceptions thrown in listeners */ | ||
}); | ||
} | ||
// Create the refresher but don't start it if `isTokenAutoRefreshEnabled` | ||
// is not true. | ||
if (!newState.tokenRefresher.isRunning() && | ||
state.isTokenAutoRefreshEnabled === true) { | ||
newState.tokenRefresher.start(); | ||
} | ||
// invoke the listener async immediately if there is a valid token | ||
if (state.token && isValid(state.token)) { | ||
const validToken = state.token; | ||
Promise.resolve() | ||
.then(() => listener({ token: validToken.token })) | ||
.catch(() => { | ||
/** Ignore errors in listeners. */ | ||
}); | ||
} | ||
setState(app, newState); | ||
@@ -936,4 +861,4 @@ } | ||
const state = getState(app); | ||
const newListeners = state.tokenListeners.filter(l => l !== listener); | ||
if (newListeners.length === 0 && | ||
const newObservers = state.tokenObservers.filter(tokenObserver => tokenObserver.next !== listener); | ||
if (newObservers.length === 0 && | ||
state.tokenRefresher && | ||
@@ -943,3 +868,3 @@ state.tokenRefresher.isRunning()) { | ||
} | ||
setState(app, Object.assign(Object.assign({}, state), { tokenListeners: newListeners })); | ||
setState(app, Object.assign(Object.assign({}, state), { tokenObservers: newObservers })); | ||
} | ||
@@ -987,8 +912,21 @@ function createTokenRefresher(app, platformLoggerProvider) { | ||
function notifyTokenListeners(app, token) { | ||
const listeners = getState(app).tokenListeners; | ||
for (const listener of listeners) { | ||
const observers = getState(app).tokenObservers; | ||
for (const observer of observers) { | ||
try { | ||
listener(token); | ||
if (observer.error) { | ||
// If this listener has an error handler, handle errors differently | ||
// from successes. | ||
if (token.error) { | ||
observer.error(token.error); | ||
} | ||
else { | ||
observer.next(token); | ||
} | ||
} | ||
else { | ||
// Otherwise return the token, whether or not it has an error field. | ||
observer.next(token); | ||
} | ||
} | ||
catch (e) { | ||
catch (ignored) { | ||
// If any handler fails, ignore and run next handler. | ||
@@ -1024,6 +962,128 @@ } | ||
*/ | ||
function factory(app) { | ||
/** | ||
* | ||
* @param app | ||
* @param siteKeyOrProvider - optional custom attestation provider | ||
* or reCAPTCHA siteKey | ||
* @param isTokenAutoRefreshEnabled - if true, enables auto refresh | ||
* of appCheck token. | ||
*/ | ||
function activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled) { | ||
const state = getState(app); | ||
if (state.activated) { | ||
throw ERROR_FACTORY.create("already-activated" /* ALREADY_ACTIVATED */, { | ||
appName: app.name | ||
}); | ||
} | ||
const newState = Object.assign(Object.assign({}, state), { activated: true }); | ||
if (typeof siteKeyOrProvider === 'string') { | ||
newState.siteKey = siteKeyOrProvider; | ||
} | ||
else { | ||
newState.customProvider = siteKeyOrProvider; | ||
} | ||
// Use value of global `automaticDataCollectionEnabled` (which | ||
// itself defaults to false if not specified in config) if | ||
// `isTokenAutoRefreshEnabled` param was not provided by user. | ||
newState.isTokenAutoRefreshEnabled = | ||
isTokenAutoRefreshEnabled === undefined | ||
? app.automaticDataCollectionEnabled | ||
: isTokenAutoRefreshEnabled; | ||
setState(app, newState); | ||
// initialize reCAPTCHA if siteKey is provided | ||
if (newState.siteKey) { | ||
initialize(app, newState.siteKey).catch(() => { | ||
/* we don't care about the initialization result in activate() */ | ||
}); | ||
} | ||
} | ||
function setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) { | ||
const state = getState(app); | ||
// This will exist if any product libraries have called | ||
// `addTokenListener()` | ||
if (state.tokenRefresher) { | ||
if (isTokenAutoRefreshEnabled === true) { | ||
state.tokenRefresher.start(); | ||
} | ||
else { | ||
state.tokenRefresher.stop(); | ||
} | ||
} | ||
setState(app, Object.assign(Object.assign({}, state), { isTokenAutoRefreshEnabled })); | ||
} | ||
/** | ||
* Differs from internal getToken in that it throws the error. | ||
*/ | ||
async function getToken(app, platformLoggerProvider, forceRefresh) { | ||
const result = await getToken$1(app, platformLoggerProvider, forceRefresh); | ||
if (result.error) { | ||
throw result.error; | ||
} | ||
return { token: result.token }; | ||
} | ||
function onTokenChanged(app, platformLoggerProvider, onNextOrObserver, onError, | ||
/** | ||
* NOTE: Although an `onCompletion` callback can be provided, it will | ||
* never be called because the token stream is never-ending. | ||
* It is added only for API consistency with the observer pattern, which | ||
* we follow in JS APIs. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
onCompletion) { | ||
let nextFn = () => { }; | ||
let errorFn = () => { }; | ||
if (onNextOrObserver.next != null) { | ||
nextFn = onNextOrObserver.next.bind(onNextOrObserver); | ||
} | ||
else { | ||
nextFn = onNextOrObserver; | ||
} | ||
if (onNextOrObserver.error != null) { | ||
errorFn = onNextOrObserver.error.bind(onNextOrObserver); | ||
} | ||
else if (onError) { | ||
errorFn = onError; | ||
} | ||
addTokenListener(app, platformLoggerProvider, nextFn, errorFn); | ||
return () => removeTokenListener(app, nextFn); | ||
} | ||
/** | ||
* @license | ||
* Copyright 2020 Google LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
function factory(app, platformLoggerProvider) { | ||
return { | ||
app, | ||
activate: (siteKeyOrProvider, isTokenAutoRefreshEnabled) => activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled), | ||
setTokenAutoRefreshEnabled: (isTokenAutoRefreshEnabled) => setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled) | ||
setTokenAutoRefreshEnabled: (isTokenAutoRefreshEnabled) => setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled), | ||
getToken: forceRefresh => getToken(app, platformLoggerProvider, forceRefresh), | ||
onTokenChanged: (onNextOrObserver, onError, onCompletion) => onTokenChanged(app, platformLoggerProvider, | ||
/** | ||
* This can still be an observer. Need to do this casting because | ||
* according to Typescript: "Implementation signatures of overloads | ||
* are not externally visible" | ||
*/ | ||
onNextOrObserver, onError), | ||
INTERNAL: { | ||
delete: () => { | ||
const { tokenObservers } = getState(app); | ||
for (const tokenObserver of tokenObservers) { | ||
removeTokenListener(app, tokenObserver.next); | ||
} | ||
return Promise.resolve(); | ||
} | ||
} | ||
}; | ||
@@ -1040,3 +1100,3 @@ } | ||
const name = "@firebase/app-check"; | ||
const version = "0.1.4"; | ||
const version = "0.2.0-202153001032"; | ||
@@ -1066,3 +1126,4 @@ /** | ||
const app = container.getProvider('app').getImmediate(); | ||
return factory(app); | ||
const platformLoggerProvider = container.getProvider('platform-logger'); | ||
return factory(app, platformLoggerProvider); | ||
}, "PUBLIC" /* PUBLIC */) | ||
@@ -1069,0 +1130,0 @@ /** |
@@ -17,4 +17,6 @@ /** | ||
*/ | ||
import { AppCheckProvider } from '@firebase/app-check-types'; | ||
import { AppCheckProvider, AppCheckTokenResult } from '@firebase/app-check-types'; | ||
import { FirebaseApp } from '@firebase/app-types'; | ||
import { Provider } from '@firebase/component'; | ||
import { PartialObserver, Unsubscribe } from '@firebase/util'; | ||
/** | ||
@@ -30,1 +32,11 @@ * | ||
export declare function setTokenAutoRefreshEnabled(app: FirebaseApp, isTokenAutoRefreshEnabled: boolean): void; | ||
/** | ||
* Differs from internal getToken in that it throws the error. | ||
*/ | ||
export declare function getToken(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>, forceRefresh?: boolean): Promise<AppCheckTokenResult>; | ||
/** | ||
* Wraps addTokenListener/removeTokenListener methods in an Observer | ||
* pattern for public use. | ||
*/ | ||
export declare function onTokenChanged(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>, observer: PartialObserver<AppCheckTokenResult>): Unsubscribe; | ||
export declare function onTokenChanged(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>, onNext: (tokenResult: AppCheckTokenResult) => void, onError?: (error: Error) => void, onCompletion?: () => void): Unsubscribe; |
@@ -21,3 +21,4 @@ /** | ||
import { Provider } from '@firebase/component'; | ||
export declare function factory(app: FirebaseApp): FirebaseAppCheck; | ||
import { FirebaseService } from '@firebase/app-types/private'; | ||
export declare function factory(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>): FirebaseAppCheck & FirebaseService; | ||
export declare function internalFactory(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>): FirebaseAppCheckInternal; |
@@ -18,3 +18,3 @@ /** | ||
import { FirebaseApp } from '@firebase/app-types'; | ||
import { AppCheckTokenResult, AppCheckTokenListener } from '@firebase/app-check-interop-types'; | ||
import { AppCheckTokenListener, AppCheckTokenResult } from '@firebase/app-check-interop-types'; | ||
import { Provider } from '@firebase/component'; | ||
@@ -36,3 +36,3 @@ export declare const defaultTokenErrorData: { | ||
export declare function getToken(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>, forceRefresh?: boolean): Promise<AppCheckTokenResult>; | ||
export declare function addTokenListener(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>, listener: AppCheckTokenListener): void; | ||
export declare function removeTokenListener(app: FirebaseApp, listener: AppCheckTokenListener): void; | ||
export declare function addTokenListener(app: FirebaseApp, platformLoggerProvider: Provider<'platform-logger'>, listener: AppCheckTokenListener, onError?: (error: Error) => void): void; | ||
export declare function removeTokenListener(app: FirebaseApp, listener: (token: AppCheckTokenResult) => void): void; |
@@ -18,6 +18,6 @@ /** | ||
import { FirebaseApp } from '@firebase/app-types'; | ||
import { AppCheckProvider, AppCheckToken } from '@firebase/app-check-types'; | ||
import { AppCheckProvider, AppCheckToken, AppCheckTokenResult } from '@firebase/app-check-types'; | ||
import { AppCheckTokenListener } from '@firebase/app-check-interop-types'; | ||
import { Refresher } from './proactive-refresh'; | ||
import { Deferred } from '@firebase/util'; | ||
import { Deferred, PartialObserver } from '@firebase/util'; | ||
import { GreCAPTCHA } from './recaptcha'; | ||
@@ -27,5 +27,8 @@ export interface AppCheckTokenInternal extends AppCheckToken { | ||
} | ||
export interface AppCheckTokenObserver extends PartialObserver<AppCheckTokenResult> { | ||
next: AppCheckTokenListener; | ||
} | ||
export interface AppCheckState { | ||
activated: boolean; | ||
tokenListeners: AppCheckTokenListener[]; | ||
tokenObservers: AppCheckTokenObserver[]; | ||
customProvider?: AppCheckProvider; | ||
@@ -32,0 +35,0 @@ siteKey?: string; |
{ | ||
"name": "@firebase/app-check", | ||
"version": "0.1.4", | ||
"version": "0.2.0-202153001032", | ||
"description": "The App Check component of the Firebase JS SDK", | ||
@@ -19,3 +19,3 @@ "author": "Firebase <firebase-support@google.com> (https://firebase.google.com/)", | ||
"dev": "rollup -c -w", | ||
"test": "yarn type-check && yarn test:browser", | ||
"test": "yarn lint && yarn type-check && yarn test:browser", | ||
"test:ci": "node ../../scripts/run_tests_in_ci.js", | ||
@@ -28,10 +28,10 @@ "test:browser": "karma start --single-run", | ||
"peerDependencies": { | ||
"@firebase/app": "0.x", | ||
"@firebase/app": "0.6.28-202153001032", | ||
"@firebase/app-types": "0.x" | ||
}, | ||
"dependencies": { | ||
"@firebase/app-check-types": "0.1.0", | ||
"@firebase/app-check-types": "0.2.0-202153001032", | ||
"@firebase/app-check-interop-types": "0.1.0", | ||
"@firebase/util": "1.1.0", | ||
"@firebase/component": "0.5.3", | ||
"@firebase/component": "0.5.4-202153001032", | ||
"@firebase/logger": "0.2.6", | ||
@@ -42,6 +42,6 @@ "tslib": "^2.1.0" | ||
"devDependencies": { | ||
"@firebase/app": "0.6.27", | ||
"rollup": "2.35.1", | ||
"@firebase/app": "0.6.28-202153001032", | ||
"rollup": "2.52.2", | ||
"@rollup/plugin-json": "4.1.0", | ||
"rollup-plugin-typescript2": "0.29.0", | ||
"rollup-plugin-typescript2": "0.30.0", | ||
"typescript": "4.2.2" | ||
@@ -48,0 +48,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
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
411325
4275
+ Added@firebase/app@0.6.28-202153001032(transitive)
+ Added@firebase/app-check-types@0.2.0-202153001032(transitive)
+ Added@firebase/app-types@0.6.2(transitive)
+ Added@firebase/component@0.5.4-202153001032(transitive)
+ Addeddom-storage@2.1.0(transitive)
+ Addedxmlhttprequest@1.8.0(transitive)
- Removed@firebase/app@0.10.17(transitive)
- Removed@firebase/app-check-types@0.1.0(transitive)
- Removed@firebase/component@0.5.30.6.11(transitive)
- Removed@firebase/logger@0.4.4(transitive)
- Removed@firebase/util@1.10.2(transitive)
- Removedidb@7.1.1(transitive)