cocos-rewarded-ads-kit 1.0.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.
Files changed (125) hide show
  1. package/README.md +190 -0
  2. package/ads.config.schema.json +45 -0
  3. package/bin/cocos-rewarded-ads.js +11 -0
  4. package/dist/packages/adapter-android-admob/src/index.d.ts +2 -0
  5. package/dist/packages/adapter-android-admob/src/index.js +13 -0
  6. package/dist/packages/adapter-android-max/src/index.d.ts +2 -0
  7. package/dist/packages/adapter-android-max/src/index.js +13 -0
  8. package/dist/packages/adapter-android-topon/src/index.d.ts +2 -0
  9. package/dist/packages/adapter-android-topon/src/index.js +13 -0
  10. package/dist/packages/adapter-douyin-mini-game/src/index.d.ts +15 -0
  11. package/dist/packages/adapter-douyin-mini-game/src/index.js +134 -0
  12. package/dist/packages/adapter-ios-admob/src/index.d.ts +2 -0
  13. package/dist/packages/adapter-ios-admob/src/index.js +13 -0
  14. package/dist/packages/adapter-ios-max/src/index.d.ts +2 -0
  15. package/dist/packages/adapter-ios-max/src/index.js +13 -0
  16. package/dist/packages/adapter-ios-topon/src/index.d.ts +2 -0
  17. package/dist/packages/adapter-ios-topon/src/index.js +13 -0
  18. package/dist/packages/adapter-wechat-mini-game/src/index.d.ts +15 -0
  19. package/dist/packages/adapter-wechat-mini-game/src/index.js +134 -0
  20. package/dist/packages/build-plugin/src/cli.d.ts +21 -0
  21. package/dist/packages/build-plugin/src/cli.js +60 -0
  22. package/dist/packages/build-plugin/src/context.d.ts +24 -0
  23. package/dist/packages/build-plugin/src/context.js +108 -0
  24. package/dist/packages/build-plugin/src/extension-hook.d.ts +71 -0
  25. package/dist/packages/build-plugin/src/extension-hook.js +62 -0
  26. package/dist/packages/build-plugin/src/generated-entry.d.ts +30 -0
  27. package/dist/packages/build-plugin/src/generated-entry.js +34 -0
  28. package/dist/packages/build-plugin/src/index.d.ts +8 -0
  29. package/dist/packages/build-plugin/src/index.js +8 -0
  30. package/dist/packages/build-plugin/src/materialize.d.ts +13 -0
  31. package/dist/packages/build-plugin/src/materialize.js +29 -0
  32. package/dist/packages/build-plugin/src/native-patcher.d.ts +9 -0
  33. package/dist/packages/build-plugin/src/native-patcher.js +147 -0
  34. package/dist/packages/build-plugin/src/native-provider.d.ts +22 -0
  35. package/dist/packages/build-plugin/src/native-provider.js +267 -0
  36. package/dist/packages/build-plugin/src/platform-select.d.ts +60 -0
  37. package/dist/packages/build-plugin/src/platform-select.js +302 -0
  38. package/dist/packages/build-plugin/templates/cocos-extension/main.ts.template +11 -0
  39. package/dist/packages/build-plugin/templates/cocos-extension/package.json.template.json +16 -0
  40. package/dist/packages/build-plugin/templates/native/android/admob/RewardedAdsAdMobBridge.kt.template +201 -0
  41. package/dist/packages/build-plugin/templates/native/android/max/RewardedAdsMaxBridge.kt.template +213 -0
  42. package/dist/packages/build-plugin/templates/native/android/topon/RewardedAdsTopOnBridge.kt.template +212 -0
  43. package/dist/packages/build-plugin/templates/native/ios/admob/RewardedAdsAdMobBridge.h.template +23 -0
  44. package/dist/packages/build-plugin/templates/native/ios/admob/RewardedAdsAdMobBridge.mm.template +187 -0
  45. package/dist/packages/build-plugin/templates/native/ios/max/RewardedAdsMaxBridge.h.template +23 -0
  46. package/dist/packages/build-plugin/templates/native/ios/max/RewardedAdsMaxBridge.mm.template +199 -0
  47. package/dist/packages/build-plugin/templates/native/ios/topon/RewardedAdsTopOnBridge.h.template +23 -0
  48. package/dist/packages/build-plugin/templates/native/ios/topon/RewardedAdsTopOnBridge.mm.template +200 -0
  49. package/dist/packages/core/src/config.d.ts +8 -0
  50. package/dist/packages/core/src/config.js +86 -0
  51. package/dist/packages/core/src/index.d.ts +3 -0
  52. package/dist/packages/core/src/index.js +3 -0
  53. package/dist/packages/core/src/native-bridge.d.ts +19 -0
  54. package/dist/packages/core/src/native-bridge.js +163 -0
  55. package/dist/packages/core/src/types.d.ts +99 -0
  56. package/dist/packages/core/src/types.js +21 -0
  57. package/dist/packages/runtime/src/RewardedAds.d.ts +20 -0
  58. package/dist/packages/runtime/src/RewardedAds.js +80 -0
  59. package/dist/packages/runtime/src/active-adapter.d.ts +2 -0
  60. package/dist/packages/runtime/src/active-adapter.js +4 -0
  61. package/dist/packages/runtime/src/index.d.ts +2 -0
  62. package/dist/packages/runtime/src/index.js +2 -0
  63. package/dist/packages/runtime/src/registry.d.ts +6 -0
  64. package/dist/packages/runtime/src/registry.js +18 -0
  65. package/docs/getting-started.md +381 -0
  66. package/docs/superpowers/plans/2026-03-29-bootstrap-v1.md +274 -0
  67. package/docs/superpowers/specs/2026-03-29-cocos-rewarded-ads-kit-design.md +462 -0
  68. package/examples/android-admob/ads.config.json +22 -0
  69. package/examples/android-max/ads.config.json +22 -0
  70. package/examples/android-topon/ads.config.json +24 -0
  71. package/examples/cocos-consumer/README.md +34 -0
  72. package/examples/cocos-consumer/src/RewardedAdsService.ts +33 -0
  73. package/examples/douyin-mini-game/ads.config.json +20 -0
  74. package/examples/ios-admob/ads.config.json +22 -0
  75. package/examples/ios-max/ads.config.json +22 -0
  76. package/examples/ios-topon/ads.config.json +24 -0
  77. package/examples/wechat-mini-game/ads.config.json +20 -0
  78. package/package.json +104 -0
  79. package/packages/adapter-android-admob/package.json +7 -0
  80. package/packages/adapter-android-admob/src/index.ts +19 -0
  81. package/packages/adapter-android-max/package.json +7 -0
  82. package/packages/adapter-android-max/src/index.ts +19 -0
  83. package/packages/adapter-android-topon/package.json +7 -0
  84. package/packages/adapter-android-topon/src/index.ts +19 -0
  85. package/packages/adapter-douyin-mini-game/package.json +7 -0
  86. package/packages/adapter-douyin-mini-game/src/index.ts +174 -0
  87. package/packages/adapter-ios-admob/package.json +7 -0
  88. package/packages/adapter-ios-admob/src/index.ts +19 -0
  89. package/packages/adapter-ios-max/package.json +7 -0
  90. package/packages/adapter-ios-max/src/index.ts +19 -0
  91. package/packages/adapter-ios-topon/package.json +7 -0
  92. package/packages/adapter-ios-topon/src/index.ts +19 -0
  93. package/packages/adapter-wechat-mini-game/package.json +7 -0
  94. package/packages/adapter-wechat-mini-game/src/index.ts +174 -0
  95. package/packages/build-plugin/package.json +10 -0
  96. package/packages/build-plugin/src/cli.ts +76 -0
  97. package/packages/build-plugin/src/context.ts +153 -0
  98. package/packages/build-plugin/src/extension-hook.ts +91 -0
  99. package/packages/build-plugin/src/generated-entry.ts +53 -0
  100. package/packages/build-plugin/src/index.ts +8 -0
  101. package/packages/build-plugin/src/materialize.ts +43 -0
  102. package/packages/build-plugin/src/native-patcher.ts +193 -0
  103. package/packages/build-plugin/src/native-provider.ts +334 -0
  104. package/packages/build-plugin/src/platform-select.ts +383 -0
  105. package/packages/build-plugin/templates/cocos-extension/main.ts.template +11 -0
  106. package/packages/build-plugin/templates/cocos-extension/package.json.template.json +16 -0
  107. package/packages/build-plugin/templates/native/android/admob/RewardedAdsAdMobBridge.kt.template +201 -0
  108. package/packages/build-plugin/templates/native/android/max/RewardedAdsMaxBridge.kt.template +213 -0
  109. package/packages/build-plugin/templates/native/android/topon/RewardedAdsTopOnBridge.kt.template +212 -0
  110. package/packages/build-plugin/templates/native/ios/admob/RewardedAdsAdMobBridge.h.template +23 -0
  111. package/packages/build-plugin/templates/native/ios/admob/RewardedAdsAdMobBridge.mm.template +187 -0
  112. package/packages/build-plugin/templates/native/ios/max/RewardedAdsMaxBridge.h.template +23 -0
  113. package/packages/build-plugin/templates/native/ios/max/RewardedAdsMaxBridge.mm.template +199 -0
  114. package/packages/build-plugin/templates/native/ios/topon/RewardedAdsTopOnBridge.h.template +23 -0
  115. package/packages/build-plugin/templates/native/ios/topon/RewardedAdsTopOnBridge.mm.template +200 -0
  116. package/packages/core/package.json +7 -0
  117. package/packages/core/src/config.ts +106 -0
  118. package/packages/core/src/index.ts +3 -0
  119. package/packages/core/src/native-bridge.ts +232 -0
  120. package/packages/core/src/types.ts +138 -0
  121. package/packages/runtime/package.json +7 -0
  122. package/packages/runtime/src/RewardedAds.ts +107 -0
  123. package/packages/runtime/src/active-adapter.ts +6 -0
  124. package/packages/runtime/src/index.ts +8 -0
  125. package/packages/runtime/src/registry.ts +25 -0
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # Cocos Rewarded Ads Kit
2
+
3
+ 一个独立的、面向多个 Cocos Creator 项目的激励视频广告插件仓库。
4
+
5
+ 推荐先看:
6
+
7
+ - [Quick Start](./docs/getting-started.md)
8
+ - [设计稿](./docs/superpowers/specs/2026-03-29-cocos-rewarded-ads-kit-design.md)
9
+ - [实现计划](./docs/superpowers/plans/2026-03-29-bootstrap-v1.md)
10
+
11
+ ## v1 范围
12
+
13
+ - 只做激励视频
14
+ - 支持按平台按需接入
15
+ - 重点 provider / platform:
16
+ - Android AdMob
17
+ - iOS AdMob
18
+ - Android MAX
19
+ - iOS MAX
20
+ - Android TopOn
21
+ - iOS TopOn
22
+ - 微信小游戏
23
+ - 抖音小游戏
24
+
25
+ ## 当前目录结构
26
+
27
+ ```text
28
+ packages/
29
+ core/
30
+ runtime/
31
+ adapter-wechat-mini-game/
32
+ adapter-douyin-mini-game/
33
+ adapter-android-admob/
34
+ adapter-ios-admob/
35
+ adapter-android-max/
36
+ adapter-ios-max/
37
+ adapter-android-topon/
38
+ adapter-ios-topon/
39
+ build-plugin/
40
+ examples/
41
+ cocos-consumer/
42
+ ```
43
+
44
+ ## 业务侧目标用法
45
+
46
+ ```ts
47
+ import { createPreparedRewardedAdsRuntime } from './build/rewarded-ads/generated/bootstrap-runtime.ts';
48
+
49
+ const rewardedAds = createPreparedRewardedAdsRuntime({
50
+ platform: 'wechat-mini-game',
51
+ });
52
+
53
+ await rewardedAds.init();
54
+ await rewardedAds.preload('reward_revive');
55
+
56
+ const result = await rewardedAds.show('reward_revive');
57
+ if (result.earned) {
58
+ // 发奖励
59
+ }
60
+ ```
61
+
62
+ ## 配置文件
63
+
64
+ 每个接入项目维护一份 `ads.config.json`,按目标平台分别配置:
65
+
66
+ - 微信小游戏 / 抖音小游戏:`adUnitId`
67
+ - AdMob:`appId + adUnitId`
68
+ - MAX:`sdkKey + adUnitId`
69
+ - TopOn:`appId + appKey + adUnitId`
70
+
71
+ ### v1 provider 约束
72
+
73
+ - 同一目标平台只允许一个 rewarded provider
74
+ - 同一平台可以有多个 placement
75
+ - 这些 placement 在 v1 中必须共用同一个 provider
76
+ - 如果同平台混用 MAX / TopOn,build-plugin 会直接校验失败
77
+
78
+ 可参考:
79
+ - [consumer example](./examples/cocos-consumer/README.md)
80
+ - [android-admob example](./examples/android-admob/ads.config.json)
81
+ - [ios-admob example](./examples/ios-admob/ads.config.json)
82
+ - [wechat-mini-game example](./examples/wechat-mini-game/ads.config.json)
83
+ - [douyin-mini-game example](./examples/douyin-mini-game/ads.config.json)
84
+ - [android-max example](./examples/android-max/ads.config.json)
85
+ - [ios-max example](./examples/ios-max/ads.config.json)
86
+ - [android-topon example](./examples/android-topon/ads.config.json)
87
+ - [ios-topon example](./examples/ios-topon/ads.config.json)
88
+
89
+ ## 当前实现进度
90
+
91
+ 已完成:
92
+ - 核心类型与配置归一化
93
+ - 运行时 facade 与 generated binding registry
94
+ - provider 包入口与 runtime 工厂签名对齐
95
+ - 微信小游戏 / 抖音小游戏 adapter
96
+ - Android / iOS AdMob / MAX / TopOn native provider bridge 模板
97
+ - build-plugin 平台选择、prepare CLI、Cocos build extension、bootstrap-runtime 生成
98
+ - Android / iOS 宿主工程自动 patch
99
+ - Cocos 项目消费者示例与接入文档
100
+
101
+ 仓库外仍需人工验收:
102
+ - 使用真实 MAX / TopOn 凭据做一次 Android / iOS 最终构建
103
+ - 在真实广告位上确认 preload / show / earned / cancelled 行为
104
+
105
+ ## npm 安装
106
+
107
+ 推荐在接入项目里直接安装发布包:
108
+
109
+ ```bash
110
+ npm i -D cocos-rewarded-ads-kit@1.0.0
111
+ ```
112
+
113
+ ## 一键 prepare 命令
114
+
115
+ 安装后可直接用 CLI 生成当前平台广告产物:
116
+
117
+ ```bash
118
+ npx cocos-rewarded-ads prepare --config ./ads.config.json --platform wechatgame --output ./build/rewarded-ads
119
+ ```
120
+
121
+ 可选参数:
122
+ - `--extension-name`
123
+
124
+ 当前支持的平台参数:
125
+ - `android`
126
+ - `ios`
127
+ - `wechatgame`
128
+ - `bytedance-mini-game`
129
+
130
+ ## prepare 输出内容
131
+
132
+ 执行 `prepare:ads` 后,当前版本会生成这几类产物:
133
+
134
+ - `generated/`
135
+ - `active-adapter.ts`
136
+ - `generated-rewarded-config.ts`
137
+ - `install-generated-bindings.ts`
138
+ - `bootstrap-runtime.ts`
139
+ - `cocos-extension/`
140
+ - `package.json`
141
+ - `dist/main.js`
142
+ - `dist/builder.js`
143
+ - `dist/hooks.js`
144
+ - `native/`(仅 Android / iOS)
145
+ - provider bridge 模板
146
+ - `RewardedAdsInstaller`
147
+ - provider config JSON
148
+ - 依赖片段
149
+ - AppActivity / AppDelegate 接入 snippet
150
+
151
+ ## 当前 native 输出说明
152
+
153
+ Android / iOS 当前已经能生成:
154
+
155
+ - provider bridge 模板
156
+ - 统一 installer 入口
157
+ - provider 配置文件
158
+ - Gradle / Pod 依赖片段
159
+ - 原生接入 snippet
160
+ - 原生宿主工程 patch plan
161
+
162
+ 并且当前版本已经会在检测到宿主工程文件存在时,自动 patch:
163
+
164
+ - Android
165
+ - `native/engine/android/app/build.gradle`
166
+ - `native/engine/android/app/src/**/AppActivity.java|kt`
167
+ - iOS
168
+ - `native/engine/ios/Podfile.in`
169
+ - `native/engine/ios/CMakeLists.txt`
170
+ - `native/engine/ios/AppDelegate.mm`
171
+
172
+ 这意味着:
173
+
174
+ - 微信小游戏 / 抖音小游戏已经接近可直接接入状态
175
+ - Android / iOS 已经具备“生成 + 自动 patch”的基础闭环
176
+ - provider SDK 的最终真机构建验收仍需要接入项目用真实凭据完成
177
+
178
+ ## 推荐接入姿势
179
+
180
+ 如果你是把这套能力接进一个新的 Cocos 项目,当前最稳的方式是:
181
+
182
+ 1. 在项目根目录维护 `ads.config.json`
183
+ 2. build 前执行 `cocos-rewarded-ads prepare`
184
+ 3. 在业务代码里只引入 `generated/bootstrap-runtime.ts`
185
+ 4. 用 placement 调用统一 runtime
186
+
187
+ 参考:
188
+
189
+ - [Quick Start](./docs/getting-started.md)
190
+ - [Cocos 项目接入示例](./examples/cocos-consumer/README.md)
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "required": ["version", "placements"],
5
+ "properties": {
6
+ "version": {
7
+ "type": "integer",
8
+ "const": 1
9
+ },
10
+ "defaults": {
11
+ "type": "object",
12
+ "properties": {
13
+ "preloadOnInit": {
14
+ "type": "array",
15
+ "items": {
16
+ "type": "string"
17
+ }
18
+ }
19
+ },
20
+ "additionalProperties": false
21
+ },
22
+ "placements": {
23
+ "type": "object",
24
+ "additionalProperties": {
25
+ "type": "object",
26
+ "properties": {
27
+ "android": {
28
+ "type": "object"
29
+ },
30
+ "ios": {
31
+ "type": "object"
32
+ },
33
+ "wechat-mini-game": {
34
+ "type": "object"
35
+ },
36
+ "douyin-mini-game": {
37
+ "type": "object"
38
+ }
39
+ },
40
+ "additionalProperties": true
41
+ }
42
+ }
43
+ },
44
+ "additionalProperties": false
45
+ }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ let main;
4
+
5
+ try {
6
+ ({ main } = await import('../dist/packages/build-plugin/src/cli.js'));
7
+ } catch {
8
+ ({ main } = await import('../packages/build-plugin/src/cli.ts'));
9
+ }
10
+
11
+ await main(process.argv.slice(2));
@@ -0,0 +1,2 @@
1
+ import type { NativeRewardedRuntimeAdapterOptions } from '../../core/src/native-bridge.ts';
2
+ export declare function createAdapter(options: NativeRewardedRuntimeAdapterOptions): import("../../core/src/types.ts").RewardedAdapter;
@@ -0,0 +1,13 @@
1
+ import { createNativeRewardedAdapter, createUnsupportedNativeRewardedAdapter, resolveNativeBridgeWrapper, } from "../../core/src/native-bridge.js";
2
+ export function createAdapter(options) {
3
+ const wrapper = resolveNativeBridgeWrapper(options.wrapper);
4
+ if (!wrapper) {
5
+ return createUnsupportedNativeRewardedAdapter('android jsbBridgeWrapper is unavailable');
6
+ }
7
+ return createNativeRewardedAdapter({
8
+ provider: 'admob',
9
+ wrapper,
10
+ placements: options.config.placements,
11
+ timeoutMs: options.timeoutMs,
12
+ });
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { NativeRewardedRuntimeAdapterOptions } from '../../core/src/native-bridge.ts';
2
+ export declare function createAdapter(options: NativeRewardedRuntimeAdapterOptions): import("../../core/src/types.ts").RewardedAdapter;
@@ -0,0 +1,13 @@
1
+ import { createNativeRewardedAdapter, createUnsupportedNativeRewardedAdapter, resolveNativeBridgeWrapper, } from "../../core/src/native-bridge.js";
2
+ export function createAdapter(options) {
3
+ const wrapper = resolveNativeBridgeWrapper(options.wrapper);
4
+ if (!wrapper) {
5
+ return createUnsupportedNativeRewardedAdapter('android jsbBridgeWrapper is unavailable');
6
+ }
7
+ return createNativeRewardedAdapter({
8
+ provider: 'max',
9
+ wrapper,
10
+ placements: options.config.placements,
11
+ timeoutMs: options.timeoutMs,
12
+ });
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { NativeRewardedRuntimeAdapterOptions } from '../../core/src/native-bridge.ts';
2
+ export declare function createAdapter(options: NativeRewardedRuntimeAdapterOptions): import("../../core/src/types.ts").RewardedAdapter;
@@ -0,0 +1,13 @@
1
+ import { createNativeRewardedAdapter, createUnsupportedNativeRewardedAdapter, resolveNativeBridgeWrapper, } from "../../core/src/native-bridge.js";
2
+ export function createAdapter(options) {
3
+ const wrapper = resolveNativeBridgeWrapper(options.wrapper);
4
+ if (!wrapper) {
5
+ return createUnsupportedNativeRewardedAdapter('android jsbBridgeWrapper is unavailable');
6
+ }
7
+ return createNativeRewardedAdapter({
8
+ provider: 'topon',
9
+ wrapper,
10
+ placements: options.config.placements,
11
+ timeoutMs: options.timeoutMs,
12
+ });
13
+ }
@@ -0,0 +1,15 @@
1
+ import type { DouyinMiniGameApiLike, NormalizedRewardedAdsConfig, NormalizedPlatformPlacementConfig, RewardedAdapter, RewardedAdapterFactory } from '../../core/src/types.ts';
2
+ interface DouyinAdapterOptions {
3
+ ttApi?: DouyinMiniGameApiLike | null;
4
+ placements: Record<string, NormalizedPlatformPlacementConfig>;
5
+ showTimeoutMs?: number;
6
+ }
7
+ export declare function createDouyinMiniGameRewardedAdapter(options: DouyinAdapterOptions): RewardedAdapter;
8
+ export declare const createRuntimeAdapter: RewardedAdapterFactory;
9
+ export declare function createAdapter(options: DouyinAdapterOptions | {
10
+ platform: NormalizedRewardedAdsConfig['platform'];
11
+ config: NormalizedRewardedAdsConfig;
12
+ ttApi?: DouyinMiniGameApiLike | null;
13
+ showTimeoutMs?: number;
14
+ }): RewardedAdapter;
15
+ export {};
@@ -0,0 +1,134 @@
1
+ function createError(code, message, cause) {
2
+ return { code, message, cause };
3
+ }
4
+ function createErrorResult(error) {
5
+ return {
6
+ completed: false,
7
+ cancelled: false,
8
+ earned: false,
9
+ error,
10
+ };
11
+ }
12
+ function toResult(result) {
13
+ if (!result || typeof result.isEnded !== 'boolean') {
14
+ return {
15
+ completed: true,
16
+ cancelled: false,
17
+ earned: true,
18
+ };
19
+ }
20
+ return {
21
+ completed: true,
22
+ cancelled: !result.isEnded,
23
+ earned: !!result.isEnded,
24
+ };
25
+ }
26
+ export function createDouyinMiniGameRewardedAdapter(options) {
27
+ const showTimeoutMs = Math.max(1, options.showTimeoutMs ?? 15000);
28
+ const ads = new Map();
29
+ const states = new Map();
30
+ const getAd = (placement) => {
31
+ const placementConfig = options.placements[placement];
32
+ if (!placementConfig) {
33
+ return { ad: null, error: createError('configInvalid', `${placement} config is unavailable`) };
34
+ }
35
+ if (!options.ttApi) {
36
+ return { ad: null, error: createError('unsupported', `${placement} tt api is unavailable`) };
37
+ }
38
+ const cached = ads.get(placement);
39
+ if (cached) {
40
+ return { ad: cached, error: null };
41
+ }
42
+ const ad = options.ttApi.createRewardedVideoAd({ adUnitId: placementConfig.adUnitId });
43
+ ads.set(placement, ad);
44
+ return { ad, error: null };
45
+ };
46
+ return {
47
+ async init() {
48
+ return undefined;
49
+ },
50
+ async preload(placement) {
51
+ const { ad, error } = getAd(placement);
52
+ if (!ad) {
53
+ states.set(placement, 'unsupported');
54
+ throw error;
55
+ }
56
+ states.set(placement, 'loading');
57
+ if (typeof ad.load === 'function') {
58
+ await ad.load();
59
+ }
60
+ states.set(placement, 'ready');
61
+ },
62
+ async show(placement) {
63
+ const { ad, error } = getAd(placement);
64
+ if (!ad) {
65
+ states.set(placement, 'unsupported');
66
+ return createErrorResult(error);
67
+ }
68
+ states.set(placement, 'showing');
69
+ return await new Promise((resolve) => {
70
+ let settled = false;
71
+ const settle = (result) => {
72
+ if (settled) {
73
+ return;
74
+ }
75
+ settled = true;
76
+ clearTimeout(timer);
77
+ states.set(placement, 'idle');
78
+ if (typeof ad.offClose === 'function') {
79
+ ad.offClose(handleClose);
80
+ }
81
+ if (typeof ad.offError === 'function') {
82
+ ad.offError(handleError);
83
+ }
84
+ resolve(result);
85
+ };
86
+ const handleClose = (result) => settle(toResult(result));
87
+ const handleError = (cause) => settle(createErrorResult(createError('showFailed', `${placement} show failed`, cause)));
88
+ const timer = setTimeout(() => settle(createErrorResult(createError('timeout', `${placement} show timed out`))), showTimeoutMs);
89
+ if (typeof ad.onClose === 'function') {
90
+ ad.onClose(handleClose);
91
+ }
92
+ if (typeof ad.onError === 'function') {
93
+ ad.onError(handleError);
94
+ }
95
+ Promise.resolve(typeof ad.show === 'function' ? ad.show() : undefined)
96
+ .catch((cause) => settle(createErrorResult(createError('showFailed', `${placement} show failed`, cause))));
97
+ });
98
+ },
99
+ isReady(placement) {
100
+ return states.get(placement) === 'ready';
101
+ },
102
+ getState(placement) {
103
+ return states.get(placement) ?? 'idle';
104
+ },
105
+ reset(placement) {
106
+ if (placement) {
107
+ ads.delete(placement);
108
+ states.delete(placement);
109
+ return;
110
+ }
111
+ ads.clear();
112
+ states.clear();
113
+ },
114
+ };
115
+ }
116
+ function resolveDouyinApi(override) {
117
+ if (override) {
118
+ return override;
119
+ }
120
+ return globalThis.tt ?? null;
121
+ }
122
+ export const createRuntimeAdapter = (options) => {
123
+ return createDouyinMiniGameRewardedAdapter({
124
+ ttApi: resolveDouyinApi(options.ttApi),
125
+ placements: options.config.placements,
126
+ showTimeoutMs: options.showTimeoutMs,
127
+ });
128
+ };
129
+ export function createAdapter(options) {
130
+ if ('placements' in options) {
131
+ return createDouyinMiniGameRewardedAdapter(options);
132
+ }
133
+ return createRuntimeAdapter(options);
134
+ }
@@ -0,0 +1,2 @@
1
+ import type { NativeRewardedRuntimeAdapterOptions } from '../../core/src/native-bridge.ts';
2
+ export declare function createAdapter(options: NativeRewardedRuntimeAdapterOptions): import("../../core/src/types.ts").RewardedAdapter;
@@ -0,0 +1,13 @@
1
+ import { createNativeRewardedAdapter, createUnsupportedNativeRewardedAdapter, resolveNativeBridgeWrapper, } from "../../core/src/native-bridge.js";
2
+ export function createAdapter(options) {
3
+ const wrapper = resolveNativeBridgeWrapper(options.wrapper);
4
+ if (!wrapper) {
5
+ return createUnsupportedNativeRewardedAdapter('ios jsbBridgeWrapper is unavailable');
6
+ }
7
+ return createNativeRewardedAdapter({
8
+ provider: 'admob',
9
+ wrapper,
10
+ placements: options.config.placements,
11
+ timeoutMs: options.timeoutMs,
12
+ });
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { NativeRewardedRuntimeAdapterOptions } from '../../core/src/native-bridge.ts';
2
+ export declare function createAdapter(options: NativeRewardedRuntimeAdapterOptions): import("../../core/src/types.ts").RewardedAdapter;
@@ -0,0 +1,13 @@
1
+ import { createNativeRewardedAdapter, createUnsupportedNativeRewardedAdapter, resolveNativeBridgeWrapper, } from "../../core/src/native-bridge.js";
2
+ export function createAdapter(options) {
3
+ const wrapper = resolveNativeBridgeWrapper(options.wrapper);
4
+ if (!wrapper) {
5
+ return createUnsupportedNativeRewardedAdapter('ios jsbBridgeWrapper is unavailable');
6
+ }
7
+ return createNativeRewardedAdapter({
8
+ provider: 'max',
9
+ wrapper,
10
+ placements: options.config.placements,
11
+ timeoutMs: options.timeoutMs,
12
+ });
13
+ }
@@ -0,0 +1,2 @@
1
+ import type { NativeRewardedRuntimeAdapterOptions } from '../../core/src/native-bridge.ts';
2
+ export declare function createAdapter(options: NativeRewardedRuntimeAdapterOptions): import("../../core/src/types.ts").RewardedAdapter;
@@ -0,0 +1,13 @@
1
+ import { createNativeRewardedAdapter, createUnsupportedNativeRewardedAdapter, resolveNativeBridgeWrapper, } from "../../core/src/native-bridge.js";
2
+ export function createAdapter(options) {
3
+ const wrapper = resolveNativeBridgeWrapper(options.wrapper);
4
+ if (!wrapper) {
5
+ return createUnsupportedNativeRewardedAdapter('ios jsbBridgeWrapper is unavailable');
6
+ }
7
+ return createNativeRewardedAdapter({
8
+ provider: 'topon',
9
+ wrapper,
10
+ placements: options.config.placements,
11
+ timeoutMs: options.timeoutMs,
12
+ });
13
+ }
@@ -0,0 +1,15 @@
1
+ import type { NormalizedRewardedAdsConfig, NormalizedPlatformPlacementConfig, RewardedAdapter, RewardedAdapterFactory, WeChatMiniGameApiLike } from '../../core/src/types.ts';
2
+ interface WeChatAdapterOptions {
3
+ wxApi?: WeChatMiniGameApiLike | null;
4
+ placements: Record<string, NormalizedPlatformPlacementConfig>;
5
+ showTimeoutMs?: number;
6
+ }
7
+ export declare function createWeChatMiniGameRewardedAdapter(options: WeChatAdapterOptions): RewardedAdapter;
8
+ export declare const createRuntimeAdapter: RewardedAdapterFactory;
9
+ export declare function createAdapter(options: WeChatAdapterOptions | {
10
+ platform: NormalizedRewardedAdsConfig['platform'];
11
+ config: NormalizedRewardedAdsConfig;
12
+ wxApi?: WeChatMiniGameApiLike | null;
13
+ showTimeoutMs?: number;
14
+ }): RewardedAdapter;
15
+ export {};
@@ -0,0 +1,134 @@
1
+ function createError(code, message, cause) {
2
+ return { code, message, cause };
3
+ }
4
+ function createErrorResult(error) {
5
+ return {
6
+ completed: false,
7
+ cancelled: false,
8
+ earned: false,
9
+ error,
10
+ };
11
+ }
12
+ function toResult(result) {
13
+ if (!result || typeof result.isEnded !== 'boolean') {
14
+ return {
15
+ completed: true,
16
+ cancelled: false,
17
+ earned: true,
18
+ };
19
+ }
20
+ return {
21
+ completed: true,
22
+ cancelled: !result.isEnded,
23
+ earned: !!result.isEnded,
24
+ };
25
+ }
26
+ export function createWeChatMiniGameRewardedAdapter(options) {
27
+ const showTimeoutMs = Math.max(1, options.showTimeoutMs ?? 15000);
28
+ const ads = new Map();
29
+ const states = new Map();
30
+ const getAd = (placement) => {
31
+ const placementConfig = options.placements[placement];
32
+ if (!placementConfig) {
33
+ return { ad: null, error: createError('configInvalid', `${placement} config is unavailable`) };
34
+ }
35
+ if (!options.wxApi) {
36
+ return { ad: null, error: createError('unsupported', `${placement} wx api is unavailable`) };
37
+ }
38
+ const cached = ads.get(placement);
39
+ if (cached) {
40
+ return { ad: cached, error: null };
41
+ }
42
+ const ad = options.wxApi.createRewardedVideoAd({ adUnitId: placementConfig.adUnitId });
43
+ ads.set(placement, ad);
44
+ return { ad, error: null };
45
+ };
46
+ return {
47
+ async init() {
48
+ return undefined;
49
+ },
50
+ async preload(placement) {
51
+ const { ad, error } = getAd(placement);
52
+ if (!ad) {
53
+ states.set(placement, 'unsupported');
54
+ throw error;
55
+ }
56
+ states.set(placement, 'loading');
57
+ if (typeof ad.load === 'function') {
58
+ await ad.load();
59
+ }
60
+ states.set(placement, 'ready');
61
+ },
62
+ async show(placement) {
63
+ const { ad, error } = getAd(placement);
64
+ if (!ad) {
65
+ states.set(placement, 'unsupported');
66
+ return createErrorResult(error);
67
+ }
68
+ states.set(placement, 'showing');
69
+ return await new Promise((resolve) => {
70
+ let settled = false;
71
+ const settle = (result) => {
72
+ if (settled) {
73
+ return;
74
+ }
75
+ settled = true;
76
+ clearTimeout(timer);
77
+ states.set(placement, 'idle');
78
+ if (typeof ad.offClose === 'function') {
79
+ ad.offClose(handleClose);
80
+ }
81
+ if (typeof ad.offError === 'function') {
82
+ ad.offError(handleError);
83
+ }
84
+ resolve(result);
85
+ };
86
+ const handleClose = (result) => settle(toResult(result));
87
+ const handleError = (cause) => settle(createErrorResult(createError('showFailed', `${placement} show failed`, cause)));
88
+ const timer = setTimeout(() => settle(createErrorResult(createError('timeout', `${placement} show timed out`))), showTimeoutMs);
89
+ if (typeof ad.onClose === 'function') {
90
+ ad.onClose(handleClose);
91
+ }
92
+ if (typeof ad.onError === 'function') {
93
+ ad.onError(handleError);
94
+ }
95
+ Promise.resolve(typeof ad.show === 'function' ? ad.show() : undefined)
96
+ .catch((cause) => settle(createErrorResult(createError('showFailed', `${placement} show failed`, cause))));
97
+ });
98
+ },
99
+ isReady(placement) {
100
+ return states.get(placement) === 'ready';
101
+ },
102
+ getState(placement) {
103
+ return states.get(placement) ?? 'idle';
104
+ },
105
+ reset(placement) {
106
+ if (placement) {
107
+ ads.delete(placement);
108
+ states.delete(placement);
109
+ return;
110
+ }
111
+ ads.clear();
112
+ states.clear();
113
+ },
114
+ };
115
+ }
116
+ function resolveWeChatApi(override) {
117
+ if (override) {
118
+ return override;
119
+ }
120
+ return globalThis.wx ?? null;
121
+ }
122
+ export const createRuntimeAdapter = (options) => {
123
+ return createWeChatMiniGameRewardedAdapter({
124
+ wxApi: resolveWeChatApi(options.wxApi),
125
+ placements: options.config.placements,
126
+ showTimeoutMs: options.showTimeoutMs,
127
+ });
128
+ };
129
+ export function createAdapter(options) {
130
+ if ('placements' in options) {
131
+ return createWeChatMiniGameRewardedAdapter(options);
132
+ }
133
+ return createRuntimeAdapter(options);
134
+ }