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.
Files changed (47) hide show
  1. package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +0 -11
  2. package/build/ExpoIapModule.d.ts +0 -1
  3. package/build/ExpoIapModule.d.ts.map +1 -1
  4. package/build/ExpoIapModule.js +4 -29
  5. package/build/ExpoIapModule.js.map +1 -1
  6. package/build/useIAP.d.ts +0 -2
  7. package/build/useIAP.d.ts.map +1 -1
  8. package/build/useIAP.js +3 -8
  9. package/build/useIAP.js.map +1 -1
  10. package/coverage/clover.xml +7 -7
  11. package/coverage/coverage-final.json +5 -5
  12. package/coverage/lcov-report/index.html +1 -1
  13. package/coverage/lcov-report/src/helpers/index.html +1 -1
  14. package/coverage/lcov-report/src/helpers/subscription.ts.html +1 -1
  15. package/coverage/lcov-report/src/index.html +1 -1
  16. package/coverage/lcov-report/src/index.ts.html +1 -1
  17. package/coverage/lcov-report/src/modules/android.ts.html +1 -1
  18. package/coverage/lcov-report/src/modules/index.html +1 -1
  19. package/coverage/lcov-report/src/modules/ios.ts.html +1 -1
  20. package/coverage/lcov-report/src/utils/errorMapping.ts.html +1 -1
  21. package/coverage/lcov-report/src/utils/index.html +1 -1
  22. package/expo-module.config.json +3 -10
  23. package/jest.config.js +0 -1
  24. package/openiap-versions.json +1 -1
  25. package/package.json +3 -4
  26. package/plugin/build/withIAP.d.ts +9 -22
  27. package/plugin/build/withIAP.js +9 -157
  28. package/plugin/jest.config.js +3 -13
  29. package/plugin/src/expoConfig.augmentation.d.ts +1 -30
  30. package/plugin/src/withIAP.ts +18 -258
  31. package/plugin/tsconfig.json +1 -2
  32. package/plugin/tsconfig.tsbuildinfo +1 -1
  33. package/src/ExpoIapModule.ts +4 -45
  34. package/src/useIAP.ts +3 -11
  35. package/build/utils/constants.d.ts +0 -6
  36. package/build/utils/constants.d.ts.map +0 -1
  37. package/build/utils/constants.js +0 -19
  38. package/build/utils/constants.js.map +0 -1
  39. package/coverage/lcov-report/src/ExpoIap.types.ts.html +0 -1243
  40. package/coverage/lcov-report/src/PurchaseError.ts.html +0 -787
  41. package/coverage/lcov-report/src/purchase-error.ts.html +0 -880
  42. package/coverage/lcov-report/src/types/ExpoIapAndroid.types.ts.html +0 -493
  43. package/coverage/lcov-report/src/types/index.html +0 -116
  44. package/coverage/lcov-report/src/useIap.ts.html +0 -1483
  45. package/coverage/lcov-report/src/utils/purchase.ts.html +0 -241
  46. package/ios/onside/OnsideIapModule.swift +0 -489
  47. package/src/utils/constants.ts +0 -23
@@ -146,7 +146,7 @@
146
146
  <div class='footer quiet pad2 space-top1 center small'>
147
147
  Code coverage generated by
148
148
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
149
- at 2025-09-21T17:41:08.551Z
149
+ at 2025-09-22T14:13:03.978Z
150
150
  </div>
151
151
  <script src="prettify.js"></script>
152
152
  <script>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2025-09-21T17:41:08.551Z
104
+ at 2025-09-22T14:13:03.978Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -481,7 +481,7 @@ export const hasActiveSubscriptions = async (
481
481
  <div class='footer quiet pad2 space-top1 center small'>
482
482
  Code coverage generated by
483
483
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
484
- at 2025-09-21T17:41:08.551Z
484
+ at 2025-09-22T14:13:03.978Z
485
485
  </div>
486
486
  <script src="../../prettify.js"></script>
487
487
  <script>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2025-09-21T17:41:08.551Z
104
+ at 2025-09-22T14:13:03.978Z
105
105
  </div>
106
106
  <script src="../prettify.js"></script>
107
107
  <script>
@@ -1978,7 +1978,7 @@ export type {
1978
1978
  <div class='footer quiet pad2 space-top1 center small'>
1979
1979
  Code coverage generated by
1980
1980
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1981
- at 2025-09-21T17:41:08.551Z
1981
+ at 2025-09-22T14:13:03.978Z
1982
1982
  </div>
1983
1983
  <script src="../prettify.js"></script>
1984
1984
  <script>
@@ -535,7 +535,7 @@ export const openRedeemOfferCodeAndroid = async (): Promise&lt;void&gt; =&gt; {
535
535
  <div class='footer quiet pad2 space-top1 center small'>
536
536
  Code coverage generated by
537
537
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
538
- at 2025-09-21T17:41:08.551Z
538
+ at 2025-09-22T14:13:03.978Z
539
539
  </div>
540
540
  <script src="../../prettify.js"></script>
541
541
  <script>
@@ -116,7 +116,7 @@
116
116
  <div class='footer quiet pad2 space-top1 center small'>
117
117
  Code coverage generated by
118
118
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
119
- at 2025-09-21T17:41:08.551Z
119
+ at 2025-09-22T14:13:03.978Z
120
120
  </div>
121
121
  <script src="../../prettify.js"></script>
122
122
  <script>
@@ -1207,7 +1207,7 @@ export const deepLinkToSubscriptionsIOS = (): Promise&lt;void&gt; =&gt;
1207
1207
  <div class='footer quiet pad2 space-top1 center small'>
1208
1208
  Code coverage generated by
1209
1209
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1210
- at 2025-09-21T17:41:08.551Z
1210
+ at 2025-09-22T14:13:03.978Z
1211
1211
  </div>
1212
1212
  <script src="../../prettify.js"></script>
1213
1213
  <script>
@@ -1054,7 +1054,7 @@ export function getUserFriendlyErrorMessage(error: ErrorLike): string {
1054
1054
  <div class='footer quiet pad2 space-top1 center small'>
1055
1055
  Code coverage generated by
1056
1056
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1057
- at 2025-09-21T17:41:08.551Z
1057
+ at 2025-09-22T14:13:03.978Z
1058
1058
  </div>
1059
1059
  <script src="../../prettify.js"></script>
1060
1060
  <script>
@@ -101,7 +101,7 @@
101
101
  <div class='footer quiet pad2 space-top1 center small'>
102
102
  Code coverage generated by
103
103
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
104
- at 2025-09-21T17:41:08.551Z
104
+ at 2025-09-22T14:13:03.978Z
105
105
  </div>
106
106
  <script src="../../prettify.js"></script>
107
107
  <script>
@@ -1,16 +1,9 @@
1
1
  {
2
- "platforms": [
3
- "ios",
4
- "android"
5
- ],
2
+ "platforms": ["ios", "android"],
6
3
  "ios": {
7
- "modules": [
8
- "OnsideIapModule"
9
- ]
4
+ "modules": ["ExpoIapModule"]
10
5
  },
11
6
  "android": {
12
- "modules": [
13
- "expo.modules.iap.ExpoIapModule"
14
- ]
7
+ "modules": ["expo.modules.iap.ExpoIapModule"]
15
8
  }
16
9
  }
package/jest.config.js CHANGED
@@ -36,6 +36,5 @@ module.exports = {
36
36
  coveragePathIgnorePatterns: [
37
37
  '<rootDir>/src/useIAP.ts',
38
38
  '<rootDir>/src/types.ts',
39
- '<rootDir>/src/utils/constants.ts',
40
39
  ],
41
40
  };
@@ -1,5 +1,5 @@
1
1
  {
2
- "apple": "1.2.2",
2
+ "apple": "1.2.3",
3
3
  "google": "1.2.6",
4
4
  "gql": "1.0.8"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-iap",
3
- "version": "3.1.1-rc.2",
3
+ "version": "3.1.2",
4
4
  "description": "In App Purchase module in Expo",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -13,10 +13,9 @@
13
13
  "lint:tsc": "tsc -p tsconfig.json --noEmit --skipLibCheck",
14
14
  "lint:kt": "sh -c 'command -v ktlint >/dev/null 2>&1 && ktlint --format ./android || { echo \"ktlint not installed; skipping\"; exit 0; }'",
15
15
  "lint:ci": "bun run lint:tsc && bun run lint:eslint && bun run lint:prettier && bun run lint:kt",
16
- "test": "jest && bun run test:plugin",
17
- "test:plugin": "cd plugin && npx jest",
16
+ "test": "jest",
18
17
  "test:coverage": "jest --coverage",
19
- "prepare": "bun clean:plugin && bun clean && expo-module prepare && sh -c 'command -v husky >/dev/null 2>&1 && husky install || { echo \"husky not installed; skipping\"; exit 0; }'",
18
+ "prepare": "expo-module prepare && sh -c 'command -v husky >/dev/null 2>&1 && husky install || { echo \"husky not installed; skipping\"; exit 0; }'",
20
19
  "expo-module": "expo-module",
21
20
  "open:ios": "xed example/ios",
22
21
  "open:android": "open -a \"Android Studio\" example/android",
@@ -1,25 +1,12 @@
1
1
  import { ConfigPlugin } from 'expo/config-plugins';
2
- import type { ExpoConfig } from '@expo/config-types';
3
- import type { ExpoIapPluginCommonOptions } from './expoConfig.augmentation';
4
- export declare const modifyAppBuildGradle: (gradle: string, language: "groovy" | "kotlin") => string;
5
- export type AutolinkState = {
6
- expoIap: boolean;
7
- onside: boolean;
8
- };
9
- type AutolinkEntry = {
10
- name: string;
11
- enable: boolean;
12
- };
13
- export declare function computeAutolinkModules(existing: string[], desired: AutolinkEntry[]): {
14
- modules: string[];
15
- added: string[];
16
- removed: string[];
17
- };
18
- export interface ModuleSelectionResult {
19
- selection: 'auto' | 'expo-iap' | 'onside';
20
- includeExpoIap: boolean;
21
- includeOnside: boolean;
2
+ export interface ExpoIapPluginOptions {
3
+ /** Local development path for OpenIAP library */
4
+ localPath?: string | {
5
+ ios?: string;
6
+ android?: string;
7
+ };
8
+ /** Enable local development mode */
9
+ enableLocalDev?: boolean;
22
10
  }
23
- export declare function resolveModuleSelection(config: ExpoConfig, options?: ExpoIapPluginCommonOptions | void): ModuleSelectionResult;
24
- declare const _default: ConfigPlugin<void | ExpoIapPluginCommonOptions>;
11
+ declare const _default: ConfigPlugin<void | ExpoIapPluginOptions>;
25
12
  export default _default;
@@ -36,9 +36,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.modifyAppBuildGradle = void 0;
40
- exports.computeAutolinkModules = computeAutolinkModules;
41
- exports.resolveModuleSelection = resolveModuleSelection;
42
39
  const config_plugins_1 = require("expo/config-plugins");
43
40
  const fs = __importStar(require("fs"));
44
41
  const path = __importStar(require("path"));
@@ -46,7 +43,6 @@ const withLocalOpenIAP_1 = __importDefault(require("./withLocalOpenIAP"));
46
43
  const pkg = require('../../package.json');
47
44
  const openiapVersions = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../../openiap-versions.json'), 'utf8'));
48
45
  const OPENIAP_ANDROID_VERSION = openiapVersions.google;
49
- const AUTOLINKING_CONFIG_PATH = path.resolve(__dirname, '../../expo-module.config.json');
50
46
  // Log a message only once per Node process
51
47
  const logOnce = (() => {
52
48
  const printed = new Set();
@@ -92,14 +88,13 @@ const modifyAppBuildGradle = (gradle, language) => {
92
88
  }
93
89
  return modified;
94
90
  };
95
- exports.modifyAppBuildGradle = modifyAppBuildGradle;
96
91
  const withIapAndroid = (config, props) => {
97
92
  const addDeps = props?.addDeps ?? true;
98
93
  if (addDeps) {
99
94
  config = (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
100
95
  // language provided by config-plugins: 'groovy' | 'kotlin'
101
96
  const language = config.modResults.language || 'groovy';
102
- config.modResults.contents = (0, exports.modifyAppBuildGradle)(config.modResults.contents, language);
97
+ config.modResults.contents = modifyAppBuildGradle(config.modResults.contents, language);
103
98
  return config;
104
99
  });
105
100
  }
@@ -122,88 +117,8 @@ const withIapAndroid = (config, props) => {
122
117
  });
123
118
  return config;
124
119
  };
125
- const ensureOnsidePod = (content) => {
126
- const podLine = " pod 'OnsideKit', :git => 'https://github.com/onside-io/OnsideKit-iOS.git'";
127
- const podRegex = /^\s*pod\s+'OnsideKit'\b.*$/m;
128
- if (podRegex.test(content)) {
129
- return content;
130
- }
131
- const targetMatch = content.match(/target\s+'[^']+'\s+do\s*\n/);
132
- if (!targetMatch) {
133
- config_plugins_1.WarningAggregator.addWarningIOS('expo-iap', 'Could not find a target block in Podfile when adding OnsideKit; skipping installation.');
134
- return content;
135
- }
136
- const insertIndex = targetMatch.index + targetMatch[0].length;
137
- const before = content.slice(0, insertIndex);
138
- const after = content.slice(insertIndex);
139
- logOnce('📦 expo-iap: Added OnsideKit pod to Podfile');
140
- return `${before}${podLine}\n${after}`;
141
- };
142
- function computeAutolinkModules(existing, desired) {
143
- let modules = [...existing];
144
- const added = [];
145
- const removed = [];
146
- for (const entry of desired) {
147
- const hasModule = modules.includes(entry.name);
148
- if (entry.enable && !hasModule) {
149
- modules = [...modules, entry.name];
150
- added.push(entry.name);
151
- }
152
- else if (!entry.enable && hasModule) {
153
- modules = modules.filter((module) => module !== entry.name);
154
- removed.push(entry.name);
155
- }
156
- }
157
- return { modules, added, removed };
158
- }
159
- const syncAutolinking = (state) => {
160
- if (!fs.existsSync(AUTOLINKING_CONFIG_PATH)) {
161
- return;
162
- }
163
- try {
164
- const raw = fs.readFileSync(AUTOLINKING_CONFIG_PATH, 'utf8');
165
- const config = JSON.parse(raw);
166
- const iosConfig = config.ios ?? (config.ios = {});
167
- const existing = Array.isArray(iosConfig.modules)
168
- ? iosConfig.modules.filter((module) => module !== 'OneSideModule')
169
- : [];
170
- const desiredEntries = [
171
- {
172
- name: 'ExpoIapModule',
173
- enable: state.expoIap,
174
- addLog: '🔗 expo-iap: Enabled ExpoIapModule autolinking',
175
- removeLog: '🧹 expo-iap: Disabled ExpoIapModule autolinking',
176
- },
177
- {
178
- name: 'OnsideIapModule',
179
- enable: state.onside,
180
- addLog: '🔗 expo-iap: Enabled OnsideIapModule autolinking',
181
- removeLog: '🧹 expo-iap: Disabled OnsideIapModule autolinking',
182
- },
183
- ];
184
- const { modules: nextModules, added, removed, } = computeAutolinkModules(existing, desiredEntries.map(({ name, enable }) => ({ name, enable })));
185
- for (const name of added) {
186
- const entry = desiredEntries.find((candidate) => candidate.name === name);
187
- if (entry) {
188
- logOnce(entry.addLog);
189
- }
190
- }
191
- for (const name of removed) {
192
- const entry = desiredEntries.find((candidate) => candidate.name === name);
193
- if (entry) {
194
- logOnce(entry.removeLog);
195
- }
196
- }
197
- if (added.length > 0 || removed.length > 0) {
198
- iosConfig.modules = nextModules;
199
- fs.writeFileSync(AUTOLINKING_CONFIG_PATH, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
200
- }
201
- }
202
- catch (error) {
203
- config_plugins_1.WarningAggregator.addWarningIOS('expo-iap', `Failed to sync Expo IAP autolinking modules: ${String(error)}`);
204
- }
205
- };
206
- const withIapIOS = (config, props) => {
120
+ /** Ensure Podfile uses CocoaPods CDN and no stale local OpenIAP entry remains. */
121
+ const withIapIOS = (config) => {
207
122
  return (0, config_plugins_1.withDangerousMod)(config, [
208
123
  'ios',
209
124
  async (config) => {
@@ -225,77 +140,17 @@ const withIapIOS = (config, props) => {
225
140
  content = content.replace(localPodRegex, '').replace(/\n{3,}/g, '\n\n');
226
141
  logOnce('🧹 expo-iap: Removed local OpenIAP pod from Podfile');
227
142
  }
228
- // 3) Optionally install OnsideKit when enabled in config
229
- if (props?.enableOnside) {
230
- content = ensureOnsidePod(content);
231
- }
232
143
  fs.writeFileSync(podfilePath, content);
233
144
  return config;
234
145
  },
235
146
  ]);
236
147
  };
237
- const MODULE_RULES = {
238
- expoIap: {
239
- when: {
240
- 'expo-iap': true,
241
- onside: false,
242
- },
243
- default: ({ options }) => options?.modules?.expoIap ?? true,
244
- },
245
- onside: {
246
- when: {
247
- 'expo-iap': false,
248
- onside: true,
249
- },
250
- default: ({ config, options }) => options?.modules?.onside ?? config.ios?.onside?.enabled ?? true,
251
- },
252
- };
253
- function resolveModuleSelection(config, options) {
254
- const normalizedOptions = (options ?? undefined);
255
- const selection = normalizedOptions?.module ?? 'auto';
256
- const includeExpoIap = pickModuleState('expoIap', selection, config, normalizedOptions);
257
- const includeOnside = pickModuleState('onside', selection, config, normalizedOptions);
258
- return { selection, includeExpoIap, includeOnside };
259
- }
260
- function pickModuleState(key, selection, config, options) {
261
- const rules = MODULE_RULES[key];
262
- const explicit = rules.when[selection];
263
- if (explicit !== undefined) {
264
- return explicit;
265
- }
266
- const override = options?.modules?.[key];
267
- if (override !== undefined) {
268
- return override;
269
- }
270
- return rules.default({ config, options });
271
- }
272
- const withIAP = (config, options) => {
148
+ const withIap = (config, options) => {
273
149
  try {
274
- const { includeExpoIap, includeOnside } = resolveModuleSelection(config, options);
275
- const autolinkState = {
276
- expoIap: includeExpoIap,
277
- onside: includeOnside,
278
- };
279
- if (includeOnside) {
280
- config.ios = {
281
- ...config.ios,
282
- onside: {
283
- ...(config.ios?.onside ?? {}),
284
- enabled: true,
285
- },
286
- };
287
- }
288
- else if (config.ios?.onside?.enabled) {
289
- config.ios.onside.enabled = false;
290
- }
291
150
  // Respect explicit flag; fall back to presence of localPath only when flag is unset
292
151
  const isLocalDev = options?.enableLocalDev ?? !!options?.localPath;
293
- const shouldConfigureAndroid = includeExpoIap;
294
- const shouldAddAndroidDeps = includeExpoIap && !isLocalDev;
295
- // Apply Android modifications (skip when Expo IAP disabled)
296
- let result = shouldConfigureAndroid
297
- ? withIapAndroid(config, { addDeps: shouldAddAndroidDeps })
298
- : config;
152
+ // Apply Android modifications (skip adding deps when linking local module)
153
+ let result = withIapAndroid(config, { addDeps: !isLocalDev });
299
154
  // iOS: choose one path to avoid overlap
300
155
  if (isLocalDev) {
301
156
  if (!options?.localPath) {
@@ -318,12 +173,9 @@ const withIAP = (config, options) => {
318
173
  }
319
174
  else {
320
175
  // Ensure iOS Podfile is set up to resolve public CocoaPods specs
321
- result = withIapIOS(result, { enableOnside: includeOnside });
322
- if (includeExpoIap) {
323
- logOnce('📦 [expo-iap] Using OpenIAP from CocoaPods');
324
- }
176
+ result = withIapIOS(result);
177
+ logOnce('📦 [expo-iap] Using OpenIAP from CocoaPods');
325
178
  }
326
- syncAutolinking(autolinkState);
327
179
  return result;
328
180
  }
329
181
  catch (error) {
@@ -332,4 +184,4 @@ const withIAP = (config, options) => {
332
184
  return config;
333
185
  }
334
186
  };
335
- exports.default = (0, config_plugins_1.createRunOncePlugin)(withIAP, pkg.name, pkg.version);
187
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withIap, pkg.name, pkg.version);
@@ -1,15 +1,5 @@
1
+ // In documentation there is `preset: expo-module-scripts`, but it runs tests for every platform (ios, android, web, node)
2
+ // We need only node tests right now
1
3
  module.exports = {
2
- preset: 'ts-jest',
3
- testEnvironment: 'node',
4
- transform: {
5
- '^.+\\.(ts|tsx)$': [
6
- 'ts-jest',
7
- {
8
- tsconfig: '<rootDir>/tsconfig.json',
9
- },
10
- ],
11
- },
12
- moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
13
- roots: ['<rootDir>/__tests__'],
14
- testMatch: ['**/?(*.)+(spec|test).ts?(x)'],
4
+ preset: 'jest-expo/node',
15
5
  };
@@ -1,11 +1,4 @@
1
- import type {IOS} from '@expo/config-types';
2
-
3
- export type ExpoIapModuleOverrides = {
4
- expoIap?: boolean;
5
- onside?: boolean;
6
- };
7
-
8
- type BaseExpoIapOptions = {
1
+ export interface ExpoIapPluginCommonOptions {
9
2
  enableLocalDev?: boolean;
10
3
  localPath?:
11
4
  | string
@@ -13,26 +6,4 @@ type BaseExpoIapOptions = {
13
6
  ios?: string;
14
7
  android?: string;
15
8
  };
16
- };
17
-
18
- type AutoModuleOptions = BaseExpoIapOptions & {
19
- module?: 'auto';
20
- modules?: ExpoIapModuleOverrides;
21
- };
22
-
23
- type ExplicitModuleOptions = BaseExpoIapOptions & {
24
- module: 'expo-iap' | 'onside';
25
- modules?: never;
26
- };
27
-
28
- export type ExpoIapPluginCommonOptions =
29
- | AutoModuleOptions
30
- | ExplicitModuleOptions;
31
-
32
- declare module '@expo/config-types' {
33
- interface IOS {
34
- onside?: {
35
- enabled?: boolean;
36
- };
37
- }
38
9
  }