runcloud 0.2.161 → 0.2.163

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.
@@ -1,6 +1,8 @@
1
1
  import { existsSync, readFileSync, readdirSync, statSync, } from 'node:fs';
2
2
  import path from 'node:path';
3
3
  const PREVIEW_APP_ID = 'app.newly.preview';
4
+ const SCAFFOLD_SCHEME = 'expobase';
5
+ const INBOUND_LINK = /Linking\.createURL|makeRedirectUri|emailRedirectTo|\bredirectTo\s*:|expobase:\/\//;
4
6
  const PLACEHOLDER_COPY = /lorem ipsum|example\.com|\bTBD\b|\bTODO\b|\bplaceholder\b/i;
5
7
  const INPUT_PLACEHOLDER = /\bplaceholder\??\s*[=:]\s*(\{[^}]*\}|"[^"]*"|'[^']*'|`[^`]*`|[\w.$]+)/gi;
6
8
  const PLACEHOLDER_NAME = /\.placeholder\b|\bplaceholder\b(?=\s*[,})\]])/gi;
@@ -45,6 +47,10 @@ const LIVE_STORE_IDS = new Set([
45
47
  'apple_content_rights',
46
48
  'apple_age_rating',
47
49
  'apple_privacy_label',
50
+ 'apple_review_notes',
51
+ 'apple_review_contact',
52
+ 'apple_review_recording',
53
+ 'apple_eu_trader_status',
48
54
  'google_play_title',
49
55
  'google_play_short_description',
50
56
  'google_play_description',
@@ -86,6 +92,7 @@ const TEXT_EXTENSIONS = new Set([
86
92
  '.swift',
87
93
  '.ts',
88
94
  '.tsx',
95
+ '.xcprivacy',
89
96
  '.xml',
90
97
  ]);
91
98
  const SKIP_DIRS = new Set([
@@ -154,6 +161,8 @@ function activeItems(manifest) {
154
161
  return manifest.items.filter((item) => !item.deferred && item.resolvedBy !== 'card');
155
162
  }
156
163
  function evaluateLocalItem(root, appJson, item) {
164
+ if (item.id === 'scheme')
165
+ return evaluateScheme(root, appJson, item);
157
166
  const rule = CONFIG_RULES[item.id];
158
167
  if (rule)
159
168
  return evaluateConfigItem(appJson, item, rule);
@@ -200,7 +209,7 @@ function evaluateLocalItem(root, appJson, item) {
200
209
  case 'permission_descriptions':
201
210
  return evaluatePermissionDescriptions(root, appJson, item);
202
211
  case 'privacy_manifest':
203
- return evaluatePrivacyManifest(root, item);
212
+ return evaluatePrivacyManifest(root, appJson, item);
204
213
  default:
205
214
  if (STORE_REMINDER_IDS.has(item.id)) {
206
215
  return makeItem(item, 'info', 'Complete this declaration in Google Play Console.', 'Play Console questionnaire');
@@ -225,6 +234,14 @@ function evaluateConfigItem(appJson, item, rule) {
225
234
  return makeItem(item, 'pass', `${item.label} is set.`, evidence);
226
235
  return makeItem(item, rule.absent, `${item.label} is not set.`, evidence);
227
236
  }
237
+ function evaluateScheme(root, appJson, item) {
238
+ const value = getPath(appJson, ['expo', 'scheme']);
239
+ const schemes = typeof value === 'string' ? [value] : arrayOfStrings(value);
240
+ const shared = schemes.includes(SCAFFOLD_SCHEME) ? scan(root, INBOUND_LINK, { dirs: ['app', 'src', 'components'] }) : [];
241
+ if (!shared.length)
242
+ return evaluateConfigItem(appJson, item, CONFIG_RULES['scheme']);
243
+ return makeItem(item, 'warning', `This app still uses the link name every new Newly app starts with (${SCAFFOLD_SCHEME}). A link back into the app, such as a sign-in email, can open another Newly-built app on the same phone. Give it its own scheme, and update any redirect address saved with your sign-in provider. The next preview then takes several minutes to rebuild.`, `app.json expo.scheme = ${JSON.stringify(value)}\n${evidence(shared)}`);
244
+ }
228
245
  function evaluateEncryption(appJson, item) {
229
246
  const plist = getPath(appJson, ['expo', 'ios', 'infoPlist', 'ITSAppUsesNonExemptEncryption']);
230
247
  const config = getPath(appJson, ['expo', 'ios', 'config', 'usesNonExemptEncryption']);
@@ -288,16 +305,19 @@ function evaluatePermissionDescriptions(root, appJson, item) {
288
305
  return makeItem(item, 'pass', 'Used iOS capabilities have usage descriptions.', 'app.json ios.infoPlist cross-check');
289
306
  return makeItem(item, 'fail', 'Used iOS capability is missing an NS*UsageDescription.', missing.join('; '));
290
307
  }
291
- function evaluatePrivacyManifest(root, item) {
292
- const hasManifest = findByName(root, 'PrivacyInfo.xcprivacy').length > 0;
293
- const requiredReasonApi = scan(root, /NSUserDefaults|systemUptime|fileModificationDate|diskSpace|activeInputModes/i);
294
- const tracking = scan(root, TRACKING_SDK);
295
- if (hasManifest)
308
+ function evaluatePrivacyManifest(root, appJson, item) {
309
+ if (findByName(root, 'PrivacyInfo.xcprivacy').length > 0)
296
310
  return makeItem(item, 'pass', 'PrivacyInfo.xcprivacy is present.', 'scan: PrivacyInfo.xcprivacy found');
297
- if (tracking.length)
298
- return makeItem(item, 'fail', 'Tracking SDK pattern found but no PrivacyInfo.xcprivacy file was found.', evidence(tracking));
299
- if (requiredReasonApi.length)
300
- return makeItem(item, 'warning', 'Required-reason API pattern found but no PrivacyInfo.xcprivacy file was found.', evidence(requiredReasonApi));
311
+ if (Object.keys(objectValue(getPath(appJson, ['expo', 'ios', 'privacyManifests']))).length > 0)
312
+ return makeItem(item, 'pass', 'app.json declares the privacy manifest.', 'app.json expo.ios.privacyManifests is set');
313
+ const tracking = scan(root, TRACKING_SDK);
314
+ if (tracking.length) {
315
+ return makeItem(item, 'warning', 'This app uses a tracking SDK and app.json declares no privacy manifest. Add expo.ios.privacyManifests with NSPrivacyTracking and the domains the SDK tracks through, so the manifest matches your App Privacy answers.', evidence(tracking));
316
+ }
317
+ const requiredReasonApi = scan(root, /NSUserDefaults|systemUptime|fileModificationDate|diskSpace|activeInputModes/i);
318
+ if (requiredReasonApi.length) {
319
+ return makeItem(item, 'warning', 'This code uses an API Apple wants a reason for, and app.json declares none. Add the reason under expo.ios.privacyManifests (NSPrivacyAccessedAPITypes).', evidence(requiredReasonApi));
320
+ }
301
321
  return makeItem(item, 'pass', 'No required-reason API patterns found and no tracking SDK patterns found.', 'scan: no required privacy manifest signals found');
302
322
  }
303
323
  function patternItem(root, item, regex, statusOnHit, messageOnHit, messageOnMiss, options = {}) {
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.2.161';
1
+ export const CLI_VERSION = '0.2.163';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.2.161",
3
+ "version": "0.2.163",
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