umpordez 1.5.0 → 1.5.1
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/.claude/settings.local.json +7 -1
- package/create.mjs +104 -0
- package/package.json +1 -1
- package/template/gitignore +2 -0
- package/template/install.sh +4 -0
- package/template/scripts/clean-appledouble.sh +42 -0
- package/template/scripts/prebuild.sh +8 -1
- package/template/scripts/run-ios.sh +5 -0
|
@@ -57,7 +57,13 @@
|
|
|
57
57
|
"Bash(git *)",
|
|
58
58
|
"Bash(npm init *)",
|
|
59
59
|
"Bash(awk 'NR>=383 && NR<=386 {print NR\": \"substr\\($0,1,120\\)}' '/Users/ligeiro/dev/umpordez-cli/template/mobile/{{PROJECT_SLUG}}/src/pages/auth/AuthLanding.tsx')",
|
|
60
|
-
"Bash(awk 'NR>=394 && NR<=410 {print NR\": \"substr\\($0,1,100\\)}' '/Users/ligeiro/dev/umpordez-cli/template/mobile/{{PROJECT_SLUG}}/src/pages/auth/AuthLanding.tsx')"
|
|
60
|
+
"Bash(awk 'NR>=394 && NR<=410 {print NR\": \"substr\\($0,1,100\\)}' '/Users/ligeiro/dev/umpordez-cli/template/mobile/{{PROJECT_SLUG}}/src/pages/auth/AuthLanding.tsx')",
|
|
61
|
+
"Bash(diskutil info *)",
|
|
62
|
+
"Bash(mount)",
|
|
63
|
+
"Bash(bash -n template/scripts/clean-appledouble.sh)",
|
|
64
|
+
"Bash(bash -n template/scripts/prebuild.sh)",
|
|
65
|
+
"Bash(bash -n template/scripts/run-ios.sh)",
|
|
66
|
+
"Bash(bash -n template/install.sh)"
|
|
61
67
|
]
|
|
62
68
|
}
|
|
63
69
|
}
|
package/create.mjs
CHANGED
|
@@ -394,6 +394,104 @@ function validatePort(v) {
|
|
|
394
394
|
: 'Must be a valid port number';
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
+
// Filesystems that can't store extended attributes or symlinks. On
|
|
398
|
+
// macOS these make the OS scatter AppleDouble `._*` sidecar files next
|
|
399
|
+
// to everything npm installs — CocoaPods then fails parsing a
|
|
400
|
+
// `._Foo.podspec` during `expo prebuild`, and node_modules symlinks
|
|
401
|
+
// break. Generating an Expo project on one of these is a trap, so we
|
|
402
|
+
// warn before doing it.
|
|
403
|
+
const NON_NATIVE_FS = new Set([
|
|
404
|
+
'exfat', 'msdos', 'fat32', 'vfat',
|
|
405
|
+
'ntfs', 'ntfs-3g', 'fuseblk',
|
|
406
|
+
'smbfs', 'cifs', 'nfs', 'afpfs', 'webdav',
|
|
407
|
+
]);
|
|
408
|
+
|
|
409
|
+
// Resolve the filesystem type backing `targetPath`. The output dir
|
|
410
|
+
// usually doesn't exist yet, so we walk up to the nearest existing
|
|
411
|
+
// ancestor, then match it against the longest mount point in `mount`.
|
|
412
|
+
// Returns { mountPoint, fsType } or null (non-darwin, or undetectable).
|
|
413
|
+
function volumeInfo(targetPath) {
|
|
414
|
+
if (process.platform !== 'darwin') {
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
let dir = path.resolve(targetPath);
|
|
419
|
+
while (dir !== path.dirname(dir) && !fs.existsSync(dir)) {
|
|
420
|
+
dir = path.dirname(dir);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
let mounts;
|
|
424
|
+
try {
|
|
425
|
+
mounts = execSync('mount', { encoding: 'utf-8' });
|
|
426
|
+
} catch {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Lines look like: `/dev/disk10s1 on /Volumes/big (exfat, local, …)`
|
|
431
|
+
let best = null;
|
|
432
|
+
for (const line of mounts.split('\n')) {
|
|
433
|
+
const m = line.match(/ on (.+?) \(([^,)]+)/);
|
|
434
|
+
if (!m) {
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
const mountPoint = m[1];
|
|
438
|
+
const fsType = m[2].trim().toLowerCase();
|
|
439
|
+
const prefix = mountPoint.endsWith('/') ? mountPoint : mountPoint + '/';
|
|
440
|
+
if (dir === mountPoint || dir.startsWith(prefix)) {
|
|
441
|
+
if (!best || mountPoint.length > best.mountPoint.length) {
|
|
442
|
+
best = { mountPoint, fsType };
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return best;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// Warn (and confirm) before generating a mobile project onto a
|
|
450
|
+
// filesystem macOS can't build native code on. Returns true to
|
|
451
|
+
// proceed, false to abort. Only meaningful when a mobile app is part
|
|
452
|
+
// of the project — the acute failure is CocoaPods + `expo prebuild`.
|
|
453
|
+
async function confirmFilesystem(outputDir, components) {
|
|
454
|
+
if (!components.mobile) {
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
const vol = volumeInfo(outputDir);
|
|
458
|
+
if (!vol || !NON_NATIVE_FS.has(vol.fsType)) {
|
|
459
|
+
return true;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
console.log('');
|
|
463
|
+
console.log(red.bold(
|
|
464
|
+
` ⚠ ${vol.mountPoint} is a ${vol.fsType} volume.`
|
|
465
|
+
));
|
|
466
|
+
console.log(dim(
|
|
467
|
+
' macOS can\'t store extended attributes or symlinks there,'
|
|
468
|
+
));
|
|
469
|
+
console.log(dim(
|
|
470
|
+
' so it scatters AppleDouble `._*` files next to everything'
|
|
471
|
+
));
|
|
472
|
+
console.log(dim(
|
|
473
|
+
' npm installs. `expo prebuild` then fails when CocoaPods'
|
|
474
|
+
));
|
|
475
|
+
console.log(dim(
|
|
476
|
+
' tries to parse a `._Foo.podspec`, and node_modules'
|
|
477
|
+
));
|
|
478
|
+
console.log(dim(' symlinks break.'));
|
|
479
|
+
console.log('');
|
|
480
|
+
console.log(dim(
|
|
481
|
+
' Recommended: generate on your internal drive (e.g. ~/dev),'
|
|
482
|
+
));
|
|
483
|
+
console.log(dim(' an APFS / Mac OS Extended volume.'));
|
|
484
|
+
console.log('');
|
|
485
|
+
|
|
486
|
+
const { proceed } = await inquirer.prompt([{
|
|
487
|
+
type: 'confirm',
|
|
488
|
+
name: 'proceed',
|
|
489
|
+
message: `Generate on the ${vol.fsType} volume anyway?`,
|
|
490
|
+
default: false,
|
|
491
|
+
}]);
|
|
492
|
+
return proceed;
|
|
493
|
+
}
|
|
494
|
+
|
|
397
495
|
function componentsLabel(c) {
|
|
398
496
|
const parts = [];
|
|
399
497
|
if (c.server) parts.push('server API');
|
|
@@ -604,6 +702,11 @@ export async function createProject() {
|
|
|
604
702
|
|
|
605
703
|
const outputDir = path.resolve(details.outputDir);
|
|
606
704
|
|
|
705
|
+
if (!await confirmFilesystem(outputDir, details.components)) {
|
|
706
|
+
console.log(chalk.yellow('Aborted. No files were created.'));
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
|
|
607
710
|
if (fs.existsSync(outputDir)) {
|
|
608
711
|
const { overwrite } = await inquirer.prompt([{
|
|
609
712
|
type: 'confirm',
|
|
@@ -710,6 +813,7 @@ export async function createProject() {
|
|
|
710
813
|
if (details.components.mobile) {
|
|
711
814
|
scripts.push(
|
|
712
815
|
'scripts/bump-version.sh',
|
|
816
|
+
'scripts/clean-appledouble.sh',
|
|
713
817
|
'scripts/prebuild.sh',
|
|
714
818
|
'scripts/run-ios.sh',
|
|
715
819
|
'scripts/release-android.sh',
|
package/package.json
CHANGED
package/template/gitignore
CHANGED
package/template/install.sh
CHANGED
|
@@ -55,6 +55,10 @@ if [ -d "mobile/{{PROJECT_SLUG}}" ]; then
|
|
|
55
55
|
|
|
56
56
|
if [[ "$(uname)" == "Darwin" ]]; then
|
|
57
57
|
if [ -d "mobile/{{PROJECT_SLUG}}/ios" ]; then
|
|
58
|
+
# Strip AppleDouble `._*` files (exFAT/NTFS/network
|
|
59
|
+
# volumes) so pod install doesn't choke on a
|
|
60
|
+
# `._Foo.podspec`. No-op on APFS.
|
|
61
|
+
./scripts/clean-appledouble.sh "mobile/{{PROJECT_SLUG}}"
|
|
58
62
|
echo "Installing iOS pods..."
|
|
59
63
|
(cd "mobile/{{PROJECT_SLUG}}/ios" && pod install)
|
|
60
64
|
fi
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# clean-appledouble — remove macOS AppleDouble `._*` sidecar files.
|
|
4
|
+
#
|
|
5
|
+
# macOS drops a `._<name>` metadata file next to every file that carries
|
|
6
|
+
# extended attributes when it lives on a filesystem that can't store
|
|
7
|
+
# xattrs natively (exFAT, MS-DOS/FAT, NTFS, SMB/NFS network mounts).
|
|
8
|
+
# CocoaPods then scans for `*.podspec`, finds `._Foo.podspec`, tries to
|
|
9
|
+
# parse the binary metadata as Ruby, and `pod install` — and therefore
|
|
10
|
+
# `expo prebuild` / `expo run:ios` — dies with:
|
|
11
|
+
#
|
|
12
|
+
# Invalid `Podfile` file: Invalid podspec file at path
|
|
13
|
+
# .../node_modules/.../ios/._Foo.podspec
|
|
14
|
+
#
|
|
15
|
+
# On APFS / Mac OS Extended there are none, so this is a fast no-op. Run
|
|
16
|
+
# it before any pod install / prebuild / native build.
|
|
17
|
+
#
|
|
18
|
+
# The real fix is to keep the project on an APFS / Mac OS Extended disk
|
|
19
|
+
# (e.g. ~/dev) — exFAT/NTFS regenerate these files on every npm install.
|
|
20
|
+
#
|
|
21
|
+
# Usage: ./scripts/clean-appledouble.sh [dir] (default: repo root)
|
|
22
|
+
|
|
23
|
+
set -euo pipefail
|
|
24
|
+
|
|
25
|
+
# AppleDouble files are a macOS-only artifact.
|
|
26
|
+
[[ "$(uname)" == "Darwin" ]] || exit 0
|
|
27
|
+
|
|
28
|
+
TARGET="${1:-$(cd "$(dirname "$0")/.." && pwd)}"
|
|
29
|
+
[[ -d "$TARGET" ]] || exit 0
|
|
30
|
+
|
|
31
|
+
n=$(
|
|
32
|
+
find "$TARGET" -name '._*' -type f -print -delete 2>/dev/null \
|
|
33
|
+
| wc -l | tr -d ' '
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
if [[ "${n:-0}" -gt 0 ]]; then
|
|
37
|
+
echo "==> Removed $n AppleDouble ._* file(s) under $TARGET"
|
|
38
|
+
echo " This disk can't store macOS extended attributes (likely"
|
|
39
|
+
echo " exFAT/NTFS/network), so they'll return on the next npm"
|
|
40
|
+
echo " install. For clean native builds, move the project to an"
|
|
41
|
+
echo " APFS / Mac OS Extended disk (e.g. ~/dev)."
|
|
42
|
+
fi
|
|
@@ -24,5 +24,12 @@ for arg in "$@"; do
|
|
|
24
24
|
esac
|
|
25
25
|
done
|
|
26
26
|
|
|
27
|
-
cd "$(dirname "$0")
|
|
27
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
28
|
+
cd "$SCRIPT_DIR/../mobile/{{PROJECT_SLUG}}"
|
|
29
|
+
|
|
30
|
+
# Strip macOS AppleDouble `._*` files before prebuild — CocoaPods
|
|
31
|
+
# chokes on `._Foo.podspec` when the project lives on exFAT/NTFS/network
|
|
32
|
+
# volumes. No-op on APFS. See scripts/clean-appledouble.sh.
|
|
33
|
+
"$SCRIPT_DIR/clean-appledouble.sh" "$PWD"
|
|
34
|
+
|
|
28
35
|
exec npx expo prebuild "$@"
|
|
@@ -53,6 +53,11 @@ done
|
|
|
53
53
|
|
|
54
54
|
cd "$APP_DIR"
|
|
55
55
|
|
|
56
|
+
# Strip macOS AppleDouble `._*` files so the pod install triggered by
|
|
57
|
+
# `expo run:ios` doesn't choke on `._Foo.podspec` (exFAT/NTFS/network
|
|
58
|
+
# volumes). No-op on APFS. See scripts/clean-appledouble.sh.
|
|
59
|
+
"$SCRIPT_DIR/clean-appledouble.sh" "$APP_DIR"
|
|
60
|
+
|
|
56
61
|
if [[ $CLEAN -eq 1 ]]; then
|
|
57
62
|
echo "==> Cleaning iOS build artifacts..."
|
|
58
63
|
rm -rf ios/build
|