expo-iap 3.1.1-rc.2 → 3.1.2
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/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +0 -11
- package/build/ExpoIapModule.d.ts +0 -1
- package/build/ExpoIapModule.d.ts.map +1 -1
- package/build/ExpoIapModule.js +4 -29
- package/build/ExpoIapModule.js.map +1 -1
- package/build/useIAP.d.ts +0 -2
- package/build/useIAP.d.ts.map +1 -1
- package/build/useIAP.js +3 -8
- package/build/useIAP.js.map +1 -1
- package/coverage/clover.xml +7 -7
- package/coverage/coverage-final.json +5 -5
- package/coverage/lcov-report/index.html +1 -1
- package/coverage/lcov-report/src/helpers/index.html +1 -1
- package/coverage/lcov-report/src/helpers/subscription.ts.html +1 -1
- package/coverage/lcov-report/src/index.html +1 -1
- package/coverage/lcov-report/src/index.ts.html +1 -1
- package/coverage/lcov-report/src/modules/android.ts.html +1 -1
- package/coverage/lcov-report/src/modules/index.html +1 -1
- package/coverage/lcov-report/src/modules/ios.ts.html +1 -1
- package/coverage/lcov-report/src/utils/errorMapping.ts.html +1 -1
- package/coverage/lcov-report/src/utils/index.html +1 -1
- package/expo-module.config.json +3 -10
- package/jest.config.js +0 -1
- package/openiap-versions.json +1 -1
- package/package.json +3 -4
- package/plugin/build/withIAP.d.ts +9 -22
- package/plugin/build/withIAP.js +9 -157
- package/plugin/jest.config.js +3 -13
- package/plugin/src/expoConfig.augmentation.d.ts +1 -30
- package/plugin/src/withIAP.ts +18 -258
- package/plugin/tsconfig.json +1 -2
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/src/ExpoIapModule.ts +4 -45
- package/src/useIAP.ts +3 -11
- package/build/utils/constants.d.ts +0 -6
- package/build/utils/constants.d.ts.map +0 -1
- package/build/utils/constants.js +0 -19
- package/build/utils/constants.js.map +0 -1
- package/coverage/lcov-report/src/ExpoIap.types.ts.html +0 -1243
- package/coverage/lcov-report/src/PurchaseError.ts.html +0 -787
- package/coverage/lcov-report/src/purchase-error.ts.html +0 -880
- package/coverage/lcov-report/src/types/ExpoIapAndroid.types.ts.html +0 -493
- package/coverage/lcov-report/src/types/index.html +0 -116
- package/coverage/lcov-report/src/useIap.ts.html +0 -1483
- package/coverage/lcov-report/src/utils/purchase.ts.html +0 -241
- package/ios/onside/OnsideIapModule.swift +0 -489
- package/src/utils/constants.ts +0 -23
package/plugin/src/withIAP.ts
CHANGED
|
@@ -6,11 +6,9 @@ import {
|
|
|
6
6
|
withAppBuildGradle,
|
|
7
7
|
withDangerousMod,
|
|
8
8
|
} from 'expo/config-plugins';
|
|
9
|
-
import type {ExpoConfig} from '@expo/config-types';
|
|
10
9
|
import * as fs from 'fs';
|
|
11
10
|
import * as path from 'path';
|
|
12
11
|
import withLocalOpenIAP from './withLocalOpenIAP';
|
|
13
|
-
import type {ExpoIapPluginCommonOptions} from './expoConfig.augmentation';
|
|
14
12
|
|
|
15
13
|
const pkg = require('../../package.json');
|
|
16
14
|
const openiapVersions = JSON.parse(
|
|
@@ -20,10 +18,6 @@ const openiapVersions = JSON.parse(
|
|
|
20
18
|
),
|
|
21
19
|
);
|
|
22
20
|
const OPENIAP_ANDROID_VERSION = openiapVersions.google;
|
|
23
|
-
const AUTOLINKING_CONFIG_PATH = path.resolve(
|
|
24
|
-
__dirname,
|
|
25
|
-
'../../expo-module.config.json',
|
|
26
|
-
);
|
|
27
21
|
|
|
28
22
|
// Log a message only once per Node process
|
|
29
23
|
const logOnce = (() => {
|
|
@@ -56,7 +50,7 @@ const addLineToGradle = (
|
|
|
56
50
|
return lines.join('\n');
|
|
57
51
|
};
|
|
58
52
|
|
|
59
|
-
|
|
53
|
+
const modifyAppBuildGradle = (
|
|
60
54
|
gradle: string,
|
|
61
55
|
language: 'groovy' | 'kotlin',
|
|
62
56
|
): string => {
|
|
@@ -144,136 +138,7 @@ const withIapAndroid: ConfigPlugin<{addDeps?: boolean} | void> = (
|
|
|
144
138
|
};
|
|
145
139
|
|
|
146
140
|
/** Ensure Podfile uses CocoaPods CDN and no stale local OpenIAP entry remains. */
|
|
147
|
-
|
|
148
|
-
enableOnside?: boolean;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
const ensureOnsidePod = (content: string): string => {
|
|
152
|
-
const podLine =
|
|
153
|
-
" pod 'OnsideKit', :git => 'https://github.com/onside-io/OnsideKit-iOS.git'";
|
|
154
|
-
const podRegex = /^\s*pod\s+'OnsideKit'\b.*$/m;
|
|
155
|
-
|
|
156
|
-
if (podRegex.test(content)) {
|
|
157
|
-
return content;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const targetMatch = content.match(/target\s+'[^']+'\s+do\s*\n/);
|
|
161
|
-
if (!targetMatch) {
|
|
162
|
-
WarningAggregator.addWarningIOS(
|
|
163
|
-
'expo-iap',
|
|
164
|
-
'Could not find a target block in Podfile when adding OnsideKit; skipping installation.',
|
|
165
|
-
);
|
|
166
|
-
return content;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const insertIndex = targetMatch.index! + targetMatch[0].length;
|
|
170
|
-
const before = content.slice(0, insertIndex);
|
|
171
|
-
const after = content.slice(insertIndex);
|
|
172
|
-
|
|
173
|
-
logOnce('📦 expo-iap: Added OnsideKit pod to Podfile');
|
|
174
|
-
|
|
175
|
-
return `${before}${podLine}\n${after}`;
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
export type AutolinkState = {expoIap: boolean; onside: boolean};
|
|
179
|
-
|
|
180
|
-
type AutolinkEntry = {name: string; enable: boolean};
|
|
181
|
-
|
|
182
|
-
export function computeAutolinkModules(
|
|
183
|
-
existing: string[],
|
|
184
|
-
desired: AutolinkEntry[],
|
|
185
|
-
): {modules: string[]; added: string[]; removed: string[]} {
|
|
186
|
-
let modules = [...existing];
|
|
187
|
-
const added: string[] = [];
|
|
188
|
-
const removed: string[] = [];
|
|
189
|
-
|
|
190
|
-
for (const entry of desired) {
|
|
191
|
-
const hasModule = modules.includes(entry.name);
|
|
192
|
-
if (entry.enable && !hasModule) {
|
|
193
|
-
modules = [...modules, entry.name];
|
|
194
|
-
added.push(entry.name);
|
|
195
|
-
} else if (!entry.enable && hasModule) {
|
|
196
|
-
modules = modules.filter((module) => module !== entry.name);
|
|
197
|
-
removed.push(entry.name);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return {modules, added, removed};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const syncAutolinking = (state: AutolinkState) => {
|
|
205
|
-
if (!fs.existsSync(AUTOLINKING_CONFIG_PATH)) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
const raw = fs.readFileSync(AUTOLINKING_CONFIG_PATH, 'utf8');
|
|
211
|
-
const config = JSON.parse(raw);
|
|
212
|
-
const iosConfig = config.ios ?? (config.ios = {});
|
|
213
|
-
const existing: string[] = Array.isArray(iosConfig.modules)
|
|
214
|
-
? iosConfig.modules.filter((module: string) => module !== 'OneSideModule')
|
|
215
|
-
: [];
|
|
216
|
-
|
|
217
|
-
const desiredEntries: {
|
|
218
|
-
name: string;
|
|
219
|
-
enable: boolean;
|
|
220
|
-
addLog: string;
|
|
221
|
-
removeLog: string;
|
|
222
|
-
}[] = [
|
|
223
|
-
{
|
|
224
|
-
name: 'ExpoIapModule',
|
|
225
|
-
enable: state.expoIap,
|
|
226
|
-
addLog: '🔗 expo-iap: Enabled ExpoIapModule autolinking',
|
|
227
|
-
removeLog: '🧹 expo-iap: Disabled ExpoIapModule autolinking',
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
name: 'OnsideIapModule',
|
|
231
|
-
enable: state.onside,
|
|
232
|
-
addLog: '🔗 expo-iap: Enabled OnsideIapModule autolinking',
|
|
233
|
-
removeLog: '🧹 expo-iap: Disabled OnsideIapModule autolinking',
|
|
234
|
-
},
|
|
235
|
-
];
|
|
236
|
-
|
|
237
|
-
const {
|
|
238
|
-
modules: nextModules,
|
|
239
|
-
added,
|
|
240
|
-
removed,
|
|
241
|
-
} = computeAutolinkModules(
|
|
242
|
-
existing,
|
|
243
|
-
desiredEntries.map(({name, enable}) => ({name, enable})),
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
for (const name of added) {
|
|
247
|
-
const entry = desiredEntries.find((candidate) => candidate.name === name);
|
|
248
|
-
if (entry) {
|
|
249
|
-
logOnce(entry.addLog);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
for (const name of removed) {
|
|
254
|
-
const entry = desiredEntries.find((candidate) => candidate.name === name);
|
|
255
|
-
if (entry) {
|
|
256
|
-
logOnce(entry.removeLog);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (added.length > 0 || removed.length > 0) {
|
|
261
|
-
iosConfig.modules = nextModules;
|
|
262
|
-
fs.writeFileSync(
|
|
263
|
-
AUTOLINKING_CONFIG_PATH,
|
|
264
|
-
`${JSON.stringify(config, null, 2)}\n`,
|
|
265
|
-
'utf8',
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
} catch (error) {
|
|
269
|
-
WarningAggregator.addWarningIOS(
|
|
270
|
-
'expo-iap',
|
|
271
|
-
`Failed to sync Expo IAP autolinking modules: ${String(error)}`,
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const withIapIOS: ConfigPlugin<WithIapIosOptions | void> = (config, props) => {
|
|
141
|
+
const withIapIOS: ConfigPlugin = (config) => {
|
|
277
142
|
return withDangerousMod(config, [
|
|
278
143
|
'ios',
|
|
279
144
|
async (config) => {
|
|
@@ -301,134 +166,33 @@ const withIapIOS: ConfigPlugin<WithIapIosOptions | void> = (config, props) => {
|
|
|
301
166
|
logOnce('🧹 expo-iap: Removed local OpenIAP pod from Podfile');
|
|
302
167
|
}
|
|
303
168
|
|
|
304
|
-
// 3) Optionally install OnsideKit when enabled in config
|
|
305
|
-
if (props?.enableOnside) {
|
|
306
|
-
content = ensureOnsidePod(content);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
169
|
fs.writeFileSync(podfilePath, content);
|
|
310
170
|
return config;
|
|
311
171
|
},
|
|
312
172
|
]);
|
|
313
173
|
};
|
|
314
174
|
|
|
315
|
-
export interface
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
{
|
|
326
|
-
when: Partial<Record<ModuleSelectionResult['selection'], boolean>>;
|
|
327
|
-
default: (args: {
|
|
328
|
-
config: ExpoConfig;
|
|
329
|
-
options?: ExpoIapPluginCommonOptions;
|
|
330
|
-
}) => boolean;
|
|
331
|
-
}
|
|
332
|
-
>;
|
|
333
|
-
|
|
334
|
-
const MODULE_RULES: ModuleRules = {
|
|
335
|
-
expoIap: {
|
|
336
|
-
when: {
|
|
337
|
-
'expo-iap': true,
|
|
338
|
-
onside: false,
|
|
339
|
-
},
|
|
340
|
-
default: ({options}) => options?.modules?.expoIap ?? true,
|
|
341
|
-
},
|
|
342
|
-
onside: {
|
|
343
|
-
when: {
|
|
344
|
-
'expo-iap': false,
|
|
345
|
-
onside: true,
|
|
346
|
-
},
|
|
347
|
-
default: ({config, options}) =>
|
|
348
|
-
options?.modules?.onside ?? config.ios?.onside?.enabled ?? true,
|
|
349
|
-
},
|
|
350
|
-
};
|
|
351
|
-
|
|
352
|
-
export function resolveModuleSelection(
|
|
353
|
-
config: ExpoConfig,
|
|
354
|
-
options?: ExpoIapPluginCommonOptions | void,
|
|
355
|
-
): ModuleSelectionResult {
|
|
356
|
-
const normalizedOptions = (options ?? undefined) as
|
|
357
|
-
| ExpoIapPluginCommonOptions
|
|
358
|
-
| undefined;
|
|
359
|
-
|
|
360
|
-
const selection = normalizedOptions?.module ?? 'auto';
|
|
361
|
-
|
|
362
|
-
const includeExpoIap = pickModuleState(
|
|
363
|
-
'expoIap',
|
|
364
|
-
selection,
|
|
365
|
-
config,
|
|
366
|
-
normalizedOptions,
|
|
367
|
-
);
|
|
368
|
-
const includeOnside = pickModuleState(
|
|
369
|
-
'onside',
|
|
370
|
-
selection,
|
|
371
|
-
config,
|
|
372
|
-
normalizedOptions,
|
|
373
|
-
);
|
|
374
|
-
|
|
375
|
-
return {selection, includeExpoIap, includeOnside};
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function pickModuleState(
|
|
379
|
-
key: ModuleKey,
|
|
380
|
-
selection: ModuleSelectionResult['selection'],
|
|
381
|
-
config: ExpoConfig,
|
|
382
|
-
options?: ExpoIapPluginCommonOptions,
|
|
383
|
-
): boolean {
|
|
384
|
-
const rules = MODULE_RULES[key];
|
|
385
|
-
const explicit = rules.when[selection];
|
|
386
|
-
if (explicit !== undefined) {
|
|
387
|
-
return explicit;
|
|
388
|
-
}
|
|
389
|
-
const override = options?.modules?.[key];
|
|
390
|
-
if (override !== undefined) {
|
|
391
|
-
return override;
|
|
392
|
-
}
|
|
393
|
-
return rules.default({config, options});
|
|
175
|
+
export interface ExpoIapPluginOptions {
|
|
176
|
+
/** Local development path for OpenIAP library */
|
|
177
|
+
localPath?:
|
|
178
|
+
| string
|
|
179
|
+
| {
|
|
180
|
+
ios?: string;
|
|
181
|
+
android?: string;
|
|
182
|
+
};
|
|
183
|
+
/** Enable local development mode */
|
|
184
|
+
enableLocalDev?: boolean;
|
|
394
185
|
}
|
|
395
186
|
|
|
396
|
-
const
|
|
187
|
+
const withIap: ConfigPlugin<ExpoIapPluginOptions | void> = (
|
|
397
188
|
config,
|
|
398
189
|
options,
|
|
399
190
|
) => {
|
|
400
191
|
try {
|
|
401
|
-
const {includeExpoIap, includeOnside} = resolveModuleSelection(
|
|
402
|
-
config as ExpoConfig,
|
|
403
|
-
options,
|
|
404
|
-
);
|
|
405
|
-
|
|
406
|
-
const autolinkState: AutolinkState = {
|
|
407
|
-
expoIap: includeExpoIap,
|
|
408
|
-
onside: includeOnside,
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
if (includeOnside) {
|
|
412
|
-
config.ios = {
|
|
413
|
-
...config.ios,
|
|
414
|
-
onside: {
|
|
415
|
-
...(config.ios?.onside ?? {}),
|
|
416
|
-
enabled: true,
|
|
417
|
-
},
|
|
418
|
-
} as typeof config.ios;
|
|
419
|
-
} else if (config.ios?.onside?.enabled) {
|
|
420
|
-
config.ios.onside.enabled = false;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
192
|
// Respect explicit flag; fall back to presence of localPath only when flag is unset
|
|
424
193
|
const isLocalDev = options?.enableLocalDev ?? !!options?.localPath;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
// Apply Android modifications (skip when Expo IAP disabled)
|
|
429
|
-
let result = shouldConfigureAndroid
|
|
430
|
-
? withIapAndroid(config, {addDeps: shouldAddAndroidDeps})
|
|
431
|
-
: config;
|
|
194
|
+
// Apply Android modifications (skip adding deps when linking local module)
|
|
195
|
+
let result = withIapAndroid(config, {addDeps: !isLocalDev});
|
|
432
196
|
|
|
433
197
|
// iOS: choose one path to avoid overlap
|
|
434
198
|
if (isLocalDev) {
|
|
@@ -458,14 +222,10 @@ const withIAP: ConfigPlugin<ExpoIapPluginCommonOptions | void> = (
|
|
|
458
222
|
}
|
|
459
223
|
} else {
|
|
460
224
|
// Ensure iOS Podfile is set up to resolve public CocoaPods specs
|
|
461
|
-
result = withIapIOS(result
|
|
462
|
-
|
|
463
|
-
logOnce('📦 [expo-iap] Using OpenIAP from CocoaPods');
|
|
464
|
-
}
|
|
225
|
+
result = withIapIOS(result);
|
|
226
|
+
logOnce('📦 [expo-iap] Using OpenIAP from CocoaPods');
|
|
465
227
|
}
|
|
466
228
|
|
|
467
|
-
syncAutolinking(autolinkState);
|
|
468
|
-
|
|
469
229
|
return result;
|
|
470
230
|
} catch (error) {
|
|
471
231
|
WarningAggregator.addWarningAndroid(
|
|
@@ -477,4 +237,4 @@ const withIAP: ConfigPlugin<ExpoIapPluginCommonOptions | void> = (
|
|
|
477
237
|
}
|
|
478
238
|
};
|
|
479
239
|
|
|
480
|
-
export default createRunOncePlugin(
|
|
240
|
+
export default createRunOncePlugin(withIap, pkg.name, pkg.version);
|
package/plugin/tsconfig.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/
|
|
1
|
+
{"root":["./src/expoConfig.augmentation.d.ts","./src/withIAP.ts","./src/withLocalOpenIAP.ts"],"version":"5.9.2"}
|
package/src/ExpoIapModule.ts
CHANGED
|
@@ -1,51 +1,10 @@
|
|
|
1
|
-
import {requireNativeModule
|
|
1
|
+
import {requireNativeModule} from 'expo-modules-core';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
resolveNativeModule();
|
|
7
|
-
|
|
8
|
-
export const USING_ONSIDE_SDK = resolvedNativeModuleName === 'ExpoIapOnside';
|
|
3
|
+
// It loads the native module object from the JSI or falls back to
|
|
4
|
+
// the bridge module (from NativeModulesProxy) if the remote debugger is on.
|
|
5
|
+
const ExpoIapModule = requireNativeModule('ExpoIap');
|
|
9
6
|
|
|
10
7
|
// Platform-specific error codes from native modules
|
|
11
8
|
export const NATIVE_ERROR_CODES = ExpoIapModule.ERROR_CODES || {};
|
|
12
9
|
|
|
13
10
|
export default ExpoIapModule;
|
|
14
|
-
|
|
15
|
-
function resolveNativeModule(): {
|
|
16
|
-
module: any;
|
|
17
|
-
name: NativeIapModuleName;
|
|
18
|
-
} {
|
|
19
|
-
const candidates: NativeIapModuleName[] = ['ExpoIapOnside', 'ExpoIap'];
|
|
20
|
-
|
|
21
|
-
for (const name of candidates) {
|
|
22
|
-
try {
|
|
23
|
-
const module = requireNativeModule(name);
|
|
24
|
-
return {module, name};
|
|
25
|
-
} catch (error) {
|
|
26
|
-
if (name === 'ExpoIapOnside' && isMissingModuleError(error, name)) {
|
|
27
|
-
// Onside module is optional. If unavailable, fall back to ExpoIap.
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
throw new UnavailabilityError(
|
|
36
|
-
'expo-iap',
|
|
37
|
-
'ExpoIap native module is unavailable',
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function isMissingModuleError(error: unknown, moduleName: string): boolean {
|
|
42
|
-
if (error instanceof UnavailabilityError) {
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (error instanceof Error) {
|
|
47
|
-
return error.message.includes(`Cannot find native module '${moduleName}'`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return false;
|
|
51
|
-
}
|
package/src/useIAP.ts
CHANGED
|
@@ -49,8 +49,6 @@ import {
|
|
|
49
49
|
type UseIap = {
|
|
50
50
|
connected: boolean;
|
|
51
51
|
products: Product[];
|
|
52
|
-
promotedProductsIOS: Purchase[];
|
|
53
|
-
promotedProductIdIOS?: string;
|
|
54
52
|
subscriptions: ProductSubscription[];
|
|
55
53
|
availablePurchases: Purchase[];
|
|
56
54
|
promotedProductIOS?: Product;
|
|
@@ -96,12 +94,10 @@ export interface UseIAPOptions {
|
|
|
96
94
|
export function useIAP(options?: UseIAPOptions): UseIap {
|
|
97
95
|
const [connected, setConnected] = useState<boolean>(false);
|
|
98
96
|
const [products, setProducts] = useState<Product[]>([]);
|
|
99
|
-
const [promotedProductsIOS] = useState<Purchase[]>([]);
|
|
100
97
|
const [subscriptions, setSubscriptions] = useState<ProductSubscription[]>([]);
|
|
101
98
|
|
|
102
99
|
const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);
|
|
103
100
|
const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();
|
|
104
|
-
const [promotedProductIdIOS] = useState<string>();
|
|
105
101
|
const [activeSubscriptions, setActiveSubscriptions] = useState<
|
|
106
102
|
ActiveSubscription[]
|
|
107
103
|
>([]);
|
|
@@ -141,7 +137,6 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
141
137
|
const subscriptionsRef = useRef<{
|
|
142
138
|
purchaseUpdate?: EventSubscription;
|
|
143
139
|
purchaseError?: EventSubscription;
|
|
144
|
-
promotedProductsIOS?: EventSubscription;
|
|
145
140
|
promotedProductIOS?: EventSubscription;
|
|
146
141
|
}>({});
|
|
147
142
|
|
|
@@ -376,7 +371,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
376
371
|
|
|
377
372
|
if (Platform.OS === 'ios') {
|
|
378
373
|
// iOS promoted products listener
|
|
379
|
-
subscriptionsRef.current.
|
|
374
|
+
subscriptionsRef.current.promotedProductIOS = promotedProductListenerIOS(
|
|
380
375
|
(product: Product) => {
|
|
381
376
|
setPromotedProductIOS(product);
|
|
382
377
|
|
|
@@ -394,9 +389,9 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
394
389
|
// If connection failed, clean up listeners
|
|
395
390
|
console.warn('[useIAP] Connection failed, cleaning up listeners...');
|
|
396
391
|
subscriptionsRef.current.purchaseUpdate?.remove();
|
|
397
|
-
subscriptionsRef.current.
|
|
392
|
+
subscriptionsRef.current.promotedProductIOS?.remove();
|
|
398
393
|
subscriptionsRef.current.purchaseUpdate = undefined;
|
|
399
|
-
subscriptionsRef.current.
|
|
394
|
+
subscriptionsRef.current.promotedProductIOS = undefined;
|
|
400
395
|
// Keep purchaseError listener registered to capture subsequent retries
|
|
401
396
|
return;
|
|
402
397
|
}
|
|
@@ -409,7 +404,6 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
409
404
|
return () => {
|
|
410
405
|
currentSubscriptions.purchaseUpdate?.remove();
|
|
411
406
|
currentSubscriptions.purchaseError?.remove();
|
|
412
|
-
currentSubscriptions.promotedProductsIOS?.remove();
|
|
413
407
|
currentSubscriptions.promotedProductIOS?.remove();
|
|
414
408
|
endConnection();
|
|
415
409
|
setConnected(false);
|
|
@@ -419,8 +413,6 @@ export function useIAP(options?: UseIAPOptions): UseIap {
|
|
|
419
413
|
return {
|
|
420
414
|
connected,
|
|
421
415
|
products,
|
|
422
|
-
promotedProductsIOS,
|
|
423
|
-
promotedProductIdIOS,
|
|
424
416
|
subscriptions,
|
|
425
417
|
finishTransaction,
|
|
426
418
|
availablePurchases,
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare const CONSUMABLE_PRODUCT_IDS: string[];
|
|
2
|
-
export declare const NON_CONSUMABLE_PRODUCT_IDS: string[];
|
|
3
|
-
export declare const PRODUCT_IDS: string[];
|
|
4
|
-
export declare const SUBSCRIPTION_PRODUCT_IDS: string[];
|
|
5
|
-
export declare const DEFAULT_SUBSCRIPTION_PRODUCT_ID: string;
|
|
6
|
-
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,sBAAsB,EAAE,MAAM,EAG1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,MAAM,EAE9C,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,EAG/B,CAAC;AAGF,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAA+B,CAAC;AAG7E,eAAO,MAAM,+BAA+B,QAA8B,CAAC"}
|
package/build/utils/constants.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Centralized product ID constants for examples and internal usage
|
|
2
|
-
// Rename guide: subscriptionIds -> SUBSCRIPTION_PRODUCT_IDS, PRODUCT_IDS remains the same name
|
|
3
|
-
// One-time purchase product IDs split by consumption behavior
|
|
4
|
-
export const CONSUMABLE_PRODUCT_IDS = [
|
|
5
|
-
'dev.hyo.martie.10bulbs',
|
|
6
|
-
'dev.hyo.martie.30bulbs',
|
|
7
|
-
];
|
|
8
|
-
export const NON_CONSUMABLE_PRODUCT_IDS = [
|
|
9
|
-
'dev.hyo.martie.certified',
|
|
10
|
-
];
|
|
11
|
-
export const PRODUCT_IDS = [
|
|
12
|
-
...CONSUMABLE_PRODUCT_IDS,
|
|
13
|
-
...NON_CONSUMABLE_PRODUCT_IDS,
|
|
14
|
-
];
|
|
15
|
-
// Subscription product IDs
|
|
16
|
-
export const SUBSCRIPTION_PRODUCT_IDS = ['dev.hyo.martie.premium'];
|
|
17
|
-
// Optionally export a single default subscription for convenience
|
|
18
|
-
export const DEFAULT_SUBSCRIPTION_PRODUCT_ID = SUBSCRIPTION_PRODUCT_IDS[0];
|
|
19
|
-
//# sourceMappingURL=constants.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,+FAA+F;AAE/F,8DAA8D;AAC9D,MAAM,CAAC,MAAM,sBAAsB,GAAa;IAC9C,wBAAwB;IACxB,wBAAwB;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAa;IAClD,0BAA0B;CAC3B,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAa;IACnC,GAAG,sBAAsB;IACzB,GAAG,0BAA0B;CAC9B,CAAC;AAEF,2BAA2B;AAC3B,MAAM,CAAC,MAAM,wBAAwB,GAAa,CAAC,wBAAwB,CAAC,CAAC;AAE7E,kEAAkE;AAClE,MAAM,CAAC,MAAM,+BAA+B,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAAC","sourcesContent":["// Centralized product ID constants for examples and internal usage\n// Rename guide: subscriptionIds -> SUBSCRIPTION_PRODUCT_IDS, PRODUCT_IDS remains the same name\n\n// One-time purchase product IDs split by consumption behavior\nexport const CONSUMABLE_PRODUCT_IDS: string[] = [\n 'dev.hyo.martie.10bulbs',\n 'dev.hyo.martie.30bulbs',\n];\n\nexport const NON_CONSUMABLE_PRODUCT_IDS: string[] = [\n 'dev.hyo.martie.certified',\n];\n\nexport const PRODUCT_IDS: string[] = [\n ...CONSUMABLE_PRODUCT_IDS,\n ...NON_CONSUMABLE_PRODUCT_IDS,\n];\n\n// Subscription product IDs\nexport const SUBSCRIPTION_PRODUCT_IDS: string[] = ['dev.hyo.martie.premium'];\n\n// Optionally export a single default subscription for convenience\nexport const DEFAULT_SUBSCRIPTION_PRODUCT_ID = SUBSCRIPTION_PRODUCT_IDS[0];\n"]}
|