adwhale-sdk-react-native 2.7.200 → 2.7.201

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/README.md CHANGED
@@ -43,7 +43,7 @@ npm install adwhale-sdk-react-native
43
43
  운영 안정성을 중시하는 경우
44
44
  ```json
45
45
  {
46
- "adwhale-sdk-react-native": "~2.7.200"
46
+ "adwhale-sdk-react-native": "~2.7.201"
47
47
  }
48
48
  ```
49
49
  - Android SDK 2.7.2 기반 유지
@@ -52,7 +52,7 @@ npm install adwhale-sdk-react-native
52
52
  ### 동일한 Android SDK 기반의 최신 RN 수정만 사용
53
53
  ```json
54
54
  {
55
- "adwhale-sdk-react-native": "^2.7.200"
55
+ "adwhale-sdk-react-native": "^2.7.201"
56
56
  }
57
57
  ```
58
58
  - Android SDK 2.7.x 범위 내 최신 RN 수정 자동 반영
@@ -62,7 +62,7 @@ npm install adwhale-sdk-react-native
62
62
  ### 특정 버전을 완전히 고정하여 사용하는 경우
63
63
  ```json
64
64
  {
65
- "adwhale-sdk-react-native": "2.7.200"
65
+ "adwhale-sdk-react-native": "2.7.201"
66
66
  }
67
67
  ```
68
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adwhale-sdk-react-native",
3
- "version": "2.7.200",
3
+ "version": "2.7.201",
4
4
  "description": "Adwhale SDK React Native library for integrating Adwhale advertising mediation SDK into React Native applications.",
5
5
  "main": "./lib/module/index.js",
6
6
  "react-native": "./lib/module/index.js",
@@ -12,6 +12,8 @@
12
12
  "source": "./src/index.ts",
13
13
  "default": "./lib/module/index.js"
14
14
  },
15
+ "./app.plugin.js": "./app.plugin.js",
16
+ "./plugin": "./plugin/index.js",
15
17
  "./package.json": "./package.json"
16
18
  },
17
19
  "files": [
package/plugin/index.js CHANGED
@@ -1,8 +1,43 @@
1
- // plugin/index.js
2
- const { createRunOncePlugin, withAndroidBuildGradle } = require('@expo/config-plugins');
1
+ /**
2
+ * AdWhale Expo Config Plugin
3
+ *
4
+ * 목적:
5
+ * - Expo Bare / Managed / prebuild / EAS Dev Client 환경에서
6
+ * AdWhale Android SDK 의존성을 정상적으로 resolve 하기 위해
7
+ * Maven Repository들을 자동으로 Gradle 설정에 추가한다.
8
+ *
9
+ * 전략:
10
+ * 1) android/settings.gradle
11
+ * - dependencyResolutionManagement { repositories { ... } } 에 repo 추가
12
+ * - rootProject.name 바로 다음 줄에 삽입 (가독성 + 충돌 최소화)
13
+ *
14
+ * 2) android/build.gradle (project-level)
15
+ * - allprojects { repositories { ... } } 에 repo 추가
16
+ *
17
+ * 3) 단, settings.gradle에
18
+ * repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
19
+ * 가 존재하는 경우:
20
+ * - project-level repo 사용이 금지되므로
21
+ * - build.gradle 수정은 생략
22
+ *
23
+ * 결과:
24
+ * - AGP 7/8
25
+ * - Expo SDK 49+
26
+ * - Version Catalog / 강한 repo 정책
27
+ * 모두에서 안전하게 동작
28
+ */
29
+
30
+ const {
31
+ createRunOncePlugin,
32
+ withAndroidProjectBuildGradle,
33
+ withSettingsGradle,
34
+ } = require('expo/config-plugins');
35
+
3
36
  const pkg = require('../package.json');
4
37
 
5
- // Maven repository URLs to add
38
+ /**
39
+ * 추가할 Maven Repository 목록
40
+ */
6
41
  const MAVEN_REPOSITORIES = [
7
42
  {
8
43
  comment: 'AdWhale SDK Repository Public Access Info',
@@ -23,125 +58,243 @@ const MAVEN_REPOSITORIES = [
23
58
  ];
24
59
 
25
60
  /**
26
- * Generate maven repositories block content
61
+ * 중복 삽입 방지를 위한 마커
27
62
  */
28
- function generateMavenRepositories(indent = ' ') {
29
- return MAVEN_REPOSITORIES.map(
30
- (repo) => `${indent}// ${repo.comment}\n${indent}maven { url "${repo.url}" }`
63
+ const MARKER_BEGIN = '// [AdWhale] BEGIN Maven Repositories';
64
+ const MARKER_END = '// [AdWhale] END Maven Repositories';
65
+
66
+ /**
67
+ * repo 블록 문자열 생성
68
+ */
69
+ function generateReposBlock(indent = ' ') {
70
+ const body = MAVEN_REPOSITORIES.map(
71
+ (repo) =>
72
+ `${indent}// ${repo.comment}\n` +
73
+ `${indent}maven { url "${repo.url}" }`
31
74
  ).join('\n\n');
75
+
76
+ return `${indent}${MARKER_BEGIN}\n\n${body}\n\n${indent}${MARKER_END}`;
32
77
  }
33
78
 
34
79
  /**
35
- * Add maven repositories to Android build.gradle
36
- * This modifies the allprojects { repositories { ... } } block
80
+ * repositories { } 안에
81
+ * google(), mavenCentral() 없으면 보장해준다
37
82
  */
38
- const withAdwhaleMavenRepositories = (config) => {
39
- return withAndroidBuildGradle(config, (config) => {
40
- let buildGradle = config.modResults.contents;
83
+ function ensureGoogleAndMavenCentral(reposBlock, indent = ' ') {
84
+ if (!/google\(\)/.test(reposBlock)) {
85
+ reposBlock = reposBlock.replace(
86
+ /repositories\s*\{\s*/m,
87
+ (m) => `${m}\n${indent}google()`
88
+ );
89
+ }
41
90
 
42
- // Check if allprojects block exists
43
- if (!buildGradle.includes('allprojects')) {
44
- // If allprojects doesn't exist, add it at the end
45
- const repositoriesBlock = `
91
+ if (!/mavenCentral\(\)/.test(reposBlock)) {
92
+ if (/google\(\)/.test(reposBlock)) {
93
+ reposBlock = reposBlock.replace(
94
+ /(google\(\))/m,
95
+ `$1\n${indent}mavenCentral()`
96
+ );
97
+ } else {
98
+ reposBlock = reposBlock.replace(
99
+ /repositories\s*\{\s*/m,
100
+ (m) => `${m}\n${indent}mavenCentral()`
101
+ );
102
+ }
103
+ }
46
104
 
47
- allprojects {
48
- repositories {
49
- google()
50
- mavenCentral()
105
+ return reposBlock;
106
+ }
51
107
 
52
- ${generateMavenRepositories()}
53
- }
54
- }`;
55
- config.modResults.contents = buildGradle + repositoriesBlock;
56
- return config;
57
- }
108
+ /**
109
+ * settings.gradle 에서
110
+ * repositoriesMode = FAIL_ON_PROJECT_REPOS 가 있는지 검사
111
+ *
112
+ * 이 설정이 있으면 project-level(build.gradle) repo 사용이 금지됨
113
+ */
114
+ function hasFailOnProjectRepos(contents) {
115
+ return /repositoriesMode\.set\s*\(\s*RepositoriesMode\.FAIL_ON_PROJECT_REPOS\s*\)/
116
+ .test(contents);
117
+ }
118
+
119
+ /**
120
+ * android/settings.gradle 패치
121
+ *
122
+ * - dependencyResolutionManagement 가 없으면 새로 생성
123
+ * - 있으면 내부 repositories { } 에 repo 추가
124
+ * - rootProject.name 바로 다음 줄에 삽입
125
+ */
126
+ function patchSettingsGradle(contents) {
127
+ const failOnProjectRepos = hasFailOnProjectRepos(contents);
58
128
 
59
- // allprojects exists, check if repositories block exists inside it
60
- const allprojectsRepositoriesRegex = /allprojects\s*\{[\s\S]*?repositories\s*\{/;
61
-
62
- if (!allprojectsRepositoriesRegex.test(buildGradle)) {
63
- // allprojects exists but no repositories block, add it
64
- const repositoriesBlock = ` repositories {
65
- google()
66
- mavenCentral()
129
+ // 이미 우리가 삽입한 흔적이 있으면 그대로 유지
130
+ if (contents.includes(MARKER_BEGIN)) {
131
+ return { contents, failOnProjectRepos };
132
+ }
67
133
 
68
- ${generateMavenRepositories(' ')}
134
+ // dependencyResolutionManagement 가 아예 없는 경우
135
+ if (!/dependencyResolutionManagement\s*\{/.test(contents)) {
136
+ const drmBlock =
137
+ `\n\ndependencyResolutionManagement {\n` +
138
+ ` repositories {\n` +
139
+ ` google()\n` +
140
+ ` mavenCentral()\n\n` +
141
+ `${generateReposBlock(' ')}\n` +
142
+ ` }\n` +
143
+ `}\n`;
69
144
 
70
- }`;
145
+ // rootProject.name 바로 뒤에 삽입
146
+ const rootNameRegex =
147
+ /(^\s*rootProject\.name\s*=\s*['"][^'"]+['"]\s*$)/m;
71
148
 
72
- // Insert repositories block after allprojects {
73
- buildGradle = buildGradle.replace(
74
- /(allprojects\s*\{)/,
75
- `$1\n${repositoriesBlock}`
76
- );
77
- config.modResults.contents = buildGradle;
78
- return config;
149
+ const match = contents.match(rootNameRegex);
150
+ if (match) {
151
+ const insertAt = match.index + match[0].length;
152
+ contents =
153
+ contents.slice(0, insertAt) +
154
+ drmBlock +
155
+ contents.slice(insertAt);
156
+ } else {
157
+ contents += drmBlock;
79
158
  }
80
159
 
81
- // allprojects { repositories { ... } } exists, add missing repositories
82
- // Ensure google() exists in allprojects.repositories
83
- const googleInAllprojectsRegex = /allprojects\s*\{[\s\S]*?repositories\s*\{[\s\S]*?google\(\)/;
84
- if (!googleInAllprojectsRegex.test(buildGradle)) {
85
- buildGradle = buildGradle.replace(
86
- /(allprojects\s*\{[\s\S]*?repositories\s*\{)/,
87
- '$1\n google()'
88
- );
89
- }
160
+ return { contents, failOnProjectRepos };
161
+ }
90
162
 
91
- // Ensure mavenCentral() exists in allprojects.repositories
92
- const mavenCentralInAllprojectsRegex = /allprojects\s*\{[\s\S]*?repositories\s*\{[\s\S]*?mavenCentral\(\)/;
93
- if (!mavenCentralInAllprojectsRegex.test(buildGradle)) {
94
- if (googleInAllprojectsRegex.test(buildGradle)) {
95
- buildGradle = buildGradle.replace(
96
- /(allprojects\s*\{[\s\S]*?repositories\s*\{[\s\S]*?google\(\))/,
97
- '$1\n mavenCentral()'
98
- );
99
- } else {
100
- buildGradle = buildGradle.replace(
101
- /(allprojects\s*\{[\s\S]*?repositories\s*\{)/,
102
- '$1\n mavenCentral()'
103
- );
104
- }
105
- }
163
+ // dependencyResolutionManagement 있으나 repositories 가 없는 경우
164
+ if (
165
+ !/dependencyResolutionManagement\s*\{[\s\S]*?repositories\s*\{/
166
+ .test(contents)
167
+ ) {
168
+ contents = contents.replace(
169
+ /(dependencyResolutionManagement\s*\{)/,
170
+ `$1\n repositories {\n google()\n mavenCentral()\n\n${generateReposBlock(
171
+ ' '
172
+ )}\n }\n`
173
+ );
106
174
 
107
- // Add each maven repository if it doesn't exist
108
- MAVEN_REPOSITORIES.forEach((repo) => {
109
- const urlEscaped = repo.url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
110
- const urlInAllprojectsRegex = new RegExp(
111
- `allprojects\\s*\\{[\\s\\S]*?repositories\\s*\\{[\\s\\S]*?${urlEscaped}`
112
- );
113
-
114
- if (!urlInAllprojectsRegex.test(buildGradle)) {
115
- // Add after mavenCentral() if it exists in allprojects.repositories
116
- if (mavenCentralInAllprojectsRegex.test(buildGradle)) {
117
- buildGradle = buildGradle.replace(
118
- /(allprojects\s*\{[\s\S]*?repositories\s*\{[\s\S]*?mavenCentral\(\))/,
119
- `$1\n\n // ${repo.comment}\n maven { url "${repo.url}" }`
120
- );
121
- } else {
122
- // Add after repositories {
123
- buildGradle = buildGradle.replace(
124
- /(allprojects\s*\{[\s\S]*?repositories\s*\{)/,
125
- `$1\n // ${repo.comment}\n maven { url "${repo.url}" }`
126
- );
127
- }
128
- }
129
- });
175
+ return { contents, failOnProjectRepos };
176
+ }
130
177
 
131
- config.modResults.contents = buildGradle;
132
- return config;
178
+ // repositories 블록 내부에 repo 추가
179
+ const startMatch =
180
+ contents.match(/dependencyResolutionManagement\s*\{[\s\S]*?repositories\s*\{/);
181
+
182
+ if (!startMatch) {
183
+ return { contents, failOnProjectRepos };
184
+ }
185
+
186
+ const startIdx = contents.indexOf(startMatch[0]) + startMatch[0].length;
187
+
188
+ // brace 스캔으로 repositories { } 범위 찾기
189
+ let i = startIdx - 1;
190
+ let brace = 1;
191
+ while (i < contents.length && brace > 0) {
192
+ i++;
193
+ if (contents[i] === '{') brace++;
194
+ else if (contents[i] === '}') brace--;
195
+ }
196
+
197
+ const reposBlockStart = contents.lastIndexOf('repositories', startIdx);
198
+ let reposBlock = contents.slice(reposBlockStart, i + 1);
199
+
200
+ reposBlock = ensureGoogleAndMavenCentral(reposBlock, ' ');
201
+
202
+ const missing = MAVEN_REPOSITORIES.filter(
203
+ (r) => !reposBlock.includes(r.url)
204
+ );
205
+
206
+ if (missing.length === 0) {
207
+ return { contents, failOnProjectRepos };
208
+ }
209
+
210
+ const block =
211
+ ` ${MARKER_BEGIN}\n\n` +
212
+ missing
213
+ .map(
214
+ (r) =>
215
+ ` // ${r.comment}\n maven { url "${r.url}" }`
216
+ )
217
+ .join('\n\n') +
218
+ `\n\n ${MARKER_END}`;
219
+
220
+ reposBlock = reposBlock.replace(
221
+ /(mavenCentral\(\)\s*)/,
222
+ `$1\n\n${block}\n`
223
+ );
224
+
225
+ contents =
226
+ contents.slice(0, reposBlockStart) +
227
+ reposBlock +
228
+ contents.slice(i + 1);
229
+
230
+ return { contents, failOnProjectRepos };
231
+ }
232
+
233
+ /**
234
+ * android/build.gradle (project-level) 패치
235
+ *
236
+ * - allprojects { repositories { ... } } 에 repo 추가
237
+ * - settings.gradle 에 FAIL_ON_PROJECT_REPOS 가 있으면 호출되지 않음
238
+ */
239
+ function patchProjectBuildGradle(contents) {
240
+ if (contents.includes(MARKER_BEGIN)) return contents;
241
+
242
+ if (!/allprojects\s*\{/.test(contents)) {
243
+ return (
244
+ contents +
245
+ `\n\nallprojects {\n` +
246
+ ` repositories {\n` +
247
+ ` google()\n` +
248
+ ` mavenCentral()\n\n` +
249
+ `${generateReposBlock(' ')}\n` +
250
+ ` }\n` +
251
+ `}\n`
252
+ );
253
+ }
254
+
255
+ if (
256
+ !/allprojects\s*\{[\s\S]*?repositories\s*\{/.test(contents)
257
+ ) {
258
+ return contents.replace(
259
+ /(allprojects\s*\{)/,
260
+ `$1\n repositories {\n google()\n mavenCentral()\n\n${generateReposBlock(
261
+ ' '
262
+ )}\n }\n`
263
+ );
264
+ }
265
+
266
+ return contents;
267
+ }
268
+
269
+ /**
270
+ * 실제 적용 플러그인
271
+ */
272
+ const withAdwhaleMavenRepositories = (config) => {
273
+ let failOnProjectRepos = false;
274
+
275
+ // 1) settings.gradle 먼저 처리
276
+ config = withSettingsGradle(config, (c) => {
277
+ const result = patchSettingsGradle(c.modResults.contents);
278
+ c.modResults.contents = result.contents;
279
+ failOnProjectRepos = result.failOnProjectRepos;
280
+ return c;
133
281
  });
134
- };
135
282
 
136
- // Expo config plugin
137
- const withAdwhaleSdkReactNative = (config, props = {}) => {
138
- // Android build.gradle에 maven repositories 추가
139
- config = withAdwhaleMavenRepositories(config);
283
+ // 2) FAIL_ON_PROJECT_REPOS 가 없을 때만 build.gradle 처리
284
+ if (!failOnProjectRepos) {
285
+ config = withAndroidProjectBuildGradle(config, (c) => {
286
+ c.modResults.contents = patchProjectBuildGradle(
287
+ c.modResults.contents
288
+ );
289
+ return c;
290
+ });
291
+ }
292
+
140
293
  return config;
141
294
  };
142
295
 
143
296
  module.exports = createRunOncePlugin(
144
- withAdwhaleSdkReactNative,
297
+ withAdwhaleMavenRepositories,
145
298
  pkg.name,
146
299
  pkg.version
147
300
  );