@zappdev/cli 0.1.0

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 (209) hide show
  1. package/README.md +55 -0
  2. package/dist/zapp-cli.js +9471 -0
  3. package/native/src/app/app.zc +490 -0
  4. package/native/src/event/event.zc +24 -0
  5. package/native/src/event/events.zc +70 -0
  6. package/native/src/platform/darwin/backend.zc +923 -0
  7. package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
  8. package/native/src/platform/darwin/bootstrap.zc +9 -0
  9. package/native/src/platform/darwin/engine_jsc.zc +86 -0
  10. package/native/src/platform/darwin/engine_qjs.zc +92 -0
  11. package/native/src/platform/darwin/platform.zc +156 -0
  12. package/native/src/platform/darwin/webview.zc +550 -0
  13. package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
  14. package/native/src/platform/darwin/window.zc +1223 -0
  15. package/native/src/platform/darwin/worker/common.zc +223 -0
  16. package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
  17. package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
  18. package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
  19. package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
  20. package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
  21. package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
  22. package/native/src/platform/darwin/worker/dispatch.zc +55 -0
  23. package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
  24. package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
  25. package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
  26. package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
  27. package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
  28. package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
  29. package/native/src/platform/darwin/worker/jsc.zc +670 -0
  30. package/native/src/platform/darwin/worker/mod.zc +30 -0
  31. package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
  32. package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
  33. package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
  34. package/native/src/platform/darwin/worker/qjs.zc +1053 -0
  35. package/native/src/platform/darwin/worker/timers.zc +149 -0
  36. package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
  37. package/native/src/platform/platform.zc +64 -0
  38. package/native/src/platform/shared/log.zc +156 -0
  39. package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
  40. package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
  41. package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
  42. package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
  43. package/native/src/platform/shared/worker_registry.zc +206 -0
  44. package/native/src/platform/window.zc +446 -0
  45. package/native/src/platform/windows/backend.zc +452 -0
  46. package/native/src/platform/windows/backend_bootstrap.zc +9 -0
  47. package/native/src/platform/windows/bootstrap.zc +9 -0
  48. package/native/src/platform/windows/engine_qjs.zc +60 -0
  49. package/native/src/platform/windows/platform.zc +387 -0
  50. package/native/src/platform/windows/webview.zc +1175 -0
  51. package/native/src/platform/windows/webview_bootstrap.zc +9 -0
  52. package/native/src/platform/windows/window.zc +1271 -0
  53. package/native/src/platform/windows/worker/common.zc +409 -0
  54. package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
  55. package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
  56. package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
  57. package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
  58. package/native/src/platform/windows/worker/core/url_core.zc +216 -0
  59. package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
  60. package/native/src/platform/windows/worker/dispatch.zc +34 -0
  61. package/native/src/platform/windows/worker/mod.zc +46 -0
  62. package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
  63. package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
  64. package/native/src/platform/windows/worker/qjs.zc +1049 -0
  65. package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
  66. package/native/src/platform/worker.zc +8 -0
  67. package/native/src/service/service.zc +228 -0
  68. package/native/vendor/quickjs-ng/.gitattributes +4 -0
  69. package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
  70. package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
  71. package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
  72. package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
  73. package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
  74. package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
  75. package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
  76. package/native/vendor/quickjs-ng/.gitmodules +5 -0
  77. package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
  78. package/native/vendor/quickjs-ng/LICENSE +24 -0
  79. package/native/vendor/quickjs-ng/Makefile +149 -0
  80. package/native/vendor/quickjs-ng/amalgam.js +53 -0
  81. package/native/vendor/quickjs-ng/api-test.c +927 -0
  82. package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
  83. package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
  84. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
  85. package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
  86. package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
  87. package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
  88. package/native/vendor/quickjs-ng/ctest.c +17 -0
  89. package/native/vendor/quickjs-ng/cutils.h +2013 -0
  90. package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
  91. package/native/vendor/quickjs-ng/dtoa.c +1619 -0
  92. package/native/vendor/quickjs-ng/dtoa.h +87 -0
  93. package/native/vendor/quickjs-ng/examples/fib.c +67 -0
  94. package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
  95. package/native/vendor/quickjs-ng/examples/hello.js +1 -0
  96. package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
  97. package/native/vendor/quickjs-ng/examples/meson.build +17 -0
  98. package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
  99. package/native/vendor/quickjs-ng/examples/point.c +154 -0
  100. package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
  101. package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
  102. package/native/vendor/quickjs-ng/fuzz.c +51 -0
  103. package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
  104. package/native/vendor/quickjs-ng/gen/hello.c +53 -0
  105. package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
  106. package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
  107. package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
  108. package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
  109. package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
  110. package/native/vendor/quickjs-ng/libregexp.c +2687 -0
  111. package/native/vendor/quickjs-ng/libregexp.h +98 -0
  112. package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
  113. package/native/vendor/quickjs-ng/libunicode.c +1746 -0
  114. package/native/vendor/quickjs-ng/libunicode.h +126 -0
  115. package/native/vendor/quickjs-ng/list.h +107 -0
  116. package/native/vendor/quickjs-ng/lre-test.c +73 -0
  117. package/native/vendor/quickjs-ng/meson.build +684 -0
  118. package/native/vendor/quickjs-ng/meson_options.txt +6 -0
  119. package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
  120. package/native/vendor/quickjs-ng/qjs.c +748 -0
  121. package/native/vendor/quickjs-ng/qjsc.c +673 -0
  122. package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
  123. package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
  124. package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
  125. package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
  126. package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
  127. package/native/vendor/quickjs-ng/quickjs.c +60259 -0
  128. package/native/vendor/quickjs-ng/quickjs.h +1419 -0
  129. package/native/vendor/quickjs-ng/repl.js +1927 -0
  130. package/native/vendor/quickjs-ng/run-test262.c +2417 -0
  131. package/native/vendor/quickjs-ng/standalone.js +129 -0
  132. package/native/vendor/quickjs-ng/tests/assert.js +49 -0
  133. package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
  134. package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
  135. package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
  136. package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
  137. package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
  138. package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
  139. package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
  140. package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
  141. package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
  142. package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
  143. package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
  144. package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
  145. package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
  146. package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
  147. package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
  148. package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
  149. package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
  150. package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
  151. package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
  152. package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
  153. package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
  154. package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
  155. package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
  156. package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
  157. package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
  158. package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
  159. package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
  160. package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
  161. package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
  162. package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
  163. package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
  164. package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
  165. package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
  166. package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
  167. package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
  168. package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
  169. package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
  170. package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
  171. package/native/vendor/quickjs-ng/tests/empty.js +0 -0
  172. package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
  173. package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
  174. package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
  175. package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
  176. package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
  177. package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
  178. package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
  179. package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
  180. package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
  181. package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
  182. package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
  183. package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
  184. package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
  185. package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
  186. package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
  187. package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
  188. package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
  189. package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
  190. package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
  191. package/native/vendor/quickjs-ng/tests.conf +14 -0
  192. package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
  193. package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
  194. package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
  195. package/native/vendor/quickjs-ng/update-version.sh +32 -0
  196. package/native/vendor/webview2/include/WebView2.h +60636 -0
  197. package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
  198. package/package.json +33 -0
  199. package/src/backend.ts +139 -0
  200. package/src/build-config.ts +87 -0
  201. package/src/build.ts +276 -0
  202. package/src/common.ts +195 -0
  203. package/src/config.ts +89 -0
  204. package/src/dev.ts +164 -0
  205. package/src/generate.ts +200 -0
  206. package/src/icons.ts +116 -0
  207. package/src/init.ts +190 -0
  208. package/src/package.ts +150 -0
  209. package/src/zapp-cli.ts +263 -0
package/src/package.ts ADDED
@@ -0,0 +1,150 @@
1
+ import { mkdir, copyFile, chmod } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import { existsSync } from "node:fs";
5
+ import { runCmd } from "./common";
6
+ import type { ResolvedZappConfig } from "./config";
7
+ import { generateIcns, compileIconAsset } from "./icons";
8
+
9
+ export const runPackage = async ({ root, nativeOut, config }: { root: string; nativeOut: string; config: ResolvedZappConfig }) => {
10
+ if (process.platform === "darwin") {
11
+ await packageMacOS({ root, nativeOut, config });
12
+ } else if (process.platform === "win32") {
13
+ console.log("[zapp] Windows packaging: the binary is ready at " + nativeOut);
14
+ console.log("[zapp] Icon embedding happens during 'zapp build' (see build.ts).");
15
+ console.log("[zapp] Installer generation (NSIS/MSIX) is not yet implemented.");
16
+ } else {
17
+ console.error("[zapp] Packaging is not yet supported on this platform.");
18
+ }
19
+ };
20
+
21
+ async function packageMacOS({ root, nativeOut, config }: { root: string; nativeOut: string; config: ResolvedZappConfig }) {
22
+ const appName = config.name;
23
+ const appBundleName = `${appName}.app`;
24
+ const binDir = path.join(root, "bin");
25
+ await mkdir(binDir, { recursive: true });
26
+ const appBundlePath = path.join(binDir, appBundleName);
27
+
28
+ process.stdout.write(`[zapp] packaging ${appName} → ${appBundleName}\n`);
29
+
30
+ const contentsDir = path.join(appBundlePath, "Contents");
31
+ const macosDir = path.join(contentsDir, "MacOS");
32
+ const resourcesDir = path.join(contentsDir, "Resources");
33
+
34
+ await mkdir(macosDir, { recursive: true });
35
+ await mkdir(resourcesDir, { recursive: true });
36
+
37
+ // 1. Copy the executable
38
+ const execPath = path.resolve(root, nativeOut);
39
+ if (!existsSync(execPath)) {
40
+ console.error(`[zapp] binary not found at ${execPath}. Run 'zapp build' first.`);
41
+ return;
42
+ }
43
+
44
+ const destExecPath = path.join(macosDir, appName);
45
+ await copyFile(execPath, destExecPath);
46
+ await chmod(destExecPath, 0o755);
47
+
48
+ // 2. Icons
49
+ let hasIcon = false;
50
+ let hasLiquidGlass = false;
51
+
52
+ // Standard icon: PNG → .icns
53
+ if (config.icon) {
54
+ const iconSource = path.resolve(root, config.icon);
55
+ const icnsPath = await generateIcns(iconSource, resourcesDir);
56
+ if (icnsPath) {
57
+ hasIcon = true;
58
+ process.stdout.write(`[zapp] generated AppIcon.icns\n`);
59
+ }
60
+ }
61
+
62
+ // Liquid glass icon: .icon folder → Assets.car
63
+ if (config.macos?.iconLayers) {
64
+ const iconFolder = path.resolve(root, config.macos.iconLayers);
65
+ const carPath = await compileIconAsset(iconFolder, resourcesDir);
66
+ if (carPath) {
67
+ hasLiquidGlass = true;
68
+ process.stdout.write(`[zapp] compiled liquid glass icon → Assets.car\n`);
69
+ }
70
+ }
71
+
72
+ // 3. Generate Info.plist
73
+ const configPlistPath = path.join(root, "config", "darwin", "Info.plist");
74
+ let plistContent = "";
75
+
76
+ if (existsSync(configPlistPath)) {
77
+ plistContent = await Bun.file(configPlistPath).text();
78
+ // Inject icon keys if icon was generated and plist doesn't have them
79
+ if (hasIcon && !plistContent.includes("CFBundleIconFile")) {
80
+ plistContent = plistContent.replace(
81
+ "</dict>",
82
+ ` <key>CFBundleIconFile</key>\n <string>AppIcon</string>\n <key>CFBundleIconName</key>\n <string>AppIcon</string>\n</dict>`
83
+ );
84
+ }
85
+ process.stdout.write(`[zapp] using custom Info.plist\n`);
86
+ } else {
87
+ const minVersion = config.macos?.minimumSystemVersion ?? "13.0";
88
+ const category = config.macos?.category ?? "";
89
+ const copyright = config.author ? `Copyright © ${new Date().getFullYear()} ${config.author}` : "";
90
+
91
+ let extraKeys = "";
92
+ if (hasIcon || hasLiquidGlass) {
93
+ extraKeys += ` <key>CFBundleIconFile</key>
94
+ <string>AppIcon</string>
95
+ <key>CFBundleIconName</key>
96
+ <string>AppIcon</string>\n`;
97
+ }
98
+ if (category) {
99
+ extraKeys += ` <key>LSApplicationCategoryType</key>
100
+ <string>${category}</string>\n`;
101
+ }
102
+ if (copyright) {
103
+ extraKeys += ` <key>NSHumanReadableCopyright</key>
104
+ <string>${copyright}</string>\n`;
105
+ }
106
+
107
+ plistContent = `<?xml version="1.0" encoding="UTF-8"?>
108
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
109
+ <plist version="1.0">
110
+ <dict>
111
+ <key>CFBundleName</key>
112
+ <string>${appName}</string>
113
+ <key>CFBundleExecutable</key>
114
+ <string>${appName}</string>
115
+ <key>CFBundleIdentifier</key>
116
+ <string>${config.identifier}</string>
117
+ <key>CFBundleVersion</key>
118
+ <string>${config.version}</string>
119
+ <key>CFBundleShortVersionString</key>
120
+ <string>${config.version}</string>
121
+ <key>CFBundlePackageType</key>
122
+ <string>APPL</string>
123
+ <key>LSMinimumSystemVersion</key>
124
+ <string>${minVersion}</string>
125
+ <key>NSHighResolutionCapable</key>
126
+ <true/>
127
+ ${extraKeys}</dict>
128
+ </plist>`;
129
+ }
130
+
131
+ // Ensure CFBundleExecutable is set correctly
132
+ if (!plistContent.includes("<key>CFBundleExecutable</key>")) {
133
+ plistContent = plistContent.replace(
134
+ "<dict>",
135
+ `<dict>\n <key>CFBundleExecutable</key>\n <string>${appName}</string>`
136
+ );
137
+ }
138
+
139
+ await Bun.write(path.join(contentsDir, "Info.plist"), plistContent);
140
+
141
+ // 4. Ad-hoc codesign
142
+ try {
143
+ await runCmd("codesign", ["--force", "--deep", "--sign", "-", appBundlePath]);
144
+ process.stdout.write(`[zapp] codesigned (ad-hoc)\n`);
145
+ } catch {
146
+ console.warn("[zapp] codesign failed (non-fatal)");
147
+ }
148
+
149
+ process.stdout.write(`[zapp] packaged → ${appBundlePath}\n`);
150
+ }
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env bun
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+ import yargs from "yargs";
5
+ import { hideBin } from "yargs/helpers";
6
+ import { runDev } from "./dev";
7
+ import { runBuild } from "./build";
8
+ import { runInit } from "./init";
9
+ import { runPackage } from "./package";
10
+ import { runGenerate } from "./generate";
11
+ import { loadConfig } from "./config";
12
+
13
+ const VALID_LOG_LEVELS = ["error", "warn", "info", "debug", "trace"] as const;
14
+ type LogLevel = typeof VALID_LOG_LEVELS[number];
15
+
16
+ const checkPrerequisites = () => {
17
+ const which = Bun.which("zc");
18
+ if (!which) {
19
+ console.error(
20
+ "[zapp] Error: 'zc' (Zen-C compiler) not found on PATH.\n" +
21
+ " Install from: https://github.com/zenc-lang/zenc\n"
22
+ );
23
+ process.exit(1);
24
+ }
25
+ };
26
+
27
+ const cwd = process.cwd();
28
+
29
+ const commonOptions = {
30
+ root: {
31
+ type: "string" as const,
32
+ default: ".",
33
+ describe: "Project root directory",
34
+ },
35
+ frontend: {
36
+ type: "string" as const,
37
+ default: ".",
38
+ describe: "Frontend directory",
39
+ },
40
+ input: {
41
+ type: "string" as const,
42
+ default: "zapp/build.zc",
43
+ describe: "Build file (alias: --build-file)",
44
+ },
45
+ out: {
46
+ type: "string" as const,
47
+ describe: "Override output binary path",
48
+ },
49
+ backend: {
50
+ type: "string" as const,
51
+ describe: "Backend script path",
52
+ },
53
+ "log-level": {
54
+ type: "string" as const,
55
+ choices: VALID_LOG_LEVELS,
56
+ describe: "Log level",
57
+ },
58
+ } as const;
59
+
60
+ const cli = yargs(hideBin(process.argv))
61
+ .scriptName("zapp")
62
+ .usage("zapp <command> [options]")
63
+ .strict()
64
+ .demandCommand(1, "Please specify a command")
65
+ .command(
66
+ "init [name]",
67
+ "Scaffold a new Zapp project",
68
+ (yargs) =>
69
+ yargs
70
+ .positional("name", {
71
+ type: "string",
72
+ default: "zapp-app",
73
+ describe: "Project name",
74
+ })
75
+ .option("template", {
76
+ type: "string",
77
+ default: "vanilla-ts",
78
+ describe: "Vite template (e.g. vanilla-ts, react-ts, svelte-ts, vue-ts)",
79
+ })
80
+ .option("root", commonOptions.root),
81
+ async (argv) => {
82
+ const root = path.resolve(cwd, argv.root);
83
+ await runInit({
84
+ root,
85
+ name: argv.name,
86
+ template: argv.template,
87
+ });
88
+ }
89
+ )
90
+ .command(
91
+ "dev",
92
+ "Run Vite + native app together",
93
+ (yargs) =>
94
+ yargs
95
+ .option("root", commonOptions.root)
96
+ .option("frontend", commonOptions.frontend)
97
+ .option("input", commonOptions.input)
98
+ .option("out", commonOptions.out)
99
+ .option("backend", commonOptions.backend)
100
+ .option("log-level", commonOptions["log-level"])
101
+ .option("dev-url", {
102
+ type: "string",
103
+ default: "http://localhost:5173",
104
+ describe: "Dev server URL",
105
+ })
106
+ .option("brotli", {
107
+ type: "boolean",
108
+ default: false,
109
+ describe: "Brotli-compress embedded assets",
110
+ })
111
+ .option("embed-assets", {
112
+ type: "boolean",
113
+ default: false,
114
+ describe: "Embed assets in binary (default: false for dev)",
115
+ }),
116
+ async (argv) => {
117
+ checkPrerequisites();
118
+ const root = path.resolve(cwd, argv.root);
119
+ const frontendDir = path.resolve(root, argv.frontend);
120
+ const buildFile = path.resolve(root, argv.input);
121
+ const config = await loadConfig(root);
122
+ const nativeOut = argv.out
123
+ ? path.resolve(root, argv.out)
124
+ : path.resolve(root, "bin", process.platform === "win32" ? `${config.name}.exe` : config.name);
125
+
126
+ await runDev({
127
+ root,
128
+ frontendDir,
129
+ buildFile,
130
+ nativeOut,
131
+ devUrl: argv["dev-url"],
132
+ withBrotli: argv.brotli,
133
+ embedAssets: argv["embed-assets"],
134
+ backendScript: argv.backend,
135
+ logLevel: argv["log-level"] as LogLevel | undefined,
136
+ config,
137
+ });
138
+ }
139
+ )
140
+ .command(
141
+ "build",
142
+ "Build frontend assets + native binary",
143
+ (yargs) =>
144
+ yargs
145
+ .option("root", commonOptions.root)
146
+ .option("frontend", commonOptions.frontend)
147
+ .option("input", commonOptions.input)
148
+ .option("out", commonOptions.out)
149
+ .option("backend", commonOptions.backend)
150
+ .option("log-level", commonOptions["log-level"])
151
+ .option("asset-dir", {
152
+ type: "string",
153
+ default: "dist",
154
+ describe: "Asset directory",
155
+ })
156
+ .option("brotli", {
157
+ type: "boolean",
158
+ default: false,
159
+ describe: "Brotli-compress embedded assets",
160
+ })
161
+ .option("debug", {
162
+ type: "boolean",
163
+ default: false,
164
+ describe: "Debug build (filesystem assets, debug logs, no optimizations)",
165
+ }),
166
+ async (argv) => {
167
+ checkPrerequisites();
168
+ const root = path.resolve(cwd, argv.root);
169
+ const frontendDir = path.resolve(root, argv.frontend);
170
+ const buildFile = path.resolve(root, argv.input);
171
+ const assetDir = path.resolve(frontendDir, argv["asset-dir"]);
172
+ const config = await loadConfig(root);
173
+ const nativeOut = argv.out
174
+ ? path.resolve(root, argv.out)
175
+ : path.resolve(root, "bin", process.platform === "win32" ? `${config.name}.exe` : config.name);
176
+
177
+ // Embed assets by default for builds, unless --debug
178
+ const embedAssets = !argv.debug;
179
+
180
+ await runBuild({
181
+ root,
182
+ frontendDir,
183
+ buildFile,
184
+ nativeOut,
185
+ assetDir,
186
+ withBrotli: argv.brotli,
187
+ embedAssets,
188
+ isDebug: argv.debug,
189
+ backendScript: argv.backend,
190
+ logLevel: argv["log-level"] as LogLevel | undefined,
191
+ config,
192
+ });
193
+ }
194
+ )
195
+ .command(
196
+ "package",
197
+ "Build and package into a platform bundle (.app on macOS)",
198
+ (yargs) =>
199
+ yargs
200
+ .option("root", commonOptions.root)
201
+ .option("frontend", commonOptions.frontend)
202
+ .option("input", commonOptions.input)
203
+ .option("out", commonOptions.out)
204
+ .option("brotli", {
205
+ type: "boolean",
206
+ default: true,
207
+ describe: "Brotli-compress embedded assets",
208
+ })
209
+ .option("skip-build", {
210
+ type: "boolean",
211
+ default: false,
212
+ describe: "Skip the build step (use existing binary)",
213
+ }),
214
+ async (argv) => {
215
+ checkPrerequisites();
216
+ const root = path.resolve(cwd, argv.root);
217
+ const frontendDir = path.resolve(root, argv.frontend);
218
+ const buildFile = path.resolve(root, argv.input);
219
+ const config = await loadConfig(root);
220
+ const nativeOut = argv.out
221
+ ? path.resolve(root, argv.out)
222
+ : path.resolve(root, "bin", process.platform === "win32" ? `${config.name}.exe` : config.name);
223
+
224
+ if (!argv["skip-build"]) {
225
+ const assetDir = path.resolve(frontendDir, "dist");
226
+ await runBuild({
227
+ root,
228
+ frontendDir,
229
+ buildFile,
230
+ nativeOut,
231
+ assetDir,
232
+ isDebug: false,
233
+ embedAssets: true,
234
+ withBrotli: argv.brotli,
235
+ config,
236
+ });
237
+ }
238
+
239
+ await runPackage({ root, nativeOut, config });
240
+ }
241
+ )
242
+ .command(
243
+ "generate",
244
+ "Generate TypeScript bindings from Zen-C services",
245
+ (yargs) =>
246
+ yargs
247
+ .option("root", commonOptions.root)
248
+ .option("frontend", commonOptions.frontend)
249
+ .option("out-dir", {
250
+ type: "string",
251
+ describe: "Output directory for generated files",
252
+ }),
253
+ async (argv) => {
254
+ const root = path.resolve(cwd, argv.root);
255
+ const frontendDir = path.resolve(root, argv.frontend);
256
+ await runGenerate({ root, frontendDir, outDir: argv["out-dir"] });
257
+ }
258
+ )
259
+ .alias("h", "help")
260
+ .alias("v", "version")
261
+ .alias("build-file", "input")
262
+ .epilogue("Documentation: https://zapp.dev")
263
+ .parse();