@chipmobilesdk/rn-ads 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +88 -0
- package/lib/commonjs/config/resolveAdUnit.js +80 -0
- package/lib/commonjs/config/resolveAdUnit.js.map +1 -0
- package/lib/commonjs/config/types.js +138 -0
- package/lib/commonjs/config/types.js.map +1 -0
- package/lib/commonjs/config/validate.js +150 -0
- package/lib/commonjs/config/validate.js.map +1 -0
- package/lib/commonjs/core/adOriginatedReturn.js +119 -0
- package/lib/commonjs/core/adOriginatedReturn.js.map +1 -0
- package/lib/commonjs/core/adsInstance.js +129 -0
- package/lib/commonjs/core/adsInstance.js.map +1 -0
- package/lib/commonjs/core/consentFlow.js +154 -0
- package/lib/commonjs/core/consentFlow.js.map +1 -0
- package/lib/commonjs/core/enablement.js +64 -0
- package/lib/commonjs/core/enablement.js.map +1 -0
- package/lib/commonjs/core/fullScreenLock.js +48 -0
- package/lib/commonjs/core/fullScreenLock.js.map +1 -0
- package/lib/commonjs/core/gates.js +95 -0
- package/lib/commonjs/core/gates.js.map +1 -0
- package/lib/commonjs/core/initMachine.js +159 -0
- package/lib/commonjs/core/initMachine.js.map +1 -0
- package/lib/commonjs/core/instance/consent.js +155 -0
- package/lib/commonjs/core/instance/consent.js.map +1 -0
- package/lib/commonjs/core/instance/context.js +217 -0
- package/lib/commonjs/core/instance/context.js.map +1 -0
- package/lib/commonjs/core/instance/gate.js +194 -0
- package/lib/commonjs/core/instance/gate.js.map +1 -0
- package/lib/commonjs/core/instance/init.js +326 -0
- package/lib/commonjs/core/instance/init.js.map +1 -0
- package/lib/commonjs/core/instance/internals.js +115 -0
- package/lib/commonjs/core/instance/internals.js.map +1 -0
- package/lib/commonjs/core/instance/load.js +458 -0
- package/lib/commonjs/core/instance/load.js.map +1 -0
- package/lib/commonjs/core/instance/show.js +243 -0
- package/lib/commonjs/core/instance/show.js.map +1 -0
- package/lib/commonjs/core/instance/types.js +6 -0
- package/lib/commonjs/core/instance/types.js.map +1 -0
- package/lib/commonjs/core/placementMachine.js +116 -0
- package/lib/commonjs/core/placementMachine.js.map +1 -0
- package/lib/commonjs/core/privacyGate.js +93 -0
- package/lib/commonjs/core/privacyGate.js.map +1 -0
- package/lib/commonjs/core/requestThrottle.js +152 -0
- package/lib/commonjs/core/requestThrottle.js.map +1 -0
- package/lib/commonjs/core/retryPolicy.js +120 -0
- package/lib/commonjs/core/retryPolicy.js.map +1 -0
- package/lib/commonjs/core/rewardedSession.js +65 -0
- package/lib/commonjs/core/rewardedSession.js.map +1 -0
- package/lib/commonjs/core/timers.js +162 -0
- package/lib/commonjs/core/timers.js.map +1 -0
- package/lib/commonjs/diagnostics/correlation.js +33 -0
- package/lib/commonjs/diagnostics/correlation.js.map +1 -0
- package/lib/commonjs/diagnostics/errors.js +152 -0
- package/lib/commonjs/diagnostics/errors.js.map +1 -0
- package/lib/commonjs/diagnostics/events.js +132 -0
- package/lib/commonjs/diagnostics/events.js.map +1 -0
- package/lib/commonjs/engine/admobBanner.js +58 -0
- package/lib/commonjs/engine/admobBanner.js.map +1 -0
- package/lib/commonjs/engine/admobEngine.js +343 -0
- package/lib/commonjs/engine/admobEngine.js.map +1 -0
- package/lib/commonjs/engine/admobErrors.js +45 -0
- package/lib/commonjs/engine/admobErrors.js.map +1 -0
- package/lib/commonjs/engine/port.js +6 -0
- package/lib/commonjs/engine/port.js.map +1 -0
- package/lib/commonjs/engine/testAdUnits.js +61 -0
- package/lib/commonjs/engine/testAdUnits.js.map +1 -0
- package/lib/commonjs/index.js +218 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/react/AdsBanner.js +317 -0
- package/lib/commonjs/react/AdsBanner.js.map +1 -0
- package/lib/commonjs/react/AdsProvider.js +54 -0
- package/lib/commonjs/react/AdsProvider.js.map +1 -0
- package/lib/commonjs/react/hooks.js +63 -0
- package/lib/commonjs/react/hooks.js.map +1 -0
- package/lib/commonjs/testing/clock.js +76 -0
- package/lib/commonjs/testing/clock.js.map +1 -0
- package/lib/commonjs/testing/conformance.js +99 -0
- package/lib/commonjs/testing/conformance.js.map +1 -0
- package/lib/commonjs/testing/index.js +389 -0
- package/lib/commonjs/testing/index.js.map +1 -0
- package/lib/module/config/resolveAdUnit.js +75 -0
- package/lib/module/config/resolveAdUnit.js.map +1 -0
- package/lib/module/config/types.js +134 -0
- package/lib/module/config/types.js.map +1 -0
- package/lib/module/config/validate.js +146 -0
- package/lib/module/config/validate.js.map +1 -0
- package/lib/module/core/adOriginatedReturn.js +115 -0
- package/lib/module/core/adOriginatedReturn.js.map +1 -0
- package/lib/module/core/adsInstance.js +121 -0
- package/lib/module/core/adsInstance.js.map +1 -0
- package/lib/module/core/consentFlow.js +143 -0
- package/lib/module/core/consentFlow.js.map +1 -0
- package/lib/module/core/enablement.js +58 -0
- package/lib/module/core/enablement.js.map +1 -0
- package/lib/module/core/fullScreenLock.js +44 -0
- package/lib/module/core/fullScreenLock.js.map +1 -0
- package/lib/module/core/gates.js +91 -0
- package/lib/module/core/gates.js.map +1 -0
- package/lib/module/core/initMachine.js +152 -0
- package/lib/module/core/initMachine.js.map +1 -0
- package/lib/module/core/instance/consent.js +151 -0
- package/lib/module/core/instance/consent.js.map +1 -0
- package/lib/module/core/instance/context.js +212 -0
- package/lib/module/core/instance/context.js.map +1 -0
- package/lib/module/core/instance/gate.js +183 -0
- package/lib/module/core/instance/gate.js.map +1 -0
- package/lib/module/core/instance/init.js +321 -0
- package/lib/module/core/instance/init.js.map +1 -0
- package/lib/module/core/instance/internals.js +109 -0
- package/lib/module/core/instance/internals.js.map +1 -0
- package/lib/module/core/instance/load.js +452 -0
- package/lib/module/core/instance/load.js.map +1 -0
- package/lib/module/core/instance/show.js +238 -0
- package/lib/module/core/instance/show.js.map +1 -0
- package/lib/module/core/instance/types.js +4 -0
- package/lib/module/core/instance/types.js.map +1 -0
- package/lib/module/core/placementMachine.js +109 -0
- package/lib/module/core/placementMachine.js.map +1 -0
- package/lib/module/core/privacyGate.js +86 -0
- package/lib/module/core/privacyGate.js.map +1 -0
- package/lib/module/core/requestThrottle.js +146 -0
- package/lib/module/core/requestThrottle.js.map +1 -0
- package/lib/module/core/retryPolicy.js +113 -0
- package/lib/module/core/retryPolicy.js.map +1 -0
- package/lib/module/core/rewardedSession.js +61 -0
- package/lib/module/core/rewardedSession.js.map +1 -0
- package/lib/module/core/timers.js +150 -0
- package/lib/module/core/timers.js.map +1 -0
- package/lib/module/diagnostics/correlation.js +29 -0
- package/lib/module/diagnostics/correlation.js.map +1 -0
- package/lib/module/diagnostics/errors.js +143 -0
- package/lib/module/diagnostics/errors.js.map +1 -0
- package/lib/module/diagnostics/events.js +128 -0
- package/lib/module/diagnostics/events.js.map +1 -0
- package/lib/module/engine/admobBanner.js +52 -0
- package/lib/module/engine/admobBanner.js.map +1 -0
- package/lib/module/engine/admobEngine.js +334 -0
- package/lib/module/engine/admobEngine.js.map +1 -0
- package/lib/module/engine/admobErrors.js +41 -0
- package/lib/module/engine/admobErrors.js.map +1 -0
- package/lib/module/engine/port.js +4 -0
- package/lib/module/engine/port.js.map +1 -0
- package/lib/module/engine/testAdUnits.js +56 -0
- package/lib/module/engine/testAdUnits.js.map +1 -0
- package/lib/module/index.js +59 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/react/AdsBanner.js +312 -0
- package/lib/module/react/AdsBanner.js.map +1 -0
- package/lib/module/react/AdsProvider.js +48 -0
- package/lib/module/react/AdsProvider.js.map +1 -0
- package/lib/module/react/hooks.js +58 -0
- package/lib/module/react/hooks.js.map +1 -0
- package/lib/module/testing/clock.js +72 -0
- package/lib/module/testing/clock.js.map +1 -0
- package/lib/module/testing/conformance.js +93 -0
- package/lib/module/testing/conformance.js.map +1 -0
- package/lib/module/testing/index.js +366 -0
- package/lib/module/testing/index.js.map +1 -0
- package/lib/typescript/commonjs/config/resolveAdUnit.d.ts +43 -0
- package/lib/typescript/commonjs/config/resolveAdUnit.d.ts.map +1 -0
- package/lib/typescript/commonjs/config/types.d.ts +280 -0
- package/lib/typescript/commonjs/config/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/config/validate.d.ts +49 -0
- package/lib/typescript/commonjs/config/validate.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/adOriginatedReturn.d.ts +61 -0
- package/lib/typescript/commonjs/core/adOriginatedReturn.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/adsInstance.d.ts +33 -0
- package/lib/typescript/commonjs/core/adsInstance.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/consentFlow.d.ts +84 -0
- package/lib/typescript/commonjs/core/consentFlow.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/enablement.d.ts +74 -0
- package/lib/typescript/commonjs/core/enablement.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/fullScreenLock.d.ts +25 -0
- package/lib/typescript/commonjs/core/fullScreenLock.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/gates.d.ts +76 -0
- package/lib/typescript/commonjs/core/gates.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/initMachine.d.ts +66 -0
- package/lib/typescript/commonjs/core/initMachine.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/consent.d.ts +4 -0
- package/lib/typescript/commonjs/core/instance/consent.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/context.d.ts +118 -0
- package/lib/typescript/commonjs/core/instance/context.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/gate.d.ts +38 -0
- package/lib/typescript/commonjs/core/instance/gate.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/init.d.ts +13 -0
- package/lib/typescript/commonjs/core/instance/init.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/internals.d.ts +60 -0
- package/lib/typescript/commonjs/core/instance/internals.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/load.d.ts +9 -0
- package/lib/typescript/commonjs/core/instance/load.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/show.d.ts +7 -0
- package/lib/typescript/commonjs/core/instance/show.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/instance/types.d.ts +240 -0
- package/lib/typescript/commonjs/core/instance/types.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/placementMachine.d.ts +55 -0
- package/lib/typescript/commonjs/core/placementMachine.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/privacyGate.d.ts +40 -0
- package/lib/typescript/commonjs/core/privacyGate.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/requestThrottle.d.ts +99 -0
- package/lib/typescript/commonjs/core/requestThrottle.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/retryPolicy.d.ts +66 -0
- package/lib/typescript/commonjs/core/retryPolicy.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/rewardedSession.d.ts +37 -0
- package/lib/typescript/commonjs/core/rewardedSession.d.ts.map +1 -0
- package/lib/typescript/commonjs/core/timers.d.ts +135 -0
- package/lib/typescript/commonjs/core/timers.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/correlation.d.ts +18 -0
- package/lib/typescript/commonjs/diagnostics/correlation.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts +59 -0
- package/lib/typescript/commonjs/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/diagnostics/events.d.ts +126 -0
- package/lib/typescript/commonjs/diagnostics/events.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/admobBanner.d.ts +10 -0
- package/lib/typescript/commonjs/engine/admobBanner.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/admobEngine.d.ts +71 -0
- package/lib/typescript/commonjs/engine/admobEngine.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/admobErrors.d.ts +9 -0
- package/lib/typescript/commonjs/engine/admobErrors.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/port.d.ts +171 -0
- package/lib/typescript/commonjs/engine/port.d.ts.map +1 -0
- package/lib/typescript/commonjs/engine/testAdUnits.d.ts +33 -0
- package/lib/typescript/commonjs/engine/testAdUnits.d.ts.map +1 -0
- package/lib/typescript/commonjs/index.d.ts +42 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/react/AdsBanner.d.ts +29 -0
- package/lib/typescript/commonjs/react/AdsBanner.d.ts.map +1 -0
- package/lib/typescript/commonjs/react/AdsProvider.d.ts +36 -0
- package/lib/typescript/commonjs/react/AdsProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/react/hooks.d.ts +27 -0
- package/lib/typescript/commonjs/react/hooks.d.ts.map +1 -0
- package/lib/typescript/commonjs/testing/clock.d.ts +29 -0
- package/lib/typescript/commonjs/testing/clock.d.ts.map +1 -0
- package/lib/typescript/commonjs/testing/conformance.d.ts +26 -0
- package/lib/typescript/commonjs/testing/conformance.d.ts.map +1 -0
- package/lib/typescript/commonjs/testing/index.d.ts +133 -0
- package/lib/typescript/commonjs/testing/index.d.ts.map +1 -0
- package/lib/typescript/module/config/resolveAdUnit.d.ts +43 -0
- package/lib/typescript/module/config/resolveAdUnit.d.ts.map +1 -0
- package/lib/typescript/module/config/types.d.ts +280 -0
- package/lib/typescript/module/config/types.d.ts.map +1 -0
- package/lib/typescript/module/config/validate.d.ts +49 -0
- package/lib/typescript/module/config/validate.d.ts.map +1 -0
- package/lib/typescript/module/core/adOriginatedReturn.d.ts +61 -0
- package/lib/typescript/module/core/adOriginatedReturn.d.ts.map +1 -0
- package/lib/typescript/module/core/adsInstance.d.ts +33 -0
- package/lib/typescript/module/core/adsInstance.d.ts.map +1 -0
- package/lib/typescript/module/core/consentFlow.d.ts +84 -0
- package/lib/typescript/module/core/consentFlow.d.ts.map +1 -0
- package/lib/typescript/module/core/enablement.d.ts +74 -0
- package/lib/typescript/module/core/enablement.d.ts.map +1 -0
- package/lib/typescript/module/core/fullScreenLock.d.ts +25 -0
- package/lib/typescript/module/core/fullScreenLock.d.ts.map +1 -0
- package/lib/typescript/module/core/gates.d.ts +76 -0
- package/lib/typescript/module/core/gates.d.ts.map +1 -0
- package/lib/typescript/module/core/initMachine.d.ts +66 -0
- package/lib/typescript/module/core/initMachine.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/consent.d.ts +4 -0
- package/lib/typescript/module/core/instance/consent.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/context.d.ts +118 -0
- package/lib/typescript/module/core/instance/context.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/gate.d.ts +38 -0
- package/lib/typescript/module/core/instance/gate.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/init.d.ts +13 -0
- package/lib/typescript/module/core/instance/init.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/internals.d.ts +60 -0
- package/lib/typescript/module/core/instance/internals.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/load.d.ts +9 -0
- package/lib/typescript/module/core/instance/load.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/show.d.ts +7 -0
- package/lib/typescript/module/core/instance/show.d.ts.map +1 -0
- package/lib/typescript/module/core/instance/types.d.ts +240 -0
- package/lib/typescript/module/core/instance/types.d.ts.map +1 -0
- package/lib/typescript/module/core/placementMachine.d.ts +55 -0
- package/lib/typescript/module/core/placementMachine.d.ts.map +1 -0
- package/lib/typescript/module/core/privacyGate.d.ts +40 -0
- package/lib/typescript/module/core/privacyGate.d.ts.map +1 -0
- package/lib/typescript/module/core/requestThrottle.d.ts +99 -0
- package/lib/typescript/module/core/requestThrottle.d.ts.map +1 -0
- package/lib/typescript/module/core/retryPolicy.d.ts +66 -0
- package/lib/typescript/module/core/retryPolicy.d.ts.map +1 -0
- package/lib/typescript/module/core/rewardedSession.d.ts +37 -0
- package/lib/typescript/module/core/rewardedSession.d.ts.map +1 -0
- package/lib/typescript/module/core/timers.d.ts +135 -0
- package/lib/typescript/module/core/timers.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/correlation.d.ts +18 -0
- package/lib/typescript/module/diagnostics/correlation.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/errors.d.ts +59 -0
- package/lib/typescript/module/diagnostics/errors.d.ts.map +1 -0
- package/lib/typescript/module/diagnostics/events.d.ts +126 -0
- package/lib/typescript/module/diagnostics/events.d.ts.map +1 -0
- package/lib/typescript/module/engine/admobBanner.d.ts +10 -0
- package/lib/typescript/module/engine/admobBanner.d.ts.map +1 -0
- package/lib/typescript/module/engine/admobEngine.d.ts +71 -0
- package/lib/typescript/module/engine/admobEngine.d.ts.map +1 -0
- package/lib/typescript/module/engine/admobErrors.d.ts +9 -0
- package/lib/typescript/module/engine/admobErrors.d.ts.map +1 -0
- package/lib/typescript/module/engine/port.d.ts +171 -0
- package/lib/typescript/module/engine/port.d.ts.map +1 -0
- package/lib/typescript/module/engine/testAdUnits.d.ts +33 -0
- package/lib/typescript/module/engine/testAdUnits.d.ts.map +1 -0
- package/lib/typescript/module/index.d.ts +42 -0
- package/lib/typescript/module/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/react/AdsBanner.d.ts +29 -0
- package/lib/typescript/module/react/AdsBanner.d.ts.map +1 -0
- package/lib/typescript/module/react/AdsProvider.d.ts +36 -0
- package/lib/typescript/module/react/AdsProvider.d.ts.map +1 -0
- package/lib/typescript/module/react/hooks.d.ts +27 -0
- package/lib/typescript/module/react/hooks.d.ts.map +1 -0
- package/lib/typescript/module/testing/clock.d.ts +29 -0
- package/lib/typescript/module/testing/clock.d.ts.map +1 -0
- package/lib/typescript/module/testing/conformance.d.ts +26 -0
- package/lib/typescript/module/testing/conformance.d.ts.map +1 -0
- package/lib/typescript/module/testing/index.d.ts +133 -0
- package/lib/typescript/module/testing/index.d.ts.map +1 -0
- package/package.json +48 -12
- package/src/testing/index.ts +17 -3
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Catalog and configuration validation (FR-008), plus the fail-closed check
|
|
5
|
+
* that substitution cannot cover (FR-012).
|
|
6
|
+
*
|
|
7
|
+
* Configuration faults throw rather than returning a result. They mean the app
|
|
8
|
+
* is wired wrong, and no runtime status could describe a usable outcome — every
|
|
9
|
+
* other failure in this package is a typed result instead.
|
|
10
|
+
*
|
|
11
|
+
* Every message names the offending placement key. An error that says only
|
|
12
|
+
* "invalid configuration" makes the integrator hunt through a catalog by hand.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { AdsConfigError } from "../diagnostics/errors.js";
|
|
16
|
+
import { resolvePlacementAdUnits } from "./resolveAdUnit.js";
|
|
17
|
+
import { checkBand, resolveTimeouts } from "../core/timers.js";
|
|
18
|
+
import { defaultMinRequestIntervalMs, MIN_REQUEST_INTERVAL_BOUNDS } from "../core/requestThrottle.js";
|
|
19
|
+
import { toEnablement } from "../core/enablement.js";
|
|
20
|
+
import { resolveEffectiveRetry } from "../core/retryPolicy.js";
|
|
21
|
+
const FORMATS = new Set(['banner', 'interstitial', 'rewarded', 'app_open']);
|
|
22
|
+
export function validateConfig(config, options) {
|
|
23
|
+
// FR-012. Substitution deliberately does not apply in production, so a debug
|
|
24
|
+
// build declaring `production` is the one case it cannot make safe: it would
|
|
25
|
+
// send real requests from a build that should never generate traffic. Fail
|
|
26
|
+
// closed rather than continue.
|
|
27
|
+
if (config.environment === 'production' && options.isDevBuild) {
|
|
28
|
+
throw new AdsConfigError('production_in_dev_build', {
|
|
29
|
+
message: 'environment is "production" but this is a development build. ' + 'Non-production builds must declare "development" or "test" so the package can ' + 'substitute official Google test ad units and keep production traffic impossible.'
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (!Array.isArray(config.placements) || config.placements.length === 0) {
|
|
33
|
+
throw new AdsConfigError('invalid_config', {
|
|
34
|
+
message: 'placements must be a non-empty array; the package can show nothing without one'
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const byKey = new Map();
|
|
38
|
+
for (const placement of config.placements) {
|
|
39
|
+
const key = typeof placement?.key === 'string' ? placement.key.trim() : '';
|
|
40
|
+
if (!key) {
|
|
41
|
+
throw new AdsConfigError('invalid_config', {
|
|
42
|
+
message: 'every placement needs a non-empty key'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
if (byKey.has(key)) {
|
|
46
|
+
// Rejecting the whole catalog rather than picking a winner: a repeated
|
|
47
|
+
// key means the app's own naming produced two placements for one slot,
|
|
48
|
+
// and the package has no basis to guess which was meant.
|
|
49
|
+
throw new AdsConfigError('duplicate_placement_key', {
|
|
50
|
+
message: `duplicate placement key "${key}"`,
|
|
51
|
+
placementKey: key
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (!FORMATS.has(placement.format)) {
|
|
55
|
+
throw new AdsConfigError('invalid_config', {
|
|
56
|
+
message: `placement "${key}" has unsupported format "${String(placement.format)}"; supported formats are banner, interstitial, rewarded, and app_open`,
|
|
57
|
+
placementKey: key
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (!placement.androidAdUnitId || !placement.androidAdUnitId.trim()) {
|
|
61
|
+
throw new AdsConfigError('missing_ad_unit_id', {
|
|
62
|
+
message: `placement "${key}" is missing androidAdUnitId`,
|
|
63
|
+
placementKey: key,
|
|
64
|
+
format: placement.format
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
byKey.set(key, {
|
|
68
|
+
...placement,
|
|
69
|
+
key
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const timeouts = resolveTimeouts({
|
|
73
|
+
timeouts: config.timeouts,
|
|
74
|
+
adValidityMs: config.adValidityMs,
|
|
75
|
+
appOpenValidityMs: config.appOpenValidityMs,
|
|
76
|
+
undecidedWarningMs: config.undecidedWarningMs
|
|
77
|
+
});
|
|
78
|
+
const catalog = resolvePlacementAdUnits(Array.from(byKey.values()), config.environment);
|
|
79
|
+
|
|
80
|
+
// Resolved eagerly, for every placement, so an out-of-bounds override fails
|
|
81
|
+
// at construction rather than on the first failed load in production — which
|
|
82
|
+
// is the one moment nobody is watching for a configuration error.
|
|
83
|
+
const retryByKey = new Map();
|
|
84
|
+
// Resolved in the same loop and for the same reason: an out-of-bounds floor
|
|
85
|
+
// must fail at construction, not silently refuse every request in production.
|
|
86
|
+
const minRequestIntervalByKey = new Map();
|
|
87
|
+
for (const [key, placement] of byKey) {
|
|
88
|
+
retryByKey.set(key, resolveEffectiveRetry(config.retry, placement.retry, key));
|
|
89
|
+
minRequestIntervalByKey.set(key, placement.minRequestIntervalMs === undefined ? defaultMinRequestIntervalMs(placement.format) :
|
|
90
|
+
// A request floor, not a timeout: its own code (ADS-16).
|
|
91
|
+
checkBand(`placements["${key}"].minRequestIntervalMs`, placement.minRequestIntervalMs, MIN_REQUEST_INTERVAL_BOUNDS, 'invalid_config'));
|
|
92
|
+
}
|
|
93
|
+
const isProduction = config.environment === 'production';
|
|
94
|
+
const {
|
|
95
|
+
consentTesting,
|
|
96
|
+
ignoredConsentTools
|
|
97
|
+
} = resolveConsentTesting(config.consentTesting, isProduction);
|
|
98
|
+
return {
|
|
99
|
+
enablement: toEnablement(config.enabled),
|
|
100
|
+
environment: config.environment,
|
|
101
|
+
placements: byKey,
|
|
102
|
+
catalog,
|
|
103
|
+
timeouts,
|
|
104
|
+
// FR-014: debug and test-device settings must not be able to alter
|
|
105
|
+
// production behavior, so they are dropped rather than carried and
|
|
106
|
+
// conditionally ignored somewhere further down.
|
|
107
|
+
testDeviceIds: isProduction ? [] : [...(config.testDeviceIds ?? [])],
|
|
108
|
+
retryByKey,
|
|
109
|
+
minRequestIntervalByKey,
|
|
110
|
+
consentTesting,
|
|
111
|
+
ignoredConsentTools
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Neutralizes the consent testing tools in production (FR-113).
|
|
117
|
+
*
|
|
118
|
+
* Dropped here, at the single validation point, rather than checked wherever
|
|
119
|
+
* they are used. That is what makes the guarantee provable: a rule enforced in
|
|
120
|
+
* one place can be asserted by a test, while one spread across the consent
|
|
121
|
+
* module's call sites is a hope. It is the same reasoning that makes the ad-unit
|
|
122
|
+
* substitution guarantee hold, and it is why both are enforced identically.
|
|
123
|
+
*
|
|
124
|
+
* The names of what was dropped are returned rather than only logged, so an
|
|
125
|
+
* automated test — and the demo app's diagnostics screen — can see it.
|
|
126
|
+
*/
|
|
127
|
+
function resolveConsentTesting(testing, isProduction) {
|
|
128
|
+
if (!testing || !isProduction) {
|
|
129
|
+
return {
|
|
130
|
+
consentTesting: testing,
|
|
131
|
+
ignoredConsentTools: []
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const ignored = [];
|
|
135
|
+
if (testing.debugGeography !== undefined && testing.debugGeography !== 'disabled') {
|
|
136
|
+
ignored.push('debugGeography');
|
|
137
|
+
}
|
|
138
|
+
if (testing.resetOnStart === true) {
|
|
139
|
+
ignored.push('resetOnStart');
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
consentTesting: undefined,
|
|
143
|
+
ignoredConsentTools: ignored
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["AdsConfigError","resolvePlacementAdUnits","checkBand","resolveTimeouts","defaultMinRequestIntervalMs","MIN_REQUEST_INTERVAL_BOUNDS","toEnablement","resolveEffectiveRetry","FORMATS","Set","validateConfig","config","options","environment","isDevBuild","message","Array","isArray","placements","length","byKey","Map","placement","key","trim","has","placementKey","format","String","androidAdUnitId","set","timeouts","adValidityMs","appOpenValidityMs","undecidedWarningMs","catalog","from","values","retryByKey","minRequestIntervalByKey","retry","minRequestIntervalMs","undefined","isProduction","consentTesting","ignoredConsentTools","resolveConsentTesting","enablement","enabled","testDeviceIds","testing","ignored","debugGeography","push","resetOnStart"],"sourceRoot":"../../../src","sources":["config/validate.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Ad-originated return detection (FR-128).
|
|
5
|
+
*
|
|
6
|
+
* This is the reason app-open belongs in the package rather than in the app.
|
|
7
|
+
* Every other app-open rule — when to show one, how often, on which screens — is
|
|
8
|
+
* policy the app owns. This one is not policy; it is a fact only the package
|
|
9
|
+
* holds. When a user dismisses a full-screen ad, or comes back from a browser an
|
|
10
|
+
* ad opened, the app sees an ordinary return to the foreground and has no way to
|
|
11
|
+
* tell it apart from any other. Showing an app-open ad on that return means
|
|
12
|
+
* showing an ad immediately after an ad, which is both a poor experience and the
|
|
13
|
+
* kind of thing store review notices.
|
|
14
|
+
*
|
|
15
|
+
* The package knows, because it holds the full-screen lock and it sees the click
|
|
16
|
+
* events. So it refuses, with a reason distinct from `busy` and `not_ready` so
|
|
17
|
+
* the app can tell what happened.
|
|
18
|
+
*
|
|
19
|
+
* **Bounded on both sides, deliberately.** Arming has to be tied to something
|
|
20
|
+
* that actually happened, and it has to expire:
|
|
21
|
+
*
|
|
22
|
+
* - Armed when the provider reports a full-screen ad opened, or on a click —
|
|
23
|
+
* that second case is a browser the ad opened, which is the only signal the
|
|
24
|
+
* provider gives for it. Arming is deliberately not tied to the app
|
|
25
|
+
* reporting that it went to the background; see `noteFullScreenShown`.
|
|
26
|
+
* - Disarmed without firing if the app was away longer than
|
|
27
|
+
* `AD_RETURN_MAX_AWAY_MS`. Someone who left, did something else, and came
|
|
28
|
+
* back an hour later is not returning from an ad, and treating them as if
|
|
29
|
+
* they were would refuse a legitimate show.
|
|
30
|
+
* - Refusals last `AD_RETURN_GRACE_MS` after the return, then stop. The window
|
|
31
|
+
* only needs to cover the moment right after the return, where an app-open
|
|
32
|
+
* show would otherwise fire. A window that outlived that moment would start
|
|
33
|
+
* refusing shows that have nothing to do with the ad.
|
|
34
|
+
*
|
|
35
|
+
* Three limits are worth stating plainly, because they are limits rather than
|
|
36
|
+
* defects and the documentation must not imply otherwise:
|
|
37
|
+
*
|
|
38
|
+
* 1. It cannot survive process death. If the OS kills the app while an ad is
|
|
39
|
+
* on screen, the return is a cold start and nothing links it to the ad.
|
|
40
|
+
* 2. It depends on the app reporting `setAppActive` faithfully — an obligation
|
|
41
|
+
* 0.1.0 already imposes for staleness re-evaluation, not a new one.
|
|
42
|
+
* 3. A browser opened by an ad without a preceding click event is undetectable.
|
|
43
|
+
*
|
|
44
|
+
* Pure state. No listener, no timer — it is driven entirely by transitions the
|
|
45
|
+
* package already observes, which is why `dispose()` has nothing extra to
|
|
46
|
+
* release for it.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
import { AD_CLICK_WINDOW_MS, AD_RETURN_GRACE_MS, AD_RETURN_MAX_AWAY_MS } from "./timers.js";
|
|
50
|
+
export function createAdOriginatedTracker() {
|
|
51
|
+
let lastClickAtMs = null;
|
|
52
|
+
let armedAtMs = null;
|
|
53
|
+
let refusalUntilMs = null;
|
|
54
|
+
return {
|
|
55
|
+
/**
|
|
56
|
+
* Arming happens here — when the provider says an ad is on screen — and
|
|
57
|
+
* deliberately **not** when the app reports going to the background.
|
|
58
|
+
*
|
|
59
|
+
* That was the first design and it does not survive a real device. React
|
|
60
|
+
* Native delivers app-state changes over the bridge, and while the app is
|
|
61
|
+
* backgrounded its JS thread is throttled, so the `background` event is
|
|
62
|
+
* routinely processed only once the app is already returning. By then the
|
|
63
|
+
* ad has been dismissed and the full-screen lock released, so sampling the
|
|
64
|
+
* lock at that moment reports "no ad was showing" and the return is let
|
|
65
|
+
* through — the exact case FR-128 exists to catch. Arming on a fact the
|
|
66
|
+
* provider reports, rather than on the timeliness of an event, removes the
|
|
67
|
+
* race entirely.
|
|
68
|
+
*/
|
|
69
|
+
noteFullScreenShown(nowMs) {
|
|
70
|
+
armedAtMs = nowMs;
|
|
71
|
+
},
|
|
72
|
+
noteClick(nowMs) {
|
|
73
|
+
lastClickAtMs = nowMs;
|
|
74
|
+
// A click is itself grounds to arm: the ad may be opening a browser,
|
|
75
|
+
// and if it is, no `opened` callback will follow.
|
|
76
|
+
armedAtMs = nowMs;
|
|
77
|
+
},
|
|
78
|
+
noteBackground(nowMs) {
|
|
79
|
+
// Only meaningful for the browser case, and only as a refinement: a
|
|
80
|
+
// background that closely follows a click is that browser opening.
|
|
81
|
+
if (lastClickAtMs !== null && nowMs - lastClickAtMs <= AD_CLICK_WINDOW_MS) {
|
|
82
|
+
armedAtMs = nowMs;
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
noteForeground(nowMs) {
|
|
86
|
+
if (armedAtMs === null) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const away = nowMs - armedAtMs;
|
|
90
|
+
armedAtMs = null;
|
|
91
|
+
lastClickAtMs = null;
|
|
92
|
+
if (away > AD_RETURN_MAX_AWAY_MS) {
|
|
93
|
+
// Too long to still be attributable to the ad. Not a refusal.
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
refusalUntilMs = nowMs + AD_RETURN_GRACE_MS;
|
|
97
|
+
},
|
|
98
|
+
isRefusing(nowMs) {
|
|
99
|
+
if (refusalUntilMs === null) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
if (nowMs >= refusalUntilMs) {
|
|
103
|
+
refusalUntilMs = null;
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
},
|
|
108
|
+
reset() {
|
|
109
|
+
lastClickAtMs = null;
|
|
110
|
+
armedAtMs = null;
|
|
111
|
+
refusalUntilMs = null;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=adOriginatedReturn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["AD_CLICK_WINDOW_MS","AD_RETURN_GRACE_MS","AD_RETURN_MAX_AWAY_MS","createAdOriginatedTracker","lastClickAtMs","armedAtMs","refusalUntilMs","noteFullScreenShown","nowMs","noteClick","noteBackground","noteForeground","away","isRefusing","reset"],"sourceRoot":"../../../src","sources":["core/adOriginatedReturn.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,kBAAkB,EAAEC,kBAAkB,EAAEC,qBAAqB,QAAQ,aAAU;AAiBxF,OAAO,SAASC,yBAAyBA,CAAA,EAAwB;EAChE,IAAIC,aAA4B,GAAG,IAAI;EACvC,IAAIC,SAAwB,GAAG,IAAI;EACnC,IAAIC,cAA6B,GAAG,IAAI;EAExC,OAAO;IACN;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;IACEC,mBAAmBA,CAACC,KAAK,EAAE;MAC1BH,SAAS,GAAGG,KAAK;IAClB,CAAC;IAEDC,SAASA,CAACD,KAAK,EAAE;MAChBJ,aAAa,GAAGI,KAAK;MACrB;MACA;MACAH,SAAS,GAAGG,KAAK;IAClB,CAAC;IAEDE,cAAcA,CAACF,KAAK,EAAE;MACrB;MACA;MACA,IAAIJ,aAAa,KAAK,IAAI,IAAII,KAAK,GAAGJ,aAAa,IAAIJ,kBAAkB,EAAE;QAC1EK,SAAS,GAAGG,KAAK;MAClB;IACD,CAAC;IAEDG,cAAcA,CAACH,KAAK,EAAE;MACrB,IAAIH,SAAS,KAAK,IAAI,EAAE;QACvB;MACD;MACA,MAAMO,IAAI,GAAGJ,KAAK,GAAGH,SAAS;MAC9BA,SAAS,GAAG,IAAI;MAChBD,aAAa,GAAG,IAAI;MACpB,IAAIQ,IAAI,GAAGV,qBAAqB,EAAE;QACjC;QACA;MACD;MACAI,cAAc,GAAGE,KAAK,GAAGP,kBAAkB;IAC5C,CAAC;IAEDY,UAAUA,CAACL,KAAK,EAAE;MACjB,IAAIF,cAAc,KAAK,IAAI,EAAE;QAC5B,OAAO,KAAK;MACb;MACA,IAAIE,KAAK,IAAIF,cAAc,EAAE;QAC5BA,cAAc,GAAG,IAAI;QACrB,OAAO,KAAK;MACb;MACA,OAAO,IAAI;IACZ,CAAC;IAEDQ,KAAKA,CAAA,EAAG;MACPV,aAAa,GAAG,IAAI;MACpBC,SAAS,GAAG,IAAI;MAChBC,cAAc,GAAG,IAAI;IACtB;EACD,CAAC;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The ads instance — the public contract's implementation.
|
|
5
|
+
*
|
|
6
|
+
* Every guarantee the specification treats as a rule rather than a convention
|
|
7
|
+
* converges here, and none of it needs a device to prove:
|
|
8
|
+
*
|
|
9
|
+
* FR-022 one native initialization, however many callers race
|
|
10
|
+
* FR-017 no request before the privacy gate permits one
|
|
11
|
+
* FR-011 no production ad unit outside production
|
|
12
|
+
* FR-029 one in-flight provider request per placement
|
|
13
|
+
* FR-030 exactly one full-screen ad, never a queue
|
|
14
|
+
* FR-031 a consumed ad is never reused
|
|
15
|
+
* FR-035 after dispose, a late callback updates nothing and emits nothing
|
|
16
|
+
*
|
|
17
|
+
* This file only composes. Each responsibility lives in `core/instance/` and
|
|
18
|
+
* takes the shared context (ADS-10): the gate, initialization and enablement,
|
|
19
|
+
* full-screen load, show, consent, and the banner host's internals.
|
|
20
|
+
*
|
|
21
|
+
* Nothing here imports the provider. It talks to the engine port, which the
|
|
22
|
+
* caller injects — the AdMob adapter in production, the fake in tests.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { createConsentApi } from "./instance/consent.js";
|
|
26
|
+
import { createInstanceContext } from "./instance/context.js";
|
|
27
|
+
import { cancelAllRetries, disarmUndecidedWarning } from "./instance/gate.js";
|
|
28
|
+
import { createInitController } from "./instance/init.js";
|
|
29
|
+
import { attachInternals, createInternals } from "./instance/internals.js";
|
|
30
|
+
import { createLoader } from "./instance/load.js";
|
|
31
|
+
import { createShower } from "./instance/show.js";
|
|
32
|
+
export { getInternals } from "./instance/internals.js";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The instance itself. The public `createAds` (src/index.ts) passes the AdMob
|
|
36
|
+
* adapter as `defaultEngine`: core/ never loads an adapter, so it stays testable
|
|
37
|
+
* in Node and the provider stays replaceable (ADS-14).
|
|
38
|
+
*/
|
|
39
|
+
export function createAds(config, options = {}, defaultEngine = noDefaultEngine) {
|
|
40
|
+
// Throws on a structural fault or the FR-012 fail-closed case, before
|
|
41
|
+
// anything else exists.
|
|
42
|
+
const context = createInstanceContext(config, options, defaultEngine);
|
|
43
|
+
const {
|
|
44
|
+
state,
|
|
45
|
+
engine,
|
|
46
|
+
resolved,
|
|
47
|
+
events
|
|
48
|
+
} = context;
|
|
49
|
+
const init = createInitController(context);
|
|
50
|
+
const loader = createLoader(context);
|
|
51
|
+
const shower = createShower(context);
|
|
52
|
+
const instance = {
|
|
53
|
+
initialize: privacy => init.initialize(privacy),
|
|
54
|
+
updatePrivacy: privacy => init.updatePrivacy(privacy),
|
|
55
|
+
setEnabled: enabled => init.setEnablement(enabled ? 'enabled' : 'disabled'),
|
|
56
|
+
setEnablement: next => init.setEnablement(next),
|
|
57
|
+
setAppActive: active => shower.setAppActive(active),
|
|
58
|
+
consent: createConsentApi(context, () => init.reevaluateAfterConsent()),
|
|
59
|
+
getStatus: () => state.init.status,
|
|
60
|
+
subscribeStatus: listener => context.statusListeners.add(listener),
|
|
61
|
+
load: placementKey => loader.load(placementKey),
|
|
62
|
+
show: placementKey => shower.show(placementKey),
|
|
63
|
+
getPlacementState(placementKey) {
|
|
64
|
+
if (!resolved.placements.has(placementKey)) {
|
|
65
|
+
return 'unavailable';
|
|
66
|
+
}
|
|
67
|
+
if (!engine.isAvailable() || state.enablement === 'disabled') {
|
|
68
|
+
return 'unavailable';
|
|
69
|
+
}
|
|
70
|
+
// Reported distinctly from `unavailable` so the app can choose to hold
|
|
71
|
+
// the banner's space rather than reclaim it (FR-116).
|
|
72
|
+
if (state.enablement === 'undecided') {
|
|
73
|
+
return 'undecided';
|
|
74
|
+
}
|
|
75
|
+
return context.placements.get(placementKey)?.snapshot.state ?? 'idle';
|
|
76
|
+
},
|
|
77
|
+
subscribePlacement(key, listener) {
|
|
78
|
+
return context.placements.get(key)?.listeners.add(listener) ?? (() => undefined);
|
|
79
|
+
},
|
|
80
|
+
subscribeEvents: listener => events.subscribe(listener),
|
|
81
|
+
/** FR-011a — substitution is observable state, not only a log line. */
|
|
82
|
+
getSubstitutedPlacements: () => resolved.catalog.substitutedKeys,
|
|
83
|
+
/** FR-113 — the same treatment for consent tools dropped in production. */
|
|
84
|
+
getIgnoredConsentTools: () => resolved.ignoredConsentTools,
|
|
85
|
+
dispose() {
|
|
86
|
+
// FR-005: idempotent. A second call is a no-op, not an error.
|
|
87
|
+
if (state.disposed) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
state.disposed = true;
|
|
91
|
+
cancelAllRetries(context);
|
|
92
|
+
disarmUndecidedWarning(context);
|
|
93
|
+
for (const [key, runtime] of context.placements) {
|
|
94
|
+
const abort = runtime.abortLoad;
|
|
95
|
+
context.releasePlacementResources(key);
|
|
96
|
+
runtime.listeners.clear();
|
|
97
|
+
// Settled rather than left hanging, with the answer a `load` after
|
|
98
|
+
// dispose gets (FR-159). No refusal event: nothing is emitted after
|
|
99
|
+
// dispose (FR-035).
|
|
100
|
+
abort?.({
|
|
101
|
+
status: 'unavailable',
|
|
102
|
+
reason: 'provider_missing'
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
context.timers.clearAll();
|
|
106
|
+
context.requestThrottle.clear();
|
|
107
|
+
context.lock.reset();
|
|
108
|
+
context.adReturn.reset();
|
|
109
|
+
context.statusListeners.clear();
|
|
110
|
+
context.consentListeners.clear();
|
|
111
|
+
events.dispose();
|
|
112
|
+
state.inFlightInit = null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
attachInternals(instance, createInternals(context));
|
|
116
|
+
return instance;
|
|
117
|
+
}
|
|
118
|
+
function noDefaultEngine() {
|
|
119
|
+
throw new Error('core/createAds was called without an engine; production code uses createAds from the package entrypoint.');
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=adsInstance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["createConsentApi","createInstanceContext","cancelAllRetries","disarmUndecidedWarning","createInitController","attachInternals","createInternals","createLoader","createShower","getInternals","createAds","config","options","defaultEngine","noDefaultEngine","context","state","engine","resolved","events","init","loader","shower","instance","initialize","privacy","updatePrivacy","setEnabled","enabled","setEnablement","next","setAppActive","active","consent","reevaluateAfterConsent","getStatus","status","subscribeStatus","listener","statusListeners","add","load","placementKey","show","getPlacementState","placements","has","isAvailable","enablement","get","snapshot","subscribePlacement","key","listeners","undefined","subscribeEvents","subscribe","getSubstitutedPlacements","catalog","substitutedKeys","getIgnoredConsentTools","ignoredConsentTools","dispose","disposed","runtime","abort","abortLoad","releasePlacementResources","clear","reason","timers","clearAll","requestThrottle","lock","reset","adReturn","consentListeners","inFlightInit","Error"],"sourceRoot":"../../../src","sources":["core/adsInstance.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA,SAASA,gBAAgB,QAAQ,uBAAoB;AACrD,SAASC,qBAAqB,QAAQ,uBAAoB;AAC1D,SAASC,gBAAgB,EAAEC,sBAAsB,QAAQ,oBAAiB;AAC1E,SAASC,oBAAoB,QAAQ,oBAAiB;AACtD,SAASC,eAAe,EAAEC,eAAe,QAAQ,yBAAsB;AACvE,SAASC,YAAY,QAAQ,oBAAiB;AAC9C,SAASC,YAAY,QAAQ,oBAAiB;AAe9C,SAASC,YAAY,QAAgC,yBAAsB;;AAE3E;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,SAASA,CACxBC,MAAiB,EACjBC,OAAyB,GAAG,CAAC,CAAC,EAC9BC,aAA8B,GAAGC,eAAe,EAClC;EACd;EACA;EACA,MAAMC,OAAO,GAAGd,qBAAqB,CAACU,MAAM,EAAEC,OAAO,EAAEC,aAAa,CAAC;EACrE,MAAM;IAAEG,KAAK;IAAEC,MAAM;IAAEC,QAAQ;IAAEC;EAAO,CAAC,GAAGJ,OAAO;EAEnD,MAAMK,IAAI,GAAGhB,oBAAoB,CAACW,OAAO,CAAC;EAC1C,MAAMM,MAAM,GAAGd,YAAY,CAACQ,OAAO,CAAC;EACpC,MAAMO,MAAM,GAAGd,YAAY,CAACO,OAAO,CAAC;EAEpC,MAAMQ,QAAqB,GAAG;IAC7BC,UAAU,EAAEC,OAAO,IAAIL,IAAI,CAACI,UAAU,CAACC,OAAO,CAAC;IAC/CC,aAAa,EAAED,OAAO,IAAIL,IAAI,CAACM,aAAa,CAACD,OAAO,CAAC;IACrDE,UAAU,EAAEC,OAAO,IAAIR,IAAI,CAACS,aAAa,CAACD,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;IAC3EC,aAAa,EAAEC,IAAI,IAAIV,IAAI,CAACS,aAAa,CAACC,IAAI,CAAC;IAC/CC,YAAY,EAAEC,MAAM,IAAIV,MAAM,CAACS,YAAY,CAACC,MAAM,CAAC;IACnDC,OAAO,EAAEjC,gBAAgB,CAACe,OAAO,EAAE,MAAMK,IAAI,CAACc,sBAAsB,CAAC,CAAC,CAAC;IAEvEC,SAAS,EAAEA,CAAA,KAAMnB,KAAK,CAACI,IAAI,CAACgB,MAAM;IAClCC,eAAe,EAAEC,QAAQ,IAAIvB,OAAO,CAACwB,eAAe,CAACC,GAAG,CAACF,QAAQ,CAAC;IAElEG,IAAI,EAAEC,YAAY,IAAIrB,MAAM,CAACoB,IAAI,CAACC,YAAY,CAAC;IAC/CC,IAAI,EAAED,YAAY,IAAIpB,MAAM,CAACqB,IAAI,CAACD,YAAY,CAAC;IAE/CE,iBAAiBA,CAACF,YAAY,EAAE;MAC/B,IAAI,CAACxB,QAAQ,CAAC2B,UAAU,CAACC,GAAG,CAACJ,YAAY,CAAC,EAAE;QAC3C,OAAO,aAAa;MACrB;MACA,IAAI,CAACzB,MAAM,CAAC8B,WAAW,CAAC,CAAC,IAAI/B,KAAK,CAACgC,UAAU,KAAK,UAAU,EAAE;QAC7D,OAAO,aAAa;MACrB;MACA;MACA;MACA,IAAIhC,KAAK,CAACgC,UAAU,KAAK,WAAW,EAAE;QACrC,OAAO,WAAW;MACnB;MACA,OAAOjC,OAAO,CAAC8B,UAAU,CAACI,GAAG,CAACP,YAAY,CAAC,EAAEQ,QAAQ,CAAClC,KAAK,IAAI,MAAM;IACtE,CAAC;IAEDmC,kBAAkBA,CAACC,GAAG,EAAEd,QAAQ,EAAE;MACjC,OAAOvB,OAAO,CAAC8B,UAAU,CAACI,GAAG,CAACG,GAAG,CAAC,EAAEC,SAAS,CAACb,GAAG,CAACF,QAAQ,CAAC,KAAK,MAAMgB,SAAS,CAAC;IACjF,CAAC;IAEDC,eAAe,EAAEjB,QAAQ,IAAInB,MAAM,CAACqC,SAAS,CAAClB,QAAQ,CAAC;IAEvD;IACAmB,wBAAwB,EAAEA,CAAA,KAAMvC,QAAQ,CAACwC,OAAO,CAACC,eAAe;IAChE;IACAC,sBAAsB,EAAEA,CAAA,KAAM1C,QAAQ,CAAC2C,mBAAmB;IAE1DC,OAAOA,CAAA,EAAG;MACT;MACA,IAAI9C,KAAK,CAAC+C,QAAQ,EAAE;QACnB;MACD;MACA/C,KAAK,CAAC+C,QAAQ,GAAG,IAAI;MACrB7D,gBAAgB,CAACa,OAAO,CAAC;MACzBZ,sBAAsB,CAACY,OAAO,CAAC;MAC/B,KAAK,MAAM,CAACqC,GAAG,EAAEY,OAAO,CAAC,IAAIjD,OAAO,CAAC8B,UAAU,EAAE;QAChD,MAAMoB,KAAK,GAAGD,OAAO,CAACE,SAAS;QAC/BnD,OAAO,CAACoD,yBAAyB,CAACf,GAAG,CAAC;QACtCY,OAAO,CAACX,SAAS,CAACe,KAAK,CAAC,CAAC;QACzB;QACA;QACA;QACAH,KAAK,GAAG;UAAE7B,MAAM,EAAE,aAAa;UAAEiC,MAAM,EAAE;QAAmB,CAAC,CAAC;MAC/D;MACAtD,OAAO,CAACuD,MAAM,CAACC,QAAQ,CAAC,CAAC;MACzBxD,OAAO,CAACyD,eAAe,CAACJ,KAAK,CAAC,CAAC;MAC/BrD,OAAO,CAAC0D,IAAI,CAACC,KAAK,CAAC,CAAC;MACpB3D,OAAO,CAAC4D,QAAQ,CAACD,KAAK,CAAC,CAAC;MACxB3D,OAAO,CAACwB,eAAe,CAAC6B,KAAK,CAAC,CAAC;MAC/BrD,OAAO,CAAC6D,gBAAgB,CAACR,KAAK,CAAC,CAAC;MAChCjD,MAAM,CAAC2C,OAAO,CAAC,CAAC;MAChB9C,KAAK,CAAC6D,YAAY,GAAG,IAAI;IAC1B;EACD,CAAC;EAEDxE,eAAe,CAACkB,QAAQ,EAAEjB,eAAe,CAACS,OAAO,CAAC,CAAC;EACnD,OAAOQ,QAAQ;AAChB;AAEA,SAAST,eAAeA,CAAA,EAAc;EACrC,MAAM,IAAIgE,KAAK,CACd,0GACD,CAAC;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Consent orchestration and normalization (FR-101 – FR-110).
|
|
5
|
+
*
|
|
6
|
+
* This closes the most serious gap in 0.1.0. The package *consumed* a consent
|
|
7
|
+
* decision but nothing *produced* one, and the flow that produces it lives
|
|
8
|
+
* inside the very provider library the package promised an app would never have
|
|
9
|
+
* to import. So any app shipping to a consent-required region had to import the
|
|
10
|
+
* provider directly — breaking the package's central promise at exactly the
|
|
11
|
+
* point where it mattered most — and hand-write the same order-sensitive
|
|
12
|
+
* orchestration every other such app was also writing.
|
|
13
|
+
*
|
|
14
|
+
* What this module does **not** do is as load-bearing as what it does:
|
|
15
|
+
*
|
|
16
|
+
* - It renders no consent UI. The form is the provider's (FR-103).
|
|
17
|
+
* - It decides nothing about jurisdictions. Which regions require consent is
|
|
18
|
+
* the provider's answer and the publisher's console configuration; the
|
|
19
|
+
* package forwards it (FR-107).
|
|
20
|
+
* - It never infers consent. An error, a cancellation, a dismissed form, a
|
|
21
|
+
* network failure — all of them land on `error`, and `error` never carries
|
|
22
|
+
* permission (FR-106). This is the invariant the whole module exists to
|
|
23
|
+
* protect, because the failure it prevents is invisible: a request that
|
|
24
|
+
* should not have happened looks exactly like one that should.
|
|
25
|
+
*
|
|
26
|
+
* Pure apart from the port calls it awaits. No React, no provider type crossing
|
|
27
|
+
* outward.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { AdsError } from "../diagnostics/errors.js";
|
|
31
|
+
export const INITIAL_CONSENT = {
|
|
32
|
+
state: 'undetermined',
|
|
33
|
+
canRequestAds: false,
|
|
34
|
+
isFormAvailable: false,
|
|
35
|
+
privacyOptionsRequirement: 'unknown',
|
|
36
|
+
error: null
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Maps the engine's status onto the published one.
|
|
41
|
+
*
|
|
42
|
+
* `canRequestAds` is taken from the provider rather than derived from the
|
|
43
|
+
* status. The two are not the same question — a region can be `not_required`
|
|
44
|
+
* while the provider still withholds permission — and inventing the second
|
|
45
|
+
* answer from the first is how a package ends up requesting ads it should not.
|
|
46
|
+
*/
|
|
47
|
+
export function normalizeConsent(info) {
|
|
48
|
+
const state = info.status === 'obtained' ? 'obtained' : info.status === 'required' ? 'required' : info.status === 'not_required' ? 'not_required' : 'undetermined';
|
|
49
|
+
return {
|
|
50
|
+
state,
|
|
51
|
+
canRequestAds: info.canRequestAds === true,
|
|
52
|
+
isFormAvailable: info.isFormAvailable === true,
|
|
53
|
+
privacyOptionsRequirement: info.privacyOptions,
|
|
54
|
+
error: null
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The snapshot for a failed flow.
|
|
60
|
+
*
|
|
61
|
+
* `canRequestAds` is hard-coded false rather than carried through from anywhere.
|
|
62
|
+
* There is no failure mode in which "the flow broke" should mean "go ahead", and
|
|
63
|
+
* making that structural rather than conditional means no future edit can
|
|
64
|
+
* accidentally reintroduce the inference.
|
|
65
|
+
*
|
|
66
|
+
* The privacy-options requirement is `unknown` for the same reason: a broken
|
|
67
|
+
* flow has no provider verdict to forward, and reporting `not_required` would be
|
|
68
|
+
* the package deciding the user has no right to change their mind (FR-150).
|
|
69
|
+
*/
|
|
70
|
+
export function consentFailure(error) {
|
|
71
|
+
return {
|
|
72
|
+
state: 'error',
|
|
73
|
+
canRequestAds: false,
|
|
74
|
+
isFormAvailable: false,
|
|
75
|
+
privacyOptionsRequirement: 'unknown',
|
|
76
|
+
error
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function toConsentError(cause, message) {
|
|
80
|
+
return new AdsError('consent_flow_failed', {
|
|
81
|
+
message,
|
|
82
|
+
operation: 'configure',
|
|
83
|
+
cause
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Projects a snapshot onto the consent gate's second input.
|
|
89
|
+
*
|
|
90
|
+
* Only `obtained` and `not_required` open it. `undetermined` and `required` are
|
|
91
|
+
* both "we do not have permission yet" and are reported as
|
|
92
|
+
* `consent_flow_required`; `error` gets its own reason so an app can tell a
|
|
93
|
+
* user who has not answered from a flow that broke.
|
|
94
|
+
*/
|
|
95
|
+
export function toGateInput(snapshot) {
|
|
96
|
+
if (snapshot.canRequestAds && (snapshot.state === 'obtained' || snapshot.state === 'not_required')) {
|
|
97
|
+
return {
|
|
98
|
+
permitted: true
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
permitted: false,
|
|
103
|
+
reason: snapshot.state === 'error' ? 'consent_flow_error' : 'consent_flow_required'
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Builds the options for a consent information update.
|
|
109
|
+
*
|
|
110
|
+
* `testing` has already been stripped by config validation when the environment
|
|
111
|
+
* is production, so this function does not re-check. That is deliberate: the
|
|
112
|
+
* guarantee lives at one point rather than being re-asserted at each call site,
|
|
113
|
+
* which is the same reason the ad-unit substitution guarantee is provable
|
|
114
|
+
* (FR-113).
|
|
115
|
+
*/
|
|
116
|
+
export function buildConsentOptions(testing, underAgeOfConsent, testDeviceIds) {
|
|
117
|
+
return {
|
|
118
|
+
debugGeography: testing?.debugGeography,
|
|
119
|
+
underAgeOfConsent,
|
|
120
|
+
testDeviceIds
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* One consent operation, with the never-infer rule applied to every exit.
|
|
126
|
+
*
|
|
127
|
+
* Every path out of here is either a normalized snapshot or a normalized error
|
|
128
|
+
* snapshot. Nothing throws, because a consent failure must not be able to block
|
|
129
|
+
* app startup or crash the host (FR-108).
|
|
130
|
+
*/
|
|
131
|
+
export async function runConsentStep(step, failureMessage) {
|
|
132
|
+
try {
|
|
133
|
+
return normalizeConsent(await step());
|
|
134
|
+
} catch (cause) {
|
|
135
|
+
return consentFailure(toConsentError(cause, failureMessage));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Whether a form should be presented, per the provider's own report. */
|
|
140
|
+
export function needsForm(snapshot) {
|
|
141
|
+
return snapshot.isFormAvailable && (snapshot.state === 'required' || snapshot.state === 'undetermined');
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=consentFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["AdsError","INITIAL_CONSENT","state","canRequestAds","isFormAvailable","privacyOptionsRequirement","error","normalizeConsent","info","status","privacyOptions","consentFailure","toConsentError","cause","message","operation","toGateInput","snapshot","permitted","reason","buildConsentOptions","testing","underAgeOfConsent","testDeviceIds","debugGeography","runConsentStep","step","failureMessage","needsForm"],"sourceRoot":"../../../src","sources":["core/consentFlow.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Three-state enablement and the typed result of changing it (FR-114 – FR-125).
|
|
5
|
+
*
|
|
6
|
+
* 0.1.0 had a boolean, which forced an app selling an ad-removal tier to lie at
|
|
7
|
+
* startup. It does not yet know whether this user has paid — that answer arrives
|
|
8
|
+
* after a store sync — and both available answers are wrong: `true` flashes ads
|
|
9
|
+
* at someone who paid to never see them, `false` delays ads for everyone else
|
|
10
|
+
* and then runs into the silent re-enable trap below. The missing third state
|
|
11
|
+
* was a hole in the contract, not an omission in the app.
|
|
12
|
+
*
|
|
13
|
+
* The package still knows nothing about payments, entitlements, or why the app
|
|
14
|
+
* decided anything (FR-120). It only stops insisting the decision already exists
|
|
15
|
+
* at construction time.
|
|
16
|
+
*
|
|
17
|
+
* Pure — no provider, no React, no I/O.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Normalizes the configured value. `true`/`false` keep their exact 0.1.0
|
|
22
|
+
* meaning, which is what makes the widened config type additive (BC-003).
|
|
23
|
+
*/
|
|
24
|
+
export function toEnablement(value) {
|
|
25
|
+
if (value === 'undecided') {
|
|
26
|
+
return 'undecided';
|
|
27
|
+
}
|
|
28
|
+
return value ? 'enabled' : 'disabled';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Neither `disabled` nor `undecided` may reach the provider (FR-115). */
|
|
32
|
+
export function permitsRequests(enablement) {
|
|
33
|
+
return enablement === 'enabled';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The outcome of an enablement change.
|
|
38
|
+
*
|
|
39
|
+
* 0.1.0 returned `void`, which is the defect FR-122 supersedes. Re-enabling
|
|
40
|
+
* after a disable sent the init status back to `not_started`, so the app *had*
|
|
41
|
+
* to call `initialize()` again or every later load and show was refused — and
|
|
42
|
+
* nothing said so. Not the result, not the status, not the documentation. An app
|
|
43
|
+
* whose user's subscription lapsed would turn ads back on and silently show
|
|
44
|
+
* none.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Whether re-enabling can resume, given what the instance was doing when it was
|
|
49
|
+
* turned off.
|
|
50
|
+
*
|
|
51
|
+
* Only `ready` resumes. Everything else — never started, still initializing,
|
|
52
|
+
* blocked, failed — has no completed initialization to return to, so claiming a
|
|
53
|
+
* resume would put the instance in a state it never actually reached.
|
|
54
|
+
*/
|
|
55
|
+
export function canResume(resumeTo) {
|
|
56
|
+
return resumeTo === 'ready';
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=enablement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["toEnablement","value","permitsRequests","enablement","canResume","resumeTo"],"sourceRoot":"../../../src","sources":["core/enablement.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACA;AACA,OAAO,SAASA,YAAYA,CAACC,KAA4B,EAAc;EACtE,IAAIA,KAAK,KAAK,WAAW,EAAE;IAC1B,OAAO,WAAW;EACnB;EACA,OAAOA,KAAK,GAAG,SAAS,GAAG,UAAU;AACtC;;AAEA;AACA,OAAO,SAASC,eAAeA,CAACC,UAAsB,EAAW;EAChE,OAAOA,UAAU,KAAK,SAAS;AAChC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAqBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,SAASA,CAACC,QAA2B,EAAuB;EAC3E,OAAOA,QAAQ,KAAK,OAAO;AAC5B","ignoreList":[]}
|