catalyst-core 1.0.2-canary.1 → 1.0.2
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/bin/catalyst.js +105 -1
- package/changelog.md +34 -0
- package/dist/cli/README.md +119 -0
- package/dist/cli/appConfig.js +51 -0
- package/dist/cli/buildErrors.js +170 -0
- package/dist/cli/buildWarnings.js +28 -0
- package/dist/cli/devOutput.js +524 -0
- package/dist/cli/diagnostic.js +388 -0
- package/dist/cli/hints.js +69 -0
- package/dist/cli/package.json +3 -0
- package/dist/cli/spinner.js +141 -0
- package/dist/cli/theme.js +155 -0
- package/dist/errors/index.js +7 -3
- package/dist/logger.js +61 -6
- package/dist/native/androidProject/app/build.gradle.kts +2 -1
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +2 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +9 -0
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/SplashActivity.kt +65 -34
- package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/SplashOverlay.kt +109 -0
- package/dist/native/androidSetup.js +46 -57
- package/dist/native/buildAndroid/assets.js +22 -13
- package/dist/native/buildAndroid/build.js +98 -26
- package/dist/native/buildAndroid/config.js +43 -12
- package/dist/native/buildAndroid/index.js +49 -191
- package/dist/native/buildAppAndroid.js +19 -8
- package/dist/native/buildAppIos.js +35 -16
- package/dist/native/buildIos/assets.js +1 -6
- package/dist/native/buildIos/build.js +66 -95
- package/dist/native/buildIos/config.js +26 -8
- package/dist/native/buildIos/index.js +143 -64
- package/dist/native/buildIos/plugins.js +12 -15
- package/dist/native/internalPluginUtils.js +0 -1
- package/dist/native/iosnativeWebView/CoreLogic/Sources/CatalystCoreLogic/Constants/ConfigConstants.swift +2 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashHTMLView.swift +31 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashView.swift +17 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashViewModel.swift +41 -1
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewModel.swift +2 -0
- package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +3 -0
- package/dist/native/pluginComposerAndroid.js +2 -3
- package/dist/native/renameAndroidProject.js +42 -20
- package/dist/native/setupEmulatorIos.js +28 -49
- package/dist/native/setupServer.js +12 -15
- package/dist/native/terminalProgress.js +186 -147
- package/dist/native/utils.js +340 -54
- package/dist/otel.js +15 -9
- package/dist/scripts/build.js +313 -42
- package/dist/scripts/generateOfflineManifest.js +11 -1
- package/dist/scripts/loadEnvironmentVariables.js +24 -2
- package/dist/scripts/preServerInit.js +32 -10
- package/dist/scripts/preflight.js +35 -11
- package/dist/scripts/scriptUtils.js +34 -0
- package/dist/scripts/serve.js +64 -15
- package/dist/scripts/start.js +58 -21
- package/dist/server/expressServer.js +167 -32
- package/dist/server/renderer/handler.jsx +87 -11
- package/dist/server/utils/validator.js +14 -11
- package/dist/vite/manifest-categorization-plugin.js +7 -5
- package/dist/vite/resolveDevServerConfig.js +9 -2
- package/dist/vite/vite.config.client.js +18 -0
- package/dist/vite/vite.config.js +73 -13
- package/dist/vite/vite.config.server.js +21 -0
- package/dist/web-router/components/MetaTag.jsx +15 -2
- package/dist/web-router/components/MetaTag.test.jsx +71 -2
- package/dist/webmcp/WebMcpProvider.jsx +3 -2
- package/dist/webmcp/useTool.js +4 -1
- package/mcp_v2/conversion-tasks.json +6 -5
- package/mcp_v2/knowledge-base.json +124 -7
- package/mcp_v2/test/config.test.ts +59 -0
- package/mcp_v2/tools/build.js +6 -6
- package/mcp_v2/tools/config.js +35 -18
- package/mcp_v2/tools/conversion.js +7 -13
- package/package.json +5 -5
- package/test/cli/buildErrors.test.ts +173 -0
- package/test/cli/buildWarnings.test.cjs +62 -0
- package/test/cli/devOutput.test.ts +549 -0
- package/test/cli/diagnostic.test.ts +434 -0
- package/test/cli/output.test.cjs +90 -0
- package/test/cli/spinner.test.ts +177 -0
- package/test/cli/theme.test.ts +163 -0
- package/test/native/redactSecrets.test.ts +72 -0
- package/test/native/utils.test.ts +532 -0
- package/test/scripts/build.test.ts +275 -0
- package/test/scripts/serve.test.ts +102 -0
- package/test/server/fixtures/template/src/js/routes/index.jsx +8 -0
- package/test/server/handler.test.ts +17 -0
- package/test/server/logger.test.ts +185 -0
- package/test/server/otel.test.ts +556 -0
- package/test/server/validator.test.ts +19 -8
- package/dist/scripts/checkVersion.js +0 -3
- package/dist/scripts/cleanCache.js +0 -30
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
var _fs = _interopRequireDefault(require("fs"));
|
|
5
5
|
var _path = _interopRequireDefault(require("path"));
|
|
6
6
|
var _utils = require("./utils.js");
|
|
7
|
+
var _theme = require("../cli/theme.js");
|
|
7
8
|
function _interopRequireDefault(e) {
|
|
8
9
|
return e && e.__esModule ? e : {
|
|
9
10
|
default: e
|
|
@@ -15,27 +16,45 @@ class SimpleProgress {
|
|
|
15
16
|
constructor(title) {
|
|
16
17
|
this.title = title;
|
|
17
18
|
this.currentStep = null;
|
|
18
|
-
|
|
19
|
+
this.startedAt = 0;
|
|
20
|
+
// Deferred: this module is imported by the Android build, which prints
|
|
21
|
+
// its own header. Printing here on import produced two headers, the
|
|
22
|
+
// first of them for work that had not started and often never runs.
|
|
23
|
+
this.headerShown = false;
|
|
24
|
+
}
|
|
25
|
+
ensureHeader() {
|
|
26
|
+
if (this.headerShown) return;
|
|
27
|
+
this.headerShown = true;
|
|
28
|
+
console.log(_theme.header(this.title));
|
|
19
29
|
}
|
|
20
30
|
start(stepId) {
|
|
31
|
+
this.ensureHeader();
|
|
21
32
|
this.currentStep = {
|
|
22
33
|
id: stepId
|
|
23
34
|
};
|
|
24
|
-
|
|
35
|
+
this.startedAt = Date.now();
|
|
36
|
+
console.log(`${_theme.GUTTER}${_theme.t.accent(_theme.glyph.running)} ${stepId}`);
|
|
25
37
|
}
|
|
26
38
|
complete(stepId) {
|
|
27
|
-
|
|
39
|
+
this.ensureHeader();
|
|
40
|
+
console.log(_theme.step(stepId, this.startedAt ? Date.now() - this.startedAt : null));
|
|
28
41
|
this.currentStep = null;
|
|
29
42
|
}
|
|
30
43
|
fail(stepId, message) {
|
|
31
|
-
|
|
44
|
+
this.ensureHeader();
|
|
45
|
+
console.log(_theme.step(stepId, null, "fail"));
|
|
46
|
+
// Backstop: runCommand already scrubs its errors, but this is where any
|
|
47
|
+
// failure in the signing flow ends up on screen.
|
|
48
|
+
if (message) console.log(`${_theme.GUTTER}${_theme.t.dim(_theme.glyph.last)} ${_theme.t.bad((0, _utils.redactSecrets)(message))}`);
|
|
32
49
|
}
|
|
33
50
|
log(message, type = "info") {
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
this.ensureHeader();
|
|
52
|
+
const mark = type === "error" ? _theme.t.bad(_theme.glyph.fail) : type === "warning" ? _theme.t.warn(_theme.glyph.warn) : type === "success" ? _theme.t.ok(_theme.glyph.done) : _theme.t.dim(_theme.glyph.info);
|
|
53
|
+
console.log(`${_theme.GUTTER}${_theme.t.dim(_theme.glyph.pipe)} ${mark} ${message}`);
|
|
36
54
|
}
|
|
37
55
|
printTreeContent(title, items) {
|
|
38
|
-
|
|
56
|
+
this.ensureHeader();
|
|
57
|
+
console.log(`\n${_theme.GUTTER}${_theme.t.bold(title)}`);
|
|
39
58
|
items.forEach(item => {
|
|
40
59
|
if (typeof item === "string") {
|
|
41
60
|
console.log(item);
|
|
@@ -142,7 +161,7 @@ async function createKeystore(projectPaths, androidConfig) {
|
|
|
142
161
|
} catch (testError) {
|
|
143
162
|
throw new Error(`Created keystore failed verification: ${testError.message}`);
|
|
144
163
|
}
|
|
145
|
-
progress.log(`Keystore created
|
|
164
|
+
progress.log(`Keystore created at: ${keystorePath}`, "note");
|
|
146
165
|
progress.log(`Key alias: ${keystoreConfig.keyAlias}`, "info");
|
|
147
166
|
progress.log(`Validity: ${keystoreConfig.validityYears || 25} years`, "info");
|
|
148
167
|
progress.log(`Store type: PKCS12`, "info");
|
|
@@ -220,8 +239,11 @@ async function createSignedAAB(projectPaths, androidConfig, keystorePath) {
|
|
|
220
239
|
|
|
221
240
|
// For PKCS12 keystores, use store password for both store and key
|
|
222
241
|
const effectiveKeyPassword = keystoreConfig.storePassword;
|
|
223
|
-
const bundleCommand = ["./gradlew bundleRelease --
|
|
224
|
-
|
|
242
|
+
const bundleCommand = ["./gradlew bundleRelease --console=plain", `-Pandroid.injected.signing.store.file="${keystorePath}"`, `-Pandroid.injected.signing.store.password="${keystoreConfig.storePassword}"`, `-Pandroid.injected.signing.key.alias="${keystoreConfig.keyAlias}"`, `-Pandroid.injected.signing.key.password="${effectiveKeyPassword}"`].join(" ");
|
|
243
|
+
|
|
244
|
+
// Never log this command as-is: it carries the keystore and key
|
|
245
|
+
// passwords, which would put them in the terminal and in CI logs.
|
|
246
|
+
progress.log("Executing: ./gradlew bundleRelease (signing args redacted)", "info");
|
|
225
247
|
(0, _utils.runCommand)(bundleCommand);
|
|
226
248
|
progress.log("Bundle build completed", "success");
|
|
227
249
|
|
|
@@ -404,10 +426,10 @@ async function diagnoseAndroidProject(projectPath) {
|
|
|
404
426
|
...pattern,
|
|
405
427
|
foundFile
|
|
406
428
|
});
|
|
407
|
-
progress.log(
|
|
429
|
+
progress.log(`Found: ${pattern.description}${foundFile ? ` (${foundFile})` : ""}`, "success");
|
|
408
430
|
} else {
|
|
409
431
|
diagnostics.missingFiles.push(pattern);
|
|
410
|
-
progress.log(
|
|
432
|
+
progress.log(`Missing: ${pattern.description}`, "warning");
|
|
411
433
|
}
|
|
412
434
|
}
|
|
413
435
|
|
|
@@ -585,7 +607,7 @@ async function createTempDeploymentProject(projectPaths, androidConfig) {
|
|
|
585
607
|
filesToCheck.forEach(file => {
|
|
586
608
|
const fullPath = _path.default.join(tempDir, file.path);
|
|
587
609
|
const exists = _fs.default.existsSync(fullPath);
|
|
588
|
-
progress.log(` ${file.desc}: ${exists ? "
|
|
610
|
+
progress.log(` ${file.desc}: ${exists ? "found" : "not found"}`, exists ? "info" : "warning");
|
|
589
611
|
});
|
|
590
612
|
|
|
591
613
|
// List all files in temp directory for debugging
|
|
@@ -647,7 +669,7 @@ async function finalizeAABAndCleanup(projectPaths, androidConfig, aabResult, tem
|
|
|
647
669
|
const finalAabName = `${androidConfig.newProjectName}-release-${timestamp}.aab`;
|
|
648
670
|
const finalAabPath = _path.default.join(outputDir, finalAabName);
|
|
649
671
|
_fs.default.copyFileSync(aabResult.outputAabPath, finalAabPath);
|
|
650
|
-
progress.log(`AAB saved to
|
|
672
|
+
progress.log(`AAB saved to: ${finalAabPath}`, "note");
|
|
651
673
|
|
|
652
674
|
// Copy keystore to output directory for future use
|
|
653
675
|
const keystorePath = _path.default.join(tempDeploymentPath, "app", "keystore.jks");
|
|
@@ -704,7 +726,7 @@ async function updateFileContents(projectPaths, androidConfig) {
|
|
|
704
726
|
content = content.replace(/namespace = "io\.yourname\.androidproject"/g, `namespace = "${packageName}"`);
|
|
705
727
|
content = content.replace(/applicationId = "io\.yourname\.androidproject"/g, `applicationId = "${packageName}"`);
|
|
706
728
|
_fs.default.writeFileSync(buildGradlePath, content, "utf8");
|
|
707
|
-
progress.log(
|
|
729
|
+
progress.log(`Updated build.gradle.kts with package: ${packageName}`, "success");
|
|
708
730
|
}
|
|
709
731
|
|
|
710
732
|
// Update source directory structure for all source sets
|
|
@@ -726,7 +748,7 @@ async function updateFileContents(projectPaths, androidConfig) {
|
|
|
726
748
|
// Move source files
|
|
727
749
|
;
|
|
728
750
|
(0, _utils.runCommand)(`mv "${oldPackagePath}" "${newPackagePath}"`);
|
|
729
|
-
progress.log(
|
|
751
|
+
progress.log(`Moved ${sourceSet} source files to: ${newPackagePath}`, "success");
|
|
730
752
|
} else {
|
|
731
753
|
progress.log(`Package path unchanged for ${sourceSet}; skipping source directory move`, "info");
|
|
732
754
|
}
|
|
@@ -744,7 +766,7 @@ async function updateFileContents(projectPaths, androidConfig) {
|
|
|
744
766
|
}
|
|
745
767
|
}
|
|
746
768
|
totalUpdatedFiles += updatedCount;
|
|
747
|
-
progress.log(
|
|
769
|
+
progress.log(`Updated package declarations in ${updatedCount} ${sourceSet} files`, "success");
|
|
748
770
|
|
|
749
771
|
// Clean up old empty directories
|
|
750
772
|
try {
|
|
@@ -756,7 +778,7 @@ async function updateFileContents(projectPaths, androidConfig) {
|
|
|
756
778
|
}
|
|
757
779
|
}
|
|
758
780
|
if (totalUpdatedFiles > 0) {
|
|
759
|
-
progress.log(
|
|
781
|
+
progress.log(`Total package declarations updated: ${totalUpdatedFiles} files`, "success");
|
|
760
782
|
}
|
|
761
783
|
|
|
762
784
|
// Update AndroidManifest.xml
|
|
@@ -766,7 +788,7 @@ async function updateFileContents(projectPaths, androidConfig) {
|
|
|
766
788
|
if (content.includes(OLD_PACKAGE)) {
|
|
767
789
|
content = content.replace(new RegExp(OLD_PACKAGE, "g"), packageName);
|
|
768
790
|
_fs.default.writeFileSync(manifestPath, content, "utf8");
|
|
769
|
-
progress.log(
|
|
791
|
+
progress.log(`Updated AndroidManifest.xml with package: ${packageName}`, "success");
|
|
770
792
|
}
|
|
771
793
|
}
|
|
772
794
|
|
|
@@ -777,7 +799,7 @@ async function updateFileContents(projectPaths, androidConfig) {
|
|
|
777
799
|
if (content.includes(OLD_PACKAGE)) {
|
|
778
800
|
content = content.replace(new RegExp(OLD_PACKAGE.replace(/\./g, "\\."), "g"), packageName);
|
|
779
801
|
_fs.default.writeFileSync(proguardPath, content, "utf8");
|
|
780
|
-
progress.log(
|
|
802
|
+
progress.log(`Updated proguard-rules.pro with package: ${packageName}`, "success");
|
|
781
803
|
}
|
|
782
804
|
}
|
|
783
805
|
}
|
|
@@ -11,22 +11,16 @@ const {
|
|
|
11
11
|
} = require("./setupServer.js");
|
|
12
12
|
const ITEMS_PER_PAGE = 10;
|
|
13
13
|
const steps = {
|
|
14
|
-
platform: "Check
|
|
15
|
-
config: "Initialize
|
|
16
|
-
simulator: "Configure iOS
|
|
17
|
-
launch: "Launch iOS
|
|
18
|
-
saveConfig: "
|
|
19
|
-
setupServer: "
|
|
14
|
+
platform: "Check platform compatibility",
|
|
15
|
+
config: "Initialize configuration",
|
|
16
|
+
simulator: "Configure iOS simulator",
|
|
17
|
+
launch: "Launch iOS simulator",
|
|
18
|
+
saveConfig: "Save configuration",
|
|
19
|
+
setupServer: "Set up server"
|
|
20
20
|
};
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
stepPaddingLeft: 4,
|
|
25
|
-
stepSpacing: 1,
|
|
26
|
-
errorPaddingLeft: 6,
|
|
27
|
-
bottomMargin: 2
|
|
28
|
-
};
|
|
29
|
-
const progress = new _terminalProgress.default(steps, "Catalyst Universal Ios Setup", progressPaddingConfig);
|
|
21
|
+
const progress = new _terminalProgress.default(steps, "catalyst setupEmulator", {
|
|
22
|
+
subject: "ios"
|
|
23
|
+
});
|
|
30
24
|
async function initializeConfig() {
|
|
31
25
|
const configFile = _fs.default.readFileSync(configPath, "utf8");
|
|
32
26
|
const config = JSON.parse(configFile);
|
|
@@ -72,7 +66,7 @@ async function setupIOSEnvironment() {
|
|
|
72
66
|
try {
|
|
73
67
|
progress.start("platform");
|
|
74
68
|
if (process.platform !== "darwin") {
|
|
75
|
-
progress.log("iOS Simulator is only available on macOS.");
|
|
69
|
+
progress.log("iOS Simulator is only available on macOS.", "error");
|
|
76
70
|
process.exit(1);
|
|
77
71
|
}
|
|
78
72
|
progress.complete("platform");
|
|
@@ -91,40 +85,26 @@ async function setupIOSEnvironment() {
|
|
|
91
85
|
const config = await (0, _utils.validateAndCompleteConfig)("ios", configPath);
|
|
92
86
|
progress.complete("saveConfig");
|
|
93
87
|
progress.start("setupServer");
|
|
94
|
-
await setupServer(configPath);
|
|
95
|
-
progress.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
prefix: "├─ ",
|
|
100
|
-
color: "gray"
|
|
101
|
-
}, {
|
|
102
|
-
text: "ios: iOS-specific configuration",
|
|
103
|
-
indent: 1,
|
|
104
|
-
prefix: "└─ ",
|
|
105
|
-
color: "gray"
|
|
106
|
-
}, {
|
|
107
|
-
text: "buildType: Build type (debug/release)",
|
|
108
|
-
indent: 2,
|
|
109
|
-
prefix: "├─ ",
|
|
88
|
+
await setupServer(configPath, message => progress.log(message, "info"));
|
|
89
|
+
progress.complete("setupServer");
|
|
90
|
+
const iosCfg = config.ios || {};
|
|
91
|
+
progress.printTreeContent("Config config/config.json", [{
|
|
92
|
+
text: `port ${config.port ?? ""}`,
|
|
110
93
|
color: "gray"
|
|
111
94
|
}, {
|
|
112
|
-
text:
|
|
113
|
-
indent: 2,
|
|
114
|
-
prefix: "├─ ",
|
|
95
|
+
text: `appBundleId ${iosCfg.appBundleId ?? ""}`,
|
|
115
96
|
color: "gray"
|
|
116
97
|
}, {
|
|
117
|
-
text:
|
|
118
|
-
indent: 2,
|
|
119
|
-
prefix: "└─ ",
|
|
98
|
+
text: `simulatorName ${iosCfg.simulatorName ?? ""}`,
|
|
120
99
|
color: "gray"
|
|
121
100
|
}]);
|
|
122
|
-
progress.
|
|
101
|
+
progress.summary("Ready", "Run catalyst buildApp:ios to install the app");
|
|
123
102
|
process.exit(0);
|
|
124
103
|
} catch (error) {
|
|
125
104
|
if (progress.currentStep) {
|
|
126
105
|
progress.fail(progress.currentStep.id, error.message);
|
|
127
106
|
}
|
|
107
|
+
progress.hint(error.hint);
|
|
128
108
|
process.exit(1);
|
|
129
109
|
}
|
|
130
110
|
}
|
|
@@ -147,13 +127,13 @@ async function getRuntime() {
|
|
|
147
127
|
if (!availableRuntime) {
|
|
148
128
|
const runningSimulators = (0, _child_process.execSync)("xcrun simctl list devices booted").toString();
|
|
149
129
|
if (runningSimulators.includes("(Booted)") && parsedRuntimes.length > 0) {
|
|
150
|
-
|
|
130
|
+
progress.status(`runtime ${parsedRuntimes[0].name}`);
|
|
151
131
|
return parsedRuntimes[0];
|
|
152
132
|
}
|
|
153
|
-
|
|
133
|
+
progress.log("No available iOS runtime found. Install one through Xcode.", "error");
|
|
154
134
|
process.exit(1);
|
|
155
135
|
}
|
|
156
|
-
|
|
136
|
+
progress.status(`runtime ${availableRuntime.name}`);
|
|
157
137
|
return availableRuntime;
|
|
158
138
|
}
|
|
159
139
|
async function configureSimulator(config) {
|
|
@@ -269,7 +249,7 @@ function resolveSimulatorAppBundleId() {
|
|
|
269
249
|
// instead of throwing.
|
|
270
250
|
const SIMULATOR_APP_NOT_FOUND_WARNING = "[IOS-001] Could not find an installed iOS Simulator app (checked DeviceHub.app and the legacy Simulator.app). " + "The simulator is booted but its window may not be visible. Suggested action: confirm a full Xcode.app is installed and selected via xcode-select -p, then open it once from Spotlight.";
|
|
271
251
|
async function launchIOSSimulator(simulatorName) {
|
|
272
|
-
progress.
|
|
252
|
+
progress.status("launching simulator");
|
|
273
253
|
try {
|
|
274
254
|
// Get all simulators including both available and booted ones
|
|
275
255
|
const allSimulatorInfo = (0, _child_process.execSync)("xcrun simctl list devices -j").toString();
|
|
@@ -301,20 +281,20 @@ async function launchIOSSimulator(simulatorName) {
|
|
|
301
281
|
});
|
|
302
282
|
});
|
|
303
283
|
if (!foundSimulator) {
|
|
304
|
-
|
|
284
|
+
progress.log(`Configured simulator "${simulatorName}" not found`, "warning");
|
|
305
285
|
return;
|
|
306
286
|
}
|
|
307
287
|
if (!isBooted) {
|
|
308
|
-
|
|
288
|
+
progress.status(`booting ${simulatorName}`);
|
|
309
289
|
(0, _utils.runCommand)(`xcrun simctl boot ${foundSimulatorId}`);
|
|
310
290
|
} else {
|
|
311
|
-
|
|
291
|
+
progress.status("already booted");
|
|
312
292
|
}
|
|
313
293
|
|
|
314
294
|
// Open the simulator UI (DeviceHub on Xcode 27+, Simulator.app on older Xcode) and focus it
|
|
315
295
|
const simulatorAppBundleId = resolveSimulatorAppBundleId();
|
|
316
296
|
if (simulatorAppBundleId) {
|
|
317
|
-
progress.
|
|
297
|
+
progress.status("opening simulator");
|
|
318
298
|
(0, _utils.runCommand)(`open -b ${simulatorAppBundleId}`);
|
|
319
299
|
|
|
320
300
|
// Give the simulator a moment to open/focus
|
|
@@ -325,9 +305,8 @@ async function launchIOSSimulator(simulatorName) {
|
|
|
325
305
|
} else {
|
|
326
306
|
progress.log(SIMULATOR_APP_NOT_FOUND_WARNING, "warning");
|
|
327
307
|
}
|
|
328
|
-
console.log("iOS Simulator launched successfully.");
|
|
329
308
|
} catch (error) {
|
|
330
|
-
|
|
309
|
+
progress.log(`Failed to launch iOS Simulator: ${error.message}`, "error");
|
|
331
310
|
}
|
|
332
311
|
// process.exit(0);
|
|
333
312
|
}
|
|
@@ -44,14 +44,12 @@ async function isServerRunning(port) {
|
|
|
44
44
|
* Start server in background using npm start
|
|
45
45
|
*/
|
|
46
46
|
function startServerBackground() {
|
|
47
|
-
console.log("Starting server in background...");
|
|
48
47
|
const serverProcess = exec("npm start", {
|
|
49
48
|
detached: true,
|
|
50
49
|
stdio: "ignore"
|
|
51
50
|
});
|
|
52
51
|
if (serverProcess.pid) {
|
|
53
52
|
serverProcess.unref(); // Allow parent to exit
|
|
54
|
-
console.log("Server started in background");
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
55
|
|
|
@@ -90,7 +88,6 @@ function replaceIPInObject(obj, localIP, path = "") {
|
|
|
90
88
|
shouldUpdate = true;
|
|
91
89
|
}
|
|
92
90
|
if (shouldUpdate && newValue !== value) {
|
|
93
|
-
console.log(`Updating ${currentPath}: ${value} -> ${newValue}`);
|
|
94
91
|
obj[key] = newValue;
|
|
95
92
|
updated = true;
|
|
96
93
|
}
|
|
@@ -106,7 +103,7 @@ function replaceIPInObject(obj, localIP, path = "") {
|
|
|
106
103
|
/**
|
|
107
104
|
* Update config.json with current local IP address
|
|
108
105
|
*/
|
|
109
|
-
function updateConfigWithLocalIP(configPath, localIP) {
|
|
106
|
+
function updateConfigWithLocalIP(configPath, localIP, log = () => {}) {
|
|
110
107
|
try {
|
|
111
108
|
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
112
109
|
|
|
@@ -116,9 +113,7 @@ function updateConfigWithLocalIP(configPath, localIP) {
|
|
|
116
113
|
// Write back if updated
|
|
117
114
|
if (updated) {
|
|
118
115
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf8");
|
|
119
|
-
|
|
120
|
-
} else {
|
|
121
|
-
console.log("No IP addresses needed updating in configuration");
|
|
116
|
+
log(`Updated config addresses to ${localIP}`);
|
|
122
117
|
}
|
|
123
118
|
return config;
|
|
124
119
|
} catch (error) {
|
|
@@ -132,15 +127,18 @@ function updateConfigWithLocalIP(configPath, localIP) {
|
|
|
132
127
|
* @param {string} configPath - Path to config.json file
|
|
133
128
|
* @returns {Promise<{serverURL: string, localIP: string, port: number}>}
|
|
134
129
|
*/
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
/**
|
|
131
|
+
* @param {string} configPath
|
|
132
|
+
* @param {(message: string, type?: string) => void} [log] - progress sink.
|
|
133
|
+
* Defaults to silence: this runs inside a progress sequence, where a stray
|
|
134
|
+
* console.log lands at column 0 and collides with the live spinner row.
|
|
135
|
+
*/
|
|
136
|
+
async function setupServer(configPath, log = () => {}) {
|
|
138
137
|
// Get local IP
|
|
139
138
|
const localIP = getLocalIPAddress();
|
|
140
|
-
console.log(`Local IP: ${localIP}`);
|
|
141
139
|
|
|
142
140
|
// Update config with current IP
|
|
143
|
-
const config = updateConfigWithLocalIP(configPath, localIP);
|
|
141
|
+
const config = updateConfigWithLocalIP(configPath, localIP, log);
|
|
144
142
|
|
|
145
143
|
// Get port from config
|
|
146
144
|
const port = config.WEBVIEW_CONFIG?.port || 3005;
|
|
@@ -149,14 +147,13 @@ async function setupServer(configPath) {
|
|
|
149
147
|
// Check if server is running
|
|
150
148
|
const running = await isServerRunning(port);
|
|
151
149
|
if (!running) {
|
|
152
|
-
|
|
150
|
+
log(`Starting server at ${serverURL}`);
|
|
153
151
|
startServerBackground();
|
|
154
152
|
// Give it a moment to start
|
|
155
153
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
156
154
|
} else {
|
|
157
|
-
|
|
155
|
+
log(`Server already running at ${serverURL}`);
|
|
158
156
|
}
|
|
159
|
-
console.log(`Server setup complete: ${serverURL}`);
|
|
160
157
|
return {
|
|
161
158
|
serverURL,
|
|
162
159
|
localIP,
|