runcloud 0.2.145 → 0.2.147

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';
@@ -5,6 +5,11 @@ export function assertDevOnly(env, command) {
5
5
  throw new Error(`\`newly ${command}\` is dev-only from the CLI. Prod ${command} requires the Newly web app (a browser session).`);
6
6
  }
7
7
  }
8
+ export function assertKnownEnv(env, command) {
9
+ if (env !== 'dev' && env !== 'prod') {
10
+ throw new Error(`\`newly ${command}\` --env must be dev or prod (got ${JSON.stringify(env)})`);
11
+ }
12
+ }
8
13
  export function parseDuration(s) {
9
14
  const m = /^(\d+)(s|m|h)$/.exec(s.trim());
10
15
  if (!m)
@@ -128,7 +133,7 @@ export function registerMisc(program) {
128
133
  .option('--project <id>', 'project id')
129
134
  .action(async (opts) => {
130
135
  try {
131
- assertDevOnly(opts.env, 'secrets list');
136
+ assertKnownEnv(opts.env, 'secrets list');
132
137
  const { client, projectId } = makeClient(opts.project);
133
138
  console.log(await listSecrets(client, projectId, opts.env, opts.service));
134
139
  }
@@ -146,7 +151,7 @@ export function registerMisc(program) {
146
151
  .option('--project <id>', 'project id')
147
152
  .action(async (key, value, opts) => {
148
153
  try {
149
- assertDevOnly(opts.env, 'secrets set');
154
+ assertKnownEnv(opts.env, 'secrets set');
150
155
  const { client, projectId } = makeClient(opts.project);
151
156
  await setSecret(client, projectId, opts.env, opts.service, key, value);
152
157
  console.log(`Secret ${key} set for ${opts.service} (${opts.env}). Redeploy to apply.`);
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const CLI_VERSION = '0.2.145';
1
+ export const CLI_VERSION = '0.2.147';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runcloud",
3
- "version": "0.2.145",
3
+ "version": "0.2.147",
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