@ceraph/react-native-mcp 0.3.2 → 0.4.5
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/README.md +335 -68
- package/dist/babel-plugin/index.cjs +1 -0
- package/dist/babel-plugin/index.js +1 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +1 -47
- package/dist/index.d.ts +106 -1
- package/dist/index.js +2 -1651
- package/dist/shim/async-storage-ops.d.ts +26 -0
- package/dist/shim/async-storage-ops.js +1 -0
- package/dist/shim/boot.d.ts +9 -0
- package/dist/shim/boot.js +1 -141
- package/dist/shim/camera.js +1 -62
- package/dist/shim/command-poll.d.ts +18 -0
- package/dist/shim/command-poll.js +1 -0
- package/dist/shim/config.js +1 -56
- package/dist/shim/console-capture.d.ts +16 -0
- package/dist/shim/console-capture.js +1 -0
- package/dist/shim/deep-link.js +1 -25
- package/dist/shim/dev-guard.js +1 -3
- package/dist/shim/dev-host.d.ts +1 -0
- package/dist/shim/dev-host.js +1 -0
- package/dist/shim/error-handler.js +1 -66
- package/dist/shim/fetch-interceptor.js +1 -93
- package/dist/shim/index.d.ts +3 -0
- package/dist/shim/index.js +1 -6
- package/dist/shim/keep-awake.js +1 -118
- package/dist/shim/network-ownership.d.ts +4 -0
- package/dist/shim/network-ownership.js +1 -0
- package/dist/shim/optimistic-observer.d.ts +29 -0
- package/dist/shim/optimistic-observer.js +1 -0
- package/dist/shim/reload.js +1 -76
- package/dist/shim/reset.d.ts +30 -0
- package/dist/shim/reset.js +1 -0
- package/dist/shim/signal-capture.d.ts +8 -0
- package/dist/shim/signal-capture.js +1 -15
- package/dist/shim/signal-transport.d.ts +14 -1
- package/dist/shim/signal-transport.js +1 -43
- package/dist/shim/xhr-interceptor.d.ts +39 -0
- package/dist/shim/xhr-interceptor.js +1 -0
- package/package.json +41 -15
- package/dist/app-lifecycle.d.ts +0 -50
- package/dist/app-lifecycle.js +0 -487
- package/dist/camera-image-writer.d.ts +0 -43
- package/dist/camera-image-writer.js +0 -280
- package/dist/camera-registry-sync.d.ts +0 -18
- package/dist/camera-registry-sync.js +0 -117
- package/dist/device-autonomy.d.ts +0 -30
- package/dist/device-autonomy.js +0 -117
- package/dist/error-parser.d.ts +0 -51
- package/dist/error-parser.js +0 -275
- package/dist/expo-manager.d.ts +0 -62
- package/dist/expo-manager.js +0 -447
- package/dist/init/ast-camera.d.ts +0 -29
- package/dist/init/ast-camera.js +0 -267
- package/dist/init/ast-layout.d.ts +0 -15
- package/dist/init/ast-layout.js +0 -167
- package/dist/init/claude-hook-constants.d.ts +0 -9
- package/dist/init/claude-hook-constants.js +0 -91
- package/dist/init/lan-ip.d.ts +0 -11
- package/dist/init/lan-ip.js +0 -51
- package/dist/init/monorepo.d.ts +0 -13
- package/dist/init/monorepo.js +0 -185
- package/dist/init/oauth.d.ts +0 -52
- package/dist/init/oauth.js +0 -220
- package/dist/init/package-manager.d.ts +0 -11
- package/dist/init/package-manager.js +0 -60
- package/dist/init/prompt.d.ts +0 -12
- package/dist/init/prompt.js +0 -68
- package/dist/init/shell-profile.d.ts +0 -22
- package/dist/init/shell-profile.js +0 -85
- package/dist/init/steps.d.ts +0 -135
- package/dist/init/steps.js +0 -399
- package/dist/init/url-scheme.d.ts +0 -42
- package/dist/init/url-scheme.js +0 -187
- package/dist/init/walkthrough.d.ts +0 -76
- package/dist/init/walkthrough.js +0 -340
- package/dist/init.d.ts +0 -8
- package/dist/init.js +0 -395
- package/dist/iproxy-manager.d.ts +0 -32
- package/dist/iproxy-manager.js +0 -216
- package/dist/mac-caffeinate.d.ts +0 -10
- package/dist/mac-caffeinate.js +0 -56
- package/dist/permission-interceptor.d.ts +0 -29
- package/dist/permission-interceptor.js +0 -185
- package/dist/prebuild-detector.d.ts +0 -19
- package/dist/prebuild-detector.js +0 -174
- package/dist/preflight.d.ts +0 -34
- package/dist/preflight.js +0 -847
- package/dist/screen.d.ts +0 -184
- package/dist/screen.js +0 -931
- package/dist/signal-listener.d.ts +0 -27
- package/dist/signal-listener.js +0 -135
- package/dist/simulator-boot.d.ts +0 -52
- package/dist/simulator-boot.js +0 -227
- package/dist/target.d.ts +0 -48
- package/dist/target.js +0 -267
- package/dist/uninstall/cli-runner.d.ts +0 -32
- package/dist/uninstall/cli-runner.js +0 -223
- package/dist/uninstall/footprint.d.ts +0 -40
- package/dist/uninstall/footprint.js +0 -288
- package/dist/uninstall/mcp-tools.d.ts +0 -14
- package/dist/uninstall/mcp-tools.js +0 -175
- package/dist/uninstall/revert-auth.d.ts +0 -22
- package/dist/uninstall/revert-auth.js +0 -31
- package/dist/uninstall/revert-boot.d.ts +0 -24
- package/dist/uninstall/revert-boot.js +0 -242
- package/dist/uninstall/revert-camera.d.ts +0 -12
- package/dist/uninstall/revert-camera.js +0 -199
- package/dist/uninstall/revert-ceraph-dir.d.ts +0 -27
- package/dist/uninstall/revert-ceraph-dir.js +0 -38
- package/dist/uninstall/revert-claude-hooks.d.ts +0 -19
- package/dist/uninstall/revert-claude-hooks.js +0 -191
- package/dist/uninstall/revert-gitignore.d.ts +0 -17
- package/dist/uninstall/revert-gitignore.js +0 -43
- package/dist/uninstall/revert-mcp-clients.d.ts +0 -57
- package/dist/uninstall/revert-mcp-clients.js +0 -194
- package/dist/uninstall/revert-package.d.ts +0 -34
- package/dist/uninstall/revert-package.js +0 -98
- package/dist/uninstall/revert-scheme.d.ts +0 -36
- package/dist/uninstall/revert-scheme.js +0 -139
- package/dist/uninstall/revert-signal-host-env.d.ts +0 -31
- package/dist/uninstall/revert-signal-host-env.js +0 -61
- package/dist/uninstall/walkthrough.d.ts +0 -80
- package/dist/uninstall/walkthrough.js +0 -1244
- package/dist/utils/atomic-write.d.ts +0 -1
- package/dist/utils/atomic-write.js +0 -30
- package/dist/wait-for-device.d.ts +0 -68
- package/dist/wait-for-device.js +0 -368
- package/dist/wda-manager.d.ts +0 -38
- package/dist/wda-manager.js +0 -186
- package/dist/wda-simulator.d.ts +0 -28
- package/dist/wda-simulator.js +0 -257
package/dist/mac-caffeinate.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { spawn as nodeSpawn } from "node:child_process";
|
|
2
|
-
let child = null;
|
|
3
|
-
let active = false;
|
|
4
|
-
let spawnerOverride = null;
|
|
5
|
-
export function _resetForTesting() {
|
|
6
|
-
child = null;
|
|
7
|
-
active = false;
|
|
8
|
-
spawnerOverride = null;
|
|
9
|
-
}
|
|
10
|
-
export function _setSpawnerForTesting(fn) {
|
|
11
|
-
spawnerOverride = fn;
|
|
12
|
-
}
|
|
13
|
-
export function enableCaffeinate() {
|
|
14
|
-
if (process.platform !== "darwin") {
|
|
15
|
-
return { applied: false, reason: "not-darwin" };
|
|
16
|
-
}
|
|
17
|
-
if (active && child && !child.killed) {
|
|
18
|
-
return { applied: true, reason: "already-active" };
|
|
19
|
-
}
|
|
20
|
-
try {
|
|
21
|
-
const spawnFn = spawnerOverride ?? nodeSpawn;
|
|
22
|
-
const proc = spawnFn("caffeinate", ["-di", "-w", String(process.pid)], {
|
|
23
|
-
detached: true,
|
|
24
|
-
stdio: "ignore",
|
|
25
|
-
});
|
|
26
|
-
if (typeof proc.unref === "function") {
|
|
27
|
-
proc.unref();
|
|
28
|
-
}
|
|
29
|
-
child = proc;
|
|
30
|
-
active = true;
|
|
31
|
-
const thisChild = proc;
|
|
32
|
-
proc.once("exit", () => {
|
|
33
|
-
if (child === thisChild) {
|
|
34
|
-
child = null;
|
|
35
|
-
active = false;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
return { applied: true, reason: "started" };
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
return { applied: false, reason: "spawn-failed" };
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export function disableCaffeinate() {
|
|
45
|
-
if (!active)
|
|
46
|
-
return;
|
|
47
|
-
if (child) {
|
|
48
|
-
try {
|
|
49
|
-
child.kill("SIGTERM");
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
child = null;
|
|
55
|
-
active = false;
|
|
56
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { ScreenManager } from "./screen.js";
|
|
2
|
-
export type InterceptorMode = "auto-accept" | "ask" | "off";
|
|
3
|
-
export interface PermissionInterceptorOpts {
|
|
4
|
-
screen: ScreenManager;
|
|
5
|
-
mode: InterceptorMode;
|
|
6
|
-
onDialog?: (info: {
|
|
7
|
-
title: string;
|
|
8
|
-
body: string;
|
|
9
|
-
}) => Promise<"accept" | "deny">;
|
|
10
|
-
}
|
|
11
|
-
export interface DialogInfo {
|
|
12
|
-
title: string;
|
|
13
|
-
body: string;
|
|
14
|
-
action: "accept" | "deny";
|
|
15
|
-
}
|
|
16
|
-
export interface InterceptResult {
|
|
17
|
-
handled: boolean;
|
|
18
|
-
dialog?: DialogInfo;
|
|
19
|
-
}
|
|
20
|
-
export declare class PermissionInterceptor {
|
|
21
|
-
private readonly screen;
|
|
22
|
-
private mode;
|
|
23
|
-
private readonly onDialog?;
|
|
24
|
-
constructor(opts: PermissionInterceptorOpts);
|
|
25
|
-
getMode(): InterceptorMode;
|
|
26
|
-
setMode(mode: InterceptorMode): void;
|
|
27
|
-
checkAndHandle(): Promise<InterceptResult>;
|
|
28
|
-
}
|
|
29
|
-
export declare function modeFromEnv(value: string | undefined): InterceptorMode;
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
const KNOWN_DIALOGS = [
|
|
2
|
-
{
|
|
3
|
-
id: "camera",
|
|
4
|
-
titlePattern: /Would Like to Access the Camera/i,
|
|
5
|
-
acceptButtons: ["OK", "Allow"],
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
id: "microphone",
|
|
9
|
-
titlePattern: /Would Like to Access the Microphone/i,
|
|
10
|
-
acceptButtons: ["OK", "Allow"],
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
id: "photos",
|
|
14
|
-
titlePattern: /Would Like to Access Your Photos/i,
|
|
15
|
-
acceptButtons: [
|
|
16
|
-
"Allow Access to All Photos",
|
|
17
|
-
"Allow Full Access",
|
|
18
|
-
"Allow",
|
|
19
|
-
],
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
id: "location",
|
|
23
|
-
titlePattern: /Allow .* to Use Your Location\??/i,
|
|
24
|
-
acceptButtons: [
|
|
25
|
-
"Allow While Using App",
|
|
26
|
-
"Allow Once",
|
|
27
|
-
"Allow",
|
|
28
|
-
],
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: "notifications",
|
|
32
|
-
titlePattern: /Would Like to Send You Notifications/i,
|
|
33
|
-
acceptButtons: ["Allow"],
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: "local-network",
|
|
37
|
-
titlePattern: /Would Like to Find and Connect to Devices on Your Local Network/i,
|
|
38
|
-
acceptButtons: ["Allow", "OK"],
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
id: "bluetooth",
|
|
42
|
-
titlePattern: /Would Like to Use Bluetooth/i,
|
|
43
|
-
acceptButtons: ["OK", "Allow"],
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: "tracking",
|
|
47
|
-
titlePattern: /Allow .* to track your activity|would like permission to track/i,
|
|
48
|
-
acceptButtons: ["Allow"],
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
id: "faceid",
|
|
52
|
-
titlePattern: /Would Like to Use Face ID/i,
|
|
53
|
-
acceptButtons: ["OK", "Allow"],
|
|
54
|
-
},
|
|
55
|
-
];
|
|
56
|
-
const ALERT_TYPE_PATTERNS = [
|
|
57
|
-
/XCUIElementTypeAlert/i,
|
|
58
|
-
/SBAlertController/i,
|
|
59
|
-
];
|
|
60
|
-
function isAlertElement(el) {
|
|
61
|
-
const type = String(el.type ?? "");
|
|
62
|
-
return ALERT_TYPE_PATTERNS.some((p) => p.test(type));
|
|
63
|
-
}
|
|
64
|
-
function findAlert(root) {
|
|
65
|
-
if (isAlertElement(root))
|
|
66
|
-
return root;
|
|
67
|
-
const children = root.children;
|
|
68
|
-
if (Array.isArray(children)) {
|
|
69
|
-
for (const child of children) {
|
|
70
|
-
const found = findAlert(child);
|
|
71
|
-
if (found)
|
|
72
|
-
return found;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
function collectAlertContents(root) {
|
|
78
|
-
const texts = [];
|
|
79
|
-
const buttons = [];
|
|
80
|
-
const visit = (el) => {
|
|
81
|
-
const type = String(el.type ?? "");
|
|
82
|
-
const label = String(el.label ?? el.name ?? "");
|
|
83
|
-
const value = String(el.value ?? "");
|
|
84
|
-
if (/XCUIElementTypeStaticText/i.test(type)) {
|
|
85
|
-
const text = label || value;
|
|
86
|
-
if (text)
|
|
87
|
-
texts.push(text);
|
|
88
|
-
}
|
|
89
|
-
else if (/XCUIElementTypeButton/i.test(type)) {
|
|
90
|
-
if (label)
|
|
91
|
-
buttons.push({ label, element: el });
|
|
92
|
-
}
|
|
93
|
-
else if (!type) {
|
|
94
|
-
}
|
|
95
|
-
const children = el.children;
|
|
96
|
-
if (Array.isArray(children)) {
|
|
97
|
-
for (const child of children)
|
|
98
|
-
visit(child);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
visit(root);
|
|
102
|
-
return { texts, buttons };
|
|
103
|
-
}
|
|
104
|
-
export class PermissionInterceptor {
|
|
105
|
-
screen;
|
|
106
|
-
mode;
|
|
107
|
-
onDialog;
|
|
108
|
-
constructor(opts) {
|
|
109
|
-
this.screen = opts.screen;
|
|
110
|
-
this.mode = opts.mode;
|
|
111
|
-
this.onDialog = opts.onDialog;
|
|
112
|
-
}
|
|
113
|
-
getMode() {
|
|
114
|
-
return this.mode;
|
|
115
|
-
}
|
|
116
|
-
setMode(mode) {
|
|
117
|
-
this.mode = mode;
|
|
118
|
-
}
|
|
119
|
-
async checkAndHandle() {
|
|
120
|
-
if (this.mode === "off") {
|
|
121
|
-
return { handled: false };
|
|
122
|
-
}
|
|
123
|
-
const src = await this.screen.getSource().catch(() => undefined);
|
|
124
|
-
if (!src?.success || !src.source) {
|
|
125
|
-
return { handled: false };
|
|
126
|
-
}
|
|
127
|
-
const alert = findAlert(src.source);
|
|
128
|
-
if (!alert)
|
|
129
|
-
return { handled: false };
|
|
130
|
-
const { texts, buttons } = collectAlertContents(alert);
|
|
131
|
-
if (texts.length === 0 && buttons.length === 0) {
|
|
132
|
-
return { handled: false };
|
|
133
|
-
}
|
|
134
|
-
const title = texts[0] ?? "";
|
|
135
|
-
const body = texts.slice(1).join(" ");
|
|
136
|
-
const pattern = KNOWN_DIALOGS.find((p) => p.titlePattern.test(title));
|
|
137
|
-
if (!pattern) {
|
|
138
|
-
return { handled: false };
|
|
139
|
-
}
|
|
140
|
-
let action = "accept";
|
|
141
|
-
if (this.mode === "ask") {
|
|
142
|
-
if (this.onDialog) {
|
|
143
|
-
try {
|
|
144
|
-
action = await this.onDialog({ title, body });
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
action = "accept";
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
const buttonLabels = action === "accept"
|
|
152
|
-
? pattern.acceptButtons
|
|
153
|
-
: pattern.denyButtons ?? ["Don't Allow", "Cancel"];
|
|
154
|
-
const target = buttonLabels
|
|
155
|
-
.map((preferred) => buttons.find((b) => b.label.toLowerCase() === preferred.toLowerCase()))
|
|
156
|
-
.find((b) => !!b);
|
|
157
|
-
if (!target) {
|
|
158
|
-
return {
|
|
159
|
-
handled: false,
|
|
160
|
-
dialog: { title, body, action },
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
const tap = await this.screen.findAndTap({
|
|
164
|
-
accessibilityLabel: target.label,
|
|
165
|
-
});
|
|
166
|
-
if (!tap.success) {
|
|
167
|
-
return {
|
|
168
|
-
handled: false,
|
|
169
|
-
dialog: { title, body, action },
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
return {
|
|
173
|
-
handled: true,
|
|
174
|
-
dialog: { title, body, action },
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
export function modeFromEnv(value) {
|
|
179
|
-
const v = (value ?? "").toLowerCase();
|
|
180
|
-
if (v === "off" || v === "false" || v === "0")
|
|
181
|
-
return "off";
|
|
182
|
-
if (v === "ask")
|
|
183
|
-
return "ask";
|
|
184
|
-
return "auto-accept";
|
|
185
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
interface PrebuildCheckResult {
|
|
2
|
-
needsClean: boolean;
|
|
3
|
-
reasons: string[];
|
|
4
|
-
}
|
|
5
|
-
export declare class PrebuildDetector {
|
|
6
|
-
private cacheDir;
|
|
7
|
-
private projectDir;
|
|
8
|
-
private snapshotPath;
|
|
9
|
-
constructor(projectDir: string, cacheDir: string);
|
|
10
|
-
private fileExists;
|
|
11
|
-
private readJson;
|
|
12
|
-
private hashFile;
|
|
13
|
-
private getCurrentState;
|
|
14
|
-
private loadSnapshot;
|
|
15
|
-
saveSnapshot(): Promise<void>;
|
|
16
|
-
private diffDependencies;
|
|
17
|
-
check(): Promise<PrebuildCheckResult>;
|
|
18
|
-
}
|
|
19
|
-
export {};
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { readFile, writeFile, mkdir, access } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
export class PrebuildDetector {
|
|
4
|
-
cacheDir;
|
|
5
|
-
projectDir;
|
|
6
|
-
snapshotPath;
|
|
7
|
-
constructor(projectDir, cacheDir) {
|
|
8
|
-
this.projectDir = projectDir;
|
|
9
|
-
this.cacheDir = cacheDir;
|
|
10
|
-
this.snapshotPath = join(cacheDir, "last-build-snapshot.json");
|
|
11
|
-
}
|
|
12
|
-
async fileExists(path) {
|
|
13
|
-
try {
|
|
14
|
-
await access(path);
|
|
15
|
-
return true;
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
async readJson(path) {
|
|
22
|
-
try {
|
|
23
|
-
const content = await readFile(path, "utf-8");
|
|
24
|
-
return JSON.parse(content);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async hashFile(path) {
|
|
31
|
-
try {
|
|
32
|
-
const content = await readFile(path, "utf-8");
|
|
33
|
-
let hash = 0;
|
|
34
|
-
for (let i = 0; i < content.length; i++) {
|
|
35
|
-
const chr = content.charCodeAt(i);
|
|
36
|
-
hash = (hash << 5) - hash + chr;
|
|
37
|
-
hash |= 0;
|
|
38
|
-
}
|
|
39
|
-
return hash.toString(36);
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
return "missing";
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
async getCurrentState() {
|
|
46
|
-
const pkgJson = await this.readJson(join(this.projectDir, "package.json"));
|
|
47
|
-
let appConfig = await this.readJson(join(this.projectDir, "app.json"));
|
|
48
|
-
if (!appConfig) {
|
|
49
|
-
const configHash = await this.hashFile(join(this.projectDir, "app.config.js"));
|
|
50
|
-
const configTsHash = await this.hashFile(join(this.projectDir, "app.config.ts"));
|
|
51
|
-
appConfig = {
|
|
52
|
-
_fileHash: configHash,
|
|
53
|
-
_tsFileHash: configTsHash,
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
const podfileLockHash = await this.hashFile(join(this.projectDir, "ios", "Podfile.lock"));
|
|
57
|
-
return {
|
|
58
|
-
dependencies: (pkgJson?.dependencies ?? {}),
|
|
59
|
-
devDependencies: (pkgJson?.devDependencies ?? {}),
|
|
60
|
-
appConfig: appConfig ?? {},
|
|
61
|
-
podfileLockHash,
|
|
62
|
-
timestamp: new Date().toISOString(),
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
async loadSnapshot() {
|
|
66
|
-
try {
|
|
67
|
-
const content = await readFile(this.snapshotPath, "utf-8");
|
|
68
|
-
return JSON.parse(content);
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
async saveSnapshot() {
|
|
75
|
-
const state = await this.getCurrentState();
|
|
76
|
-
await mkdir(this.cacheDir, { recursive: true });
|
|
77
|
-
await writeFile(this.snapshotPath, JSON.stringify(state, null, 2), "utf-8");
|
|
78
|
-
}
|
|
79
|
-
diffDependencies(oldDeps, newDeps) {
|
|
80
|
-
const added = [];
|
|
81
|
-
const removed = [];
|
|
82
|
-
const changed = [];
|
|
83
|
-
const allKeys = new Set([
|
|
84
|
-
...Object.keys(oldDeps),
|
|
85
|
-
...Object.keys(newDeps),
|
|
86
|
-
]);
|
|
87
|
-
for (const key of allKeys) {
|
|
88
|
-
if (!(key in oldDeps)) {
|
|
89
|
-
added.push(key);
|
|
90
|
-
}
|
|
91
|
-
else if (!(key in newDeps)) {
|
|
92
|
-
removed.push(key);
|
|
93
|
-
}
|
|
94
|
-
else if (oldDeps[key] !== newDeps[key]) {
|
|
95
|
-
changed.push(key);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return { added, removed, changed };
|
|
99
|
-
}
|
|
100
|
-
async check() {
|
|
101
|
-
const reasons = [];
|
|
102
|
-
const iosExists = await this.fileExists(join(this.projectDir, "ios"));
|
|
103
|
-
if (!iosExists) {
|
|
104
|
-
return {
|
|
105
|
-
needsClean: true,
|
|
106
|
-
reasons: [
|
|
107
|
-
"ios/ directory does not exist. Run `npx expo prebuild` to generate native projects.",
|
|
108
|
-
],
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
const snapshot = await this.loadSnapshot();
|
|
112
|
-
if (!snapshot) {
|
|
113
|
-
return {
|
|
114
|
-
needsClean: true,
|
|
115
|
-
reasons: [
|
|
116
|
-
"No previous build snapshot found. Run a build to establish a baseline. " +
|
|
117
|
-
"A clean prebuild is recommended for the first build.",
|
|
118
|
-
],
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
const current = await this.getCurrentState();
|
|
122
|
-
const depDiff = this.diffDependencies(snapshot.dependencies, current.dependencies);
|
|
123
|
-
if (depDiff.added.length > 0) {
|
|
124
|
-
reasons.push(`New dependencies added: ${depDiff.added.join(", ")}. ` +
|
|
125
|
-
"Native modules may need linking.");
|
|
126
|
-
}
|
|
127
|
-
if (depDiff.removed.length > 0) {
|
|
128
|
-
reasons.push(`Dependencies removed: ${depDiff.removed.join(", ")}. ` +
|
|
129
|
-
"Stale native modules may cause build errors.");
|
|
130
|
-
}
|
|
131
|
-
if (depDiff.changed.length > 0) {
|
|
132
|
-
const nativeIndicators = [
|
|
133
|
-
"react-native",
|
|
134
|
-
"expo",
|
|
135
|
-
"@react-native",
|
|
136
|
-
"react-native-",
|
|
137
|
-
];
|
|
138
|
-
const nativeChanges = depDiff.changed.filter((dep) => nativeIndicators.some((indicator) => dep.includes(indicator)));
|
|
139
|
-
if (nativeChanges.length > 0) {
|
|
140
|
-
reasons.push(`Native dependency versions changed: ${nativeChanges.join(", ")}. ` +
|
|
141
|
-
"Clean prebuild recommended.");
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
const devDepDiff = this.diffDependencies(snapshot.devDependencies, current.devDependencies);
|
|
145
|
-
if (devDepDiff.added.length > 0 || devDepDiff.removed.length > 0) {
|
|
146
|
-
const nativeDevDeps = [
|
|
147
|
-
...devDepDiff.added,
|
|
148
|
-
...devDepDiff.removed,
|
|
149
|
-
].filter((dep) => dep.includes("react-native") ||
|
|
150
|
-
dep.includes("expo") ||
|
|
151
|
-
dep.includes("@react-native"));
|
|
152
|
-
if (nativeDevDeps.length > 0) {
|
|
153
|
-
reasons.push(`Native dev dependencies changed: ${nativeDevDeps.join(", ")}.`);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
const configChanged = JSON.stringify(snapshot.appConfig) !==
|
|
157
|
-
JSON.stringify(current.appConfig);
|
|
158
|
-
if (configChanged) {
|
|
159
|
-
reasons.push("app.json / app.config.js has changed since last build. " +
|
|
160
|
-
"Expo plugins or native config may have changed.");
|
|
161
|
-
}
|
|
162
|
-
if (current.podfileLockHash === "missing") {
|
|
163
|
-
reasons.push("ios/Podfile.lock is missing. Pods may need to be installed.");
|
|
164
|
-
}
|
|
165
|
-
else if (snapshot.podfileLockHash !== current.podfileLockHash) {
|
|
166
|
-
reasons.push("ios/Podfile.lock has changed since last build. " +
|
|
167
|
-
"Pod dependencies may be out of sync.");
|
|
168
|
-
}
|
|
169
|
-
return {
|
|
170
|
-
needsClean: reasons.length > 0,
|
|
171
|
-
reasons,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
}
|
package/dist/preflight.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ScreenManager } from "./screen.js";
|
|
2
|
-
import type { AppLifecycle } from "./app-lifecycle.js";
|
|
3
|
-
import type { DeviceAutonomy } from "./device-autonomy.js";
|
|
4
|
-
import type { TargetResolver } from "./target.js";
|
|
5
|
-
import type { IproxyManager } from "./iproxy-manager.js";
|
|
6
|
-
export interface PreflightOpts {
|
|
7
|
-
screen: ScreenManager;
|
|
8
|
-
apps: AppLifecycle;
|
|
9
|
-
autonomy: DeviceAutonomy;
|
|
10
|
-
iproxyManager?: IproxyManager | null;
|
|
11
|
-
bundleId?: string;
|
|
12
|
-
requiredEnv?: string[];
|
|
13
|
-
expectedNetwork?: string;
|
|
14
|
-
projectDir?: string;
|
|
15
|
-
target?: TargetResolver;
|
|
16
|
-
excludeRuntimeChecks?: boolean;
|
|
17
|
-
}
|
|
18
|
-
export interface PreflightCheck {
|
|
19
|
-
name: string;
|
|
20
|
-
ok: boolean;
|
|
21
|
-
severity: "error" | "warning" | "info";
|
|
22
|
-
message: string;
|
|
23
|
-
remediation?: string;
|
|
24
|
-
details?: Record<string, unknown>;
|
|
25
|
-
}
|
|
26
|
-
export interface PreflightResult {
|
|
27
|
-
ok: boolean;
|
|
28
|
-
checks: PreflightCheck[];
|
|
29
|
-
}
|
|
30
|
-
export declare function pollUntil(fn: () => Promise<boolean>, opts: {
|
|
31
|
-
intervalMs: number;
|
|
32
|
-
timeoutMs: number;
|
|
33
|
-
}): Promise<boolean>;
|
|
34
|
-
export declare function runPreflight(opts: PreflightOpts): Promise<PreflightResult>;
|