runcloud 0.2.155 → 0.2.156
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/dist/commands/appStoreEvaluate.js +12 -26
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/runcloud-0.2.156.tgz +0 -0
- package/runcloud-0.2.155.tgz +0 -0
|
@@ -1,6 +1,14 @@
|
|
|
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 PLACEHOLDER_COPY = /lorem ipsum|example\.com|\bTBD\b|\bTODO\b|\bplaceholder\b/i;
|
|
5
|
+
const INPUT_PLACEHOLDER = /\bplaceholder\??\s*[=:]\s*(\{[^}]*\}|"[^"]*"|'[^']*'|`[^`]*`|[\w.$]+)/gi;
|
|
6
|
+
const PLACEHOLDER_NAME = /\.placeholder\b|\bplaceholder\b(?=\s*[,})\]])/gi;
|
|
7
|
+
function withoutInputPlaceholders(line) {
|
|
8
|
+
return line
|
|
9
|
+
.replace(INPUT_PLACEHOLDER, (_prop, value) => (/^["'`]/.test(value) ? value.replace(/example\.com/gi, '') : ''))
|
|
10
|
+
.replace(PLACEHOLDER_NAME, '');
|
|
11
|
+
}
|
|
4
12
|
const CONFIG_RULES = {
|
|
5
13
|
app_name: { path: ['expo', 'name'], absent: 'fail' },
|
|
6
14
|
slug: { path: ['expo', 'slug'], absent: 'fail' },
|
|
@@ -157,7 +165,9 @@ function evaluateLocalItem(root, appJson, item) {
|
|
|
157
165
|
case 'http_endpoints':
|
|
158
166
|
return patternItem(root, item, /http:\/\/(?!localhost|127\.0\.0\.1)/i, 'warning', 'Non-local HTTP endpoint found.', 'No non-local HTTP endpoints found.');
|
|
159
167
|
case 'placeholder_content':
|
|
160
|
-
return patternItem(root, item,
|
|
168
|
+
return patternItem(root, item, PLACEHOLDER_COPY, 'warning', 'Placeholder text found.', 'No placeholder text found.', {
|
|
169
|
+
filter: (match) => PLACEHOLDER_COPY.test(withoutInputPlaceholders(match.text)),
|
|
170
|
+
});
|
|
161
171
|
case 'competitor_reference':
|
|
162
172
|
return patternItem(root, item, /google play|\.apk\b|samsung|android app/i, 'warning', 'Possible platform/competitor reference found in user-facing copy.', 'No competitor platform references found.', { dirs: ['app', 'src', 'components'] });
|
|
163
173
|
case 'private_api_usage':
|
|
@@ -180,7 +190,7 @@ function evaluateLocalItem(root, appJson, item) {
|
|
|
180
190
|
case 'external_payment_digital':
|
|
181
191
|
return evaluateExternalPayment(root, item);
|
|
182
192
|
case 'expo_layout_missing':
|
|
183
|
-
return
|
|
193
|
+
return makeItem(item, 'pass', 'Expo Router adds a layout where a directory has none.', 'expo-router getRoutesCore.js');
|
|
184
194
|
case 'expo_duplicate_route':
|
|
185
195
|
return evaluateDuplicateRoutes(root, item);
|
|
186
196
|
case 'ios_encryption':
|
|
@@ -248,16 +258,6 @@ function evaluateExternalPayment(root, item) {
|
|
|
248
258
|
return makeItem(item, 'pass', 'No external payment SDK patterns found.', 'scan: no Stripe/PayPal/Braintree patterns found');
|
|
249
259
|
return makeItem(item, 'warning', 'External payment SDK found; verify it is not used for digital goods on iOS.', evidence(matches));
|
|
250
260
|
}
|
|
251
|
-
function evaluateExpoLayout(root, item) {
|
|
252
|
-
const appDir = path.join(root, 'app');
|
|
253
|
-
if (!existsSync(appDir))
|
|
254
|
-
return makeItem(item, 'pass', 'No Expo Router app directory found.', 'scan: app/ directory absent');
|
|
255
|
-
const dirs = walkDirs(appDir).map((dir) => path.relative(root, dir) || 'app');
|
|
256
|
-
const missing = dirs.filter((dir) => !hasLayoutFile(path.join(root, dir)));
|
|
257
|
-
if (!missing.length)
|
|
258
|
-
return makeItem(item, 'pass', 'Every app route directory has a layout file.', 'scan: app route directories');
|
|
259
|
-
return makeItem(item, 'fail', 'Expo Router directories without _layout files found.', missing.slice(0, 8).join(', '));
|
|
260
|
-
}
|
|
261
261
|
function evaluateDuplicateRoutes(root, item) {
|
|
262
262
|
const appDir = routerDir(root);
|
|
263
263
|
if (!existsSync(appDir))
|
|
@@ -516,17 +516,6 @@ function walkFiles(dir) {
|
|
|
516
516
|
}
|
|
517
517
|
return files;
|
|
518
518
|
}
|
|
519
|
-
function walkDirs(dir) {
|
|
520
|
-
const dirs = [dir];
|
|
521
|
-
for (const entry of safeReadDir(dir)) {
|
|
522
|
-
if (SKIP_DIRS.has(entry.name))
|
|
523
|
-
continue;
|
|
524
|
-
const full = path.join(dir, entry.name);
|
|
525
|
-
if (entry.isDirectory())
|
|
526
|
-
dirs.push(...walkDirs(full));
|
|
527
|
-
}
|
|
528
|
-
return dirs;
|
|
529
|
-
}
|
|
530
519
|
function shouldScanFile(file) {
|
|
531
520
|
return TEXT_EXTENSIONS.has(path.extname(file));
|
|
532
521
|
}
|
|
@@ -536,9 +525,6 @@ function findByName(root, name) {
|
|
|
536
525
|
function sourceText(root, dirs) {
|
|
537
526
|
return collectScanFiles(root, dirs).map((file) => readText(file) ?? '').join('\n');
|
|
538
527
|
}
|
|
539
|
-
function hasLayoutFile(dir) {
|
|
540
|
-
return ['_layout.tsx', '_layout.ts', '_layout.jsx', '_layout.js'].some((name) => existsSync(path.join(dir, name)));
|
|
541
|
-
}
|
|
542
528
|
function routerDir(root) {
|
|
543
529
|
const src = path.join(root, 'src', 'app');
|
|
544
530
|
return safeStat(src)?.isDirectory() ? src : path.join(root, 'app');
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = '0.2.
|
|
1
|
+
export const CLI_VERSION = '0.2.156';
|
package/package.json
CHANGED
|
Binary file
|
package/runcloud-0.2.155.tgz
DELETED
|
Binary file
|