runcloud 0.2.146 → 0.2.148

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.
@@ -213,8 +213,9 @@ function evaluateRestorePurchases(root, item) {
213
213
  return makeItem(item, 'pass', 'Restore purchases flow appears in source.', evidence(restore));
214
214
  return makeItem(item, 'fail', 'IAP APIs found but no restore purchases flow was found.', evidence(iap));
215
215
  }
216
+ const TRACKING_SDK = /["'](?:@react-native-firebase\/analytics|react-native-fbsdk(?:-next)?|expo-facebook|react-native-appsflyer|@amplitude\/[\w.-]+|@segment\/[\w.-]+)(?:\/[^"']*)?["']/;
216
217
  function evaluateTrackingWithoutAtt(root, item) {
217
- const tracking = scan(root, /react-native-firebase\/analytics|facebook|appsflyer|amplitude|segment/i);
218
+ const tracking = scan(root, TRACKING_SDK);
218
219
  if (!tracking.length)
219
220
  return makeItem(item, 'pass', 'No tracking SDK patterns found.', 'scan: no tracking SDK patterns found');
220
221
  const att = scan(root, /expo-tracking-transparency|requestTrackingPermission/i);
@@ -271,7 +272,7 @@ function evaluatePermissionDescriptions(root, appJson, item) {
271
272
  function evaluatePrivacyManifest(root, item) {
272
273
  const hasManifest = findByName(root, 'PrivacyInfo.xcprivacy').length > 0;
273
274
  const requiredReasonApi = scan(root, /NSUserDefaults|systemUptime|fileModificationDate|diskSpace|activeInputModes/i);
274
- const tracking = scan(root, /react-native-firebase\/analytics|facebook|appsflyer|amplitude|segment/i);
275
+ const tracking = scan(root, TRACKING_SDK);
275
276
  if (hasManifest)
276
277
  return makeItem(item, 'pass', 'PrivacyInfo.xcprivacy is present.', 'scan: PrivacyInfo.xcprivacy found');
277
278
  if (tracking.length)
@@ -323,8 +324,27 @@ function missingIosUsageDescriptions(root, appJson) {
323
324
  missing.push(`ios ${check.name} usage description (${check.keys.join(' or ')})`);
324
325
  }
325
326
  }
327
+ const entitlements = objectValue(getPath(appJson, ['expo', 'ios', 'entitlements']));
328
+ if (entitlements['com.apple.developer.healthkit'] === true || /@kingstinct\/react-native-healthkit/.test(source)) {
329
+ const plugin = configPluginOptions(appJson, '@kingstinct/react-native-healthkit');
330
+ const lacking = ['NSHealthShareUsageDescription', 'NSHealthUpdateUsageDescription'].filter((key) => !hasValue(infoPlist[key]) && !(plugin && plugin[key] !== false));
331
+ if (lacking.length)
332
+ missing.push(`ios HealthKit usage descriptions (${lacking.join(' and ')})`);
333
+ }
326
334
  return missing;
327
335
  }
336
+ function configPluginOptions(appJson, name) {
337
+ const plugins = getPath(appJson, ['expo', 'plugins']);
338
+ if (!Array.isArray(plugins))
339
+ return undefined;
340
+ for (const entry of plugins) {
341
+ if (entry === name)
342
+ return {};
343
+ if (Array.isArray(entry) && entry[0] === name)
344
+ return objectValue(entry[1]);
345
+ }
346
+ return undefined;
347
+ }
328
348
  function unresolvedReason(item) {
329
349
  if (JUDGMENT_IDS.has(item.id))
330
350
  return 'requires app-specific judgment over UI/copy behavior';
@@ -67,7 +67,8 @@ export async function runDomainBuy(client, projectId, domainName, opts, log = co
67
67
  }));
68
68
  if (!result.checkout_url)
69
69
  throw new Error('Backend did not return a checkout URL.');
70
- log(`Checkout: ${result.checkout_url}`);
70
+ log(`Payment required — open this URL in a browser to complete the purchase:`);
71
+ log(` ${result.checkout_url}`);
71
72
  if (result.order?.id)
72
73
  log(`Order: ${result.order.id} (${result.order.status ?? 'checkout_created'})`);
73
74
  }
@@ -137,7 +138,7 @@ export function registerDomains(program) {
137
138
  .option('--years <n>', 'registration term in years', '1')
138
139
  .option('--project <id>', 'project id (defaults to the linked directory)')
139
140
  .option('--yes', 'confirm purchase without an interactive prompt', false)
140
- .description('Buy a domain through Cloudflare Registrar')
141
+ .description('Buy a domain through Cloudflare Registrar — it prints a Stripe checkout URL the account owner opens in a browser to pay.')
141
142
  .action(async (domainName, opts) => {
142
143
  try {
143
144
  const { client, projectId, appUrl } = makeClient(opts.project);
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.2.146';
1
+ export const CLI_VERSION = '0.2.148';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.2.146",
3
+ "version": "0.2.148",
4
4
  "description": "Create and control run.cloud remote mobile simulators and cloud sandboxes",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [
Binary file
Binary file