diff --git a/.eslintrc.js b/.eslintrc.js index 30b4093d..76801010 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -46,7 +46,6 @@ module.exports = { 'no-empty-description': 'off', '@typescript-eslint/ban-ts-comment': 'off', // keep it professional when you use them though please '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-explicit-any': 'off', '@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', diff --git a/.gitignore b/.gitignore index 91b3b993..78f4f3f2 100644 --- a/.gitignore +++ b/.gitignore @@ -551,6 +551,7 @@ google-services.json GoogleService-Info.plist # generated files +src/version.ts RNFBVersion.m ReactNativeFirebaseVersion.java @@ -564,3 +565,6 @@ spelling.json # Gatsby / Website website/.cache website/public + +# generated files by bob +lib/ diff --git a/__tests__/consent.test.ts b/__tests__/consent.test.ts index 52addaaf..1dfd2630 100644 --- a/__tests__/consent.test.ts +++ b/__tests__/consent.test.ts @@ -1,4 +1,4 @@ -import { AdsConsent } from '../lib'; +import { AdsConsent } from '../src'; describe('Google Ads AdsConsent', function () { describe('requestInfoUpdate', function () { diff --git a/__tests__/googleAds.test.ts b/__tests__/googleAds.test.ts index 9206e84a..d4d08273 100644 --- a/__tests__/googleAds.test.ts +++ b/__tests__/googleAds.test.ts @@ -1,4 +1,4 @@ -import admob, { GoogleAdsTypes } from '../lib'; +import admob, { MaxAdContentRating } from '../src'; describe('Admob', function () { describe('setRequestConfiguration()', function () { @@ -13,8 +13,7 @@ describe('Admob', function () { it('throws if maxAdContentRating is invalid', function () { expect(() => admob().setRequestConfiguration({ - maxAdContentRating: - 'Y' as GoogleAdsTypes.MaxAdContentRating[keyof GoogleAdsTypes.MaxAdContentRating], + maxAdContentRating: 'Y' as MaxAdContentRating, }), ).toThrowError( "setRequestConfiguration(*) 'requestConfiguration.maxAdContentRating' expected on of MaxAdContentRating.G, MaxAdContentRating.PG, MaxAdContentRating.T or MaxAdContentRating.MA", diff --git a/__tests__/interstitial.test.ts b/__tests__/interstitial.test.ts index 8119805d..188f725a 100644 --- a/__tests__/interstitial.test.ts +++ b/__tests__/interstitial.test.ts @@ -1,4 +1,4 @@ -import { InterstitialAd } from '../lib'; +import { InterstitialAd } from '../src'; describe('Google Ads Interstitial', function () { describe('createForAdRequest', function () { diff --git a/android/src/main/java/io/invertase/googleads/common/ReactNativeModule.java b/android/src/main/java/io/invertase/googleads/common/ReactNativeModule.java index 40546baa..bc7de014 100644 --- a/android/src/main/java/io/invertase/googleads/common/ReactNativeModule.java +++ b/android/src/main/java/io/invertase/googleads/common/ReactNativeModule.java @@ -37,10 +37,6 @@ public ReactNativeModule(ReactApplicationContext reactContext, String moduleName this.executorService = new TaskExecutorService(getName()); } - public static void rejectPromiseWithExceptionMap(Promise promise, Exception exception) { - promise.reject(exception, SharedUtils.getExceptionMap(exception)); - } - public static void rejectPromiseWithCodeAndMessage(Promise promise, String code, String message) { WritableMap userInfoMap = Arguments.createMap(); userInfoMap.putString("code", code); @@ -48,15 +44,6 @@ public static void rejectPromiseWithCodeAndMessage(Promise promise, String code, promise.reject(code, message, userInfoMap); } - public static void rejectPromiseWithCodeAndMessage( - Promise promise, String code, String message, String nativeErrorMessage) { - WritableMap userInfoMap = Arguments.createMap(); - userInfoMap.putString("code", code); - userInfoMap.putString("message", message); - userInfoMap.putString("nativeErrorMessage", nativeErrorMessage); - promise.reject(code, message, userInfoMap); - } - @Override public void initialize() { super.initialize(); diff --git a/android/src/main/java/io/invertase/googleads/common/SharedUtils.java b/android/src/main/java/io/invertase/googleads/common/SharedUtils.java index 91feb19b..492c5d71 100644 --- a/android/src/main/java/io/invertase/googleads/common/SharedUtils.java +++ b/android/src/main/java/io/invertase/googleads/common/SharedUtils.java @@ -82,17 +82,6 @@ public static Uri getUri(String uri) { return parsed; } - public static WritableMap getExceptionMap(Exception exception) { - WritableMap exceptionMap = Arguments.createMap(); - String code = "unknown"; - String message = exception.getMessage(); - exceptionMap.putString("code", code); - exceptionMap.putString("nativeErrorCode", code); - exceptionMap.putString("message", message); - exceptionMap.putString("nativeErrorMessage", message); - return exceptionMap; - } - public static String timestampToUTC(long timestamp) { long millisTimestamp = timestamp * 1000; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); diff --git a/docs/index.mdx b/docs/index.mdx index 9e3a5b97..2dadae8f 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -78,9 +78,9 @@ receive content suitable for children before loading any adverts. If you need to set a custom request configuration, you must call the `setRequestConfiguration` method before initializing the Google Mobile Ads SDK: ```js -import admob, { MaxAdContentRating } from '@invertase/react-native-google-ads'; +import mobileAds, { MaxAdContentRating } from '@invertase/react-native-google-ads'; -admob() +mobileAds() .setRequestConfiguration({ // Update all future requests suitable for parental guidance maxAdContentRating: MaxAdContentRating.PG, @@ -111,9 +111,9 @@ This needs to be done only once, ideally at app launch. If you need to obtain consent from users in the European Economic Area (EEA), set any request-specific flags (such as tagForChildDirectedTreatment), or otherwise take action before loading ads, ensure you do so before initializing the Mobile Ads SDK. ```js -import admob from '@invertase/react-native-google-ads'; +import mobileAds from '@invertase/react-native-google-ads'; -admob() +mobileAds() .initialize() .then((adapterStatuses) => { // Initialization complete! diff --git a/ios/RNGoogleAds/common/RNSharedUtils.h b/ios/RNGoogleAds/common/RNSharedUtils.h index 2b74bee6..6ab0653c 100644 --- a/ios/RNGoogleAds/common/RNSharedUtils.h +++ b/ios/RNGoogleAds/common/RNSharedUtils.h @@ -38,11 +38,6 @@ + (void)sendJSEvent:name:(NSString *)name body:(NSDictionary *)body; -+ (void)rejectPromiseWithExceptionDict:(RCTPromiseRejectBlock)reject - exception:(NSException *)exception; - -+ (void)rejectPromiseWithNSError:(RCTPromiseRejectBlock)reject error:(NSError *)error; - + (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject userInfo:(NSMutableDictionary *)userInfo; diff --git a/ios/RNGoogleAds/common/RNSharedUtils.m b/ios/RNGoogleAds/common/RNSharedUtils.m index 2b7b180f..d4831264 100644 --- a/ios/RNGoogleAds/common/RNSharedUtils.m +++ b/ios/RNGoogleAds/common/RNSharedUtils.m @@ -27,36 +27,6 @@ @implementation RNSharedUtils #pragma mark - #pragma mark Methods -+ (void)rejectPromiseWithExceptionDict:(RCTPromiseRejectBlock)reject - exception:(NSException *)exception { - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - - [userInfo setValue:@(YES) forKey:@"fatal"]; - [userInfo setValue:@"unknown" forKey:@"code"]; - [userInfo setValue:exception.reason forKey:@"message"]; - [userInfo setValue:exception.name forKey:@"nativeErrorCode"]; - [userInfo setValue:exception.reason forKey:@"nativeErrorMessage"]; - - NSError *error = [NSError errorWithDomain:RNErrorDomain code:666 userInfo:userInfo]; - - reject(exception.name, exception.reason, error); -} - -+ (void)rejectPromiseWithNSError:(RCTPromiseRejectBlock)reject error:(NSError *)error { - NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; - - [userInfo setValue:@(NO) forKey:@"fatal"]; - [userInfo setValue:@"unknown" forKey:@"code"]; - [userInfo setValue:error.localizedDescription forKey:@"message"]; - [userInfo setValue:@(error.code) forKey:@"nativeErrorCode"]; - [userInfo setValue:error.localizedDescription forKey:@"nativeErrorMessage"]; - - NSError *newErrorWithUserInfo = [NSError errorWithDomain:RNErrorDomain - code:666 - userInfo:userInfo]; - reject(@"unknown", error.localizedDescription, newErrorWithUserInfo); -} - + (void)rejectPromiseWithUserInfo:(RCTPromiseRejectBlock)reject userInfo:(NSMutableDictionary *)userInfo { NSError *error = [NSError errorWithDomain:RNErrorDomain code:666 userInfo:userInfo]; diff --git a/jest.config.js b/jest.config.js index 65dbcff8..bedef32d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,13 +1,6 @@ module.exports = { - maxConcurrency: 10, - preset: './node_modules/react-native/jest-preset.js', - transform: { - '^.+\\.(js)$': '/node_modules/babel-jest', - '\\.(ts|tsx)$': 'ts-jest', - }, + preset: 'react-native', + modulePathIgnorePatterns: ['/example/node_modules', '/lib/'], setupFiles: ['./jest.setup.ts'], testRegex: '(/^__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$', - modulePaths: ['node_modules'], - moduleDirectories: ['node_modules'], - moduleFileExtensions: ['ts', 'tsx', 'js'], }; diff --git a/lib/AdEventType.js b/lib/AdEventType.js deleted file mode 100644 index c16d2a05..00000000 --- a/lib/AdEventType.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -export default { - LOADED: 'loaded', - ERROR: 'error', - OPENED: 'opened', - CLICKED: 'clicked', - CLOSED: 'closed', -}; diff --git a/lib/MaxAdContentRating.js b/lib/MaxAdContentRating.js deleted file mode 100644 index 9c70b282..00000000 --- a/lib/MaxAdContentRating.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -export default { - G: 'G', - PG: 'PG', - T: 'T', - MA: 'MA', -}; diff --git a/lib/RewardedAdEventType.js b/lib/RewardedAdEventType.js deleted file mode 100644 index 199b1235..00000000 --- a/lib/RewardedAdEventType.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -export default { - LOADED: 'rewarded_loaded', - EARNED_REWARD: 'rewarded_earned_reward', -}; diff --git a/lib/ads/InterstitialAd.js b/lib/ads/InterstitialAd.js deleted file mode 100644 index bafcedeb..00000000 --- a/lib/ads/InterstitialAd.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -import { isFunction, isString } from '../common'; -import googleAds from '../googleMobileAds'; -import validateAdRequestOptions from '../validateAdRequestOptions'; -import validateAdShowOptions from '../validateAdShowOptions'; -import MobileAd from './MobileAd'; - -let _interstitialRequest = 0; - -export default class InterstitialAd extends MobileAd { - static createForAdRequest(adUnitId, requestOptions) { - if (!isString(adUnitId)) { - throw new Error("InterstitialAd.createForAdRequest(*) 'adUnitId' expected an string value."); - } - - let options = {}; - try { - options = validateAdRequestOptions(requestOptions); - } catch (e) { - throw new Error(`InterstitialAd.createForAdRequest(_, *) ${e.message}.`); - } - - const requestId = _interstitialRequest++; - return new InterstitialAd('interstitial', googleAds(), requestId, adUnitId, options); - } - - load() { - // Prevent multiple load calls - if (this._loaded || this._isLoadCalled) { - return; - } - - this._isLoadCalled = true; - this._googleAds.native.interstitialLoad(this._requestId, this._adUnitId, this._requestOptions); - } - - onAdEvent(handler) { - if (!isFunction(handler)) { - throw new Error("InterstitialAd.onAdEvent(*) 'handler' expected a function."); - } - - return this._setAdEventHandler(handler); - } - - show(showOptions) { - if (!this._loaded) { - throw new Error( - 'InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown.', - ); - } - - let options; - try { - options = validateAdShowOptions(showOptions); - } catch (e) { - throw new Error(`InterstitialAd.show(*) ${e.message}.`); - } - - return this._googleAds.native.interstitialShow(this._requestId, options); - } -} diff --git a/lib/ads/RewardedAd.js b/lib/ads/RewardedAd.js deleted file mode 100644 index 2c2a837e..00000000 --- a/lib/ads/RewardedAd.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -import { isFunction, isString } from '../common'; -import googleAds from '../googleMobileAds'; -import validateAdRequestOptions from '../validateAdRequestOptions'; -import validateAdShowOptions from '../validateAdShowOptions'; -import MobileAd from './MobileAd'; - -let _rewardedRequest = 0; - -export default class RewardedAd extends MobileAd { - static createForAdRequest(adUnitId, requestOptions) { - if (!isString(adUnitId)) { - throw new Error("RewardedAd.createForAdRequest(*) 'adUnitId' expected an string value."); - } - - let options = {}; - try { - options = validateAdRequestOptions(requestOptions); - } catch (e) { - throw new Error(`RewardedAd.createForAdRequest(_, *) ${e.message}.`); - } - - const requestId = _rewardedRequest++; - return new RewardedAd('rewarded', googleAds(), requestId, adUnitId, options); - } - - load() { - // Prevent multiple load calls - if (this._loaded || this._isLoadCalled) { - return; - } - - this._isLoadCalled = true; - this._googleAds.native.rewardedLoad(this._requestId, this._adUnitId, this._requestOptions); - } - - onAdEvent(handler) { - if (!isFunction(handler)) { - throw new Error("RewardedAd.onAdEvent(*) 'handler' expected a function."); - } - - return this._setAdEventHandler(handler); - } - - show(showOptions) { - if (!this._loaded) { - throw new Error( - 'RewardedAd.show() The requested RewardedAd has not loaded and could not be shown.', - ); - } - - let options; - try { - options = validateAdShowOptions(showOptions); - } catch (e) { - throw new Error(`RewardedAd.show(*) ${e.message}.`); - } - return this._googleAds.native.rewardedShow(this._requestId, this._adUnitId, options); - } -} diff --git a/lib/googleMobileAds.js b/lib/googleMobileAds.js deleted file mode 100644 index 873e2f95..00000000 --- a/lib/googleMobileAds.js +++ /dev/null @@ -1,54 +0,0 @@ -import { Module } from './internal'; -import validateAdRequestConfiguration from './validateAdRequestConfiguration'; -import version from './version'; - -const namespace = 'google_ads'; - -const nativeModuleName = [ - 'RNGoogleAdsModule', - 'RNGoogleAdsInterstitialModule', - 'RNGoogleAdsRewardedModule', -]; - -class GoogleAdsModule extends Module { - constructor(...args) { - super(...args); - - this.emitter.addListener('google_ads_interstitial_event', event => { - this.emitter.emit( - `google_ads_interstitial_event:${event.adUnitId}:${event.requestId}`, - event, - ); - }); - - this.emitter.addListener('google_ads_rewarded_event', event => { - this.emitter.emit(`google_ads_rewarded_event:${event.adUnitId}:${event.requestId}`, event); - }); - } - - initialize() { - return this.native.initialize(); - } - - setRequestConfiguration(requestConfiguration) { - let config; - try { - config = validateAdRequestConfiguration(requestConfiguration); - } catch (e) { - throw new Error(`googleAds.setRequestConfiguration(*) ${e.message}`); - } - - return this.native.setRequestConfiguration(config); - } -} - -const googleMobileAds = new GoogleAdsModule('AppName', { - version, - namespace, - nativeModuleName, - nativeEvents: ['google_ads_interstitial_event', 'google_ads_rewarded_event'], -}); - -export default () => { - return googleMobileAds; -}; diff --git a/lib/index.d.ts b/lib/index.d.ts deleted file mode 100644 index 3de66887..00000000 --- a/lib/index.d.ts +++ /dev/null @@ -1,1184 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ -import * as React from 'react'; - -/** - * Google Ads package for React Native. - * - * #### Example: Using the default export from the `google-ads` package: - * - * ```js - * import googleAds from '@invertase/react-native-google-ads'; - * - * // googleAds.X - * ``` - */ -export namespace GoogleAdsTypes { - /** - * googleAds.X - */ - export interface Statics { - /** - * This module version. - */ - readonly SDK_VERSION: string; - - /** - * AdsConsentStatus interface. - */ - AdsConsentStatus: AdsConsentStatus; - - /** - * AdsConsentDebugGeography interface. - */ - AdsConsentDebugGeography: AdsConsentDebugGeography; - - /** - * AdsConsentDebugGeography interface. - */ - MaxAdContentRating: MaxAdContentRating; - - /** - * AdEventType enum. - */ - AdEventType: AdEventType; - - /** - * RewardedAdEventType enum. - */ - RewardedAdEventType: RewardedAdEventType; - - /** - * TestIds interface - */ - TestIds: TestIds; - - /** - * Used to sets the size of an Advert. - */ - BannerAdSize: BannerAdSize; - } - - /** - * Common event types for ads. - */ - export interface AdEventType { - /** - * When an ad has loaded. At this point, the ad is ready to be shown to the user. - * - * #### Example - * - * ```js - * import { AdEventType } from '@invertase/react-native-google-ads'; - * - * advert.onAdEvent((type,error,data) => { - * if (type === AdEventType.LOADED) { - * advert.show(); - * } - * }); - * ``` - */ - LOADED: 'loaded'; - - /** - * The ad has thrown an error. See the error parameter the listener callback for more information. - * - * #### Example - * - * ```js - * import { AdEventType } from '@invertase/react-native-google-ads'; - * - * advert.onAdEvent((type, error, data) => { - * if (type === AdEventType.ERROR) { - * console.log('Ad error:', error); - * } - * }); - * ``` - */ - ERROR: 'error'; - - /** - * The ad opened and is currently visible to the user. This event is fired after the `show()` - * method has been called. - */ - OPENED: 'opened'; - - /** - * The user clicked the advert. - */ - CLICKED: 'clicked'; - - /** - * The user closed the ad and has returned back to your application. - */ - CLOSED: 'closed'; - } - - /** - * Ad event types specially for `RewardedAd`. - */ - export interface RewardedAdEventType { - /** - * An event fired when a rewarded ad has loaded. - * - * This type differs from `AdEventType.LOADED` as when a rewarded ad is loaded, - * an additional data payload is provided to the event handler containing the ad reward - * (assuming the user earns the reward). - * - * The reward contains a `type` and `amount`. - * - * #### Example - * - * ```js - * import { RewardedAdEventType } from '@invertase/react-native-google-ads'; - * - * rewardedAd.onAdEvent((type, error, data) => { - * if (type === RewardedAdEventType.LOADED) { - * console.log(`Rewarded Ad loaded with ${data.amount} ${data.type} as reward`); - * // E.g. "Rewarded Ad loaded with 50 coins as reward" - * rewardedAd.show(); - * } - * }); - * ``` - */ - LOADED: 'rewarded_loaded'; - - /** - * An event fired when the user earned the reward for the video. If the user does not earn a reward, - * the `AdEventType.CLOSED` event will be fired with no rewarded event. - * - * The reward contains a `type` and `amount`. - * - * #### Example - * - * ```js - * import { RewardedAdEventType } from '@invertase/react-native-google-ads'; - * - * rewardedAd.onAdEvent((type, error, data) => { - * if (type === RewardedAdEventType.EARNED_REWARD) { - * console.log(`User earned ${data.amount} ${data.type}`); - * // E.g. "User earned 50 coins" - * } - * }); - * ``` - */ - EARNED_REWARD: 'rewarded_earned_reward'; - } - - /** - * Used to sets the size of an Advert. - */ - export interface BannerAdSize { - /** - * Mobile Marketing Association (MMA) banner ad size (320x50 density-independent pixels). - */ - BANNER: 'BANNER'; - - /** - * Interactive Advertising Bureau (IAB) full banner ad size (468x60 density-independent pixels). - */ - FULL_BANNER: 'FULL_BANNER'; - - /** - * Large banner ad size (320x100 density-independent pixels). - */ - LARGE_BANNER: 'LARGE_BANNER'; - - /** - * Interactive Advertising Bureau (IAB) leaderboard ad size (728x90 density-independent pixels). - */ - LEADERBOARD: 'LEADERBOARD'; - - /** - * Interactive Advertising Bureau (IAB) medium rectangle ad size (300x250 density-independent pixels). - */ - MEDIUM_RECTANGLE: 'MEDIUM_RECTANGLE'; - - /** - * A (next generation) dynamically sized banner that is full-width and auto-height. - */ - ADAPTIVE_BANNER: 'ADAPTIVE_BANNER'; - - /** - * A dynamically sized banner that matches its parent's width and expands/contracts its height to match the ad's content after loading completes. - */ - FLUID: 'FLUID'; - - /** - * IAB wide skyscraper ad size (160x600 density-independent pixels). This size is currently not supported by the Google Mobile Ads network; this is intended for mediation ad networks only. - */ - WIDE_SKYSCRAPER: 'WIDE_SKYSCRAPER'; - } - - /** - * Ad Unit IDs used for testing purposes. These should not be used in production apps. - */ - export interface TestIds { - BANNER: string; - INTERSTITIAL: string; - REWARDED: string; - } - - /** - * Under the Google [EU User Consent Policy](https://www.google.com/about/company/consentstaging.html), you must make certain disclosures to your users in the European Economic Area (EEA) - * and obtain their consent to use cookies or other local storage, where legally required, and to use personal data - * (such as AdID) to serve ads. This policy reflects the requirements of the EU ePrivacy Directive and the - * General Data Protection Regulation (GDPR). - * - * It is recommended that you determine the status of a user's consent at every app launch. The user consent status is held - * on the device until a condition changes which requires the user to consent again, such as a change in publishers. - * - * For more information, see [here](https://developers.google.com/admob/android/eu-consent#delay_app_measurement_optional). - */ - export interface AdsConsent { - /** - * Requests user consent for a given list of publisher IDs. - * - * The list of publisher IDs can be obtained from the settings panel on the Google Mobile Ads console. If the list of - * publisher IDs has changed since the last time a user provided consent, their consent status will be reset to - * 'UNKNOWN' and they must provide consent again. - * - * If the request fails with the error "Could not parse Event FE preflight response", this means the state of your - * Google Mobile Ads account is not complete. Ensure you have validated your account and have setup valid payment - * information. This error is also thrown when a Publisher ID is invalid. - * - * The response from this method provides request location and consent status properties. - * - * If request location is within the EEA or unknown, and the consent status is also unknown, you - * must request consent via the `showForm()` method or your own means. - * - * If the consent status is not unknown, the user has already previously provided consent for the current publisher - * scope. - * - * #### Example - * - * ```js - * import { AdsConsent } from '@invertase/react-native-google-ads'; - * - * const consent = await AdsConsent.requestInfoUpdate(['pub-6189033257628554']); - * console.log('User location within EEA or Unknown:', consent.isRequestLocationInEeaOrUnknown); - * console.log('User consent status:', consent.status); - * ``` - * - * @param publisherIds A list of publisher IDs found on your Google Mobile Ads dashboard. - */ - requestInfoUpdate(publisherIds: string[]): Promise; - - /** - * Shows a Google-rendered user consent form. - * - * The Google-rendered consent form is a full-screen configurable form that displays over your app content. The form - * allows the following configuration options: - * - * - * 1. Consent to view personalized ads (via `withPersonalizedAds`). - * 2. Consent to view non-personalized ads (via `withNonPersonalizedAds`). - * 3. Use a paid version of the app instead of viewing ads (via `withAdFree`). - * - * Every consent form requires a privacy policy URL which outlines the usage of your application. - * - * You should review the consent text carefully: what appears by default is a message that might be appropriate if - * you use Google to monetize your app. - * - * If providing an ad-free version of your app, ensure you handle this once the form has been handled by the user - * via the `userPrefersAdFree` property. The users preference on consent is automatically forwarded onto the Google - * Mobile SDKs and saved. - * - * If the user is outside of the EEA, the request form will error. - * - * #### Example - * - * ```js - * import { AdsConsent, AdsConsentStatus } from '@invertase/react-native-google-ads'; - * - * async function requestConsent() { - * const consent = await AdsConsent.requestInfoUpdate(['pub-6189033257628554']); - * - * // Check if user requires consent - * if (consent.isRequestLocationInEeaOrUnknown && consent.status === AdsConsentStatus.UNKNOWN) { - * // Show a Google-rendered form - * const result = await AdsConsent.showForm({ - * privacyPolicy: 'https://invertase.io/privacy-policy', - * withPersonalizedAds: true, - * withNonPersonalizedAds: true, - * withAdFree: true, - * }); - * - * console.log('User accepted personalized: ', result.status === AdsConsentStatus.PERSONALIZED); - * console.log('User accepted non-personalized: ', result.status === AdsConsentStatus.NON_PERSONALIZED); - * console.log('User prefers Ad Free version of app: ', result.userPrefersAdFree); - * } - * } - * - * ``` - * - * @param options An AdsConsentFormOptions interface to control the Google-rendered form. - */ - showForm(options?: AdsConsentFormOptions): Promise; - - /** - * Returns a list of ad providers currently in use for the given Google Mobile Ads App ID. - * - * If requesting consent from the user via your own method, this list of ad providers must be shown to the user - * for them to accept consent. - * - * #### Example - * - * ```js - * import { AdsConsent } from '@invertase/react-native-google-ads'; - * - * const providers = await AdsConsent.getAdProviders(); - * ``` - */ - getAdProviders(): Promise; - - /** - * Sets the debug geography to locally test consent. - * - * If debugging on an emulator (where location cannot be determined) or outside of the EEA, - * it is possible set your own location to test how your app handles different scenarios. - * - * If using a real device, ensure you have set it as a test device via `addTestDevice()` otherwise this method will have - * no effect. - * - * #### Example - * - * ```js - * import { AdsConsent, AdsConsentDebugGeography } from '@invertase/react-native-google-ads'; - * - * // Set disabled - * await AdsConsentDebugGeography.setDebugGeography(AdsConsentDebugGeography.DISABLED); - * - * // Set within EEA - * await AdsConsentDebugGeography.setDebugGeography(AdsConsentDebugGeography.EEA); - * - * // Set outside EEA - * await AdsConsentDebugGeography.setDebugGeography(AdsConsentDebugGeography.NOT_EEA); - * ``` - * - * @param geography The debug geography location. - */ - setDebugGeography( - geography: - | AdsConsentDebugGeography['DISABLED'] - | AdsConsentDebugGeography['EEA'] - | AdsConsentDebugGeography['NOT_EEA'], - ): Promise; - - /** - * Manually update the consent status of the user. - * - * This method is used when providing your own means of user consent. If using the Google-rendered form via `showForm()`, - * the consent status is automatically set and calling this method is not required. - * - * This method can also be used to reset the consent status, by setting it to `AdsConsentStatus.UNKNOWN`, which may be useful in certain circumstances. - * - * #### Example - * - * ```js - * import { AdsConsent, AdsConsentStatus } from '@invertase/react-native-google-ads'; - * - * // User accepted personalized ads - * await AdsConsent.setStatus(AdsConsentStatus.PERSONALIZED); - * ``` - * - * @param status The user consent status. - */ - setStatus( - status: - | AdsConsentStatus['UNKNOWN'] - | AdsConsentStatus['NON_PERSONALIZED'] - | AdsConsentStatus['PERSONALIZED'], - ): Promise; - - /** - * Returns the current consent status of the user. - * - * > The user consent status may change at any time, therefore don't reuse old values locally and always request the current value at any time consent is required. - * - * #### Example - * - * ```js - * import { AdsConsent } from '@invertase/react-native-google-ads'; - * - * const status = await AdsConsent.getStatus(); - * ``` - */ - getStatus(): Promise< - | AdsConsentStatus['UNKNOWN'] - | AdsConsentStatus['NON_PERSONALIZED'] - | AdsConsentStatus['PERSONALIZED'] - >; - - /** - * If a publisher is aware that the user is under the age of consent, all ad requests must set TFUA (Tag For Users - * Under the Age of consent in Europe). This setting takes effect for all future ad requests. - * - * Once the TFUA setting is enabled, the Google-rendered consent form will fail to load. All ad requests that include - * TFUA will be made ineligible for personalized advertising and remarketing. TFUA disables requests to third-party - * ad technology providers, such as ad measurement pixels and third-party ad servers. - * - * To remove TFUA from ad requests, set the value to `false`. - * - * #### Example - * - * ```js - * import { AdsConsent } from '@invertase/react-native-google-ads'; - * - * // User is under age of consent - * await AdsConsent.setTagForUnderAgeOfConsent(true); - * ``` - * - * @param tag The boolean value to tag for under age consent. - */ - setTagForUnderAgeOfConsent(tag: boolean): Promise; - - /** - * If using a real device to test, ensure the device ID is provided to the Google Mobile Ads SDK so any mock debug locations - * can take effect. - * - * Emulators are automatically whitelisted and should require no action. - * - * If you are seeing real ad activity from a test device, examine logcat / console - * during execution in association with google mobile ads test device documentation to - * configure your device correctly. - * - * @param deviceIds An array of testing device ID. - */ - addTestDevices(deviceIds: string[]): Promise; - } - - /** - * The options used to show on the Google-rendered consent form. At least one of `withAdFree`, `withPersonalizedAds` and `WithNonPersonalizedAds` needs to be set to `true`. - */ - export interface AdsConsentFormOptions { - /** - * A fully formed HTTP or HTTPS privacy policy URL for your application. - * - * Users will have the option to visit this web page before consenting to ads. - */ - privacyPolicy: string; - - /** - * Set to `true` to provide the option for the user to accept being shown personalized ads, defaults to `false`. - */ - withPersonalizedAds?: boolean; - - /** - * Set to `true` to provide the option for the user to accept being shown non-personalized ads, defaults to `false`. - */ - withNonPersonalizedAds?: boolean; - - /** - * Set to `true` to provide the option for the user to choose an ad-free version of your app, defaults to `false`. - * - * If the user chooses this option, you must handle it as required (e.g. navigating to a paid version of the app, - * or a subscribe view). - */ - withAdFree?: boolean; - } - - /** - * A `AdShowOptions` interface used when showing an ad. - */ - export interface AdShowOptions { - /** - * - On Android, enables [immersive mode](https://developer.android.com/training/system-ui/immersive). - * - On iOS, this has no effect on how the ad is shown. - * - * @android - */ - immersiveModeEnabled?: boolean; - } - - /** - * The result of a Google-rendered consent form. - */ - export interface AdsConsentFormResult { - /** - * The consent status of the user after closing the consent form. - * - * - UNKNOWN: The form was unable to determine the users consent status. - * - NON_PERSONALIZED: The user has accepted non-personalized ads. - * - PERSONALIZED: The user has accepted personalized ads. - */ - status: - | AdsConsentStatus['UNKNOWN'] - | AdsConsentStatus['NON_PERSONALIZED'] - | AdsConsentStatus['PERSONALIZED']; - - /** - * If `true`, the user requested an ad-free version of your application. - */ - userPrefersAdFree: boolean; - } - - /** - * The result of requesting info about a users consent status. - */ - export interface AdsConsentInfo { - /** - * The consent status of the user. - * - * - UNKNOWN: The consent status is unknown and the user must provide consent to show ads if they are within the EEA or location is also unknown. - * - NON_PERSONALIZED: The user has accepted non-personalized ads. - * - PERSONALIZED: The user has accepted personalized ads. - */ - status: - | AdsConsentStatus['UNKNOWN'] - | AdsConsentStatus['NON_PERSONALIZED'] - | AdsConsentStatus['PERSONALIZED']; - - /** - * If `true` the user is within the EEA or their location could not be determined. - */ - isRequestLocationInEeaOrUnknown: boolean; - } - - /** - * A AdProvider interface returned from `AdsConsent.getProviders`. - */ - export interface AdProvider { - /** - * A provider company ID. - */ - companyId: string; - - /** - * A provider company name. - */ - companyName: string; - - /** - * A fully formed URL for the privacy policy of the provider. - */ - privacyPolicyUrl: string; - } - - /** - * AdsConsentDebugGeography interface. - * - * Used to set a mock location when testing the `AdsConsent` helper. - */ - export interface AdsConsentDebugGeography { - /** - * Disable any debug geography. - */ - DISABLED: 0; - - /** - * Sets the location to within the EEA. - */ - EEA: 1; - - /** - * Sets the location to outside of the EEA. - */ - NOT_EEA: 2; - } - - /** - * AdsConsentStatus interface. - */ - export interface AdsConsentStatus { - /** - * The consent status is unknown and the user must provide consent to show ads if they are within the EEA or location is also unknown. - */ - UNKNOWN: 0; - - /** - * The user has accepted non-personalized ads. - */ - NON_PERSONALIZED: 1; - - /** - * The user has accepted personalized ads. - */ - PERSONALIZED: 2; - } - - /** - * The `RequestOptions` interface. Used when passing additional request options before an advert is loaded. - */ - export interface RequestOptions { - /** - * If `true` only non-personalized ads will be loaded. - * - * Google serves personalized ads by default. This option must be `true` if users who are within the EEA have only - * given consent to non-personalized ads. - */ - requestNonPersonalizedAdsOnly?: boolean; - - /** - * Attaches additional properties to an ad request for direct campaign delivery. - * - * Takes an array of string key/value pairs. - * - * #### Example - * - * Attaches `?campaign=abc&user=123` to the ad request: - * - * ```js - * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { - * networkExtras: { - * campaign: 'abc', - * user: '123', - * }, - * }); - */ - networkExtras?: { [key: string]: string }; - - /** - * An array of keywords to be sent when loading the ad. - * - * Setting keywords helps deliver more specific ads to a user based on the keywords. - * - * #### Example - * - * ```js - * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { - * keywords: ['fashion', 'clothing'], - * }); - * ``` - */ - keywords?: string[]; - - /** - * Sets a content URL for targeting purposes. - * - * Max length of 512. - */ - contentUrl?: string; - - /** - * The latitude and longitude location of the user. - * - * Ensure your app requests location permissions from the user. - * - * #### Example - * - * ```js - * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { - * location: [53.481073, -2.237074], - * }); - * ``` - */ - location?: [number, number]; - - /** - * Sets the location accuracy if the location is set, in meters. - * - * This option is only applied to iOS devices. On Android, this option has no effect. - * - * @ios - */ - locationAccuracy?: number; - - /** - * Sets the request agent string to identify the ad request's origin. Third party libraries that reference the Mobile - * Ads SDK should call this method to denote the platform from which the ad request originated. For example, if a - * third party ad network called "CoolAds network" mediates requests to the Mobile Ads SDK, it should call this - * method with "CoolAds". - * - * #### Example - * - * ```js - * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { - * requestAgent: 'CoolAds', - * }); - * ``` - */ - requestAgent?: string; - - /** - * Server Side Verification(SSV) Options - * See [Google Mobile SDK Docs](https://developers.google.com/admob/android/ssv) for more information. - */ - serverSideVerificationOptions?: ServerSideVerificationOptions; - } - - export interface ServerSideVerificationOptions { - /** - * User identifier. - * If no user identifier is provided by the app, this query parameter will not be present in the SSV callback. - */ - userId?: string; - - /** - * Custom data string. - * If no custom data string is provided by the app, this query parameter value will not be present in the SSV callback. - */ - customData?: string; - } - - /** - * An immutable snapshot of a mediation adapter's initialization status. - */ - export type AdapterStatus = { - name: string; - description: string; - status: 0 | 1; - }; - - /** - * The `RequestConfiguration` used when setting global ad settings via `setRequestConfiguration`. - */ - export interface RequestConfiguration { - /** - * The maximum ad content rating for all ads. Google Mobile Ads returns ads at or below the specified level. - * - * Ratings are based on the [digital content label classifications](https://support.google.com/admob/answer/7562142). - */ - maxAdContentRating?: - | MaxAdContentRating['G'] - | MaxAdContentRating['PG'] - | MaxAdContentRating['T'] - | MaxAdContentRating['MA']; - - /** - * If `true`, indicates that you want your content treated as child-directed for purposes of COPPA. - * - * For purposes of the [Children's Online Privacy Protection Act (COPPA)](http://business.ftc.gov/privacy-and-security/children%27s-privacy), - * there is a setting called "tag for child-directed treatment". By setting this tag, you certify that this notification - * is accurate and you are authorized to act on behalf of the owner of the app. You understand that abuse of this - * setting may result in termination of your Google account. - */ - tagForChildDirectedTreatment?: boolean; - - /** - * If `true`, indicates that you want the ad request to be handled in a manner suitable for users under the age of consent. - * - * You can mark your ad requests to receive treatment for users in the European Economic Area (EEA) under the age of consent. - * This feature is designed to help facilitate compliance with the [General Data Protection Regulation (GDPR)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32016R0679). - * - * See the [Google Mobile SDK docs](https://developers.google.com/admob/android/targeting#ad_content_filtering) for more information. - */ - tagForUnderAgeOfConsent?: boolean; - - /** - * An array of test device IDs to whitelist. - * - * If using an emulator, set the device ID to `EMULATOR`. - */ - testDeviceIdentifiers?: string[]; - } - - /** - * The MaxAdContentRating interface used when setting global advert request options. - */ - export interface MaxAdContentRating { - /** - * "General audiences." Content suitable for all audiences, including families and children. - */ - G: 'G'; - - /** - * "Parental guidance." Content suitable for most audiences with parental guidance, including topics like non-realistic, cartoonish violence. - */ - PG: 'PG'; - - /** - * T: "Teen." Content suitable for teen and older audiences, including topics such as general health, social networks, scary imagery, and fight sports. - */ - T: 'T'; - - /** - * "Mature audiences." Content suitable only for mature audiences; includes topics such as alcohol, gambling, sexual content, and weapons. - */ - MA: 'MA'; - } - - /** - * A `RewardedAdReward` returned from rewarded ads. - */ - export interface RewardedAdReward { - /** - * The reward name, e.g. 'coins', 'diamonds'. - */ - type: string; - - /** - * The number value of the reward, e.g. 10 - */ - amount: number; - } - - /** - * A callback interface for all ad events. - * - * @param type The event type, e.g. `AdEventType.LOADED`. - * @param error An optional JavaScript Error containing the error code and message. - * @param data Optional data for the event, e.g. reward type and amount - */ - export type AdEventListener = ( - type: - | AdEventType['LOADED'] - | AdEventType['ERROR'] - | AdEventType['OPENED'] - | AdEventType['CLICKED'] - | AdEventType['CLOSED'] - | RewardedAdEventType['LOADED'] - | RewardedAdEventType['EARNED_REWARD'], - error?: Error, - data?: any | RewardedAdReward, - ) => void; - - /** - * Base class for InterstitialAd, RewardedAd, NativeAd and BannerAd. - */ - export class MobileAd { - /** - * The Ad Unit ID for this Gogole Mobile Ads ad. - */ - adUnitId: string; - - /** - * Whether the advert is loaded and can be shown. - */ - loaded: boolean; - - /** - * Start loading the advert with the provided RequestOptions. - * - * It is recommended you setup ad event handlers before calling this method. - */ - load(): void; - - /** - * Listen to ad events. See AdEventTypes for more information. - * - * Returns an unsubscriber function to stop listening to further events. - * - * #### Example - * - * ```js - * // Create InterstitialAd/RewardedAd - * const advert = InterstitialAd.createForAdRequest('...'); - * - * const unsubscribe = advert.onAdEvent((type) => { - * - * }); - * - * // Sometime later... - * unsubscribe(); - * ``` - * - * @param listener A listener callback containing a event type, error and data. - */ - onAdEvent(listener: AdEventListener): () => void; - - /** - * Show the loaded advert to the user. - * - * #### Example - * - * ```js - * // Create InterstitialAd/RewardedAd - * const advert = InterstitialAd.createForAdRequest('...'); - * - * advert.onAdEvent((type) => { - * if (type === AdEventType.LOADED) { - * advert.show({ - * immersiveModeEnabled: true, - * }); - * } - * }); - * ``` - * - * @param showOptions An optional `AdShowOptions` interface. - */ - show(showOptions?: AdShowOptions): Promise; - } - - /** - * A class for interacting and showing Interstitial Ads. - * - * An Interstitial advert can be pre-loaded and shown at a suitable point in your apps flow, such as at the end of a level - * in a game. An Interstitial is a full screen advert, laid on-top of your entire application which the user can interact with. - * Interactions are passed back via events which should be handled accordingly inside of your app. - * - * #### Example - * - * First create a new Interstitial instance, passing in your Ad Unit ID from the Google Ads configuration console, and any additional - * request options. The example below will present a test advert, and only request a non-personalized ad. - * - * ```js - * import { InterstitialAd, TestIds } from '@invertase/react-native-google-ads'; - * - * const interstitial = InterstitialAd.createForAdRequest(TestIds.INTERSTITIAL, { - * requestNonPersonalizedAdsOnly: true, - * }); - * ``` - * - * Each advert needs to be loaded from Google Ads before being shown. It is recommended this is performed before the user - * reaches the checkpoint to show the advert, so it's ready to go. Before loading the advert, we need to setup - * event listeners to listen for updates from Google Mobile Ads, such as advert loaded or failed to load. - * - * Event types match the `AdEventType` interface. Once the advert has loaded, we can trigger it to show: - * - * ```js - * import { AdEventType } from '@invertase/react-native-google-ads'; - * - * interstitial.onAdEvent((type) => { - * if (type === AdEventType.LOADED) { - * interstitial.show(); - * } - * }); - * - * interstitial.load(); - * ``` - * - * The advert will be presented to the user, and several more events can be triggered such as the user clicking the - * advert or closing it. - */ - export class InterstitialAd extends MobileAd { - /** - * Creates a new InterstitialAd instance. - * - * #### Example - * - * ```js - * import { InterstitialAd, AdEventType, TestIds } from '@invertase/react-native-google-ads'; - * - * const interstitialAd = await InterstitialAd.request(TestIds.INTERSTITIAL, { - * requestAgent: 'CoolAds', - * }); - * - * interstitialAd.onAdEvent((type, error) => { - * console.log('New event: ', type, error); - * - * if (type === AdEventType.LOADED) { - * interstitialAd.show(); - * } - * }); - * - * interstitialAd.load(); - * ``` - * - * @param adUnitId The Ad Unit ID for the Interstitial. You can find this on your Google Mobile Ads dashboard. - * @param requestOptions Optional RequestOptions used to load the ad. - */ - static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions): InterstitialAd; - } - - /** - * A class for interacting and showing Rewarded Ads. - * - * An Rewarded advert can be pre-loaded and shown at a suitable point in your apps flow, such as at the end of a level - * in a game. The content of a rewarded advert can be controlled via your Google Mobile Ads dashboard. Typically users are rewarded - * after completing a specific advert action (e.g. watching a video or submitting an option via an interactive form). - * Events (such as the user earning a reward or closing a rewarded advert early) are sent back for you to handle accordingly - * within your application. - * - * #### Example - * - * First create a new Rewarded instance, passing in your Ad Unit ID from the Google Mobile Ads configuration console, and any additional - * request options. The example below will present a test advert, and only request a non-personalized ad. - * - * ```js - * import { RewardedAd, TestIds } from '@invertase/react-native-google-ads'; - * - * const rewarded = RewardedAd.createForAdRequest(TestIds.REWARDED, { - * requestNonPersonalizedAdsOnly: true, - * }); - * ``` - * - * Each advert needs to be loaded from Google Ads before being shown. It is recommended this is performed before the user - * reaches the checkpoint to show the advert, so it's ready to go. Before loading the advert, we need to setup - * event listeners to listen for updates from Google Ads, such as advert loaded or failed to load. - * - * Event types match the `AdEventType` or `RewardedAdEventType` interface. The potential user reward for rewarded - * adverts are passed back to the event handler on advert load and when the user earns the reward. - * - * ```js - * import { RewardedAdEventType } from '@invertase/react-native-google-ads'; - * - * rewarded.onAdEvent((type, error, reward) => { - * if (type === RewardedAdEventType.LOADED) { - * rewarded.show(); - * } - * if (type === RewardedAdEventType.EARNED_REWARD) { - * console.log('User earned reward of ', reward); - * } - * }); - * - * rewarded.load(); - * ``` - * - * The rewarded advert will be presented to the user, and several more events can be triggered such as the user clicking the - * advert, closing it or completing the action. - */ - export class RewardedAd extends MobileAd { - /** - * Creates a new RewardedAd instance. - * - * #### Example - * - * ```js - * import { RewardedAd, RewardedAdEventType, TestIds } from '@invertase/react-native-google-ads'; - * - * const rewardedAd = await RewardedAd.request(TestIds.REWARDED, { - * requestAgent: 'CoolAds', - * }); - * - * rewardedAd.onAdEvent((type, error, data) => { - * console.log('New event: ', type, error); - * - * if (type === RewardedAdEventType.LOADED) { - * rewardedAd.show(); - * } - * }); - * - * rewardedAd.load(); - * ``` - * - * @param adUnitId The Ad Unit ID for the Rewarded Ad. You can find this on your Google Mobile Ads dashboard. - * @param requestOptions Optional RequestOptions used to load the ad. - */ - static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions): RewardedAd; - } - - /** - * An interface for a Banner advert component. - * - * #### Example - * - * The `BannerAd` interface is exposed as a React component, allowing you to integrate ads within your existing React - * Native code base. The component itself is isolated, meaning any standard `View` props (e.g. `style`) are not - * forwarded on. It is recommended you wrap the `BannerAd` within your own `View` if you wish to apply custom props for use-cases - * such as positioning. - * - * ```js - * import { BannerAd, BannerAdSize, TestIds } from '@invertase/react-native-google-ads'; - * - * function HomeScreen() { - * return ( - * { - * console.log('Advert loaded'); - * }} - * onAdFailedToLoad={(error) => { - * console.error('Advert failed to load: ', error); - * }} - * /> - * ); - * } - * ``` - */ - export interface BannerAd { - /** - * The Google Mobile Ads unit ID for the banner. - */ - unitId: string; - - /** - * The size of the banner. Can be a predefined size via `BannerAdSize` or custom dimensions, e.g. `300x200`. - * - * Inventory must be available for the banner size specified, otherwise a no-fill error will be sent to `onAdFailedToLoad`. - */ - size: BannerAdSize | string; - - /** - * The request options for this banner. - */ - requestOptions?: RequestOptions; - - /** - * When an ad has finished loading. - */ - onAdLoaded?: () => void; - - /** - * When an ad has failed to load. Callback contains an Error. - */ - onAdFailedToLoad?: (error: Error) => void; - - /** - * The ad is now visible to the user. - */ - onAdOpened?: () => void; - - /** - * Called when the user is about to return to the app after tapping on an ad. - */ - onAdClosed?: () => void; - - /** - * Called when the user has left the application (e.g. clicking an advert). - */ - onAdLeftApplication?: () => void; - } - - /** - * The Google Ads service interface. - */ - export class Module { - /** - * Initialize the SDK. - */ - initialize(): Promise; - - /** - * Sets request options for all future ad requests. - * - * #### Example - * - * ```js - * import googleAds, { MaxAdContentRating } from '@invertase/react-native-google-ads'; - * - * await googleAds().setRequestConfiguration({ - * // Update all future requests suitable for parental guidance - * maxAdContentRating: MaxAdContentRating.PG, - * }); - * ``` - * - * @param requestConfiguration An RequestConfiguration interface used on all future Google Ads ad requests. - */ - setRequestConfiguration(requestConfiguration: RequestConfiguration): Promise; - - /** - * The native module instance for the Google Ads service. - */ - private native: any; - - /** - * Returns the shared event emitter instance used for all JS event routing. - */ - private emitter: any; - } -} - -export const AdsConsentDebugGeography: GoogleAdsTypes.AdsConsentDebugGeography; -export const AdsConsentStatus: GoogleAdsTypes.AdsConsentStatus; -export const MaxAdContentRating: GoogleAdsTypes.MaxAdContentRating; -export const TestIds: GoogleAdsTypes.TestIds; -export const AdEventType: GoogleAdsTypes.AdEventType; -export const BannerAdSize: GoogleAdsTypes.BannerAdSize; -export const RewardedAdEventType: GoogleAdsTypes.RewardedAdEventType; -export const AdsConsent: GoogleAdsTypes.AdsConsent; -export const InterstitialAd: typeof GoogleAdsTypes.InterstitialAd; -export const RewardedAd: typeof GoogleAdsTypes.RewardedAd; -export const BannerAd: React.SFC; - -declare const defaultExport: () => GoogleAdsTypes.Module & GoogleAdsTypes.Statics; - -export default defaultExport; diff --git a/lib/index.js b/lib/index.js deleted file mode 100644 index 1d9fd682..00000000 --- a/lib/index.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -import version from './version'; - -// import { SDK_VERSION } from '@invertase/react-native-google-ads'; -export const SDK_VERSION = version; - -export { default } from './googleMobileAds'; -export { default as AdsConsentDebugGeography } from './AdsConsentDebugGeography'; -export { default as AdsConsentStatus } from './AdsConsentStatus'; -export { default as MaxAdContentRating } from './MaxAdContentRating'; -export { default as TestIds } from './TestIds'; -export { default as AdEventType } from './AdEventType'; -export { default as BannerAdSize } from './BannerAdSize'; -export { default as RewardedAdEventType } from './RewardedAdEventType'; -export { default as AdsConsent } from './AdsConsent'; -export { default as InterstitialAd } from './ads/InterstitialAd'; -export { default as RewardedAd } from './ads/RewardedAd'; -export { default as BannerAd } from './ads/BannerAd'; diff --git a/lib/internal/NativeError.js b/lib/internal/NativeError.js deleted file mode 100644 index 6948011d..00000000 --- a/lib/internal/NativeError.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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. - * - */ - -export default class NativeError extends Error { - static fromEvent(errorEvent, namespace, stack) { - return new NativeError({ userInfo: errorEvent }, stack || new Error().stack, namespace); - } - - constructor(nativeError, jsStack, namespace) { - super(); - const { userInfo } = nativeError; - - Object.defineProperty(this, 'namespace', { - enumerable: false, - value: namespace, - }); - - Object.defineProperty(this, 'code', { - enumerable: false, - value: `${this.namespace}/${userInfo.code || 'unknown'}`, - }); - - Object.defineProperty(this, 'message', { - enumerable: false, - value: `[${this.code}] ${userInfo.message || nativeError.message}`, - }); - - Object.defineProperty(this, 'jsStack', { - enumerable: false, - value: jsStack, - }); - - Object.defineProperty(this, 'userInfo', { - enumerable: false, - value: userInfo, - }); - - Object.defineProperty(this, 'nativeErrorCode', { - enumerable: false, - value: userInfo.nativeErrorCode || null, - }); - - Object.defineProperty(this, 'nativeErrorMessage', { - enumerable: false, - value: userInfo.nativeErrorMessage || null, - }); - - this.stack = NativeError.getStackWithMessage(`NativeError: ${this.message}`, this.jsStack); - } - - /** - * Build a stack trace that includes JS stack prior to calling the native method. - * - * @returns {string} - */ - static getStackWithMessage(message, jsStack) { - return [message, ...jsStack.split('\n').slice(2, 13)].join('\n'); - } -} diff --git a/lib/version.js b/lib/version.js deleted file mode 100644 index b45ff147..00000000 --- a/lib/version.js +++ /dev/null @@ -1,2 +0,0 @@ -// generated by genversion -module.exports = '1.0.0'; diff --git a/package.json b/package.json index 10a0eda4..8ee6a138 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,10 @@ "version": "3.4.0", "author": "Invertase (http://invertase.io)", "description": "React Native Google Ads is an easy way to monetize mobile apps with targeted, in-app advertising.", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "lib/commonjs/index.js", + "module": "lib/module/index.js", + "react-native": "src/index.ts", + "types": "lib/typescript/index.d.ts", "repository": { "type": "git", "url": "https://github.com/invertase/react-native-google-ads" @@ -49,12 +51,21 @@ "googleAds": "19.8.0" } }, + "react-native-builder-bob": { + "source": "src", + "output": "lib", + "targets": [ + "commonjs", + "module", + "typescript" + ] + }, "scripts": { "prepare": "yarn build", - "build": "genversion --semi lib/version.js", - "build:clean": "rimraf android/build && rimraf ios/build", + "build": "genversion --es6 --semi src/version.ts && bob build", + "build:clean": "rimraf android/build && rimraf ios/build && rimraf lib", "lint:code": "yarn lint:js && yarn lint:android && yarn lint:ios:check", - "lint:js": "eslint lib/ --ext .js,.jsx,.ts,.tsx --max-warnings=0", + "lint:js": "eslint src/ --ext .js,.jsx,.ts,.tsx --max-warnings=0", "lint:android": "google-java-format --set-exit-if-changed --replace --glob=\"android/**/*.java\"", "lint:ios:check": "clang-format --glob=\"ios/**/*.{h,cpp,m,mm}\" --style=Google -n -Werror", "lint:ios:fix": "clang-format -i --glob=\"ios/**/*.{h,cpp,m,mm}\" --style=Google", @@ -62,7 +73,7 @@ "lint:markdown:fix": "prettier --write \"docs/**/*.md\"", "lint:report": "eslint --output-file=eslint-report.json --format=json . --ext .js,.jsx,.ts,.tsx", "lint:spellcheck": "spellchecker --quiet --files=\"docs/**/*.md\" --dictionaries=\"./.spellcheck.dict.txt\" --reports=\"spelling.json\" --plugins spell indefinite-article repeated-words syntax-mentions syntax-urls frontmatter", - "tsc:compile": "tsc --project .", + "tsc:compile": "tsc --project . --noEmit", "lint": "yarn lint:code && yarn tsc:compile", "tests:jest": "jest", "tests:jest-watch": "jest --watch", @@ -118,6 +129,7 @@ "prettier": "^2.5.1", "react": "^17.0.2", "react-native": "0.66.3", + "react-native-builder-bob": "^0.18.2", "rimraf": "^3.0.2", "semantic-release": "^18.0.1", "shelljs": "^0.8.3", diff --git a/src/AdEventType.ts b/src/AdEventType.ts new file mode 100644 index 00000000..c484eed5 --- /dev/null +++ b/src/AdEventType.ts @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +export enum AdEventType { + /** + * When an ad has loaded. At this point, the ad is ready to be shown to the user. + * + * #### Example + * + * ```js + * import { AdEventType } from '@invertase/react-native-google-ads'; + * + * advert.onAdEvent((type,error,data) => { + * if (type === AdEventType.LOADED) { + * advert.show(); + * } + * }); + * ``` + */ + LOADED = 'loaded', + + /** + * The ad has thrown an error. See the error parameter the listener callback for more information. + * + * #### Example + * + * ```js + * import { AdEventType } from '@invertase/react-native-google-ads'; + * + * advert.onAdEvent((type, error, data) => { + * if (type === AdEventType.ERROR) { + * console.log('Ad error:', error); + * } + * }); + * ``` + */ + ERROR = 'error', + + /** + * The ad opened and is currently visible to the user. This event is fired after the `show()` + * method has been called. + */ + OPENED = 'opened', + + /** + * The user clicked the advert. + */ + CLICKED = 'clicked', + + /** + * The user closed the ad and has returned back to your application. + */ + CLOSED = 'closed', +} diff --git a/lib/AdsConsent.js b/src/AdsConsent.ts similarity index 95% rename from lib/AdsConsent.js rename to src/AdsConsent.ts index 7102de6f..366023ba 100644 --- a/lib/AdsConsent.js +++ b/src/AdsConsent.ts @@ -25,12 +25,13 @@ import { isValidUrl, } from './common'; import { NativeModules } from 'react-native'; -import AdsConsentDebugGeography from './AdsConsentDebugGeography'; -import AdsConsentStatus from './AdsConsentStatus'; +import { AdsConsentDebugGeography } from './AdsConsentDebugGeography'; +import { AdsConsentStatus } from './AdsConsentStatus'; +import { AdsConsentInterface } from './types/AdsConsent.interface'; const native = NativeModules.RNGoogleAdsConsentModule; -export default { +export const AdsConsent: AdsConsentInterface = { /** * * @param publisherIds diff --git a/lib/BannerAdSize.js b/src/AdsConsentDebugGeography.ts similarity index 64% rename from lib/BannerAdSize.js rename to src/AdsConsentDebugGeography.ts index fe4ce026..0417a1a2 100644 --- a/lib/BannerAdSize.js +++ b/src/AdsConsentDebugGeography.ts @@ -13,16 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. * + */ + +/** + * AdsConsentDebugGeography enum. * + * Used to set a mock location when testing the `AdsConsent` helper. */ +export enum AdsConsentDebugGeography { + /** + * Disable any debug geography. + */ + DISABLED = 0, + + /** + * Sets the location to within the EEA. + */ + EEA = 1, -export default { - BANNER: 'BANNER', - ADAPTIVE_BANNER: 'ADAPTIVE_BANNER', - FULL_BANNER: 'FULL_BANNER', - LARGE_BANNER: 'LARGE_BANNER', - LEADERBOARD: 'LEADERBOARD', - MEDIUM_RECTANGLE: 'MEDIUM_RECTANGLE', - FLUID: 'FLUID', - WIDE_SKYSCRAPER: 'WIDE_SKYSCRAPER', -}; + /** + * Sets the location to outside of the EEA. + */ + NOT_EEA = 2, +} diff --git a/lib/AdsConsentDebugGeography.js b/src/AdsConsentStatus.ts similarity index 61% rename from lib/AdsConsentDebugGeography.js rename to src/AdsConsentStatus.ts index b44110c6..63207ae2 100644 --- a/lib/AdsConsentDebugGeography.js +++ b/src/AdsConsentStatus.ts @@ -15,8 +15,22 @@ * */ -export default { - DISABLED: 0, - EEA: 1, - NOT_EEA: 2, -}; +/** + * AdsConsentStatus enum. + */ +export enum AdsConsentStatus { + /** + * The consent status is unknown and the user must provide consent to show ads if they are within the EEA or location is also unknown. + */ + UNKNOWN = 0, + + /** + * The user has accepted non-personalized ads. + */ + NON_PERSONALIZED = 1, + + /** + * The user has accepted personalized ads. + */ + PERSONALIZED = 2, +} diff --git a/src/BannerAdSize.ts b/src/BannerAdSize.ts new file mode 100644 index 00000000..178035cb --- /dev/null +++ b/src/BannerAdSize.ts @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + * + */ + +export enum BannerAdSize { + /** + * Mobile Marketing Association (MMA) banner ad size (320x50 density-independent pixels). + */ + BANNER = 'BANNER', + + /** + * Interactive Advertising Bureau (IAB) full banner ad size (468x60 density-independent pixels). + */ + FULL_BANNER = 'FULL_BANNER', + + /** + * Large banner ad size (320x100 density-independent pixels). + */ + LARGE_BANNER = 'LARGE_BANNER', + + /** + * Interactive Advertising Bureau (IAB) leaderboard ad size (728x90 density-independent pixels). + */ + LEADERBOARD = 'LEADERBOARD', + + /** + * Interactive Advertising Bureau (IAB) medium rectangle ad size (300x250 density-independent pixels). + */ + MEDIUM_RECTANGLE = 'MEDIUM_RECTANGLE', + + /** + * A (next generation) dynamically sized banner that is full-width and auto-height. + */ + ADAPTIVE_BANNER = 'ADAPTIVE_BANNER', + + /** + * A dynamically sized banner that matches its parent's width and expands/contracts its height to match the ad's content after loading completes. + */ + FLUID = 'FLUID', + + /** + * IAB wide skyscraper ad size (160x600 density-independent pixels). This size is currently not supported by the Google Mobile Ads network; this is intended for mediation ad networks only. + */ + WIDE_SKYSCRAPER = 'WIDE_SKYSCRAPER', +} diff --git a/src/MaxAdContentRating.ts b/src/MaxAdContentRating.ts new file mode 100644 index 00000000..f693ca1d --- /dev/null +++ b/src/MaxAdContentRating.ts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +export enum MaxAdContentRating { + /** + * "General audiences." Content suitable for all audiences, including families and children. + */ + G = 'G', + + /** + * "Parental guidance." Content suitable for most audiences with parental guidance, including topics like non-realistic, cartoonish violence. + */ + PG = 'PG', + + /** + * T: "Teen." Content suitable for teen and older audiences, including topics such as general health, social networks, scary imagery, and fight sports. + */ + T = 'T', + + /** + * "Mature audiences." Content suitable only for mature audiences; includes topics such as alcohol, gambling, sexual content, and weapons. + */ + MA = 'MA', +} diff --git a/src/MobileAds.ts b/src/MobileAds.ts new file mode 100644 index 00000000..94c191ee --- /dev/null +++ b/src/MobileAds.ts @@ -0,0 +1,69 @@ +import { Module } from './internal'; +import { validateAdRequestConfiguration } from './validateAdRequestConfiguration'; +import { version } from './version'; +import { MobileAdsModuleInterface } from './types/MobileAdsModule.interface'; +import { RequestConfiguration } from './types/RequestConfiguration'; +import { App, Config } from './types/Module.interface'; + +const namespace = 'google_ads'; + +const nativeModuleName = [ + 'RNGoogleAdsModule', + 'RNGoogleAdsInterstitialModule', + 'RNGoogleAdsRewardedModule', +]; + +type Event = { + adUnitId: string; + requestId: number; +}; + +class MobileAdsModule extends Module implements MobileAdsModuleInterface { + constructor(app: App, config: Config) { + super(app, config); + + this.emitter.addListener('google_ads_interstitial_event', (event: Event) => { + this.emitter.emit( + `google_ads_interstitial_event:${event.adUnitId}:${event.requestId}`, + event, + ); + }); + + this.emitter.addListener('google_ads_rewarded_event', (event: Event) => { + this.emitter.emit(`google_ads_rewarded_event:${event.adUnitId}:${event.requestId}`, event); + }); + } + + initialize() { + return this.native.initialize(); + } + + setRequestConfiguration(requestConfiguration: RequestConfiguration) { + let config; + try { + config = validateAdRequestConfiguration(requestConfiguration); + } catch (e) { + if (e instanceof Error) { + throw new Error(`googleAds.setRequestConfiguration(*) ${e.message}`); + } + } + + return this.native.setRequestConfiguration(config); + } +} + +const MobileAdsInstance = new MobileAdsModule( + { name: 'AppName' }, + { + version, + namespace, + nativeModuleName, + nativeEvents: ['google_ads_interstitial_event', 'google_ads_rewarded_event'], + }, +); + +export const MobileAds = () => { + return MobileAdsInstance; +}; + +export default MobileAds; diff --git a/src/RewardedAdEventType.ts b/src/RewardedAdEventType.ts new file mode 100644 index 00000000..a8e8f0c4 --- /dev/null +++ b/src/RewardedAdEventType.ts @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +export enum RewardedAdEventType { + /** + * An event fired when a rewarded ad has loaded. + * + * This type differs from `AdEventType.LOADED` as when a rewarded ad is loaded, + * an additional data payload is provided to the event handler containing the ad reward + * (assuming the user earns the reward). + * + * The reward contains a `type` and `amount`. + * + * #### Example + * + * ```js + * import { RewardedAdEventType } from '@invertase/react-native-google-ads'; + * + * rewardedAd.onAdEvent((type, error, data) => { + * if (type === RewardedAdEventType.LOADED) { + * console.log(`Rewarded Ad loaded with ${data.amount} ${data.type} as reward`); + * // E.g. "Rewarded Ad loaded with 50 coins as reward" + * rewardedAd.show(); + * } + * }); + * ``` + */ + LOADED = 'rewarded_loaded', + + /** + * An event fired when the user earned the reward for the video. If the user does not earn a reward, + * the `AdEventType.CLOSED` event will be fired with no rewarded event. + * + * The reward contains a `type` and `amount`. + * + * #### Example + * + * ```js + * import { RewardedAdEventType } from '@invertase/react-native-google-ads'; + * + * rewardedAd.onAdEvent((type, error, data) => { + * if (type === RewardedAdEventType.EARNED_REWARD) { + * console.log(`User earned ${data.amount} ${data.type}`); + * // E.g. "User earned 50 coins" + * } + * }); + * ``` + */ + EARNED_REWARD = 'rewarded_earned_reward', +} diff --git a/lib/TestIds.js b/src/TestIds.ts similarity index 93% rename from lib/TestIds.js rename to src/TestIds.ts index 01f97277..03c456f2 100644 --- a/lib/TestIds.js +++ b/src/TestIds.ts @@ -17,7 +17,10 @@ import { Platform } from 'react-native'; -export default { +export const TestIds = { + BANNER: '', + INTERSTITIAL: '', + REWARDED: '', ...Platform.select({ android: { BANNER: 'ca-app-pub-3940256099942544/6300978111', diff --git a/lib/ads/BannerAd.js b/src/ads/BannerAd.tsx similarity index 52% rename from lib/ads/BannerAd.js rename to src/ads/BannerAd.tsx index 5035718e..d5e0ba17 100644 --- a/lib/ads/BannerAd.js +++ b/src/ads/BannerAd.tsx @@ -16,17 +16,31 @@ */ import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { requireNativeComponent } from 'react-native'; +import { HostComponent, requireNativeComponent } from 'react-native'; import { isFunction } from '../common'; -import NativeError from '../internal/NativeError'; -import BannerAdSize from '../BannerAdSize'; -import validateAdRequestOptions from '../validateAdRequestOptions'; +import { NativeError } from '../internal/NativeError'; +import { BannerAdSize } from '../BannerAdSize'; +import { validateAdRequestOptions } from '../validateAdRequestOptions'; +import { BannerAdProps } from '../types/BannerAdProps'; +import { RequestOptions } from '../types/RequestOptions'; + +type NativeEvent = + | { + type: 'onAdLoaded' | 'onSizeChanged'; + width: number; + height: number; + } + | { type: 'onAdOpened' | 'onAdClosed' } + | { + type: 'onAdFailedToLoad'; + code: string; + message: string; + }; const initialState = [0, 0]; const sizeRegex = /([0-9]+)x([0-9]+)/; -function BannerAd({ unitId, size, requestOptions, ...props }) { +export function BannerAd({ unitId, size, requestOptions, ...props }: BannerAdProps) { const [dimensions, setDimensions] = useState(initialState); useEffect(() => { @@ -36,13 +50,13 @@ function BannerAd({ unitId, size, requestOptions, ...props }) { }, [unitId]); useEffect(() => { - if (!BannerAdSize[size] && !sizeRegex.test(size)) { + if (!(size in BannerAdSize) && !sizeRegex.test(size)) { throw new Error("BannerAd: 'size' expected a valid BannerAdSize or custom size string."); } }, [size]); useEffect(() => { - if (!BannerAdSize[size] && !sizeRegex.test(size)) { + if (!(size in BannerAdSize) && !sizeRegex.test(size)) { throw new Error("BannerAd: 'size' expected a valid BannerAdSize or custom size string."); } }, [size]); @@ -54,30 +68,33 @@ function BannerAd({ unitId, size, requestOptions, ...props }) { try { validateAdRequestOptions(requestOptions); } catch (e) { - throw new Error(`BannerAd: ${e.message}`); + if (e instanceof Error) { + throw new Error(`BannerAd: ${e.message}`); + } } } }, [parsedRequestOptions]); - function onNativeEvent({ nativeEvent }) { - const { width, height, type } = nativeEvent; + function onNativeEvent({ nativeEvent }: { nativeEvent: NativeEvent }) { + const { type } = nativeEvent; if (type !== 'onSizeChanged' && isFunction(props[type])) { - let eventPayload; + let eventHandler; if (type === 'onAdFailedToLoad') { - eventPayload = NativeError.fromEvent(nativeEvent, 'googleAds'); - } - props[type](eventPayload); + const eventPayload = NativeError.fromEvent(nativeEvent, 'googleAds'); + if ((eventHandler = props[type])) eventHandler(eventPayload); + } else if ((eventHandler = props[type])) eventHandler(); } - if (width && height && size !== 'FLUID') { - setDimensions([width, height]); + if ((type === 'onAdLoaded' || type === 'onSizeChanged') && size !== 'FLUID') { + const { width, height } = nativeEvent; + if (width && height) setDimensions([width, height]); } } let style; if (size === 'FLUID') { - // eslint-disable-next-line react/prop-types + // @ts-ignore: Property 'style' does not exist on type error style = props.style; } else { style = { @@ -97,17 +114,13 @@ function BannerAd({ unitId, size, requestOptions, ...props }) { ); } -const GoogleAdsBannerView = requireNativeComponent('RNGoogleAdsBannerView', BannerAd); - -BannerAd.propTypes = { - unitId: PropTypes.string.isRequired, - size: PropTypes.string.isRequired, - requestOptions: PropTypes.object, - onAdLoaded: PropTypes.func, - onAdFailedToLoad: PropTypes.func, - onAdOpened: PropTypes.func, - onAdClosed: PropTypes.func, - onAdLeftApplication: PropTypes.func, -}; - -export default BannerAd; +const GoogleAdsBannerView: HostComponent<{ + size: BannerAdProps['size']; + style: { + width: number; + height: number; + }; + unitId: string; + request: RequestOptions; + onNativeEvent: (event: { nativeEvent: NativeEvent }) => void; +}> = requireNativeComponent('RNGoogleAdsBannerView'); diff --git a/src/ads/InterstitialAd.ts b/src/ads/InterstitialAd.ts new file mode 100644 index 00000000..91c06a46 --- /dev/null +++ b/src/ads/InterstitialAd.ts @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +import { isFunction, isString } from '../common'; +import { MobileAds } from '../MobileAds'; +import { validateAdRequestOptions } from '../validateAdRequestOptions'; +import { validateAdShowOptions } from '../validateAdShowOptions'; +import { MobileAd } from './MobileAd'; +import { AdEventListener } from '../types/AdEventListener'; +import { AdShowOptions } from '../types/AdShowOptions'; +import { RequestOptions } from '../types/RequestOptions'; +import { MobileAdInterface } from '../types/MobileAd.interface'; + +let _interstitialRequest = 0; + +/** + * A class for interacting and showing Interstitial Ads. + * + * An Interstitial advert can be pre-loaded and shown at a suitable point in your apps flow, such as at the end of a level + * in a game. An Interstitial is a full screen advert, laid on-top of your entire application which the user can interact with. + * Interactions are passed back via events which should be handled accordingly inside of your app. + * + * #### Example + * + * First create a new Interstitial instance, passing in your Ad Unit ID from the Google Ads configuration console, and any additional + * request options. The example below will present a test advert, and only request a non-personalized ad. + * + * ```js + * import { InterstitialAd, TestIds } from '@invertase/react-native-google-ads'; + * + * const interstitial = InterstitialAd.createForAdRequest(TestIds.INTERSTITIAL, { + * requestNonPersonalizedAdsOnly: true, + * }); + * ``` + * + * Each advert needs to be loaded from Google Ads before being shown. It is recommended this is performed before the user + * reaches the checkpoint to show the advert, so it's ready to go. Before loading the advert, we need to setup + * event listeners to listen for updates from Google Mobile Ads, such as advert loaded or failed to load. + * + * Event types match the `AdEventType` interface. Once the advert has loaded, we can trigger it to show: + * + * ```js + * import { AdEventType } from '@invertase/react-native-google-ads'; + * + * interstitial.onAdEvent((type) => { + * if (type === AdEventType.LOADED) { + * interstitial.show(); + * } + * }); + * + * interstitial.load(); + * ``` + * + * The advert will be presented to the user, and several more events can be triggered such as the user clicking the + * advert or closing it. + */ +export class InterstitialAd extends MobileAd implements MobileAdInterface { + /** + * Creates a new InterstitialAd instance. + * + * #### Example + * + * ```js + * import { InterstitialAd, AdEventType, TestIds } from '@invertase/react-native-google-ads'; + * + * const interstitialAd = await InterstitialAd.request(TestIds.INTERSTITIAL, { + * requestAgent: 'CoolAds', + * }); + * + * interstitialAd.onAdEvent((type, error) => { + * console.log('New event: ', type, error); + * + * if (type === AdEventType.LOADED) { + * interstitialAd.show(); + * } + * }); + * + * interstitialAd.load(); + * ``` + * + * @param adUnitId The Ad Unit ID for the Interstitial. You can find this on your Google Mobile Ads dashboard. + * @param requestOptions Optional RequestOptions used to load the ad. + */ + static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions): InterstitialAd { + if (!isString(adUnitId)) { + throw new Error("InterstitialAd.createForAdRequest(*) 'adUnitId' expected an string value."); + } + + let options = {}; + try { + options = validateAdRequestOptions(requestOptions); + } catch (e) { + if (e instanceof Error) { + throw new Error(`InterstitialAd.createForAdRequest(_, *) ${e.message}.`); + } + } + + const requestId = _interstitialRequest++; + return new InterstitialAd('interstitial', MobileAds(), requestId, adUnitId, options); + } + + load() { + // Prevent multiple load calls + if (this._loaded || this._isLoadCalled) { + return; + } + + this._isLoadCalled = true; + this._googleAds.native.interstitialLoad(this._requestId, this._adUnitId, this._requestOptions); + } + + onAdEvent(handler: AdEventListener) { + if (!isFunction(handler)) { + throw new Error("InterstitialAd.onAdEvent(*) 'handler' expected a function."); + } + + return this._setAdEventHandler(handler); + } + + show(showOptions?: AdShowOptions) { + if (!this._loaded) { + throw new Error( + 'InterstitialAd.show() The requested InterstitialAd has not loaded and could not be shown.', + ); + } + + let options; + try { + options = validateAdShowOptions(showOptions); + } catch (e) { + if (e instanceof Error) { + throw new Error(`InterstitialAd.show(*) ${e.message}.`); + } + } + + return this._googleAds.native.interstitialShow(this._requestId, options); + } +} diff --git a/lib/ads/MobileAd.js b/src/ads/MobileAd.ts similarity index 57% rename from lib/ads/MobileAd.js rename to src/ads/MobileAd.ts index 309e7190..85649b0c 100644 --- a/lib/ads/MobileAd.js +++ b/src/ads/MobileAd.ts @@ -15,12 +15,33 @@ * */ -import NativeError from '../internal/NativeError'; -import AdEventType from '../AdEventType'; -import RewardedAdEventType from '../RewardedAdEventType'; +import { EmitterSubscription } from 'react-native'; +import { NativeError } from '../internal/NativeError'; +import { RewardedAdEventType } from '../RewardedAdEventType'; +import { AdEventType } from '../AdEventType'; +import { AdEventListener } from '../types/AdEventListener'; +import { RequestOptions } from '../types/RequestOptions'; +import { MobileAdsModuleInterface } from '../types/MobileAdsModule.interface'; +import { RewardedAdReward } from '../types/RewardedAdReward'; -export default class MobileAd { - constructor(type, googleAds, requestId, adUnitId, requestOptions) { +export class MobileAd { + _type: 'interstitial' | 'rewarded'; + _googleAds: MobileAdsModuleInterface; + _requestId: number; + _adUnitId: string; + _requestOptions: RequestOptions; + _loaded: boolean; + _isLoadCalled: boolean; + _onAdEventHandler: AdEventListener | null; + _nativeListener: EmitterSubscription; + + constructor( + type: 'interstitial' | 'rewarded', + googleAds: MobileAdsModuleInterface, + requestId: number, + adUnitId: string, + requestOptions: RequestOptions, + ) { this._type = type; this._googleAds = googleAds; this._requestId = requestId; @@ -37,14 +58,20 @@ export default class MobileAd { ); } - _handleAdEvent(event) { + _handleAdEvent(event: { + body: { + type: AdEventType | RewardedAdEventType; + error?: { code: string; message: string }; + data?: RewardedAdReward; + }; + }) { const { type, error, data } = event.body; if (type === AdEventType.LOADED || type === RewardedAdEventType.LOADED) { this._loaded = true; } - if (type === AdEventType.CLOSED || type === RewardedAdEventType.CLOSED) { + if (type === AdEventType.CLOSED) { this._loaded = false; this._isLoadCalled = false; } @@ -59,7 +86,7 @@ export default class MobileAd { } } - _setAdEventHandler(handler) { + _setAdEventHandler(handler: AdEventListener) { this._onAdEventHandler = handler; return () => (this._onAdEventHandler = null); } diff --git a/src/ads/RewardedAd.ts b/src/ads/RewardedAd.ts new file mode 100644 index 00000000..5cec74a2 --- /dev/null +++ b/src/ads/RewardedAd.ts @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +import { isFunction, isString } from '../common'; +import { MobileAds } from '../MobileAds'; +import { validateAdRequestOptions } from '../validateAdRequestOptions'; +import { validateAdShowOptions } from '../validateAdShowOptions'; +import { MobileAd } from './MobileAd'; +import { AdEventListener } from '../types/AdEventListener'; +import { AdShowOptions } from '../types/AdShowOptions'; +import { RequestOptions } from '../types/RequestOptions'; +import { MobileAdInterface } from '../types/MobileAd.interface'; + +let _rewardedRequest = 0; + +/** + * A class for interacting and showing Rewarded Ads. + * + * An Rewarded advert can be pre-loaded and shown at a suitable point in your apps flow, such as at the end of a level + * in a game. The content of a rewarded advert can be controlled via your Google Mobile Ads dashboard. Typically users are rewarded + * after completing a specific advert action (e.g. watching a video or submitting an option via an interactive form). + * Events (such as the user earning a reward or closing a rewarded advert early) are sent back for you to handle accordingly + * within your application. + * + * #### Example + * + * First create a new Rewarded instance, passing in your Ad Unit ID from the Google Mobile Ads configuration console, and any additional + * request options. The example below will present a test advert, and only request a non-personalized ad. + * + * ```js + * import { RewardedAd, TestIds } from '@invertase/react-native-google-ads'; + * + * const rewarded = RewardedAd.createForAdRequest(TestIds.REWARDED, { + * requestNonPersonalizedAdsOnly: true, + * }); + * ``` + * + * Each advert needs to be loaded from Google Ads before being shown. It is recommended this is performed before the user + * reaches the checkpoint to show the advert, so it's ready to go. Before loading the advert, we need to setup + * event listeners to listen for updates from Google Ads, such as advert loaded or failed to load. + * + * Event types match the `AdEventType` or `RewardedAdEventType` interface. The potential user reward for rewarded + * adverts are passed back to the event handler on advert load and when the user earns the reward. + * + * ```js + * import { RewardedAdEventType } from '@invertase/react-native-google-ads'; + * + * rewarded.onAdEvent((type, error, reward) => { + * if (type === RewardedAdEventType.LOADED) { + * rewarded.show(); + * } + * if (type === RewardedAdEventType.EARNED_REWARD) { + * console.log('User earned reward of ', reward); + * } + * }); + * + * rewarded.load(); + * ``` + * + * The rewarded advert will be presented to the user, and several more events can be triggered such as the user clicking the + * advert, closing it or completing the action. + */ +export class RewardedAd extends MobileAd implements MobileAdInterface { + /** + * Creates a new RewardedAd instance. + * + * #### Example + * + * ```js + * import { RewardedAd, RewardedAdEventType, TestIds } from '@invertase/react-native-google-ads'; + * + * const rewardedAd = await RewardedAd.request(TestIds.REWARDED, { + * requestAgent: 'CoolAds', + * }); + * + * rewardedAd.onAdEvent((type, error, data) => { + * console.log('New event: ', type, error); + * + * if (type === RewardedAdEventType.LOADED) { + * rewardedAd.show(); + * } + * }); + * + * rewardedAd.load(); + * ``` + * + * @param adUnitId The Ad Unit ID for the Rewarded Ad. You can find this on your Google Mobile Ads dashboard. + * @param requestOptions Optional RequestOptions used to load the ad. + */ + static createForAdRequest(adUnitId: string, requestOptions?: RequestOptions): RewardedAd { + if (!isString(adUnitId)) { + throw new Error("RewardedAd.createForAdRequest(*) 'adUnitId' expected an string value."); + } + + let options = {}; + try { + options = validateAdRequestOptions(requestOptions); + } catch (e) { + if (e instanceof Error) { + throw new Error(`RewardedAd.createForAdRequest(_, *) ${e.message}.`); + } + } + + const requestId = _rewardedRequest++; + return new RewardedAd('rewarded', MobileAds(), requestId, adUnitId, options); + } + + load() { + // Prevent multiple load calls + if (this._loaded || this._isLoadCalled) { + return; + } + + this._isLoadCalled = true; + this._googleAds.native.rewardedLoad(this._requestId, this._adUnitId, this._requestOptions); + } + + onAdEvent(handler: AdEventListener) { + if (!isFunction(handler)) { + throw new Error("RewardedAd.onAdEvent(*) 'handler' expected a function."); + } + + return this._setAdEventHandler(handler); + } + + show(showOptions?: AdShowOptions) { + if (!this._loaded) { + throw new Error( + 'RewardedAd.show() The requested RewardedAd has not loaded and could not be shown.', + ); + } + + let options; + try { + options = validateAdShowOptions(showOptions); + } catch (e) { + if (e instanceof Error) { + throw new Error(`RewardedAd.show(*) ${e.message}.`); + } + } + return this._googleAds.native.rewardedShow(this._requestId, this._adUnitId, options); + } +} diff --git a/lib/common/Base64.js b/src/common/Base64.ts similarity index 95% rename from lib/common/Base64.js rename to src/common/Base64.ts index b0d060d9..0f8b7285 100644 --- a/lib/common/Base64.js +++ b/src/common/Base64.ts @@ -25,7 +25,7 @@ const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= /** * window.btoa */ -function btoa(input) { +export function btoa(input: string) { let map; let i = 0; let block = 0; @@ -53,7 +53,7 @@ function btoa(input) { /** * window.atob */ -function atob(input) { +export function atob(input: string) { let i = 0; let bc = 0; let bs = 0; @@ -84,7 +84,7 @@ function atob(input) { /** * Converts a Blob, ArrayBuffer or Uint8Array to a base64 string. */ -function fromData(data) { +export function fromData(data: Blob | ArrayBuffer | Uint8Array) { if (data instanceof Blob) { const fileReader = new FileReader(); const { resolve, reject, promise } = promiseDefer(); @@ -112,9 +112,3 @@ function fromData(data) { throw new Error("'RNFirebase.Base64.fromData' failed: Unknown data type."); } - -export default { - btoa, - atob, - fromData, -}; diff --git a/lib/common/MutatableParams.js b/src/common/MutatableParams.ts similarity index 83% rename from lib/common/MutatableParams.js rename to src/common/MutatableParams.ts index 8b998dad..5bae0c5f 100644 --- a/lib/common/MutatableParams.js +++ b/src/common/MutatableParams.ts @@ -17,8 +17,11 @@ import { deepGet, deepSet } from './deeps'; -export default class MutatableParams { - constructor(parentInstance) { +export class MutatableParams { + _mutatableParams: Record; + _parentInstance: MutatableParams; + + constructor(parentInstance: MutatableParams) { if (parentInstance) { this._mutatableParams = parentInstance._mutatableParams; this._parentInstance = parentInstance; @@ -28,12 +31,12 @@ export default class MutatableParams { } } - set(param, value) { + set(param: string, value: unknown) { deepSet(this._mutatableParams, param, value); return this._parentInstance; } - get(param) { + get(param: string) { return deepGet(this._mutatableParams, param, '.'); } diff --git a/lib/common/ReferenceBase.js b/src/common/ReferenceBase.ts similarity index 94% rename from lib/common/ReferenceBase.js rename to src/common/ReferenceBase.ts index 0fe24f60..d19f9117 100644 --- a/lib/common/ReferenceBase.js +++ b/src/common/ReferenceBase.ts @@ -15,8 +15,10 @@ * */ -export default class ReferenceBase { - constructor(_path) { +export class ReferenceBase { + path: string; + + constructor(_path: string) { let path = _path; if (path) { diff --git a/lib/common/deeps.js b/src/common/deeps.ts similarity index 80% rename from lib/common/deeps.js rename to src/common/deeps.ts index cf235c37..0531f683 100644 --- a/lib/common/deeps.js +++ b/src/common/deeps.ts @@ -25,25 +25,25 @@ import { isArray, isObject } from './validate'; * @param joiner * @returns {*} */ -export function deepGet(object, path, joiner = '/') { +export function deepGet(object: Record, path: string, joiner = '/') { if (!isObject(object) && !Array.isArray(object)) { return undefined; } const keys = path.split(joiner); let i = 0; - let tmp = object; + let value; const len = keys.length; while (i < len) { const key = keys[i++]; - if (!tmp || !Object.hasOwnProperty.call(tmp, key)) { + if (!object || !Object.hasOwnProperty.call(object, key)) { return undefined; } - tmp = tmp[key]; + value = object[key]; } - return tmp; + return value; } /** @@ -54,7 +54,13 @@ export function deepGet(object, path, joiner = '/') { * @param initPaths * @param joiner */ -export function deepSet(object, path, value, initPaths = true, joiner = '.') { +export function deepSet( + object: Record, + path: string, + value: unknown, + initPaths = true, + joiner = '.', +) { if (!isObject(object)) { return false; } @@ -69,7 +75,7 @@ export function deepSet(object, path, value, initPaths = true, joiner = '.') { if (initPaths && !Object.hasOwnProperty.call(object, key)) { _object[key] = {}; } - _object = _object[key]; + _object = _object[key] as Record; } if (isObject(_object) || (isArray(_object) && !Number.isNaN(keys[i]))) { diff --git a/lib/common/id.js b/src/common/id.ts similarity index 98% rename from lib/common/id.js rename to src/common/id.ts index 1266cb81..de697832 100644 --- a/lib/common/id.js +++ b/src/common/id.ts @@ -9,7 +9,7 @@ let lastPushTime = 0; // timestamp to prevent collisions with other clients. We store the last characters we // generated because in the event of a collision, we'll use those same characters except // "incremented" by one. -const lastRandChars = []; +const lastRandChars: number[] = []; /** * Generate a firebase id - for use with ref().push(val, cb) - e.g. -KXMr7k2tXUFQqiaZRY4' diff --git a/lib/common/index.js b/src/common/index.ts similarity index 78% rename from lib/common/index.js rename to src/common/index.ts index 809d8b3a..6522ad4e 100644 --- a/lib/common/index.js +++ b/src/common/index.ts @@ -14,8 +14,9 @@ * limitations under the License. * */ + import { Platform } from 'react-native'; -import Base64 from './Base64'; +import * as Base64 from './Base64'; import { isString } from './validate'; export * from './id'; @@ -23,10 +24,10 @@ export * from './path'; export * from './promise'; export * from './validate'; -export { default as Base64 } from './Base64'; -export { default as ReferenceBase } from './ReferenceBase'; +export { Base64 }; +export { ReferenceBase } from './ReferenceBase'; -export function getDataUrlParts(dataUrlString) { +export function getDataUrlParts(dataUrlString: string) { const isBase64 = dataUrlString.includes(';base64'); let [mediaType, base64String] = dataUrlString.split(','); if (!mediaType || !base64String) { @@ -42,11 +43,11 @@ export function getDataUrlParts(dataUrlString) { return { base64String, mediaType }; } -export function once(fn, context) { - let onceResult; +export function once(fn: () => void, context: unknown): (this: T, ...args: []) => void { + let onceResult: unknown; let ranOnce = false; - return function onceInner(...args) { + return function onceInner(...args: []) { if (!ranOnce) { ranOnce = true; onceResult = fn.apply(context || this, args); @@ -56,7 +57,7 @@ export function once(fn, context) { }; } -export function isError(value) { +export function isError(value: unknown) { if (Object.prototype.toString.call(value) === '[object Error]') { return true; } @@ -64,7 +65,7 @@ export function isError(value) { return value instanceof Error; } -export function hasOwnProperty(target, property) { +export function hasOwnProperty(target: unknown, property: PropertyKey) { return Object.hasOwnProperty.call(target, property); } @@ -74,7 +75,7 @@ export function hasOwnProperty(target, property) { * @param string * @returns {*} */ -export function stripTrailingSlash(string) { +export function stripTrailingSlash(string: string) { if (!isString(string)) { return string; } @@ -85,7 +86,7 @@ export const isIOS = Platform.OS === 'ios'; export const isAndroid = Platform.OS === 'android'; -export function tryJSONParse(string) { +export function tryJSONParse(string: string) { try { return string && JSON.parse(string); } catch (jsonError) { @@ -93,7 +94,7 @@ export function tryJSONParse(string) { } } -export function tryJSONStringify(data) { +export function tryJSONStringify(data: unknown) { try { return JSON.stringify(data); } catch (jsonError) { diff --git a/lib/common/path.js b/src/common/path.ts similarity index 86% rename from lib/common/path.js rename to src/common/path.ts index 6a3f13fb..2dd28b95 100644 --- a/lib/common/path.js +++ b/src/common/path.ts @@ -18,7 +18,7 @@ /** * Returns the next parent of the path e.g. /foo/bar/car -> /foo/bar */ -export function pathParent(path) { +export function pathParent(path: string) { if (path.length === 0) { return null; } @@ -34,7 +34,7 @@ export function pathParent(path) { /** * Joins a parent and a child path */ -export function pathChild(path, childPath) { +export function pathChild(path: string, childPath: string) { const canonicalChildPath = pathPieces(childPath).join('/'); if (path.length === 0) { @@ -47,7 +47,7 @@ export function pathChild(path, childPath) { /** * Returns the last component of a path, e.g /foo/bar.jpeg -> bar.jpeg */ -export function pathLastComponent(path) { +export function pathLastComponent(path: string) { const index = path.lastIndexOf('/', path.length - 2); if (index === -1) { return path; @@ -61,7 +61,7 @@ export function pathLastComponent(path) { * @param path * @returns {*} */ -export function pathPieces(path) { +export function pathPieces(path: string) { return path.split('/').filter($ => $.length > 0); } @@ -70,7 +70,7 @@ export function pathPieces(path) { * @param path * @returns {boolean} */ -export function pathIsEmpty(path) { +export function pathIsEmpty(path: string) { return !pathPieces(path).length; } @@ -79,7 +79,7 @@ export function pathIsEmpty(path) { * @param path * @returns {string|string} */ -export function pathToUrlEncodedString(path) { +export function pathToUrlEncodedString(path: string) { const pieces = pathPieces(path); let pathString = ''; for (let i = 0; i < pieces.length; i++) { @@ -96,7 +96,7 @@ export const INVALID_PATH_REGEX = /[[\].#$\u0000-\u001F\u007F]/; * @param path * @returns {boolean} */ -export function isValidPath(path) { +export function isValidPath(path: unknown) { return typeof path === 'string' && path.length !== 0 && !INVALID_PATH_REGEX.test(path); } @@ -105,7 +105,7 @@ export function isValidPath(path) { * @param path * @returns {*} */ -export function toFilePath(path) { +export function toFilePath(path: string) { let _filePath = path.replace('file://', ''); if (_filePath.includes('%')) { _filePath = decodeURIComponent(_filePath); diff --git a/lib/common/promise.js b/src/common/promise.ts similarity index 80% rename from lib/common/promise.js rename to src/common/promise.ts index b1f9b86e..2ecf41ef 100644 --- a/lib/common/promise.js +++ b/src/common/promise.ts @@ -21,10 +21,11 @@ import { isFunction } from './validate'; * */ export function promiseDefer() { - const deferred = { - resolve: null, - reject: null, - }; + const deferred: { + promise: Promise | null; + resolve: (value: unknown) => void; + reject: (value: unknown) => void; + } = { promise: null, resolve: () => {}, reject: () => {} }; deferred.promise = new Promise((resolve, reject) => { deferred.resolve = resolve; @@ -38,7 +39,10 @@ export function promiseDefer() { * @param promise * @param callback */ -export function promiseWithOptionalCallback(promise, callback) { +export function promiseWithOptionalCallback( + promise: Promise, + callback: (a: unknown, b?: unknown) => void, +) { if (!isFunction(callback)) { return promise; } diff --git a/lib/common/serialize.js b/src/common/serialize.ts similarity index 81% rename from lib/common/serialize.js rename to src/common/serialize.ts index 2d92aecc..0ec87bc8 100644 --- a/lib/common/serialize.js +++ b/src/common/serialize.ts @@ -18,8 +18,8 @@ import { tryJSONParse, tryJSONStringify } from './index'; import { isObject } from './validate'; -export function serializeType(value) { - if (isObject(value)) { +export function serializeType(value: unknown) { + if (typeof value === 'object' && !Array.isArray(value) && !(value === null)) { return { type: 'object', value: serializeObject(value), @@ -32,12 +32,12 @@ export function serializeType(value) { }; } -export function serializeObject(object) { +export function serializeObject(object: unknown) { if (!isObject(object)) { return object; } // json stringify then parse it calls toString on Objects / Classes // that support it i.e new Date() becomes a ISO string. - return tryJSONParse(tryJSONStringify(object)); + return tryJSONParse(tryJSONStringify(object) || ''); } diff --git a/lib/common/validate.js b/src/common/validate.ts similarity index 79% rename from lib/common/validate.js rename to src/common/validate.ts index 2351238e..0b88dde3 100644 --- a/lib/common/validate.js +++ b/src/common/validate.ts @@ -19,7 +19,7 @@ import { Platform } from 'react-native'; const AlphaNumericUnderscore = /^[a-zA-Z0-9_]+$/; -export function objectKeyValuesAreStrings(object) { +export function objectKeyValuesAreStrings(object: Record) { if (!isObject(object)) { return false; } @@ -42,7 +42,7 @@ export function objectKeyValuesAreStrings(object) { * @param value * @returns {boolean} */ -export function isNull(value) { +export function isNull(value: unknown) { return value === null; } @@ -52,7 +52,7 @@ export function isNull(value) { * @param value * @returns {boolean} */ -export function isObject(value) { +export function isObject(value: unknown) { return value ? typeof value === 'object' && !Array.isArray(value) && !isNull(value) : false; } @@ -62,7 +62,7 @@ export function isObject(value) { * @param value * @returns {boolean} */ -export function isDate(value) { +export function isDate(value: number) { // use the global isNaN() and not Number.isNaN() since it will validate an Invalid Date return value && Object.prototype.toString.call(value) === '[object Date]' && !isNaN(value); } @@ -73,7 +73,7 @@ export function isDate(value) { * @param value * @returns {*|boolean} */ -export function isFunction(value) { +export function isFunction(value: unknown) { return value ? typeof value === 'function' : false; } @@ -82,7 +82,7 @@ export function isFunction(value) { * @param value * @return {boolean} */ -export function isString(value) { +export function isString(value: unknown) { return typeof value === 'string'; } @@ -91,7 +91,7 @@ export function isString(value) { * @param value * @return {boolean} */ -export function isNumber(value) { +export function isNumber(value: unknown) { return typeof value === 'number'; } @@ -100,7 +100,7 @@ export function isNumber(value) { * @param value * @returns {boolean} */ -export function isFinite(value) { +export function isFinite(value: unknown) { return Number.isFinite(value); } @@ -109,7 +109,7 @@ export function isFinite(value) { * @param value * @returns {boolean} */ -export function isInteger(value) { +export function isInteger(value: unknown) { return Number.isInteger(value); } @@ -119,16 +119,16 @@ export function isInteger(value) { * @param value * @return {boolean} */ -export function isBoolean(value) { +export function isBoolean(value: unknown) { return typeof value === 'boolean'; } /** * * @param value - * @returns {arg is Array} + * @returns {arg is Array} */ -export function isArray(value) { +export function isArray(value: unknown) { return Array.isArray(value); } @@ -137,7 +137,7 @@ export function isArray(value) { * @param value * @returns {boolean} */ -export function isUndefined(value) { +export function isUndefined(value: unknown) { return typeof value === 'undefined'; } @@ -147,7 +147,7 @@ export function isUndefined(value) { * @param value * @returns {boolean} */ -export function isAlphaNumericUnderscore(value) { +export function isAlphaNumericUnderscore(value: string) { return AlphaNumericUnderscore.test(value); } @@ -157,7 +157,7 @@ export function isAlphaNumericUnderscore(value) { * @returns {boolean} */ const IS_VALID_URL_REGEX = /^(http|https):\/\/[^ "]+$/; -export function isValidUrl(url) { +export function isValidUrl(url: string) { return IS_VALID_URL_REGEX.test(url); } @@ -168,7 +168,7 @@ export function isValidUrl(url) { * @param oneOf * @returns {boolean} */ -export function isOneOf(value, oneOf = []) { +export function isOneOf(value: unknown, oneOf: unknown[] = []) { if (!isArray(oneOf)) { return false; } @@ -179,7 +179,11 @@ export function noop() { // noop-🐈 } -export function validateOptionalNativeDependencyExists(firebaseJsonKey, apiName, nativeFnExists) { +export function validateOptionalNativeDependencyExists( + firebaseJsonKey: string, + apiName: string, + nativeFnExists: boolean, +) { if (nativeFnExists) { return; } diff --git a/src/declarations.d.ts b/src/declarations.d.ts new file mode 100644 index 00000000..2939a968 --- /dev/null +++ b/src/declarations.d.ts @@ -0,0 +1,3 @@ +declare module 'react-native/Libraries/Utilities/binaryToBase64' { + export default function binaryToBase64(data: ArrayBuffer | Uint8Array): string; +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..96809689 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +import { version } from './version'; + +// import { SDK_VERSION } from '@invertase/react-native-google-ads'; +export const SDK_VERSION = version; + +export { default, MobileAds } from './MobileAds'; +export { AdsConsentDebugGeography } from './AdsConsentDebugGeography'; +export { AdsConsentStatus } from './AdsConsentStatus'; +export { MaxAdContentRating } from './MaxAdContentRating'; +export { TestIds } from './TestIds'; +export { AdEventType } from './AdEventType'; +export { BannerAdSize } from './BannerAdSize'; +export { RewardedAdEventType } from './RewardedAdEventType'; +export { AdsConsent } from './AdsConsent'; +export { InterstitialAd } from './ads/InterstitialAd'; +export { RewardedAd } from './ads/RewardedAd'; +export { BannerAd } from './ads/BannerAd'; diff --git a/lib/internal/GoogleAdsNativeEventEmitter.js b/src/internal/GoogleAdsNativeEventEmitter.ts similarity index 75% rename from lib/internal/GoogleAdsNativeEventEmitter.js rename to src/internal/GoogleAdsNativeEventEmitter.ts index 3b6f2a81..ef20df39 100644 --- a/lib/internal/GoogleAdsNativeEventEmitter.js +++ b/src/internal/GoogleAdsNativeEventEmitter.ts @@ -15,24 +15,30 @@ * */ -import { NativeEventEmitter, NativeModules } from 'react-native'; +import { NativeEventEmitter, NativeModules, EmitterSubscription } from 'react-native'; const { RNAppModule } = NativeModules; -class GoogleAdsNativeEventEmitter extends NativeEventEmitter { +class GANativeEventEmitter extends NativeEventEmitter { + ready: boolean; + constructor() { super(RNAppModule); this.ready = false; } - addListener(eventType, listener, context) { + addListener( + eventType: string, + listener: (event: { appName?: string }) => void, + context?: Record, + ) { if (!this.ready) { RNAppModule.eventsNotifyReady(true); this.ready = true; } RNAppModule.eventsAddListener(eventType); - let subscription = super.addListener(`rnapp_${eventType}`, listener, context); + const subscription = super.addListener(`rnapp_${eventType}`, listener, context); // React Native 0.65+ altered EventEmitter: // - removeSubscription is gone @@ -43,8 +49,8 @@ class GoogleAdsNativeEventEmitter extends NativeEventEmitter { // New style is to return a remove function on the object, just in csae people call that, // we will modify it to do our native unsubscription then call the original - let originalRemove = subscription.remove; - let newRemove = () => { + const originalRemove = subscription.remove; + const newRemove = () => { RNAppModule.eventsRemoveListener(eventType, false); if (super.removeSubscription != null) { // This is for RN <= 0.64 - 65 and greater no longer have removeSubscription @@ -58,18 +64,18 @@ class GoogleAdsNativeEventEmitter extends NativeEventEmitter { return subscription; } - removeAllListeners(eventType) { + removeAllListeners(eventType: string) { RNAppModule.eventsRemoveListener(eventType, true); super.removeAllListeners(`rnapp_${eventType}`); } // This is likely no longer ever called, but it is here for backwards compatibility with RN <= 0.64 - removeSubscription(subscription) { - RNAppModule.eventsRemoveListener(subscription.eventType.replace('rnapp_'), false); - if (super.removeSubscription) { + removeSubscription(subscription: EmitterSubscription) { + RNAppModule.eventsRemoveListener(subscription.eventType.replace('rnapp_', ''), false); + if (super.removeSubscription != null) { super.removeSubscription(subscription); } } } -export default new GoogleAdsNativeEventEmitter(); +export const GoogleAdsNativeEventEmitter = new GANativeEventEmitter(); diff --git a/lib/internal/Module.js b/src/internal/Module.ts similarity index 65% rename from lib/internal/Module.js rename to src/internal/Module.ts index ef4f7f21..e1812616 100644 --- a/lib/internal/Module.js +++ b/src/internal/Module.ts @@ -15,13 +15,19 @@ * */ -import { getAppModule, getNativeModule } from './registry/nativeModule'; -import SharedEventEmitter from './SharedEventEmitter'; +import { getNativeModule } from './registry/nativeModule'; +import { SharedEventEmitter } from './SharedEventEmitter'; +import { App, Config } from '../types/Module.interface'; +import { GoogleAdsNativeModule } from '../types/GoogleAdsNativeModule'; -let appJson = null; +export class AppModule { + _app: App; + _nativeModule: unknown; + _config: Config; -export default class AppModule { - constructor(app, config) { + static __extended__ = {}; + + constructor(app: App, config: Config) { this._app = app; this._nativeModule = null; this._config = Object.assign({}, config); @@ -31,28 +37,20 @@ export default class AppModule { return this._app; } - get appJson() { - if (appJson) { - return appJson; - } - appJson = JSON.parse(getAppModule().APP_RAW_JSON); - return appJson; - } - get emitter() { return SharedEventEmitter; } - eventNameForApp(...args) { + eventNameForApp(...args: string[]) { return `${this.app.name}-${args.join('-')}`; } get native() { if (this._nativeModule) { - return this._nativeModule; + return this._nativeModule as GoogleAdsNativeModule; } this._nativeModule = getNativeModule(this); - return this._nativeModule; + return this._nativeModule as GoogleAdsNativeModule; } } diff --git a/src/internal/NativeError.ts b/src/internal/NativeError.ts new file mode 100644 index 00000000..a5942aab --- /dev/null +++ b/src/internal/NativeError.ts @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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. + * + */ + +export class NativeError extends Error { + namespace: string; + code: string; + message: string; + jsStack: string; + userInfo: { code: string; message: string }; + + static fromEvent( + errorEvent: { code: string; message: string }, + namespace: string, + stack?: string, + ) { + return new NativeError({ userInfo: errorEvent }, stack || new Error().stack || '', namespace); + } + + constructor( + nativeError: { userInfo: { code: string; message: string } }, + jsStack: string, + namespace: string, + ) { + super(); + const { userInfo } = nativeError; + this.namespace = namespace; + this.code = `${this.namespace}/${userInfo.code || 'unknown'}`; + this.message = `[${this.code}] ${userInfo.message}`; + this.jsStack = jsStack; + this.userInfo = userInfo; + this.stack = NativeError.getStackWithMessage(`NativeError: ${this.message}`, this.jsStack); + } + + /** + * Build a stack trace that includes JS stack prior to calling the native method. + * + * @returns {string} + */ + static getStackWithMessage(message: string, jsStack: string) { + return [message, ...jsStack.split('\n').slice(2, 13)].join('\n'); + } +} diff --git a/lib/internal/SharedEventEmitter.js b/src/internal/SharedEventEmitter.ts similarity index 73% rename from lib/internal/SharedEventEmitter.js rename to src/internal/SharedEventEmitter.ts index 58b1ec99..9fe2c577 100644 --- a/lib/internal/SharedEventEmitter.js +++ b/src/internal/SharedEventEmitter.ts @@ -15,6 +15,8 @@ * */ -import EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter'; +// @ts-ignore: Could not find a declaration file +import Emitter from 'react-native/Libraries/vendor/emitter/EventEmitter'; +import { EventEmitter } from 'react-native'; -export default new EventEmitter(); +export const SharedEventEmitter: EventEmitter = new Emitter(); diff --git a/lib/AdsConsentStatus.js b/src/internal/constants.ts similarity index 58% rename from lib/AdsConsentStatus.js rename to src/internal/constants.ts index 55af003e..b272015e 100644 --- a/lib/AdsConsentStatus.js +++ b/src/internal/constants.ts @@ -15,8 +15,29 @@ * */ -export default { - UNKNOWN: 0, - NON_PERSONALIZED: 1, - PERSONALIZED: 2, -}; +export const APP_NATIVE_MODULE = 'RNFBAppModule'; + +export const DEFAULT_APP_NAME = '[DEFAULT]'; + +export const KNOWN_NAMESPACES = [ + 'appCheck', + 'appDistribution', + 'auth', + 'analytics', + 'remoteConfig', + 'crashlytics', + 'database', + 'inAppMessaging', + 'installations', + 'firestore', + 'functions', + 'indexing', + 'storage', + 'dynamicLinks', + 'messaging', + 'naturalLanguage', + 'ml', + 'notifications', + 'perf', + 'utils', +]; diff --git a/lib/internal/index.js b/src/internal/index.ts similarity index 79% rename from lib/internal/index.js rename to src/internal/index.ts index 95fa8da7..1db84283 100644 --- a/lib/internal/index.js +++ b/src/internal/index.ts @@ -15,7 +15,7 @@ * */ -export { default as Module } from './Module'; -export { default as NativeError } from './NativeError'; +export { AppModule as Module } from './Module'; +export { NativeError } from './NativeError'; export * from './registry/nativeModule'; -export { default as SharedEventEmitter } from './SharedEventEmitter'; +export { SharedEventEmitter } from './SharedEventEmitter'; diff --git a/lib/internal/registry/nativeModule.js b/src/internal/registry/nativeModule.ts similarity index 74% rename from lib/internal/registry/nativeModule.js rename to src/internal/registry/nativeModule.ts index 47c2987c..ab69c54e 100644 --- a/lib/internal/registry/nativeModule.js +++ b/src/internal/registry/nativeModule.ts @@ -16,14 +16,16 @@ */ import { NativeModules, Platform } from 'react-native'; -import NativeError from '../NativeError'; -import GoogleAdsNativeEventEmitter from '../GoogleAdsNativeEventEmitter'; -import SharedEventEmitter from '../SharedEventEmitter'; +import { APP_NATIVE_MODULE } from '../constants'; +import { NativeError } from '../NativeError'; +import { GoogleAdsNativeEventEmitter } from '../GoogleAdsNativeEventEmitter'; +import { SharedEventEmitter } from '../SharedEventEmitter'; +import { ModuleInterface } from '../../types/Module.interface'; -const NATIVE_MODULE_REGISTRY = {}; -const NATIVE_MODULE_EVENT_SUBSCRIPTIONS = {}; +const NATIVE_MODULE_REGISTRY: Record = {}; +const NATIVE_MODULE_EVENT_SUBSCRIPTIONS: Record = {}; -function nativeModuleKey(module) { +function nativeModuleKey(module: ModuleInterface) { return `${module._customUrlOrRegion || ''}:${module.app.name}:${module._config.namespace}`; } @@ -36,12 +38,16 @@ function nativeModuleKey(module) { * @param argToPrepend * @returns {Function} */ -function nativeModuleMethodWrapped(namespace, method, argToPrepend) { - return (...args) => { +function nativeModuleMethodWrapped( + namespace: string, + method: (...args: unknown[]) => Promise | void, + argToPrepend: [], +) { + return (...args: []) => { const possiblePromise = method(...[...argToPrepend, ...args]); if (possiblePromise && possiblePromise.then) { - const jsStack = new Error().stack; + const jsStack = new Error().stack || ''; return possiblePromise.catch(nativeError => Promise.reject(new NativeError(nativeError, jsStack, namespace)), ); @@ -58,8 +64,12 @@ function nativeModuleMethodWrapped(namespace, method, argToPrepend) { * @param NativeModule * @param argToPrepend */ -function nativeModuleWrapped(namespace, NativeModule, argToPrepend) { - const native = {}; +function nativeModuleWrapped( + namespace: string, + NativeModule: Record Promise | void>, + argToPrepend: [], +) { + const native: Record = {}; if (!NativeModule) { return NativeModule; } @@ -84,11 +94,11 @@ function nativeModuleWrapped(namespace, NativeModule, argToPrepend) { * @param module * @returns {*} */ -function initialiseNativeModule(module) { +function initialiseNativeModule(module: ModuleInterface) { const config = module._config; const key = nativeModuleKey(module); const { namespace, nativeEvents, nativeModuleName } = config; - const multiModuleRoot = {}; + const multiModuleRoot: Record = {}; const multiModule = Array.isArray(nativeModuleName); const nativeModuleNames = multiModule ? nativeModuleName : [nativeModuleName]; @@ -105,9 +115,7 @@ function initialiseNativeModule(module) { multiModuleRoot[nativeModuleNames[i]] = !!nativeModule; } - const argToPrepend = []; - - Object.assign(multiModuleRoot, nativeModuleWrapped(namespace, nativeModule, argToPrepend)); + Object.assign(multiModuleRoot, nativeModuleWrapped(namespace, nativeModule, [])); } if (nativeEvents && nativeEvents.length) { @@ -132,7 +140,7 @@ function initialiseNativeModule(module) { * @param eventName * @private */ -function subscribeToNativeModuleEvent(eventName) { +function subscribeToNativeModuleEvent(eventName: string) { if (!NATIVE_MODULE_EVENT_SUBSCRIPTIONS[eventName]) { GoogleAdsNativeEventEmitter.addListener(eventName, event => { if (event.appName) { @@ -154,7 +162,7 @@ function subscribeToNativeModuleEvent(eventName) { * @param namespace * @returns {string} */ -function getMissingModuleHelpText(namespace) { +function getMissingModuleHelpText(namespace: string) { const snippet = `${namespace}()`; const nativeModule = namespace.charAt(0).toUpperCase() + namespace.slice(1); @@ -184,7 +192,7 @@ function getMissingModuleHelpText(namespace) { * @param module * @returns {*} */ -export function getNativeModule(module) { +export function getNativeModule(module: ModuleInterface) { const key = nativeModuleKey(module); if (NATIVE_MODULE_REGISTRY[key]) { @@ -193,3 +201,25 @@ export function getNativeModule(module) { return initialiseNativeModule(module); } + +/** + * Custom wrapped app module as it does not have it's own FirebaseModule based class. + * + * @returns {*} + */ +export function getAppModule() { + if (NATIVE_MODULE_REGISTRY[APP_NATIVE_MODULE]) { + return NATIVE_MODULE_REGISTRY[APP_NATIVE_MODULE]; + } + + const namespace = 'app'; + const nativeModule = NativeModules[APP_NATIVE_MODULE]; + + if (!nativeModule) { + throw new Error(getMissingModuleHelpText(namespace)); + } + + NATIVE_MODULE_REGISTRY[APP_NATIVE_MODULE] = nativeModuleWrapped(namespace, nativeModule, []); + + return NATIVE_MODULE_REGISTRY[APP_NATIVE_MODULE]; +} diff --git a/src/types/AdEventListener.ts b/src/types/AdEventListener.ts new file mode 100644 index 00000000..beda7585 --- /dev/null +++ b/src/types/AdEventListener.ts @@ -0,0 +1,16 @@ +import { AdEventType } from '../AdEventType'; +import { RewardedAdReward } from './RewardedAdReward'; +import { RewardedAdEventType } from '../RewardedAdEventType'; + +/** + * A callback interface for all ad events. + * + * @param type The event type, e.g. `AdEventType.LOADED`. + * @param error An optional JavaScript Error containing the error code and message. + * @param data Optional data for the event, e.g. reward type and amount + */ +export type AdEventListener = ( + type: AdEventType | RewardedAdEventType, + error?: Error, + data?: RewardedAdReward, +) => void; diff --git a/src/types/AdShowOptions.ts b/src/types/AdShowOptions.ts new file mode 100644 index 00000000..4e199ced --- /dev/null +++ b/src/types/AdShowOptions.ts @@ -0,0 +1,12 @@ +/** + * A `AdShowOptions` interface used when showing an ad. + */ +export interface AdShowOptions { + /** + * - On Android, enables [immersive mode](https://developer.android.com/training/system-ui/immersive). + * - On iOS, this has no effect on how the ad is shown. + * + * @android + */ + immersiveModeEnabled?: boolean; +} diff --git a/src/types/AdapterStatus.ts b/src/types/AdapterStatus.ts new file mode 100644 index 00000000..8fec3b50 --- /dev/null +++ b/src/types/AdapterStatus.ts @@ -0,0 +1,20 @@ +export enum InitializationState { + /** + * The mediation adapter is less likely to fill ad requests. + */ + AdapterInitializationStateNotReady = 0, + + /** + * The mediation adapter is ready to service ad requests. + */ + AdapterInitializationStateReady = 1, +} + +/** + * An immutable snapshot of a mediation adapter's initialization status. + */ +export type AdapterStatus = { + name: string; + description: string; + status: InitializationState; +}; diff --git a/src/types/AdsConsent.interface.ts b/src/types/AdsConsent.interface.ts new file mode 100644 index 00000000..db841e8a --- /dev/null +++ b/src/types/AdsConsent.interface.ts @@ -0,0 +1,306 @@ +import { AdsConsentDebugGeography } from '../AdsConsentDebugGeography'; +import { AdsConsentStatus } from '../AdsConsentStatus'; + +/** + * Under the Google [EU User Consent Policy](https://www.google.com/about/company/consentstaging.html), you must make certain disclosures to your users in the European Economic Area (EEA) + * and obtain their consent to use cookies or other local storage, where legally required, and to use personal data + * (such as AdID) to serve ads. This policy reflects the requirements of the EU ePrivacy Directive and the + * General Data Protection Regulation (GDPR). + * + * It is recommended that you determine the status of a user's consent at every app launch. The user consent status is held + * on the device until a condition changes which requires the user to consent again, such as a change in publishers. + * + * For more information, see [here](https://developers.google.com/admob/android/eu-consent#delay_app_measurement_optional). + */ + +/** + * A AdProvider interface returned from `AdsConsent.getProviders`. + */ +export interface AdProvider { + /** + * A provider company ID. + */ + companyId: string; + + /** + * A provider company name. + */ + companyName: string; + + /** + * A fully formed URL for the privacy policy of the provider. + */ + privacyPolicyUrl: string; +} + +export interface AdsConsentInterface { + /** + * Requests user consent for a given list of publisher IDs. + * + * The list of publisher IDs can be obtained from the settings panel on the Google Mobile Ads console. If the list of + * publisher IDs has changed since the last time a user provided consent, their consent status will be reset to + * 'UNKNOWN' and they must provide consent again. + * + * If the request fails with the error "Could not parse Event FE preflight response", this means the state of your + * Google Mobile Ads account is not complete. Ensure you have validated your account and have setup valid payment + * information. This error is also thrown when a Publisher ID is invalid. + * + * The response from this method provides request location and consent status properties. + * + * If request location is within the EEA or unknown, and the consent status is also unknown, you + * must request consent via the `showForm()` method or your own means. + * + * If the consent status is not unknown, the user has already previously provided consent for the current publisher + * scope. + * + * #### Example + * + * ```js + * import { AdsConsent } from '@invertase/react-native-google-ads'; + * + * const consent = await AdsConsent.requestInfoUpdate(['pub-6189033257628554']); + * console.log('User location within EEA or Unknown:', consent.isRequestLocationInEeaOrUnknown); + * console.log('User consent status:', consent.status); + * ``` + * + * @param publisherIds A list of publisher IDs found on your Google Mobile Ads dashboard. + */ + requestInfoUpdate(publisherIds: string[]): Promise; + + /** + * Shows a Google-rendered user consent form. + * + * The Google-rendered consent form is a full-screen configurable form that displays over your app content. The form + * allows the following configuration options: + * + * + * 1. Consent to view personalized ads (via `withPersonalizedAds`). + * 2. Consent to view non-personalized ads (via `withNonPersonalizedAds`). + * 3. Use a paid version of the app instead of viewing ads (via `withAdFree`). + * + * Every consent form requires a privacy policy URL which outlines the usage of your application. + * + * You should review the consent text carefully: what appears by default is a message that might be appropriate if + * you use Google to monetize your app. + * + * If providing an ad-free version of your app, ensure you handle this once the form has been handled by the user + * via the `userPrefersAdFree` property. The users preference on consent is automatically forwarded onto the Google + * Mobile SDKs and saved. + * + * If the user is outside of the EEA, the request form will error. + * + * #### Example + * + * ```js + * import { AdsConsent, AdsConsentStatus } from '@invertase/react-native-google-ads'; + * + * async function requestConsent() { + * const consent = await AdsConsent.requestInfoUpdate(['pub-6189033257628554']); + * + * // Check if user requires consent + * if (consent.isRequestLocationInEeaOrUnknown && consent.status === AdsConsentStatus.UNKNOWN) { + * // Show a Google-rendered form + * const result = await AdsConsent.showForm({ + * privacyPolicy: 'https://invertase.io/privacy-policy', + * withPersonalizedAds: true, + * withNonPersonalizedAds: true, + * withAdFree: true, + * }); + * + * console.log('User accepted personalized: ', result.status === AdsConsentStatus.PERSONALIZED); + * console.log('User accepted non-personalized: ', result.status === AdsConsentStatus.NON_PERSONALIZED); + * console.log('User prefers Ad Free version of app: ', result.userPrefersAdFree); + * } + * } + * + * ``` + * + * @param options An AdsConsentFormOptions interface to control the Google-rendered form. + */ + showForm(options: AdsConsentFormOptions): Promise; + + /** + * Returns a list of ad providers currently in use for the given Google Mobile Ads App ID. + * + * If requesting consent from the user via your own method, this list of ad providers must be shown to the user + * for them to accept consent. + * + * #### Example + * + * ```js + * import { AdsConsent } from '@invertase/react-native-google-ads'; + * + * const providers = await AdsConsent.getAdProviders(); + * ``` + */ + getAdProviders(): Promise; + + /** + * Sets the debug geography to locally test consent. + * + * If debugging on an emulator (where location cannot be determined) or outside of the EEA, + * it is possible set your own location to test how your app handles different scenarios. + * + * If using a real device, ensure you have set it as a test device via `addTestDevice()` otherwise this method will have + * no effect. + * + * #### Example + * + * ```js + * import { AdsConsent, AdsConsentDebugGeography } from '@invertase/react-native-google-ads'; + * + * // Set disabled + * await AdsConsentDebugGeography.setDebugGeography(AdsConsentDebugGeography.DISABLED); + * + * // Set within EEA + * await AdsConsentDebugGeography.setDebugGeography(AdsConsentDebugGeography.EEA); + * + * // Set outside EEA + * await AdsConsentDebugGeography.setDebugGeography(AdsConsentDebugGeography.NOT_EEA); + * ``` + * + * @param geography The debug geography location. + */ + setDebugGeography(geography: AdsConsentDebugGeography): Promise; + + /** + * Manually update the consent status of the user. + * + * This method is used when providing your own means of user consent. If using the Google-rendered form via `showForm()`, + * the consent status is automatically set and calling this method is not required. + * + * This method can also be used to reset the consent status, by setting it to `AdsConsentStatus.UNKNOWN`, which may be useful in certain circumstances. + * + * #### Example + * + * ```js + * import { AdsConsent, AdsConsentStatus } from '@invertase/react-native-google-ads'; + * + * // User accepted personalized ads + * await AdsConsent.setStatus(AdsConsentStatus.PERSONALIZED); + * ``` + * + * @param status The user consent status. + */ + setStatus(status: AdsConsentStatus): Promise; + + /** + * Returns the current consent status of the user. + * + * > The user consent status may change at any time, therefore don't reuse old values locally and always request the current value at any time consent is required. + * + * #### Example + * + * ```js + * import { AdsConsent } from '@invertase/react-native-google-ads'; + * + * const status = await AdsConsent.getStatus(); + * ``` + */ + getStatus(): Promise; + + /** + * If a publisher is aware that the user is under the age of consent, all ad requests must set TFUA (Tag For Users + * Under the Age of consent in Europe). This setting takes effect for all future ad requests. + * + * Once the TFUA setting is enabled, the Google-rendered consent form will fail to load. All ad requests that include + * TFUA will be made ineligible for personalized advertising and remarketing. TFUA disables requests to third-party + * ad technology providers, such as ad measurement pixels and third-party ad servers. + * + * To remove TFUA from ad requests, set the value to `false`. + * + * #### Example + * + * ```js + * import { AdsConsent } from '@invertase/react-native-google-ads'; + * + * // User is under age of consent + * await AdsConsent.setTagForUnderAgeOfConsent(true); + * ``` + * + * @param tag The boolean value to tag for under age consent. + */ + setTagForUnderAgeOfConsent(tag: boolean): Promise; + + /** + * If using a real device to test, ensure the device ID is provided to the Google Mobile Ads SDK so any mock debug locations + * can take effect. + * + * Emulators are automatically on the allowlist and should require no action. + * + * If you are seeing real ad activity from a test device, examine logcat / console + * during execution in association with google mobile ads test device documentation to + * configure your device correctly. + * + * @param deviceIds An array of testing device ID. + */ + addTestDevices(deviceIds: string[]): Promise; +} + +/** + * The options used to show on the Google-rendered consent form. At least one of `withAdFree`, `withPersonalizedAds` and `WithNonPersonalizedAds` needs to be set to `true`. + */ +export interface AdsConsentFormOptions { + /** + * A fully formed HTTP or HTTPS privacy policy URL for your application. + * + * Users will have the option to visit this web page before consenting to ads. + */ + privacyPolicy: string; + + /** + * Set to `true` to provide the option for the user to accept being shown personalized ads, defaults to `false`. + */ + withPersonalizedAds?: boolean; + + /** + * Set to `true` to provide the option for the user to accept being shown non-personalized ads, defaults to `false`. + */ + withNonPersonalizedAds?: boolean; + + /** + * Set to `true` to provide the option for the user to choose an ad-free version of your app, defaults to `false`. + * + * If the user chooses this option, you must handle it as required (e.g. navigating to a paid version of the app, + * or a subscribe view). + */ + withAdFree?: boolean; +} + +/** + * The result of a Google-rendered consent form. + */ +export interface AdsConsentFormResult { + /** + * The consent status of the user after closing the consent form. + * + * - UNKNOWN: The form was unable to determine the users consent status. + * - NON_PERSONALIZED: The user has accepted non-personalized ads. + * - PERSONALIZED: The user has accepted personalized ads. + */ + status: AdsConsentStatus; + + /** + * If `true`, the user requested an ad-free version of your application. + */ + userPrefersAdFree: boolean; +} + +/** + * The result of requesting info about a users consent status. + */ +export interface AdsConsentInfo { + /** + * The consent status of the user. + * + * - UNKNOWN: The consent status is unknown and the user must provide consent to show ads if they are within the EEA or location is also unknown. + * - NON_PERSONALIZED: The user has accepted non-personalized ads. + * - PERSONALIZED: The user has accepted personalized ads. + */ + status: AdsConsentStatus; + + /** + * If `true` the user is within the EEA or their location could not be determined. + */ + isRequestLocationInEeaOrUnknown: boolean; +} diff --git a/src/types/BannerAdProps.ts b/src/types/BannerAdProps.ts new file mode 100644 index 00000000..f3bf4ba3 --- /dev/null +++ b/src/types/BannerAdProps.ts @@ -0,0 +1,73 @@ +import { BannerAdSize } from '../BannerAdSize'; +import { RequestOptions } from './RequestOptions'; + +/** + * An interface for a Banner advert component. + * + * #### Example + * + * The `BannerAd` interface is exposed as a React component, allowing you to integrate ads within your existing React + * Native code base. The component itself is isolated, meaning any standard `View` props (e.g. `style`) are not + * forwarded on. It is recommended you wrap the `BannerAd` within your own `View` if you wish to apply custom props for use-cases + * such as positioning. + * + * ```js + * import { BannerAd, BannerAdSize, TestIds } from '@invertase/react-native-google-ads'; + * + * function HomeScreen() { + * return ( + * { + * console.log('Advert loaded'); + * }} + * onAdFailedToLoad={(error) => { + * console.error('Advert failed to load: ', error); + * }} + * /> + * ); + * } + * ``` + */ +export type BannerAdProps = { + /** + * The Google Mobile Ads unit ID for the banner. + */ + unitId: string; + + /** + * The size of the banner. Can be a predefined size via `BannerAdSize` or custom dimensions, e.g. `300x200`. + * + * Inventory must be available for the banner size specified, otherwise a no-fill error will be sent to `onAdFailedToLoad`. + */ + size: BannerAdSize; + + /** + * The request options for this banner. + */ + requestOptions?: RequestOptions; + + /** + * When an ad has finished loading. + */ + onAdLoaded?: () => void; + + /** + * When an ad has failed to load. Callback contains an Error. + */ + onAdFailedToLoad?: (error: Error) => void; + + /** + * The ad is now visible to the user. + */ + onAdOpened?: () => void; + + /** + * Called when the user is about to return to the app after tapping on an ad. + */ + onAdClosed?: () => void; +}; diff --git a/src/types/GoogleAdsNativeModule.ts b/src/types/GoogleAdsNativeModule.ts new file mode 100644 index 00000000..f7d37d7e --- /dev/null +++ b/src/types/GoogleAdsNativeModule.ts @@ -0,0 +1,13 @@ +import { AdapterStatus } from './AdapterStatus'; +import { RequestConfiguration } from './RequestConfiguration'; +import { RequestOptions } from './RequestOptions'; +import { AdShowOptions } from './AdShowOptions'; + +export interface GoogleAdsNativeModule { + initialize(): Promise; + setRequestConfiguration(requestConfiguration?: RequestConfiguration): Promise; + interstitialLoad(requestId: number, adUnitId: string, requestOptions: RequestOptions): void; + interstitialShow(requestId: number, showOptions?: AdShowOptions): Promise; + rewardedLoad(requestId: number, adUnitId: string, requestOptions: RequestOptions): void; + rewardedShow(requestId: number, adUnitId: string, showOptions?: AdShowOptions): Promise; +} diff --git a/src/types/MobileAd.interface.ts b/src/types/MobileAd.interface.ts new file mode 100644 index 00000000..6ca24a01 --- /dev/null +++ b/src/types/MobileAd.interface.ts @@ -0,0 +1,69 @@ +import { AdEventListener } from './AdEventListener'; +import { AdShowOptions } from './AdShowOptions'; + +/** + * Base class for InterstitialAd, RewardedAd, NativeAd and BannerAd. + */ +export interface MobileAdInterface { + /** + * The Ad Unit ID for this Gogole Mobile Ads ad. + */ + adUnitId: string; + + /** + * Whether the advert is loaded and can be shown. + */ + loaded: boolean; + + /** + * Start loading the advert with the provided RequestOptions. + * + * It is recommended you setup ad event handlers before calling this method. + */ + load(): void; + + /** + * Listen to ad events. See AdEventTypes for more information. + * + * Returns an unsubscriber function to stop listening to further events. + * + * #### Example + * + * ```js + * // Create InterstitialAd/RewardedAd + * const advert = InterstitialAd.createForAdRequest('...'); + * + * const unsubscribe = advert.onAdEvent((type) => { + * + * }); + * + * // Sometime later... + * unsubscribe(); + * ``` + * + * @param listener A listener callback containing a event type, error and data. + */ + onAdEvent(listener: AdEventListener): () => void; + + /** + * Show the loaded advert to the user. + * + * #### Example + * + * ```js + * // Create InterstitialAd/RewardedAd + * const advert = InterstitialAd.createForAdRequest('...'); + * + * advert.onAdEvent((type) => { + * if (type === AdEventType.LOADED) { + * advert.show({ + * immersiveModeEnabled: true, + * }); + * } + * }); + * ``` + * + * @param showOptions An optional `AdShowOptions` interface. + */ + show(showOptions?: AdShowOptions): Promise; +} diff --git a/src/types/MobileAdsModule.interface.ts b/src/types/MobileAdsModule.interface.ts new file mode 100644 index 00000000..7168b098 --- /dev/null +++ b/src/types/MobileAdsModule.interface.ts @@ -0,0 +1,43 @@ +import { EventEmitter } from 'react-native'; + +import { AdapterStatus } from './AdapterStatus'; +import { GoogleAdsNativeModule } from './GoogleAdsNativeModule'; +import { RequestConfiguration } from './RequestConfiguration'; + +/** + * The Google Ads service interface. + */ +export interface MobileAdsModuleInterface { + /** + * Initialize the SDK. + */ + initialize(): Promise; + + /** + * Sets request options for all future ad requests. + * + * #### Example + * + * ```js + * import mobileAds, { MaxAdContentRating } from '@invertase/react-native-google-ads'; + * + * await mobileAds().setRequestConfiguration({ + * // Update all future requests suitable for parental guidance + * maxAdContentRating: MaxAdContentRating.PG, + * }); + * ``` + * + * @param requestConfiguration An RequestConfiguration interface used on all future Google Ads ad requests. + */ + setRequestConfiguration(requestConfiguration: RequestConfiguration): Promise; + + /** + * The native module instance for the Google Ads service. + */ + native: GoogleAdsNativeModule; + + /** + * Returns the shared event emitter instance used for all JS event routing. + */ + emitter: EventEmitter; +} diff --git a/src/types/Module.interface.ts b/src/types/Module.interface.ts new file mode 100644 index 00000000..c023e346 --- /dev/null +++ b/src/types/Module.interface.ts @@ -0,0 +1,16 @@ +export interface App { + name: string; +} + +export interface Config { + version: string; + namespace: string; + nativeModuleName: string[]; + nativeEvents: string[]; +} + +export interface ModuleInterface { + app: App; + _config: Config; + _customUrlOrRegion?: string; +} diff --git a/src/types/RequestConfiguration.ts b/src/types/RequestConfiguration.ts new file mode 100644 index 00000000..964e7152 --- /dev/null +++ b/src/types/RequestConfiguration.ts @@ -0,0 +1,40 @@ +import { MaxAdContentRating } from '../MaxAdContentRating'; + +/** + * The `RequestConfiguration` used when setting global ad settings via `setRequestConfiguration`. + */ +export interface RequestConfiguration { + /** + * The maximum ad content rating for all ads. Google Mobile Ads returns ads at or below the specified level. + * + * Ratings are based on the [digital content label classifications](https://support.google.com/admob/answer/7562142). + */ + maxAdContentRating?: MaxAdContentRating; + + /** + * If `true`, indicates that you want your content treated as child-directed for purposes of COPPA. + * + * For purposes of the [Children's Online Privacy Protection Act (COPPA)](http://business.ftc.gov/privacy-and-security/children%27s-privacy), + * there is a setting called "tag for child-directed treatment". By setting this tag, you certify that this notification + * is accurate and you are authorized to act on behalf of the owner of the app. You understand that abuse of this + * setting may result in termination of your Google account. + */ + tagForChildDirectedTreatment?: boolean; + + /** + * If `true`, indicates that you want the ad request to be handled in a manner suitable for users under the age of consent. + * + * You can mark your ad requests to receive treatment for users in the European Economic Area (EEA) under the age of consent. + * This feature is designed to help facilitate compliance with the [General Data Protection Regulation (GDPR)](https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32016R0679). + * + * See the [Google Mobile SDK docs](https://developers.google.com/admob/android/targeting#ad_content_filtering) for more information. + */ + tagForUnderAgeOfConsent?: boolean; + + /** + * An array of test device IDs to add to the allowlist. + * + * If using an emulator, set the device ID to `EMULATOR`. + */ + testDeviceIdentifiers?: string[]; +} diff --git a/src/types/RequestOptions.ts b/src/types/RequestOptions.ts new file mode 100644 index 00000000..1138a5cb --- /dev/null +++ b/src/types/RequestOptions.ts @@ -0,0 +1,113 @@ +export interface ServerSideVerificationOptions { + /** + * User identifier. + * If no user identifier is provided by the app, this query parameter will not be present in the SSV callback. + */ + userId?: string; + + /** + * Custom data string. + * If no custom data string is provided by the app, this query parameter value will not be present in the SSV callback. + */ + customData?: string; +} + +/** + * The `RequestOptions` interface. Used when passing additional request options before an advert is loaded. + */ +export interface RequestOptions { + /** + * If `true` only non-personalized ads will be loaded. + * + * Google serves personalized ads by default. This option must be `true` if users who are within the EEA have only + * given consent to non-personalized ads. + */ + requestNonPersonalizedAdsOnly?: boolean; + + /** + * Attaches additional properties to an ad request for direct campaign delivery. + * + * Takes an array of string key/value pairs. + * + * #### Example + * + * Attaches `?campaign=abc&user=123` to the ad request: + * + * ```js + * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { + * networkExtras: { + * campaign: 'abc', + * user: '123', + * }, + * }); + */ + networkExtras?: { [key: string]: string }; + + /** + * An array of keywords to be sent when loading the ad. + * + * Setting keywords helps deliver more specific ads to a user based on the keywords. + * + * #### Example + * + * ```js + * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { + * keywords: ['fashion', 'clothing'], + * }); + * ``` + */ + keywords?: string[]; + + /** + * Sets a content URL for targeting purposes. + * + * Max length of 512. + */ + contentUrl?: string; + + /** + * The latitude and longitude location of the user. + * + * Ensure your app requests location permissions from the user. + * + * #### Example + * + * ```js + * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { + * location: [53.481073, -2.237074], + * }); + * ``` + */ + location?: [number, number]; + + /** + * Sets the location accuracy if the location is set, in meters. + * + * This option is only applied to iOS devices. On Android, this option has no effect. + * + * @ios + */ + locationAccuracy?: number; + + /** + * Sets the request agent string to identify the ad request's origin. Third party libraries that reference the Mobile + * Ads SDK should call this method to denote the platform from which the ad request originated. For example, if a + * third party ad network called "CoolAds network" mediates requests to the Mobile Ads SDK, it should call this + * method with "CoolAds". + * + * #### Example + * + * ```js + * await Interstitial.request('ca-app-pub-3940256099942544/1033173712', { + * requestAgent: 'CoolAds', + * }); + * ``` + */ + requestAgent?: string; + + /** + * Server Side Verification(SSV) Options + * See [Google Mobile SDK Docs](https://developers.google.com/admob/android/ssv) for more information. + */ + serverSideVerificationOptions?: ServerSideVerificationOptions; +} diff --git a/src/types/RewardedAdReward.ts b/src/types/RewardedAdReward.ts new file mode 100644 index 00000000..c0ef88c1 --- /dev/null +++ b/src/types/RewardedAdReward.ts @@ -0,0 +1,14 @@ +/** + * A `RewardedAdReward` returned from rewarded ads. + */ +export interface RewardedAdReward { + /** + * The reward name, e.g. 'coins', 'diamonds'. + */ + type: string; + + /** + * The number value of the reward, e.g. 10 + */ + amount: number; +} diff --git a/lib/validateAdRequestConfiguration.js b/src/validateAdRequestConfiguration.ts similarity index 87% rename from lib/validateAdRequestConfiguration.js rename to src/validateAdRequestConfiguration.ts index a6f239f8..a4fa1ef3 100644 --- a/lib/validateAdRequestConfiguration.js +++ b/src/validateAdRequestConfiguration.ts @@ -15,11 +15,12 @@ * */ -import { hasOwnProperty, isArray, isBoolean, isObject } from '../lib/common'; -import MaxAdContentRating from './MaxAdContentRating'; +import { hasOwnProperty, isArray, isBoolean, isObject } from './common'; +import { MaxAdContentRating } from './MaxAdContentRating'; +import { RequestConfiguration } from './types/RequestConfiguration'; -export default function validateAdRequestConfiguration(requestConfiguration) { - const out = {}; +export function validateAdRequestConfiguration(requestConfiguration: RequestConfiguration) { + const out: RequestConfiguration = {}; if (!isObject(requestConfiguration)) { throw new Error("'requestConfiguration' expected an object value"); diff --git a/lib/validateAdRequestOptions.js b/src/validateAdRequestOptions.ts similarity index 88% rename from lib/validateAdRequestOptions.js rename to src/validateAdRequestOptions.ts index e2da838f..1af36f20 100644 --- a/lib/validateAdRequestOptions.js +++ b/src/validateAdRequestOptions.ts @@ -22,14 +22,14 @@ import { isNumber, isObject, isString, - isUndefined, isValidUrl, } from './common'; +import { RequestOptions } from './types/RequestOptions'; -export default function validateAdRequestOptions(options) { - const out = {}; +export function validateAdRequestOptions(options?: RequestOptions) { + const out: RequestOptions = {}; - if (isUndefined(options)) { + if (options === undefined) { return out; } @@ -75,22 +75,6 @@ export default function validateAdRequestOptions(options) { out.keywords = options.keywords; } - if (options.testDevices) { - if (!isArray(options.testDevices)) { - throw new Error("'options.testDevices' expected an array containing string values"); - } - - for (let i = 0; i < options.testDevices.length; i++) { - const device = options.testDevices[i]; - - if (!isString(device)) { - throw new Error("'options.testDevices' expected an array containing string values"); - } - } - - out.testDevices = options.testDevices; - } - if (options.contentUrl) { if (!isString(options.contentUrl)) { throw new Error("'options.contentUrl' expected a string value"); @@ -142,7 +126,7 @@ export default function validateAdRequestOptions(options) { throw new Error("'options.locationAccuracy' expected a number value."); } - if (options.locationAccuracy < 0) { + if (typeof options.locationAccuracy === 'number' && options.locationAccuracy < 0) { throw new Error("'options.locationAccuracy' expected a number greater than 0."); } diff --git a/lib/validateAdShowOptions.js b/src/validateAdShowOptions.ts similarity index 80% rename from lib/validateAdShowOptions.js rename to src/validateAdShowOptions.ts index e9dfebb6..f8a42e34 100644 --- a/lib/validateAdShowOptions.js +++ b/src/validateAdShowOptions.ts @@ -15,12 +15,13 @@ * */ -import { hasOwnProperty, isBoolean, isObject, isUndefined } from './common'; +import { hasOwnProperty, isBoolean, isObject } from './common'; +import { AdShowOptions } from './types/AdShowOptions'; -export default function validateAdShowOptions(options) { - const out = {}; +export function validateAdShowOptions(options?: AdShowOptions) { + const out: AdShowOptions = {}; - if (isUndefined(options)) { + if (options === undefined) { return out; } diff --git a/tsconfig.json b/tsconfig.json index 706f1d3a..d3d9357a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,7 @@ { - "include": ["lib/*.d.ts"], + "include": ["src"], "compilerOptions": { - "noEmit": true, - "target": "es5", + "target": "esnext", "module": "commonjs", "declaration": true, "importHelpers": true, @@ -15,9 +14,10 @@ "noFallthroughCasesInSwitch": true, "moduleResolution": "node", "skipLibCheck": true, + "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, - "lib": ["es2015", "es2016", "esnext"] + "lib": ["esnext"] }, "exclude": ["node_modules", "**/*.spec.ts"] } diff --git a/yarn.lock b/yarn.lock index a8f2f3aa..cfbfef81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,6 +35,27 @@ semver "^6.3.0" source-map "^0.5.0" +"@babel/core@^7.12.10": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.5.tgz#924aa9e1ae56e1e55f7184c8bf073a50d8677f5c" + integrity sha512-wUcenlLzuWMZ9Zt8S0KmFwGlH6QKRh3vsm/dhDA3CHkiTA45YuG1XkHRcNRl73EFPXDp/d5kVOU0/y7x2w6OaQ== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.5" + "@babel/helper-compilation-targets" "^7.16.3" + "@babel/helper-module-transforms" "^7.16.5" + "@babel/helpers" "^7.16.5" + "@babel/parser" "^7.16.5" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.5" + "@babel/types" "^7.16.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + "@babel/generator@^7.14.0", "@babel/generator@^7.16.0", "@babel/generator@^7.7.2": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" @@ -44,6 +65,15 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.5.tgz#26e1192eb8f78e0a3acaf3eede3c6fc96d22bedf" + integrity sha512-kIvCdjZqcdKqoDbVVdt5R99icaRtrtYhYK/xux5qiWCBmfdvEYMFZ68QCrpE5cbFM1JsuArUNs1ZkuKtTtUcZA== + dependencies: + "@babel/types" "^7.16.0" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d" @@ -59,6 +89,14 @@ "@babel/helper-explode-assignable-expression" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.5.tgz#a8429d064dce8207194b8bf05a70a9ea828746af" + integrity sha512-3JEA9G5dmmnIWdzaT9d0NmFRgYnWUThLsDaL7982H0XqqWr56lRrsmwheXFMjR+TMl7QMBb6mzy9kvgr1lRLUA== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.16.0" + "@babel/types" "^7.16.0" + "@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.0", "@babel/helper-compilation-targets@^7.16.3": version "7.16.3" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz#5b480cd13f68363df6ec4dc8ac8e2da11363cbf0" @@ -81,6 +119,19 @@ "@babel/helper-replace-supers" "^7.16.0" "@babel/helper-split-export-declaration" "^7.16.0" +"@babel/helper-create-class-features-plugin@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.5.tgz#5d1bcd096792c1ebec6249eebc6358eec55d0cad" + integrity sha512-NEohnYA7mkB8L5JhU7BLwcBdU3j83IziR9aseMueWGeAjblbul3zzb8UvJ3a1zuBiqCMObzCJHFqKIQE6hTVmg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-environment-visitor" "^7.16.5" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-member-expression-to-functions" "^7.16.5" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/helper-replace-supers" "^7.16.5" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/helper-create-regexp-features-plugin@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz#06b2348ce37fccc4f5e18dcd8d75053f2a7c44ff" @@ -103,6 +154,13 @@ resolve "^1.14.2" semver "^6.1.2" +"@babel/helper-environment-visitor@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.5.tgz#f6a7f38b3c6d8b07c88faea083c46c09ef5451b8" + integrity sha512-ODQyc5AnxmZWm/R2W7fzhamOk1ey8gSguo5SGvF0zcB3uUzRpTRmM/jmLSm9bDMyPlvbyJ+PwPEK0BWIoZ9wjg== + dependencies: + "@babel/types" "^7.16.0" + "@babel/helper-explode-assignable-expression@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz#753017337a15f46f9c09f674cff10cee9b9d7778" @@ -140,6 +198,13 @@ dependencies: "@babel/types" "^7.16.0" +"@babel/helper-member-expression-to-functions@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.5.tgz#1bc9f7e87354e86f8879c67b316cb03d3dc2caab" + integrity sha512-7fecSXq7ZrLE+TWshbGT+HyCLkxloWNhTbU2QM1NTI/tDqyf0oZiMcEfYtDuUDCo528EOlt39G1rftea4bRZIw== + dependencies: + "@babel/types" "^7.16.0" + "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" @@ -161,6 +226,20 @@ "@babel/traverse" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-module-transforms@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.5.tgz#530ebf6ea87b500f60840578515adda2af470a29" + integrity sha512-CkvMxgV4ZyyioElFwcuWnDCcNIeyqTkCm9BxXZi73RR1ozqlpboqsbGUNvRTflgZtFbbJ1v5Emvm+lkjMYY/LQ== + dependencies: + "@babel/helper-environment-visitor" "^7.16.5" + "@babel/helper-module-imports" "^7.16.0" + "@babel/helper-simple-access" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/helper-validator-identifier" "^7.15.7" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.5" + "@babel/types" "^7.16.0" + "@babel/helper-optimise-call-expression@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" @@ -173,6 +252,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== +"@babel/helper-plugin-utils@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.5.tgz#afe37a45f39fce44a3d50a7958129ea5b1a5c074" + integrity sha512-59KHWHXxVA9K4HNF4sbHCf+eJeFe0Te/ZFGqBT4OjXhrwvA04sGfaEGsVTdsjoszq0YTP49RC9UKe5g8uN2RwQ== + "@babel/helper-remap-async-to-generator@^7.16.0", "@babel/helper-remap-async-to-generator@^7.16.4": version "7.16.4" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz#5d7902f61349ff6b963e07f06a389ce139fbfe6e" @@ -182,6 +266,15 @@ "@babel/helper-wrap-function" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-remap-async-to-generator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.5.tgz#e706646dc4018942acb4b29f7e185bc246d65ac3" + integrity sha512-X+aAJldyxrOmN9v3FKp+Hu1NO69VWgYgDGq6YDykwRPzxs5f2N+X988CBXS7EQahDU+Vpet5QYMqLk+nsp+Qxw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-wrap-function" "^7.16.5" + "@babel/types" "^7.16.0" + "@babel/helper-replace-supers@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" @@ -192,6 +285,17 @@ "@babel/traverse" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-replace-supers@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.5.tgz#96d3988bd0ab0a2d22c88c6198c3d3234ca25326" + integrity sha512-ao3seGVa/FZCMCCNDuBcqnBFSbdr8N2EW35mzojx3TwfIbdPmNK+JV6+2d5bR0Z71W5ocLnQp9en/cTF7pBJiQ== + dependencies: + "@babel/helper-environment-visitor" "^7.16.5" + "@babel/helper-member-expression-to-functions" "^7.16.5" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/traverse" "^7.16.5" + "@babel/types" "^7.16.0" + "@babel/helper-simple-access@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" @@ -233,6 +337,16 @@ "@babel/traverse" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/helper-wrap-function@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.5.tgz#0158fca6f6d0889c3fee8a6ed6e5e07b9b54e41f" + integrity sha512-2J2pmLBqUqVdJw78U0KPNdeE2qeuIyKoG4mKV7wAq3mc4jJG282UgjZw4ZYDnqiWQuS3Y3IYdF/AQ6CpyBV3VA== + dependencies: + "@babel/helper-function-name" "^7.16.0" + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.5" + "@babel/types" "^7.16.0" + "@babel/helpers@^7.16.0": version "7.16.3" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.3.tgz#27fc64f40b996e7074dc73128c3e5c3e7f55c43c" @@ -242,6 +356,15 @@ "@babel/traverse" "^7.16.3" "@babel/types" "^7.16.0" +"@babel/helpers@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.5.tgz#29a052d4b827846dd76ece16f565b9634c554ebd" + integrity sha512-TLgi6Lh71vvMZGEkFuIxzaPsyeYCHQ5jJOOX1f0xXn0uciFuE8cEk0wyBquMcCxBXZ5BJhE2aUB7pnWTD150Tw== + dependencies: + "@babel/template" "^7.16.0" + "@babel/traverse" "^7.16.5" + "@babel/types" "^7.16.0" + "@babel/highlight@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" @@ -256,6 +379,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.4.tgz#d5f92f57cf2c74ffe9b37981c0e72fee7311372e" integrity sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng== +"@babel/parser@^7.16.5": + version "7.16.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.6.tgz#8f194828193e8fa79166f34a4b4e52f3e769a314" + integrity sha512-Gr86ujcNuPDnNOY8mi383Hvi8IYrJVJYuf3XcuBM/Dgd+bINn/7tHqsj+tKkoreMbmGsFLsltI/JJd8fOFWGDQ== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.2": version "7.16.2" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz#2977fca9b212db153c195674e57cfab807733183" @@ -281,6 +409,15 @@ "@babel/helper-remap-async-to-generator" "^7.16.4" "@babel/plugin-syntax-async-generators" "^7.8.4" +"@babel/plugin-proposal-async-generator-functions@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.5.tgz#fd3bd7e0d98404a3d4cbca15a72d533f8c9a2f67" + integrity sha512-C/FX+3HNLV6sz7AqbTQqEo1L9/kfrKjxcVtgyBCmvIgOjvuBVUWooDoi7trsLxOzCEo5FccjRvKHkfDsJFZlfA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-remap-async-to-generator" "^7.16.5" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-proposal-class-properties@^7.0.0", "@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" @@ -289,6 +426,14 @@ "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.5.tgz#3269f44b89122110f6339806e05d43d84106468a" + integrity sha512-pJD3HjgRv83s5dv1sTnDbZOaTjghKEz8KUn1Kbh2eAIRhGuyQ1XSeI4xVXU3UlIEVA3DAyIdxqT1eRn7Wcn55A== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-proposal-class-static-block@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz#5296942c564d8144c83eea347d0aa8a0b89170e7" @@ -298,6 +443,15 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-class-static-block" "^7.14.5" +"@babel/plugin-proposal-class-static-block@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.5.tgz#df58ab015a7d3b0963aafc8f20792dcd834952a9" + integrity sha512-EEFzuLZcm/rNJ8Q5krK+FRKdVkd6FjfzT9tuSZql9sQn64K0hHA2KLJ0DqVot9/iV6+SsuadC5yI39zWnm+nmQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-proposal-dynamic-import@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz#783eca61d50526202f9b296095453977e88659f1" @@ -306,6 +460,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" +"@babel/plugin-proposal-dynamic-import@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.5.tgz#2e0d19d5702db4dcb9bc846200ca02f2e9d60e9e" + integrity sha512-P05/SJZTTvHz79LNYTF8ff5xXge0kk5sIIWAypcWgX4BTRUgyHc8wRxJ/Hk+mU0KXldgOOslKaeqnhthcDJCJQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-export-default-from@^7.0.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.16.0.tgz#f8a07008ffcb0d3de4945f3eb52022ecc28b56ad" @@ -322,6 +484,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" +"@babel/plugin-proposal-export-namespace-from@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.5.tgz#3b4dd28378d1da2fea33e97b9f25d1c2f5bf1ac9" + integrity sha512-i+sltzEShH1vsVydvNaTRsgvq2vZsfyrd7K7vPLUU/KgS0D5yZMe6uipM0+izminnkKrEfdUnz7CxMRb6oHZWw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-proposal-json-strings@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz#cae35a95ed1d2a7fa29c4dc41540b84a72e9ab25" @@ -330,6 +500,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-json-strings" "^7.8.3" +"@babel/plugin-proposal-json-strings@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.5.tgz#1e726930fca139caab6b084d232a9270d9d16f9c" + integrity sha512-QQJueTFa0y9E4qHANqIvMsuxM/qcLQmKttBACtPCQzGUEizsXDACGonlPiSwynHfOa3vNw0FPMVvQzbuXwh4SQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-proposal-logical-assignment-operators@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz#a711b8ceb3ffddd3ef88d3a49e86dbd3cc7db3fd" @@ -338,6 +516,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" +"@babel/plugin-proposal-logical-assignment-operators@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.5.tgz#df1f2e4b5a0ec07abf061d2c18e53abc237d3ef5" + integrity sha512-xqibl7ISO2vjuQM+MzR3rkd0zfNWltk7n9QhaD8ghMmMceVguYrNDt7MikRyj4J4v3QehpnrU8RYLnC7z/gZLA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-proposal-nullish-coalescing-operator@^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.1.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz#44e1cce08fe2427482cf446a91bb451528ed0596" @@ -346,6 +532,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.5.tgz#652555bfeeeee2d2104058c6225dc6f75e2d0f07" + integrity sha512-YwMsTp/oOviSBhrjwi0vzCUycseCYwoXnLiXIL3YNjHSMBHicGTz7GjVU/IGgz4DtOEXBdCNG72pvCX22ehfqg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-numeric-separator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz#5d418e4fbbf8b9b7d03125d3a52730433a373734" @@ -354,6 +548,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-numeric-separator" "^7.10.4" +"@babel/plugin-proposal-numeric-separator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.5.tgz#edcb6379b6cf4570be64c45965d8da7a2debf039" + integrity sha512-DvB9l/TcsCRvsIV9v4jxR/jVP45cslTVC0PMVHvaJhhNuhn2Y1SOhCSFlPK777qLB5wb8rVDaNoqMTyOqtY5Iw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz#5fb32f6d924d6e6712810362a60e12a2609872e6" @@ -365,6 +567,17 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.3" "@babel/plugin-transform-parameters" "^7.16.0" +"@babel/plugin-proposal-object-rest-spread@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.5.tgz#f30f80dacf7bc1404bf67f99c8d9c01665e830ad" + integrity sha512-UEd6KpChoyPhCoE840KRHOlGhEZFutdPDMGj+0I56yuTTOaT51GzmnEl/0uT41fB/vD2nT+Pci2KjezyE3HmUw== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.3" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.16.5" + "@babel/plugin-proposal-optional-catch-binding@^7.0.0", "@babel/plugin-proposal-optional-catch-binding@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz#5910085811ab4c28b00d6ebffa4ab0274d1e5f16" @@ -373,6 +586,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" +"@babel/plugin-proposal-optional-catch-binding@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.5.tgz#1a5405765cf589a11a33a1fd75b2baef7d48b74e" + integrity sha512-ihCMxY1Iljmx4bWy/PIMJGXN4NS4oUj1MKynwO07kiKms23pNvIn1DMB92DNB2R0EA882sw0VXIelYGdtF7xEQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining@^7.0.0", "@babel/plugin-proposal-optional-chaining@^7.1.0", "@babel/plugin-proposal-optional-chaining@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz#56dbc3970825683608e9efb55ea82c2a2d6c8dc0" @@ -382,6 +603,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" "@babel/plugin-syntax-optional-chaining" "^7.8.3" +"@babel/plugin-proposal-optional-chaining@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.5.tgz#a5fa61056194d5059366c0009cb9a9e66ed75c1f" + integrity sha512-kzdHgnaXRonttiTfKYnSVafbWngPPr2qKw9BWYBESl91W54e+9R5pP70LtWxV56g0f05f/SQrwHYkfvbwcdQ/A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-private-methods@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz#b4dafb9c717e4301c5776b30d080d6383c89aff6" @@ -390,6 +620,14 @@ "@babel/helper-create-class-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-proposal-private-methods@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.5.tgz#2086f7d78c1b0c712d49b5c3fbc2d1ca21a7ee12" + integrity sha512-+yFMO4BGT3sgzXo+lrq7orX5mAZt57DwUK6seqII6AcJnJOIhBJ8pzKH47/ql/d426uQ7YhN8DpUFirQzqYSUA== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-proposal-private-property-in-object@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz#69e935b2c5c79d2488112d886f0c4e2790fee76f" @@ -400,6 +638,16 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" +"@babel/plugin-proposal-private-property-in-object@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.5.tgz#a42d4b56005db3d405b12841309dbca647e7a21b" + integrity sha512-+YGh5Wbw0NH3y/E5YMu6ci5qTDmAEVNoZ3I54aB6nVEOZ5BQ7QJlwKq5pYVucQilMByGn/bvX0af+uNaPRCabA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-create-class-features-plugin" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-proposal-unicode-property-regex@^7.16.0", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz#890482dfc5ea378e42e19a71e709728cabf18612" @@ -408,6 +656,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-proposal-unicode-property-regex@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.5.tgz#35fe753afa7c572f322bd068ff3377bde0f37080" + integrity sha512-s5sKtlKQyFSatt781HQwv1hoM5BQ9qRH30r+dK56OLDsHmV74mzwJNX7R1yMuE7VZKG5O6q/gmOGSAO6ikTudg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -464,6 +720,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-syntax-flow@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.16.5.tgz#ca0d85e12d71b825b4e9fd1f8d29b64acdf1b46e" + integrity sha512-Nrx+7EAJx1BieBQseZa2pavVH2Rp7hADK2xn7coYqVbWRu9C2OFizYcsKo6TrrqJkJl+qF/+Qqzrk/+XDu4GnA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -485,6 +748,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-syntax-jsx@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.5.tgz#bf255d252f78bc8b77a17cadc37d1aa5b8ed4394" + integrity sha512-42OGssv9NPk4QHKVgIHlzeLgPOW5rGgfV5jzG90AhcXXIv6hu/eqj63w4VgvRxdvZY3AlYeDgPiSJ3BqAd1Y6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -555,6 +825,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-arrow-functions@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.5.tgz#04c18944dd55397b521d9d7511e791acea7acf2d" + integrity sha512-8bTHiiZyMOyfZFULjsCnYOWG059FVMes0iljEHSfARhNgFfpsqE92OrCffv3veSw9rwMkYcFe9bj0ZoXU2IGtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-async-to-generator@^7.0.0", "@babel/plugin-transform-async-to-generator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz#df12637f9630ddfa0ef9d7a11bc414d629d38604" @@ -564,6 +841,15 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-remap-async-to-generator" "^7.16.0" +"@babel/plugin-transform-async-to-generator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.5.tgz#89c9b501e65bb14c4579a6ce9563f859de9b34e4" + integrity sha512-TMXgfioJnkXU+XRoj7P2ED7rUm5jbnDWwlCuFVTpQboMfbSya5WrmubNBAMlk7KXvywpo8rd8WuYZkis1o2H8w== + dependencies: + "@babel/helper-module-imports" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-remap-async-to-generator" "^7.16.5" + "@babel/plugin-transform-block-scoped-functions@^7.0.0", "@babel/plugin-transform-block-scoped-functions@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz#c618763233ad02847805abcac4c345ce9de7145d" @@ -571,6 +857,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-block-scoped-functions@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.5.tgz#af087494e1c387574260b7ee9b58cdb5a4e9b0b0" + integrity sha512-BxmIyKLjUGksJ99+hJyL/HIxLIGnLKtw772zYDER7UuycDZ+Xvzs98ZQw6NGgM2ss4/hlFAaGiZmMNKvValEjw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-block-scoping@^7.0.0", "@babel/plugin-transform-block-scoping@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz#bcf433fb482fe8c3d3b4e8a66b1c4a8e77d37c16" @@ -578,6 +871,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-block-scoping@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.5.tgz#b91f254fe53e210eabe4dd0c40f71c0ed253c5e7" + integrity sha512-JxjSPNZSiOtmxjX7PBRBeRJTUKTyJ607YUYeT0QJCNdsedOe+/rXITjP08eG8xUpsLfPirgzdCFN+h0w6RI+pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-classes@^7.0.0", "@babel/plugin-transform-classes@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz#54cf5ff0b2242c6573d753cd4bfc7077a8b282f5" @@ -591,6 +891,20 @@ "@babel/helper-split-export-declaration" "^7.16.0" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.5.tgz#6acf2ec7adb50fb2f3194dcd2909dbd056dcf216" + integrity sha512-DzJ1vYf/7TaCYy57J3SJ9rV+JEuvmlnvvyvYKFbk5u46oQbBvuB9/0w+YsVsxkOv8zVWKpDmUoj4T5ILHoXevA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-environment-visitor" "^7.16.5" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-optimise-call-expression" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-replace-supers" "^7.16.5" + "@babel/helper-split-export-declaration" "^7.16.0" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.0.0", "@babel/plugin-transform-computed-properties@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz#e0c385507d21e1b0b076d66bed6d5231b85110b7" @@ -598,6 +912,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-computed-properties@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.5.tgz#2af91ebf0cceccfcc701281ada7cfba40a9b322a" + integrity sha512-n1+O7xtU5lSLraRzX88CNcpl7vtGdPakKzww74bVwpAIRgz9JVLJJpOLb0uYqcOaXVM0TL6X0RVeIJGD2CnCkg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-destructuring@^7.0.0", "@babel/plugin-transform-destructuring@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz#ad3d7e74584ad5ea4eadb1e6642146c590dee33c" @@ -605,6 +926,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-destructuring@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.5.tgz#89ebc87499ac4a81b897af53bb5d3eed261bd568" + integrity sha512-GuRVAsjq+c9YPK6NeTkRLWyQskDC099XkBSVO+6QzbnOnH2d/4mBVXYStaPrZD3dFRfg00I6BFJ9Atsjfs8mlg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-dotall-regex@^7.16.0", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz#50bab00c1084b6162d0a58a818031cf57798e06f" @@ -613,6 +941,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-dotall-regex@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.5.tgz#b40739c00b6686820653536d6d143e311de67936" + integrity sha512-iQiEMt8Q4/5aRGHpGVK2Zc7a6mx7qEAO7qehgSug3SDImnuMzgmm/wtJALXaz25zUj1PmnNHtShjFgk4PDx4nw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-duplicate-keys@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz#8bc2e21813e3e89e5e5bf3b60aa5fc458575a176" @@ -620,6 +956,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-duplicate-keys@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.5.tgz#2450f2742325412b746d7d005227f5e8973b512a" + integrity sha512-81tijpDg2a6I1Yhj4aWY1l3O1J4Cg/Pd7LfvuaH2VVInAkXtzibz9+zSPdUM1WvuUi128ksstAP0hM5w48vQgg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-exponentiation-operator@^7.0.0", "@babel/plugin-transform-exponentiation-operator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz#a180cd2881e3533cef9d3901e48dad0fbeff4be4" @@ -628,6 +971,14 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-exponentiation-operator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.5.tgz#36e261fa1ab643cfaf30eeab38e00ed1a76081e2" + integrity sha512-12rba2HwemQPa7BLIKCzm1pT2/RuQHtSFHdNl41cFiC6oi4tcrp7gjB07pxQvFpcADojQywSjblQth6gJyE6CA== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-flow-strip-types@^7.0.0", "@babel/plugin-transform-flow-strip-types@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.0.tgz#edd968dc2041c1b69e451a262e948d6654a79dc2" @@ -636,6 +987,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-flow" "^7.16.0" +"@babel/plugin-transform-flow-strip-types@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.16.5.tgz#8ceb65ab6ca4a349e04d1887e2470a5bfe8f046f" + integrity sha512-skE02E/MptkZdBS4HwoRhjWXqeKQj0BWKEAPfPC+8R4/f6bjQqQ9Nftv/+HkxWwnVxh/E2NV9TNfzLN5H/oiBw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-flow" "^7.16.5" + "@babel/plugin-transform-for-of@^7.0.0", "@babel/plugin-transform-for-of@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz#f7abaced155260e2461359bbc7c7248aca5e6bd2" @@ -643,6 +1002,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-for-of@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.5.tgz#9b544059c6ca11d565457c0ff1f08e13ce225261" + integrity sha512-+DpCAJFPAvViR17PIMi9x2AE34dll5wNlXO43wagAX2YcRGgEVHCNFC4azG85b4YyyFarvkc/iD5NPrz4Oneqw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-function-name@^7.0.0", "@babel/plugin-transform-function-name@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz#02e3699c284c6262236599f751065c5d5f1f400e" @@ -651,6 +1017,14 @@ "@babel/helper-function-name" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-function-name@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.5.tgz#6896ebb6a5538a75d6a4086a277752f655a7bd15" + integrity sha512-Fuec/KPSpVLbGo6z1RPw4EE1X+z9gZk1uQmnYy7v4xr4TO9p41v1AoUuXEtyqAI7H+xNJYSICzRqZBhDEkd3kQ== + dependencies: + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-literals@^7.0.0", "@babel/plugin-transform-literals@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz#79711e670ffceb31bd298229d50f3621f7980cac" @@ -658,6 +1032,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-literals@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.5.tgz#af392b90e3edb2bd6dc316844cbfd6b9e009d320" + integrity sha512-B1j9C/IfvshnPcklsc93AVLTrNVa69iSqztylZH6qnmiAsDDOmmjEYqOm3Ts2lGSgTSywnBNiqC949VdD0/gfw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-member-expression-literals@^7.0.0", "@babel/plugin-transform-member-expression-literals@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz#5251b4cce01eaf8314403d21aedb269d79f5e64b" @@ -665,6 +1046,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-member-expression-literals@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.5.tgz#4bd6ecdc11932361631097b779ca5c7570146dd5" + integrity sha512-d57i3vPHWgIde/9Y8W/xSFUndhvhZN5Wu2TjRrN1MVz5KzdUihKnfDVlfP1U7mS5DNj/WHHhaE4/tTi4hIyHwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-modules-amd@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz#09abd41e18dcf4fd479c598c1cef7bd39eb1337e" @@ -674,6 +1062,15 @@ "@babel/helper-plugin-utils" "^7.14.5" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-amd@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.5.tgz#92c0a3e83f642cb7e75fada9ab497c12c2616527" + integrity sha512-oHI15S/hdJuSCfnwIz+4lm6wu/wBn7oJ8+QrkzPPwSFGXk8kgdI/AIKcbR/XnD1nQVMg/i6eNaXpszbGuwYDRQ== + dependencies: + "@babel/helper-module-transforms" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.1.0", "@babel/plugin-transform-modules-commonjs@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz#add58e638c8ddc4875bd9a9ecb5c594613f6c922" @@ -684,6 +1081,16 @@ "@babel/helper-simple-access" "^7.16.0" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-commonjs@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.5.tgz#4ee03b089536f076b2773196529d27c32b9d7bde" + integrity sha512-ABhUkxvoQyqhCWyb8xXtfwqNMJD7tx+irIRnUh6lmyFud7Jln1WzONXKlax1fg/ey178EXbs4bSGNd6PngO+SQ== + dependencies: + "@babel/helper-module-transforms" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-simple-access" "^7.16.0" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-systemjs@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz#a92cf240afeb605f4ca16670453024425e421ea4" @@ -695,6 +1102,17 @@ "@babel/helper-validator-identifier" "^7.15.7" babel-plugin-dynamic-import-node "^2.3.3" +"@babel/plugin-transform-modules-systemjs@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.5.tgz#07078ba2e3cc94fbdd06836e355c246e98ad006b" + integrity sha512-53gmLdScNN28XpjEVIm7LbWnD/b/TpbwKbLk6KV4KqC9WyU6rq1jnNmVG6UgAdQZVVGZVoik3DqHNxk4/EvrjA== + dependencies: + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-module-transforms" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-validator-identifier" "^7.15.7" + babel-plugin-dynamic-import-node "^2.3.3" + "@babel/plugin-transform-modules-umd@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz#195f26c2ad6d6a391b70880effce18ce625e06a7" @@ -703,6 +1121,14 @@ "@babel/helper-module-transforms" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-modules-umd@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.5.tgz#caa9c53d636fb4e3c99fd35a4c9ba5e5cd7e002e" + integrity sha512-qTFnpxHMoenNHkS3VoWRdwrcJ3FhX567GvDA3hRZKF0Dj8Fmg0UzySZp3AP2mShl/bzcywb/UWAMQIjA1bhXvw== + dependencies: + "@babel/helper-module-transforms" "^7.16.5" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-named-capturing-groups-regex@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz#d3db61cc5d5b97986559967cd5ea83e5c32096ca" @@ -710,6 +1136,13 @@ dependencies: "@babel/helper-create-regexp-features-plugin" "^7.16.0" +"@babel/plugin-transform-named-capturing-groups-regex@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.5.tgz#4afd8cdee377ce3568f4e8a9ee67539b69886a3c" + integrity sha512-/wqGDgvFUeKELW6ex6QB7dLVRkd5ehjw34tpXu1nhKC0sFfmaLabIswnpf8JgDyV2NeDmZiwoOb0rAmxciNfjA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.0" + "@babel/plugin-transform-new-target@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz#af823ab576f752215a49937779a41ca65825ab35" @@ -717,6 +1150,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-new-target@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.5.tgz#759ea9d6fbbc20796056a5d89d13977626384416" + integrity sha512-ZaIrnXF08ZC8jnKR4/5g7YakGVL6go6V9ql6Jl3ecO8PQaQqFE74CuM384kezju7Z9nGCCA20BqZaR1tJ/WvHg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-object-assign@^7.0.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.16.0.tgz#750c726397f1f6402fb1ceffe9d8ff3595c8a0df" @@ -732,6 +1172,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-replace-supers" "^7.16.0" +"@babel/plugin-transform-object-super@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.5.tgz#8ccd9a1bcd3e7732ff8aa1702d067d8cd70ce380" + integrity sha512-tded+yZEXuxt9Jdtkc1RraW1zMF/GalVxaVVxh41IYwirdRgyAxxxCKZ9XB7LxZqmsjfjALxupNE1MIz9KH+Zg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-replace-supers" "^7.16.5" + "@babel/plugin-transform-parameters@^7.0.0", "@babel/plugin-transform-parameters@^7.16.0", "@babel/plugin-transform-parameters@^7.16.3": version "7.16.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz#fa9e4c874ee5223f891ee6fa8d737f4766d31d15" @@ -739,6 +1187,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-parameters@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.5.tgz#4fc74b18a89638bd90aeec44a11793ecbe031dde" + integrity sha512-B3O6AL5oPop1jAVg8CV+haeUte9oFuY85zu0jwnRNZZi3tVAbJriu5tag/oaO2kGaQM/7q7aGPBlTI5/sr9enA== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-property-literals@^7.0.0", "@babel/plugin-transform-property-literals@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz#a95c552189a96a00059f6776dc4e00e3690c78d1" @@ -746,6 +1201,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-property-literals@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.5.tgz#58f1465a7202a2bb2e6b003905212dd7a79abe3f" + integrity sha512-+IRcVW71VdF9pEH/2R/Apab4a19LVvdVsr/gEeotH00vSDVlKD+XgfSIw+cgGWsjDB/ziqGv/pGoQZBIiQVXHg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-react-display-name@^7.0.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.0.tgz#9a0ad8aa8e8790883a7bd2736f66229a58125676" @@ -753,6 +1215,20 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-react-display-name@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.5.tgz#d5e910327d7931fb9f8f9b6c6999473ceae5a286" + integrity sha512-dHYCOnzSsXFz8UcdNQIHGvg94qPL/teF7CCiCEMRxmA1G2p5Mq4JnKVowCDxYfiQ9D7RstaAp9kwaSI+sXbnhw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + +"@babel/plugin-transform-react-jsx-development@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.5.tgz#87da9204c275ffb57f45d192a1120cf104bc1e86" + integrity sha512-uQSLacMZSGLCxOw20dzo1dmLlKkd+DsayoV54q3MHXhbqgPzoiGerZQgNPl/Ro8/OcXV2ugfnkx+rxdS0sN5Uw== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.16.5" + "@babel/plugin-transform-react-jsx-self@^7.0.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.16.0.tgz#09202158abbc716a08330f392bfb98d6b9acfa0c" @@ -778,6 +1254,25 @@ "@babel/plugin-syntax-jsx" "^7.16.0" "@babel/types" "^7.16.0" +"@babel/plugin-transform-react-jsx@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.5.tgz#5298aedc5f81e02b1cb702e597e8d6a346675765" + integrity sha512-+arLIz1d7kmwX0fKxTxbnoeG85ONSnLpvdODa4P3pc1sS7CV1hfmtYWufkW/oYsPnkDrEeQFxhUWcFnrXW7jQQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-module-imports" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-syntax-jsx" "^7.16.5" + "@babel/types" "^7.16.0" + +"@babel/plugin-transform-react-pure-annotations@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.5.tgz#6535d0fe67c7a3a26c5105f92c8cbcbe844cd94b" + integrity sha512-0nYU30hCxnCVCbRjSy9ahlhWZ2Sn6khbY4FqR91W+2RbSqkWEbVu2gXh45EqNy4Bq7sRU+H4i0/6YKwOSzh16A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-regenerator@^7.0.0", "@babel/plugin-transform-regenerator@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz#eaee422c84b0232d03aea7db99c97deeaf6125a4" @@ -785,6 +1280,13 @@ dependencies: regenerator-transform "^0.14.2" +"@babel/plugin-transform-regenerator@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.5.tgz#704cc6d8dd3dd4758267621ab7b36375238cef13" + integrity sha512-2z+it2eVWU8TtQQRauvGUqZwLy4+7rTfo6wO4npr+fvvN1SW30ZF3O/ZRCNmTuu4F5MIP8OJhXAhRV5QMJOuYg== + dependencies: + regenerator-transform "^0.14.2" + "@babel/plugin-transform-reserved-words@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz#fff4b9dcb19e12619394bda172d14f2d04c0379c" @@ -792,6 +1294,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-reserved-words@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.5.tgz#db95e98799675e193dc2b47d3e72a7c0651d0c30" + integrity sha512-aIB16u8lNcf7drkhXJRoggOxSTUAuihTSTfAcpynowGJOZiGf+Yvi7RuTwFzVYSYPmWyARsPqUGoZWWWxLiknw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-runtime@^7.0.0": version "7.16.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.4.tgz#f9ba3c7034d429c581e1bd41b4952f3db3c2c7e8" @@ -811,6 +1320,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-shorthand-properties@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.5.tgz#ccb60b1a23b799f5b9a14d97c5bc81025ffd96d7" + integrity sha512-ZbuWVcY+MAXJuuW7qDoCwoxDUNClfZxoo7/4swVbOW1s/qYLOMHlm9YRWMsxMFuLs44eXsv4op1vAaBaBaDMVg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-spread@^7.0.0", "@babel/plugin-transform-spread@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz#d21ca099bbd53ab307a8621e019a7bd0f40cdcfb" @@ -819,6 +1335,14 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" +"@babel/plugin-transform-spread@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.5.tgz#912b06cff482c233025d3e69cf56d3e8fa166c29" + integrity sha512-5d6l/cnG7Lw4tGHEoga4xSkYp1euP7LAtrah1h1PgJ3JY7yNsjybsxQAnVK4JbtReZ/8z6ASVmd3QhYYKLaKZw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/plugin-transform-sticky-regex@^7.0.0", "@babel/plugin-transform-sticky-regex@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz#c35ea31a02d86be485f6aa510184b677a91738fd" @@ -826,6 +1350,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-sticky-regex@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.5.tgz#593579bb2b5a8adfbe02cb43823275d9098f75f9" + integrity sha512-usYsuO1ID2LXxzuUxifgWtJemP7wL2uZtyrTVM4PKqsmJycdS4U4mGovL5xXkfUheds10Dd2PjoQLXw6zCsCbg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-template-literals@^7.0.0", "@babel/plugin-transform-template-literals@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz#a8eced3a8e7b8e2d40ec4ec4548a45912630d302" @@ -833,6 +1364,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-template-literals@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.5.tgz#343651385fd9923f5aa2275ca352c5d9183e1773" + integrity sha512-gnyKy9RyFhkovex4BjKWL3BVYzUDG6zC0gba7VMLbQoDuqMfJ1SDXs8k/XK41Mmt1Hyp4qNAvGFb9hKzdCqBRQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-typeof-symbol@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz#8b19a244c6f8c9d668dca6a6f754ad6ead1128f2" @@ -840,7 +1378,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-transform-typescript@^7.16.0", "@babel/plugin-transform-typescript@^7.5.0": +"@babel/plugin-transform-typeof-symbol@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.5.tgz#a1d1bf2c71573fe30965d0e4cd6a3291202e20ed" + integrity sha512-ldxCkW180qbrvyCVDzAUZqB0TAeF8W/vGJoRcaf75awm6By+PxfJKvuqVAnq8N9wz5Xa6mSpM19OfVKKVmGHSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + +"@babel/plugin-transform-typescript@^7.16.0", "@babel/plugin-transform-typescript@^7.16.1", "@babel/plugin-transform-typescript@^7.5.0": version "7.16.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.1.tgz#cc0670b2822b0338355bc1b3d2246a42b8166409" integrity sha512-NO4XoryBng06jjw/qWEU2LhcLJr1tWkhpMam/H4eas/CDKMX/b2/Ylb6EI256Y7+FVPCawwSM1rrJNOpDiz+Lg== @@ -856,6 +1401,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-unicode-escapes@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.5.tgz#80507c225af49b4f4ee647e2a0ce53d2eeff9e85" + integrity sha512-shiCBHTIIChGLdyojsKQjoAyB8MBwat25lKM7MJjbe1hE0bgIppD+LX9afr41lLHOhqceqeWl4FkLp+Bgn9o1Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/plugin-transform-unicode-regex@^7.0.0", "@babel/plugin-transform-unicode-regex@^7.16.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz#293b80950177c8c85aede87cef280259fb995402" @@ -864,6 +1416,94 @@ "@babel/helper-create-regexp-features-plugin" "^7.16.0" "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-unicode-regex@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.5.tgz#ac84d6a1def947d71ffb832426aa53b83d7ed49e" + integrity sha512-GTJ4IW012tiPEMMubd7sD07iU9O/LOo8Q/oU4xNhcaq0Xn8+6TcUQaHtC8YxySo1T+ErQ8RaWogIEeFhKGNPzw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.16.0" + "@babel/helper-plugin-utils" "^7.16.5" + +"@babel/preset-env@^7.12.11": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.5.tgz#2e94d922f4a890979af04ffeb6a6b4e44ba90847" + integrity sha512-MiJJW5pwsktG61NDxpZ4oJ1CKxM1ncam9bzRtx9g40/WkLRkxFP6mhpkYV0/DxcciqoiHicx291+eUQrXb/SfQ== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-compilation-targets" "^7.16.3" + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.2" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.0" + "@babel/plugin-proposal-async-generator-functions" "^7.16.5" + "@babel/plugin-proposal-class-properties" "^7.16.5" + "@babel/plugin-proposal-class-static-block" "^7.16.5" + "@babel/plugin-proposal-dynamic-import" "^7.16.5" + "@babel/plugin-proposal-export-namespace-from" "^7.16.5" + "@babel/plugin-proposal-json-strings" "^7.16.5" + "@babel/plugin-proposal-logical-assignment-operators" "^7.16.5" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.5" + "@babel/plugin-proposal-numeric-separator" "^7.16.5" + "@babel/plugin-proposal-object-rest-spread" "^7.16.5" + "@babel/plugin-proposal-optional-catch-binding" "^7.16.5" + "@babel/plugin-proposal-optional-chaining" "^7.16.5" + "@babel/plugin-proposal-private-methods" "^7.16.5" + "@babel/plugin-proposal-private-property-in-object" "^7.16.5" + "@babel/plugin-proposal-unicode-property-regex" "^7.16.5" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-transform-arrow-functions" "^7.16.5" + "@babel/plugin-transform-async-to-generator" "^7.16.5" + "@babel/plugin-transform-block-scoped-functions" "^7.16.5" + "@babel/plugin-transform-block-scoping" "^7.16.5" + "@babel/plugin-transform-classes" "^7.16.5" + "@babel/plugin-transform-computed-properties" "^7.16.5" + "@babel/plugin-transform-destructuring" "^7.16.5" + "@babel/plugin-transform-dotall-regex" "^7.16.5" + "@babel/plugin-transform-duplicate-keys" "^7.16.5" + "@babel/plugin-transform-exponentiation-operator" "^7.16.5" + "@babel/plugin-transform-for-of" "^7.16.5" + "@babel/plugin-transform-function-name" "^7.16.5" + "@babel/plugin-transform-literals" "^7.16.5" + "@babel/plugin-transform-member-expression-literals" "^7.16.5" + "@babel/plugin-transform-modules-amd" "^7.16.5" + "@babel/plugin-transform-modules-commonjs" "^7.16.5" + "@babel/plugin-transform-modules-systemjs" "^7.16.5" + "@babel/plugin-transform-modules-umd" "^7.16.5" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.5" + "@babel/plugin-transform-new-target" "^7.16.5" + "@babel/plugin-transform-object-super" "^7.16.5" + "@babel/plugin-transform-parameters" "^7.16.5" + "@babel/plugin-transform-property-literals" "^7.16.5" + "@babel/plugin-transform-regenerator" "^7.16.5" + "@babel/plugin-transform-reserved-words" "^7.16.5" + "@babel/plugin-transform-shorthand-properties" "^7.16.5" + "@babel/plugin-transform-spread" "^7.16.5" + "@babel/plugin-transform-sticky-regex" "^7.16.5" + "@babel/plugin-transform-template-literals" "^7.16.5" + "@babel/plugin-transform-typeof-symbol" "^7.16.5" + "@babel/plugin-transform-unicode-escapes" "^7.16.5" + "@babel/plugin-transform-unicode-regex" "^7.16.5" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.16.0" + babel-plugin-polyfill-corejs2 "^0.3.0" + babel-plugin-polyfill-corejs3 "^0.4.0" + babel-plugin-polyfill-regenerator "^0.3.0" + core-js-compat "^3.19.1" + semver "^6.3.0" + "@babel/preset-env@^7.16.4": version "7.16.4" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.4.tgz#4f6ec33b2a3fe72d6bfdcdf3859500232563a2e3" @@ -953,6 +1593,15 @@ "@babel/helper-validator-option" "^7.14.5" "@babel/plugin-transform-flow-strip-types" "^7.16.0" +"@babel/preset-flow@^7.12.1": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.16.5.tgz#fed36ad84ed09f6df41a37b372d3933fc58d0885" + integrity sha512-rmC6Nznp4V55N4Zfec87jwd14TdREqwKVJFM/6Z2wTwoeZQr56czjaPRCezqzqc8TsHF7aLP1oczjadIQ058gw== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-transform-flow-strip-types" "^7.16.5" + "@babel/preset-modules@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" @@ -964,6 +1613,18 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" +"@babel/preset-react@^7.12.10": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.5.tgz#09df3b7a6522cb3e6682dc89b4dfebb97d22031b" + integrity sha512-3kzUOQeaxY/2vhPDS7CX/KGEGu/1bOYGvdRDJ2U5yjEz5o5jmIeTPLoiQBPGjfhPascLuW5OlMiPzwOOuB6txg== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-transform-react-display-name" "^7.16.5" + "@babel/plugin-transform-react-jsx" "^7.16.5" + "@babel/plugin-transform-react-jsx-development" "^7.16.5" + "@babel/plugin-transform-react-pure-annotations" "^7.16.5" + "@babel/preset-typescript@^7.1.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.0.tgz#b0b4f105b855fb3d631ec036cdc9d1ffd1fa5eac" @@ -973,6 +1634,15 @@ "@babel/helper-validator-option" "^7.14.5" "@babel/plugin-transform-typescript" "^7.16.0" +"@babel/preset-typescript@^7.12.7": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.5.tgz#b86a5b0ae739ba741347d2f58c52f52e63cf1ba1" + integrity sha512-lmAWRoJ9iOSvs3DqOndQpj8XqXkzaiQs50VG/zESiI9D3eoZhGriU675xNCr0UwvsuXrhMAGvyk1w+EVWF3u8Q== + dependencies: + "@babel/helper-plugin-utils" "^7.16.5" + "@babel/helper-validator-option" "^7.14.5" + "@babel/plugin-transform-typescript" "^7.16.1" + "@babel/register@^7.0.0": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.16.0.tgz#f5d2aa14df37cf7146b9759f7c53818360f24ec6" @@ -1015,6 +1685,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.16.5": + version "7.16.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.5.tgz#d7d400a8229c714a59b87624fc67b0f1fbd4b2b3" + integrity sha512-FOCODAzqUMROikDYLYxl4nmwiLlu85rNqBML/A5hKRVXG2LV8d0iMqgPzdYTcIpjZEBB7D6UDU9vxRZiriASdQ== + dependencies: + "@babel/code-frame" "^7.16.0" + "@babel/generator" "^7.16.5" + "@babel/helper-environment-visitor" "^7.16.5" + "@babel/helper-function-name" "^7.16.0" + "@babel/helper-hoist-variables" "^7.16.0" + "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/parser" "^7.16.5" + "@babel/types" "^7.16.0" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.16.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" @@ -3482,6 +4168,17 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== +browserslist@^4.16.0: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + dependencies: + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + browserslist@^4.17.5, browserslist@^4.18.1: version "4.18.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" @@ -3635,6 +4332,11 @@ caniuse-lite@^1.0.30001280: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001285.tgz#fe1e52229187e11d6670590790d669b9e03315b7" integrity sha512-KAOkuUtcQ901MtmvxfKD+ODHH9YVDYnBt+TGYSz2KIfnq22CiArbUxXPN9067gNbgMlnNYRSwho8OPXZPALB9Q== +caniuse-lite@^1.0.30001286: + version "1.0.30001286" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001286.tgz#3e9debad420419618cfdf52dc9b6572b28a8fff6" + integrity sha512-zaEMRH6xg8ESMi2eQ3R4eZ5qw/hJiVsO/HlLwniIwErij0JDr9P+8V4dtx1l+kLq6j3yy8l8W4fst1lBnat5wQ== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -4244,7 +4946,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -4568,6 +5270,11 @@ electron-to-chromium@^1.3.896: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.14.tgz#b0aa41fbfbf2eff8c2c6f7a871c03075250f8956" integrity sha512-RsGkAN9JEAYMObS72kzUsPPcPGMqX1rBqGuXi9aa4TBKLzICoLf+DAAtd0fVFzrniJqYzpby47gthCUoObfs0Q== +electron-to-chromium@^1.4.17: + version "1.4.18" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.18.tgz#2fb282213937986a20a653315963070e8321b3f3" + integrity sha512-i7nKjGGBE1+YUIbfLObA1EZPmN7J1ITEllbhusDk+KIk6V6gUxN9PFe36v+Sd+8Cg0k3cgUv9lQhQZalr8rggw== + emittery@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860" @@ -4922,6 +5629,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -5281,7 +6003,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -5408,6 +6130,13 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + get-stream@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" @@ -5755,6 +6484,11 @@ https-proxy-agent@^5.0.0: agent-base "6" debug "4" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -5966,6 +6700,14 @@ ip@^1.1.5: resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= +is-absolute@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" + integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== + dependencies: + is-relative "^1.0.0" + is-windows "^1.0.1" + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -6114,6 +6856,22 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-git-dirty@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-git-dirty/-/is-git-dirty-2.0.1.tgz#29ca82fb0924ccbeaa0bae08de217546df593012" + integrity sha512-zn3CNLDbSR+y7+VDDw7/SwTRRuECn4OpAyelo5MDN+gVxdzM8SUDd51ZwPIOxhljED44Riu0jiiNtC8w0bcLdA== + dependencies: + execa "^4.0.3" + is-git-repository "^2.0.0" + +is-git-repository@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-git-repository/-/is-git-repository-2.0.0.tgz#fa036007fe9697198c2c89dac4dd8304a6101e1c" + integrity sha512-HDO50CG5suIAcmqG4F1buqVXEZRPn+RaXIn9pFKq/947FBo2bCRwK7ZluEVZOy99a4IQyqsjbKEpAiOXCccOHQ== + dependencies: + execa "^4.0.3" + is-absolute "^1.0.0" + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -6205,6 +6963,13 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-relative@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" + integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== + dependencies: + is-unc-path "^1.0.0" + is-shared-array-buffer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" @@ -6253,6 +7018,13 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unc-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" + integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== + dependencies: + unc-path-regex "^0.1.2" + is-unicode-supported@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" @@ -6265,7 +7037,7 @@ is-weakref@^1.0.1: dependencies: call-bind "^1.0.0" -is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -6853,7 +7625,7 @@ jest@^27.4.3: import-local "^3.0.2" jest-cli "^27.4.3" -jetifier@^1.6.2: +jetifier@^1.6.2, jetifier@^1.6.6: version "1.6.8" resolved "https://registry.yarnpkg.com/jetifier/-/jetifier-1.6.8.tgz#e88068697875cbda98c32472902c4d3756247798" integrity sha512-3Zi16h6L5tXDRQJTb221cnRoVG9/9OvreLdLU2/ZjRv/GILL+2Cemt0IKvkowwkDpvouAU1DQPOJ7qaiHeIdrw== @@ -7002,7 +7774,7 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json5@2.x, json5@^2.1.2: +json5@2.x, json5@^2.1.2, json5@^2.1.3: version "2.2.0" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== @@ -8338,7 +9110,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -npm-run-path@^4.0.1: +npm-run-path@^4.0.0, npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== @@ -9253,6 +10025,33 @@ react-is@^17.0.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== +react-native-builder-bob@^0.18.2: + version "0.18.2" + resolved "https://registry.yarnpkg.com/react-native-builder-bob/-/react-native-builder-bob-0.18.2.tgz#e3a96abe3ead84b167c1c1ea97747ef8ffc2a9f4" + integrity sha512-HA7ryoG99tkWh92s7Qb/619qAAfa3TMAKP4Q5l/smqZQwnJ77z5ESiPgRZl8gQMiCnrmmPVb/c5yUscKOL9GdQ== + dependencies: + "@babel/core" "^7.12.10" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/preset-env" "^7.12.11" + "@babel/preset-flow" "^7.12.1" + "@babel/preset-react" "^7.12.10" + "@babel/preset-typescript" "^7.12.7" + browserslist "^4.16.0" + chalk "^4.1.0" + cosmiconfig "^7.0.0" + cross-spawn "^7.0.3" + dedent "^0.7.0" + del "^6.0.0" + fs-extra "^9.0.1" + glob "^7.1.6" + is-git-dirty "^2.0.1" + json5 "^2.1.3" + prompts "^2.4.0" + which "^2.0.2" + yargs "^16.2.0" + optionalDependencies: + jetifier "^1.6.6" + react-native-codegen@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/react-native-codegen/-/react-native-codegen-0.0.7.tgz#86651c5c5fec67a8077ef7f4e36f7ed459043e14" @@ -10928,6 +11727,11 @@ unbox-primitive@^1.0.1: has-symbols "^1.0.2" which-boxed-primitive "^1.0.2" +unc-path-regex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"