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.
Files changed (90) hide show
  1. package/bin/catalyst.js +105 -1
  2. package/changelog.md +34 -0
  3. package/dist/cli/README.md +119 -0
  4. package/dist/cli/appConfig.js +51 -0
  5. package/dist/cli/buildErrors.js +170 -0
  6. package/dist/cli/buildWarnings.js +28 -0
  7. package/dist/cli/devOutput.js +524 -0
  8. package/dist/cli/diagnostic.js +388 -0
  9. package/dist/cli/hints.js +69 -0
  10. package/dist/cli/package.json +3 -0
  11. package/dist/cli/spinner.js +141 -0
  12. package/dist/cli/theme.js +155 -0
  13. package/dist/errors/index.js +7 -3
  14. package/dist/logger.js +61 -6
  15. package/dist/native/androidProject/app/build.gradle.kts +2 -1
  16. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/CustomWebview.kt +2 -0
  17. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/MainActivity.kt +9 -0
  18. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/SplashActivity.kt +65 -34
  19. package/dist/native/androidProject/app/src/main/java/io/yourname/androidproject/SplashOverlay.kt +109 -0
  20. package/dist/native/androidSetup.js +46 -57
  21. package/dist/native/buildAndroid/assets.js +22 -13
  22. package/dist/native/buildAndroid/build.js +98 -26
  23. package/dist/native/buildAndroid/config.js +43 -12
  24. package/dist/native/buildAndroid/index.js +49 -191
  25. package/dist/native/buildAppAndroid.js +19 -8
  26. package/dist/native/buildAppIos.js +35 -16
  27. package/dist/native/buildIos/assets.js +1 -6
  28. package/dist/native/buildIos/build.js +66 -95
  29. package/dist/native/buildIos/config.js +26 -8
  30. package/dist/native/buildIos/index.js +143 -64
  31. package/dist/native/buildIos/plugins.js +12 -15
  32. package/dist/native/internalPluginUtils.js +0 -1
  33. package/dist/native/iosnativeWebView/CoreLogic/Sources/CatalystCoreLogic/Constants/ConfigConstants.swift +2 -0
  34. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashHTMLView.swift +31 -0
  35. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashView.swift +17 -1
  36. package/dist/native/iosnativeWebView/Sources/Core/WebView/SplashViewModel.swift +41 -1
  37. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewModel.swift +2 -0
  38. package/dist/native/iosnativeWebView/Sources/Core/WebView/WebViewNavigationDelegate.swift +3 -0
  39. package/dist/native/pluginComposerAndroid.js +2 -3
  40. package/dist/native/renameAndroidProject.js +42 -20
  41. package/dist/native/setupEmulatorIos.js +28 -49
  42. package/dist/native/setupServer.js +12 -15
  43. package/dist/native/terminalProgress.js +186 -147
  44. package/dist/native/utils.js +340 -54
  45. package/dist/otel.js +15 -9
  46. package/dist/scripts/build.js +313 -42
  47. package/dist/scripts/generateOfflineManifest.js +11 -1
  48. package/dist/scripts/loadEnvironmentVariables.js +24 -2
  49. package/dist/scripts/preServerInit.js +32 -10
  50. package/dist/scripts/preflight.js +35 -11
  51. package/dist/scripts/scriptUtils.js +34 -0
  52. package/dist/scripts/serve.js +64 -15
  53. package/dist/scripts/start.js +58 -21
  54. package/dist/server/expressServer.js +167 -32
  55. package/dist/server/renderer/handler.jsx +87 -11
  56. package/dist/server/utils/validator.js +14 -11
  57. package/dist/vite/manifest-categorization-plugin.js +7 -5
  58. package/dist/vite/resolveDevServerConfig.js +9 -2
  59. package/dist/vite/vite.config.client.js +18 -0
  60. package/dist/vite/vite.config.js +73 -13
  61. package/dist/vite/vite.config.server.js +21 -0
  62. package/dist/web-router/components/MetaTag.jsx +15 -2
  63. package/dist/web-router/components/MetaTag.test.jsx +71 -2
  64. package/dist/webmcp/WebMcpProvider.jsx +3 -2
  65. package/dist/webmcp/useTool.js +4 -1
  66. package/mcp_v2/conversion-tasks.json +6 -5
  67. package/mcp_v2/knowledge-base.json +124 -7
  68. package/mcp_v2/test/config.test.ts +59 -0
  69. package/mcp_v2/tools/build.js +6 -6
  70. package/mcp_v2/tools/config.js +35 -18
  71. package/mcp_v2/tools/conversion.js +7 -13
  72. package/package.json +5 -5
  73. package/test/cli/buildErrors.test.ts +173 -0
  74. package/test/cli/buildWarnings.test.cjs +62 -0
  75. package/test/cli/devOutput.test.ts +549 -0
  76. package/test/cli/diagnostic.test.ts +434 -0
  77. package/test/cli/output.test.cjs +90 -0
  78. package/test/cli/spinner.test.ts +177 -0
  79. package/test/cli/theme.test.ts +163 -0
  80. package/test/native/redactSecrets.test.ts +72 -0
  81. package/test/native/utils.test.ts +532 -0
  82. package/test/scripts/build.test.ts +275 -0
  83. package/test/scripts/serve.test.ts +102 -0
  84. package/test/server/fixtures/template/src/js/routes/index.jsx +8 -0
  85. package/test/server/handler.test.ts +17 -0
  86. package/test/server/logger.test.ts +185 -0
  87. package/test/server/otel.test.ts +556 -0
  88. package/test/server/validator.test.ts +19 -8
  89. package/dist/scripts/checkVersion.js +0 -3
  90. package/dist/scripts/cleanCache.js +0 -30
@@ -1,11 +1,17 @@
1
1
  "use strict";
2
2
 
3
3
  const path = require("path");
4
+ const {
5
+ displayPath
6
+ } = require("../../cli/theme.js");
4
7
  const fs = require("fs");
5
8
  const {
6
9
  runCommand,
7
10
  runInteractiveCommand
8
11
  } = require("../utils.js");
12
+ const {
13
+ buildFailure
14
+ } = require("../../cli/diagnostic.js");
9
15
  const TerminalProgress = require("../terminalProgress.js").default;
10
16
  const {
11
17
  composeAndroidPlugins
@@ -21,20 +27,12 @@ const catalystCorePath = path.dirname(require.resolve("catalyst-core/package.jso
21
27
  const pwd = path.join(catalystCorePath, "dist/native");
22
28
  const ANDROID_PACKAGE = "io.yourname.androidproject";
23
29
  const steps = {
24
- config: "Initialize Configuration",
25
- tools: "Validate Android Tools",
26
- emulator: "Check and Start Emulator",
27
- copyAssets: "Copy Build Assets",
28
- build: "Build and Install Application",
29
- aab: "Build Signed AAB"
30
- };
31
- const progressConfig = {
32
- titlePaddingTop: 2,
33
- titlePaddingBottom: 1,
34
- stepPaddingLeft: 4,
35
- stepSpacing: 1,
36
- errorPaddingLeft: 6,
37
- bottomMargin: 2
30
+ config: "Initialize configuration",
31
+ tools: "Validate Android tools",
32
+ emulator: "Check and start emulator",
33
+ copyAssets: "Copy build assets",
34
+ build: "Build and install application",
35
+ aab: "Build signed AAB"
38
36
  };
39
37
  function createAndroidBuild(config) {
40
38
  const {
@@ -43,7 +41,9 @@ function createAndroidBuild(config) {
43
41
  } = config;
44
42
  const configPath = `${process.cwd()}/config/config.json`;
45
43
  const publicPath = `${process.cwd()}/public`;
46
- const progress = new TerminalProgress(steps, "Catalyst Android Build", progressConfig);
44
+ const progress = new TerminalProgress(steps, "catalyst buildApp", {
45
+ subject: "android"
46
+ });
47
47
  const ctx = {
48
48
  WEBVIEW_CONFIG,
49
49
  BUILD_OUTPUT_PATH,
@@ -63,6 +63,7 @@ function createAndroidBuild(config) {
63
63
  copyBuildAssets,
64
64
  copySplashscreenAssets,
65
65
  copyOfflinePage,
66
+ copySplashHtml,
66
67
  copyIconAssets,
67
68
  configureAppName,
68
69
  processNotifications
@@ -152,6 +153,7 @@ function createAndroidBuild(config) {
152
153
  await copyBuildAssets(androidConfig, buildOptimisation);
153
154
  await copySplashscreenAssets();
154
155
  await copyOfflinePage();
156
+ await copySplashHtml();
155
157
  await copyIconAssets();
156
158
  await configureAppName(androidConfig);
157
159
  const pluginConfig = resolvePluginConfig(wvConfig);
@@ -178,188 +180,43 @@ function createAndroidBuild(config) {
178
180
  progress.complete("build");
179
181
  movedApkPath = await moveApkToOutputPath(buildType, bop, androidConfig.appName);
180
182
  }
181
- const summaryItems = ["Build completed successfully:", {
182
- text: `Build Type: ${buildType}`,
183
- indent: 1,
184
- prefix: "├─ ",
185
- color: "gray"
186
- }, {
187
- text: `SDK Path: ${androidConfig.sdkPath}`,
188
- indent: 1,
189
- prefix: "├─ ",
190
- color: "gray"
191
- }, {
192
- text: `Build Optimization: ${buildOptimisation ? "Enabled" : "Disabled"}`,
193
- indent: 1,
194
- prefix: "├─ ",
183
+
184
+ // Aligned key/value rows, matching the Config tree the setup
185
+ // commands print. printTreeContent draws the branch glyphs.
186
+ const deviceName = targetDevice?.type === "physical" ? targetDevice.model : `${androidConfig.emulatorName} emulator`;
187
+ const summaryItems = [{
188
+ text: `device ${deviceName}`,
195
189
  color: "gray"
196
190
  }];
191
+ if (movedApkPath) {
192
+ summaryItems.push({
193
+ text: `artifact ${displayPath(movedApkPath, process.cwd())}`,
194
+ color: "gray"
195
+ });
196
+ }
197
197
  if (buildType === "release") {
198
- if (movedApkPath) {
199
- summaryItems.push({
200
- text: `APK Build Location: ${movedApkPath}`,
201
- indent: 1,
202
- prefix: "├─ ",
203
- color: "green"
204
- });
205
- }
206
198
  summaryItems.push({
207
- text: `Output: Signed AAB generated in build-output/`,
208
- indent: 1,
209
- prefix: "└─ ",
210
- color: "green"
199
+ text: `output Signed AAB in build-output/`,
200
+ color: "gray"
211
201
  });
212
- } else {
213
- if (movedApkPath) {
214
- summaryItems.push({
215
- text: `APK Build Location: ${movedApkPath}`,
216
- indent: 1,
217
- prefix: "├─ ",
218
- color: "green"
219
- });
220
- }
221
- if (targetDevice && targetDevice.type === "physical") {
222
- summaryItems.push({
223
- text: `Target Device: ${targetDevice.model} (Physical)`,
224
- indent: 1,
225
- prefix: "└─ ",
226
- color: "green"
227
- });
228
- } else {
229
- summaryItems.push({
230
- text: `Target Device: ${androidConfig.emulatorName} (Emulator)`,
231
- indent: 1,
232
- prefix: "└─ ",
233
- color: "gray"
234
- });
235
- }
236
202
  }
237
- progress.printTreeContent("Build Summary", summaryItems);
203
+ summaryItems.push({
204
+ text: `build ${buildType}${buildOptimisation ? ", optimised" : ""}`,
205
+ color: "gray"
206
+ });
207
+ progress.printTreeContent("Build", summaryItems);
208
+ progress.summary(`Installed on ${deviceName}`, "Run catalyst start to serve the app");
238
209
  } catch (error) {
239
- if (progress.currentStep) {
240
- progress.fail(progress.currentStep.id, error.message);
241
- const troubleshootingItems = ["Build failed. Please try the following steps:", {
242
- text: "Check if Android SDK is properly configured",
243
- indent: 1,
244
- prefix: "├─ ",
245
- color: "yellow"
246
- }, {
247
- text: "Verify build assets exist in the source directory",
248
- indent: 1,
249
- prefix: "├─ ",
250
- color: "yellow"
251
- }];
252
- const buildType = androidConfig?.buildType || "debug";
253
- if (buildType !== "release") {
254
- if (error.message.includes("physical device") || error.message.includes("installation test")) {
255
- troubleshootingItems.push("\nPhysical Device Issues:", {
256
- text: "Enable Developer Options on your device",
257
- indent: 1,
258
- prefix: "├─ ",
259
- color: "yellow"
260
- }, {
261
- text: "Enable USB Debugging in Developer Options",
262
- indent: 1,
263
- prefix: "├─ ",
264
- color: "yellow"
265
- }, {
266
- text: 'Accept the "Allow USB Debugging" prompt on your device',
267
- indent: 1,
268
- prefix: "├─ ",
269
- color: "yellow"
270
- }, {
271
- text: "Try disconnecting and reconnecting your device",
272
- indent: 1,
273
- prefix: "├─ ",
274
- color: "yellow"
275
- }, {
276
- text: 'Check if "adb devices" shows your device as authorized',
277
- indent: 1,
278
- prefix: "├─ ",
279
- color: "yellow"
280
- });
281
- }
282
- troubleshootingItems.push({
283
- text: "Verify that the emulator exists and is working",
284
- indent: 1,
285
- prefix: "├─ ",
286
- color: "yellow"
287
- }, {
288
- text: "If using physical device, ensure it stays connected",
289
- indent: 1,
290
- prefix: "├─ ",
291
- color: "yellow"
292
- });
293
- } else {
294
- troubleshootingItems.push({
295
- text: "Verify keystore configuration for release builds",
296
- indent: 1,
297
- prefix: "├─ ",
298
- color: "yellow"
299
- }, {
300
- text: "Check that keystore passwords are properly set",
301
- indent: 1,
302
- prefix: "├─ ",
303
- color: "yellow"
304
- });
305
- }
306
- troubleshootingItems.push({
307
- text: 'Run "npm run setupEmulator:android" to reconfigure Android settings',
308
- indent: 1,
309
- prefix: "└─ ",
310
- color: "yellow"
311
- }, "\nVerify Configuration:");
312
- if (androidConfig) {
313
- troubleshootingItems.push({
314
- text: `Build Type: ${buildType}`,
315
- indent: 1,
316
- prefix: "├─ ",
317
- color: "gray"
318
- }, {
319
- text: `Android SDK Path: ${androidConfig.sdkPath || "Not configured"}`,
320
- indent: 1,
321
- prefix: "├─ ",
322
- color: "gray"
323
- });
324
- if (buildType !== "release") {
325
- if (targetDevice) {
326
- troubleshootingItems.push({
327
- text: `Target Device: ${targetDevice.type === "physical" ? `${targetDevice.model} (Physical)` : `${androidConfig.emulatorName} (Emulator)`}`,
328
- indent: 1,
329
- prefix: "└─ ",
330
- color: "gray"
331
- });
332
- } else {
333
- troubleshootingItems.push({
334
- text: `Selected Emulator: ${androidConfig.emulatorName || "Not configured"}`,
335
- indent: 1,
336
- prefix: "└─ ",
337
- color: "gray"
338
- });
339
- }
340
- } else {
341
- troubleshootingItems.push({
342
- text: `Output Path: ${androidConfig.outputPath || "build-output/"}`,
343
- indent: 1,
344
- prefix: "└─ ",
345
- color: "gray"
346
- });
347
- }
348
- } else {
349
- troubleshootingItems.push({
350
- text: "Configuration could not be loaded",
351
- indent: 1,
352
- prefix: "├─ ",
353
- color: "red"
354
- }, {
355
- text: "Check if config/config.json exists and has valid Android configuration",
356
- indent: 1,
357
- prefix: "└─ ",
358
- color: "red"
359
- });
360
- }
361
- progress.printTreeContent("Troubleshooting Guide", troubleshootingItems);
362
- }
210
+ // Mark the step, then show what actually broke. The old handler
211
+ // printed a generic "check your SDK" checklist here, which is
212
+ // noise when the real Kotlin error is sitting in the output.
213
+ // The ✗ line carries no message: the diagnostic below is the message.
214
+ if (progress.currentStep) progress.fail(progress.currentStep.id);
215
+ process.stderr.write(buildFailure({
216
+ error,
217
+ stage: error.stage || "Android build",
218
+ code: "ANDROID-000"
219
+ }));
363
220
  throw error;
364
221
  }
365
222
  }
@@ -373,6 +230,7 @@ function createAndroidBuild(config) {
373
230
  await copyBuildAssets(androidConfig, buildOptimisation);
374
231
  await copySplashscreenAssets();
375
232
  await copyOfflinePage();
233
+ await copySplashHtml();
376
234
  await copyIconAssets();
377
235
  await configureAppName(androidConfig);
378
236
  const pluginConfig = resolvePluginConfig(wvConfig);
@@ -384,7 +242,7 @@ function createAndroidBuild(config) {
384
242
  });
385
243
  await processNotifications(wvConfig);
386
244
  syncAIPackageIfEnabled(wvConfig, progress);
387
- progress.log("✅ buildAndroidForTesting complete — project ready for gradlew test", "success");
245
+ progress.log("buildAndroidForTesting complete — project ready for gradlew test", "success");
388
246
  return {
389
247
  success: true
390
248
  };
@@ -5,12 +5,16 @@ const {
5
5
  pwd
6
6
  } = require("./buildAndroid/index.js");
7
7
  const {
8
- formatBuildError
8
+ formatBuildError,
9
+ resolveOutputMode
9
10
  } = require("./buildErrorFormat.js");
11
+ const {
12
+ loadAppConfig
13
+ } = require("../cli/appConfig.js");
10
14
  const {
11
15
  WEBVIEW_CONFIG,
12
16
  BUILD_OUTPUT_PATH
13
- } = require(`${process.cwd()}/config/config.json`);
17
+ } = loadAppConfig();
14
18
  async function main() {
15
19
  const build = createAndroidBuild({
16
20
  WEBVIEW_CONFIG,
@@ -22,12 +26,19 @@ async function main() {
22
26
  try {
23
27
  await buildAndroidApp();
24
28
  } catch (error) {
25
- console.error(formatBuildError({
26
- code: "ANDROID-000",
27
- category: "ANDROID",
28
- upstreamName: "Gradle",
29
- error
30
- }));
29
+ // buildAndroidApp already reported this through the progress tree and
30
+ // the troubleshooting guide, so the default mode does not repeat it.
31
+ // --verbose/--debug add the registry's boxed report on top.
32
+ if (resolveOutputMode() !== "default") {
33
+ console.error(formatBuildError({
34
+ code: "ANDROID-000",
35
+ category: "ANDROID",
36
+ upstreamName: "Gradle",
37
+ error
38
+ }));
39
+ } else if (process.env.CATALYST_DEBUG && error.stack) {
40
+ console.error(error.stack);
41
+ }
31
42
  process.exit(1);
32
43
  }
33
44
  process.exit(0);
@@ -14,13 +14,20 @@ const {
14
14
  resolveAIPluginSource
15
15
  } = require("./internalPluginUtils.js");
16
16
  const {
17
- formatBuildError
17
+ formatBuildError,
18
+ resolveOutputMode
18
19
  } = require("./buildErrorFormat.js");
20
+ const {
21
+ buildFailure
22
+ } = require("../cli/diagnostic.js");
23
+ const {
24
+ loadAppConfig
25
+ } = require("../cli/appConfig.js");
19
26
  const catalystCorePath = path.dirname(require.resolve("catalyst-core/package.json"));
20
27
  const {
21
28
  WEBVIEW_CONFIG,
22
29
  BUILD_OUTPUT_PATH
23
- } = require(`${process.cwd()}/config/config.json`);
30
+ } = loadAppConfig();
24
31
  async function main() {
25
32
  const build = createIosBuild({
26
33
  WEBVIEW_CONFIG,
@@ -35,8 +42,8 @@ async function main() {
35
42
  buildForIOS,
36
43
  PROJECT_DIR
37
44
  } = build;
45
+ let building = false;
38
46
  try {
39
- progress.log("Starting build process...", "info");
40
47
  const aiPlugin = resolveAIPluginSource(WEBVIEW_CONFIG, process.cwd(), (message, status = "info") => progress.log(message, status));
41
48
  const pluginConfig = {
42
49
  ...resolvePluginConfig(WEBVIEW_CONFIG),
@@ -53,21 +60,33 @@ async function main() {
53
60
  await updateInfoPlist(pluginComposition);
54
61
  await updateEntitlements(pluginComposition);
55
62
  await syncPluginResources(pluginComposition);
63
+ building = true;
56
64
  await buildForIOS(pluginComposition);
57
65
  } catch (error) {
58
- // progress.log() prefixes every call with an icon/color and does a
59
- // single console.log per invocation — it's built for single-line
60
- // status messages, not our multi-line boxed verbose/debug output
61
- // (piping a box through it would prefix an icon onto every border
62
- // line and break the box shape). Bypass it here and use plain
63
- // console.error instead, matching buildAppAndroid.js; progress.log
64
- // is unaffected everywhere else in this build.
65
- console.error(formatBuildError({
66
- code: "IOS-000",
67
- category: "IOS",
68
- upstreamName: "Xcode/CocoaPods",
69
- error
70
- }));
66
+ // buildForIOS already reported this through the progress tree, so the
67
+ // default mode does not repeat it. The steps before it report nothing
68
+ // themselves; without this their failure exited 1 with no output.
69
+ if (!building) {
70
+ if (progress.currentStep) progress.fail(progress.currentStep.id);
71
+ process.stderr.write(buildFailure({
72
+ error,
73
+ stage: error?.stage || "iOS build",
74
+ code: "IOS-000"
75
+ }));
76
+ }
77
+ // --verbose/--debug add the registry's boxed report, printed with
78
+ // console.error rather than progress.log, which would prefix every
79
+ // border line and break the box.
80
+ if (resolveOutputMode() !== "default") {
81
+ console.error(formatBuildError({
82
+ code: "IOS-000",
83
+ category: "IOS",
84
+ upstreamName: "Xcode/CocoaPods",
85
+ error
86
+ }));
87
+ } else if (process.env.CATALYST_DEBUG && error.stack) {
88
+ console.error(error.stack);
89
+ }
71
90
  process.exit(1);
72
91
  }
73
92
  process.exit(0);
@@ -305,7 +305,7 @@ module.exports = function createAssetsPhase(ctx) {
305
305
  if (groupPattern.test(projectContent)) projectContent = projectContent.replace(groupPattern, `$1\n\t\t\t\t${fileRefId} /* ${soundFile.filename} */,`);
306
306
  const resourcesPattern = /(\/\* Resources \*\/ = \{[^}]*files = \([^)]*)/;
307
307
  if (resourcesPattern.test(projectContent)) projectContent = projectContent.replace(resourcesPattern, `$1\n\t\t\t\t${buildFileId} /* ${soundFile.filename} in Resources */,`);
308
- progress.log(`✅ Added ${soundFile.filename} to Xcode project`, "success");
308
+ progress.log(`Added ${soundFile.filename} to Xcode project`, "success");
309
309
  }
310
310
  fs.writeFileSync(projectFilePath, projectContent, "utf8");
311
311
  progress.log(`Registered ${soundFiles.length} sound file(s) in Xcode project`, "success");
@@ -347,7 +347,6 @@ module.exports = function createAssetsPhase(ctx) {
347
347
  }
348
348
  await removeGoogleServicesPlistFromXcodeProject();
349
349
  }
350
- progress.log("Cleaned up notification assets", "success");
351
350
  } catch (error) {
352
351
  progress.log(`Warning: Error cleaning notification assets: ${error.message}`, "warning");
353
352
  }
@@ -357,7 +356,6 @@ module.exports = function createAssetsPhase(ctx) {
357
356
  try {
358
357
  await cleanupNotificationAssets(!hasNotificationConfig);
359
358
  if (!hasNotificationConfig) {
360
- progress.log("Notifications disabled - skipped asset processing", "info");
361
359
  return;
362
360
  }
363
361
  const hasGoogleServices = await handleGoogleServicesPlist();
@@ -401,7 +399,6 @@ module.exports = function createAssetsPhase(ctx) {
401
399
  const resourcesPattern = /(\/\* Resources \*\/ = \{[^}]*files = \([^)]*)/;
402
400
  if (resourcesPattern.test(projectContent)) projectContent = projectContent.replace(resourcesPattern, `$1\n\t\t\t\t${buildFileId} /* ${offlineFileName} in Resources */,`);
403
401
  fs.writeFileSync(projectFilePath, projectContent, "utf8");
404
- progress.log("Registered offline.html with Xcode project", "success");
405
402
  } catch (error) {
406
403
  progress.log(`Warning: Failed to register offline.html in Xcode project: ${error.message}`, "warning");
407
404
  }
@@ -418,7 +415,6 @@ module.exports = function createAssetsPhase(ctx) {
418
415
  recursive: true
419
416
  });
420
417
  fs.copyFileSync(sourcePath, `${destDir}/offline.html`);
421
- progress.log("offline.html copied to iOS bundle", "success");
422
418
  await addOfflinePageToXcodeProject();
423
419
  return true;
424
420
  } catch (error) {
@@ -478,7 +474,6 @@ module.exports = function createAssetsPhase(ctx) {
478
474
  const assetsDir = `${PROJECT_DIR}/${PROJECT_NAME}/Assets.xcassets`;
479
475
  const iconSetDir = `${assetsDir}/AppIcon.appiconset`;
480
476
  if (!fs.existsSync(publicDir)) {
481
- progress.log("Public directory not found, skipping app icon copy", "info");
482
477
  return;
483
478
  }
484
479
  const iconSizes = [{