@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.
- package/README.md +55 -0
- package/dist/zapp-cli.js +9471 -0
- package/native/src/app/app.zc +490 -0
- package/native/src/event/event.zc +24 -0
- package/native/src/event/events.zc +70 -0
- package/native/src/platform/darwin/backend.zc +923 -0
- package/native/src/platform/darwin/backend_bootstrap.zc +9 -0
- package/native/src/platform/darwin/bootstrap.zc +9 -0
- package/native/src/platform/darwin/engine_jsc.zc +86 -0
- package/native/src/platform/darwin/engine_qjs.zc +92 -0
- package/native/src/platform/darwin/platform.zc +156 -0
- package/native/src/platform/darwin/webview.zc +550 -0
- package/native/src/platform/darwin/webview_bootstrap.zc +9 -0
- package/native/src/platform/darwin/window.zc +1223 -0
- package/native/src/platform/darwin/worker/common.zc +223 -0
- package/native/src/platform/darwin/worker/core/base64_core.zc +29 -0
- package/native/src/platform/darwin/worker/core/crypto_core.zc +19 -0
- package/native/src/platform/darwin/worker/core/encoding_core.zc +32 -0
- package/native/src/platform/darwin/worker/core/fetch_core.zc +145 -0
- package/native/src/platform/darwin/worker/core/url_core.zc +69 -0
- package/native/src/platform/darwin/worker/core/websocket_core.zc +179 -0
- package/native/src/platform/darwin/worker/dispatch.zc +55 -0
- package/native/src/platform/darwin/worker/jsc/base64_jsc.zc +39 -0
- package/native/src/platform/darwin/worker/jsc/crypto_jsc.zc +49 -0
- package/native/src/platform/darwin/worker/jsc/encoding_jsc.zc +86 -0
- package/native/src/platform/darwin/worker/jsc/fetch_jsc.zc +149 -0
- package/native/src/platform/darwin/worker/jsc/url_jsc.zc +54 -0
- package/native/src/platform/darwin/worker/jsc/websocket_jsc.zc +127 -0
- package/native/src/platform/darwin/worker/jsc.zc +670 -0
- package/native/src/platform/darwin/worker/mod.zc +30 -0
- package/native/src/platform/darwin/worker/qjs/fetch_qjs.zc +233 -0
- package/native/src/platform/darwin/worker/qjs/qjs_macros.zc +23 -0
- package/native/src/platform/darwin/worker/qjs/websocket_qjs.zc +223 -0
- package/native/src/platform/darwin/worker/qjs.zc +1053 -0
- package/native/src/platform/darwin/worker/timers.zc +149 -0
- package/native/src/platform/darwin/worker/timers_qjs.zc +209 -0
- package/native/src/platform/platform.zc +64 -0
- package/native/src/platform/shared/log.zc +156 -0
- package/native/src/platform/shared/worker/qjs/base64_qjs.zc +38 -0
- package/native/src/platform/shared/worker/qjs/crypto_qjs.zc +44 -0
- package/native/src/platform/shared/worker/qjs/encoding_qjs.zc +95 -0
- package/native/src/platform/shared/worker/qjs/url_qjs.zc +65 -0
- package/native/src/platform/shared/worker_registry.zc +206 -0
- package/native/src/platform/window.zc +446 -0
- package/native/src/platform/windows/backend.zc +452 -0
- package/native/src/platform/windows/backend_bootstrap.zc +9 -0
- package/native/src/platform/windows/bootstrap.zc +9 -0
- package/native/src/platform/windows/engine_qjs.zc +60 -0
- package/native/src/platform/windows/platform.zc +387 -0
- package/native/src/platform/windows/webview.zc +1175 -0
- package/native/src/platform/windows/webview_bootstrap.zc +9 -0
- package/native/src/platform/windows/window.zc +1271 -0
- package/native/src/platform/windows/worker/common.zc +409 -0
- package/native/src/platform/windows/worker/core/base64_core.zc +52 -0
- package/native/src/platform/windows/worker/core/crypto_core.zc +34 -0
- package/native/src/platform/windows/worker/core/encoding_core.zc +60 -0
- package/native/src/platform/windows/worker/core/fetch_core.zc +274 -0
- package/native/src/platform/windows/worker/core/url_core.zc +216 -0
- package/native/src/platform/windows/worker/core/websocket_core.zc +343 -0
- package/native/src/platform/windows/worker/dispatch.zc +34 -0
- package/native/src/platform/windows/worker/mod.zc +46 -0
- package/native/src/platform/windows/worker/qjs/fetch_qjs.zc +255 -0
- package/native/src/platform/windows/worker/qjs/websocket_qjs.zc +263 -0
- package/native/src/platform/windows/worker/qjs.zc +1049 -0
- package/native/src/platform/windows/worker/timers_qjs.zc +288 -0
- package/native/src/platform/worker.zc +8 -0
- package/native/src/service/service.zc +228 -0
- package/native/vendor/quickjs-ng/.gitattributes +4 -0
- package/native/vendor/quickjs-ng/.github/dependabot.yml +7 -0
- package/native/vendor/quickjs-ng/.github/workflows/ci.yml +812 -0
- package/native/vendor/quickjs-ng/.github/workflows/docs.yml +49 -0
- package/native/vendor/quickjs-ng/.github/workflows/release.yml +162 -0
- package/native/vendor/quickjs-ng/.github/workflows/test-docs.yml +23 -0
- package/native/vendor/quickjs-ng/.github/workflows/tsan.yml +32 -0
- package/native/vendor/quickjs-ng/.github/workflows/valgrind.yml +33 -0
- package/native/vendor/quickjs-ng/.gitmodules +5 -0
- package/native/vendor/quickjs-ng/CMakeLists.txt +553 -0
- package/native/vendor/quickjs-ng/LICENSE +24 -0
- package/native/vendor/quickjs-ng/Makefile +149 -0
- package/native/vendor/quickjs-ng/amalgam.js +53 -0
- package/native/vendor/quickjs-ng/api-test.c +927 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
- package/native/vendor/quickjs-ng/builtin-array-fromasync.js +36 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip-keyed.js +194 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
- package/native/vendor/quickjs-ng/builtin-iterator-zip.js +210 -0
- package/native/vendor/quickjs-ng/ctest.c +17 -0
- package/native/vendor/quickjs-ng/cutils.h +2013 -0
- package/native/vendor/quickjs-ng/cxxtest.cc +2 -0
- package/native/vendor/quickjs-ng/dtoa.c +1619 -0
- package/native/vendor/quickjs-ng/dtoa.h +87 -0
- package/native/vendor/quickjs-ng/examples/fib.c +67 -0
- package/native/vendor/quickjs-ng/examples/fib_module.js +10 -0
- package/native/vendor/quickjs-ng/examples/hello.js +1 -0
- package/native/vendor/quickjs-ng/examples/hello_module.js +6 -0
- package/native/vendor/quickjs-ng/examples/meson.build +17 -0
- package/native/vendor/quickjs-ng/examples/pi_bigint.js +118 -0
- package/native/vendor/quickjs-ng/examples/point.c +154 -0
- package/native/vendor/quickjs-ng/examples/test_fib.js +8 -0
- package/native/vendor/quickjs-ng/examples/test_point.js +43 -0
- package/native/vendor/quickjs-ng/fuzz.c +51 -0
- package/native/vendor/quickjs-ng/gen/function_source.c +81 -0
- package/native/vendor/quickjs-ng/gen/hello.c +53 -0
- package/native/vendor/quickjs-ng/gen/hello_module.c +106 -0
- package/native/vendor/quickjs-ng/gen/repl.c +3053 -0
- package/native/vendor/quickjs-ng/gen/standalone.c +324 -0
- package/native/vendor/quickjs-ng/gen/test_fib.c +81 -0
- package/native/vendor/quickjs-ng/libregexp-opcode.h +58 -0
- package/native/vendor/quickjs-ng/libregexp.c +2687 -0
- package/native/vendor/quickjs-ng/libregexp.h +98 -0
- package/native/vendor/quickjs-ng/libunicode-table.h +4707 -0
- package/native/vendor/quickjs-ng/libunicode.c +1746 -0
- package/native/vendor/quickjs-ng/libunicode.h +126 -0
- package/native/vendor/quickjs-ng/list.h +107 -0
- package/native/vendor/quickjs-ng/lre-test.c +73 -0
- package/native/vendor/quickjs-ng/meson.build +684 -0
- package/native/vendor/quickjs-ng/meson_options.txt +6 -0
- package/native/vendor/quickjs-ng/qjs-wasi-reactor.c +208 -0
- package/native/vendor/quickjs-ng/qjs.c +748 -0
- package/native/vendor/quickjs-ng/qjsc.c +673 -0
- package/native/vendor/quickjs-ng/quickjs-atom.h +267 -0
- package/native/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
- package/native/vendor/quickjs-ng/quickjs-libc.c +4986 -0
- package/native/vendor/quickjs-ng/quickjs-libc.h +79 -0
- package/native/vendor/quickjs-ng/quickjs-opcode.h +369 -0
- package/native/vendor/quickjs-ng/quickjs.c +60259 -0
- package/native/vendor/quickjs-ng/quickjs.h +1419 -0
- package/native/vendor/quickjs-ng/repl.js +1927 -0
- package/native/vendor/quickjs-ng/run-test262.c +2417 -0
- package/native/vendor/quickjs-ng/standalone.js +129 -0
- package/native/vendor/quickjs-ng/tests/assert.js +49 -0
- package/native/vendor/quickjs-ng/tests/bug1221.js +16 -0
- package/native/vendor/quickjs-ng/tests/bug1296.js +12 -0
- package/native/vendor/quickjs-ng/tests/bug1297.js +22 -0
- package/native/vendor/quickjs-ng/tests/bug1301.js +21 -0
- package/native/vendor/quickjs-ng/tests/bug1302.js +24 -0
- package/native/vendor/quickjs-ng/tests/bug1305.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug1318.js +54 -0
- package/native/vendor/quickjs-ng/tests/bug1352.js +8 -0
- package/native/vendor/quickjs-ng/tests/bug1354.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug1355.js +58 -0
- package/native/vendor/quickjs-ng/tests/bug1368.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug39/1.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/2.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug39/3.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug488-upstream.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/0.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug633/1.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/2.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug633/3.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/0.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug645/1.js +9 -0
- package/native/vendor/quickjs-ng/tests/bug645/2.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug648.js +13 -0
- package/native/vendor/quickjs-ng/tests/bug652.js +4 -0
- package/native/vendor/quickjs-ng/tests/bug741.js +19 -0
- package/native/vendor/quickjs-ng/tests/bug775.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug776.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug832.js +2 -0
- package/native/vendor/quickjs-ng/tests/bug858.js +26 -0
- package/native/vendor/quickjs-ng/tests/bug904.js +6 -0
- package/native/vendor/quickjs-ng/tests/bug988.js +7 -0
- package/native/vendor/quickjs-ng/tests/bug999.js +3 -0
- package/native/vendor/quickjs-ng/tests/destructured-export.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/0.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/1.js +2 -0
- package/native/vendor/quickjs-ng/tests/detect_module/2.js +1 -0
- package/native/vendor/quickjs-ng/tests/detect_module/3.js +8 -0
- package/native/vendor/quickjs-ng/tests/detect_module/4.js +3 -0
- package/native/vendor/quickjs-ng/tests/empty.js +0 -0
- package/native/vendor/quickjs-ng/tests/fixture_cyclic_import.js +2 -0
- package/native/vendor/quickjs-ng/tests/fixture_string_exports.js +12 -0
- package/native/vendor/quickjs-ng/tests/function_source.js +14 -0
- package/native/vendor/quickjs-ng/tests/microbench.js +1267 -0
- package/native/vendor/quickjs-ng/tests/null_or_undefined.js +38 -0
- package/native/vendor/quickjs-ng/tests/str-pad-leak.js +5 -0
- package/native/vendor/quickjs-ng/tests/test_bigint.js +107 -0
- package/native/vendor/quickjs-ng/tests/test_bjson.js +366 -0
- package/native/vendor/quickjs-ng/tests/test_builtin.js +1314 -0
- package/native/vendor/quickjs-ng/tests/test_closure.js +220 -0
- package/native/vendor/quickjs-ng/tests/test_cyclic_import.js +12 -0
- package/native/vendor/quickjs-ng/tests/test_domexception.js +35 -0
- package/native/vendor/quickjs-ng/tests/test_language.js +755 -0
- package/native/vendor/quickjs-ng/tests/test_loop.js +367 -0
- package/native/vendor/quickjs-ng/tests/test_queue_microtask.js +39 -0
- package/native/vendor/quickjs-ng/tests/test_std.js +340 -0
- package/native/vendor/quickjs-ng/tests/test_string_exports.js +25 -0
- package/native/vendor/quickjs-ng/tests/test_worker.js +43 -0
- package/native/vendor/quickjs-ng/tests/test_worker_module.js +30 -0
- package/native/vendor/quickjs-ng/tests.conf +14 -0
- package/native/vendor/quickjs-ng/unicode_download.sh +19 -0
- package/native/vendor/quickjs-ng/unicode_gen.c +3108 -0
- package/native/vendor/quickjs-ng/unicode_gen_def.h +310 -0
- package/native/vendor/quickjs-ng/update-version.sh +32 -0
- package/native/vendor/webview2/include/WebView2.h +60636 -0
- package/native/vendor/webview2/include/WebView2EnvironmentOptions.h +406 -0
- package/package.json +33 -0
- package/src/backend.ts +139 -0
- package/src/build-config.ts +87 -0
- package/src/build.ts +276 -0
- package/src/common.ts +195 -0
- package/src/config.ts +89 -0
- package/src/dev.ts +164 -0
- package/src/generate.ts +200 -0
- package/src/icons.ts +116 -0
- package/src/init.ts +190 -0
- package/src/package.ts +150 -0
- package/src/zapp-cli.ts +263 -0
package/src/dev.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { createInterface } from "node:readline";
|
|
5
|
+
import { mkdir } from "node:fs/promises";
|
|
6
|
+
import {
|
|
7
|
+
buildFileNeedsQjs,
|
|
8
|
+
ensureQjsLib,
|
|
9
|
+
killChild,
|
|
10
|
+
nativeIncludeArgs,
|
|
11
|
+
preferredJsTool,
|
|
12
|
+
resolveNativeDir,
|
|
13
|
+
runCmd,
|
|
14
|
+
runPackageScript,
|
|
15
|
+
sleep,
|
|
16
|
+
spawnPackageScript,
|
|
17
|
+
spawnStreaming,
|
|
18
|
+
} from "./common";
|
|
19
|
+
import { buildAssetManifest, generateAssetsZc } from "./build";
|
|
20
|
+
import { generateBuildConfigZc } from "./build-config";
|
|
21
|
+
import { resolveAndBundleBackend } from "./backend";
|
|
22
|
+
import { runGenerate } from "./generate";
|
|
23
|
+
import type { ResolvedZappConfig } from "./config";
|
|
24
|
+
|
|
25
|
+
const waitForUrl = async (url: string, timeoutMs: number) => {
|
|
26
|
+
const start = Date.now();
|
|
27
|
+
while (Date.now() - start < timeoutMs) {
|
|
28
|
+
try {
|
|
29
|
+
const res = await fetch(url);
|
|
30
|
+
if (res.ok) return;
|
|
31
|
+
} catch {
|
|
32
|
+
await sleep(100);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw new Error(`Timed out waiting for ${url}`);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const runDev = async ({
|
|
39
|
+
root,
|
|
40
|
+
frontendDir,
|
|
41
|
+
buildFile,
|
|
42
|
+
nativeOut,
|
|
43
|
+
devUrl,
|
|
44
|
+
withBrotli,
|
|
45
|
+
embedAssets,
|
|
46
|
+
backendScript,
|
|
47
|
+
logLevel,
|
|
48
|
+
config,
|
|
49
|
+
}: {
|
|
50
|
+
root: string;
|
|
51
|
+
frontendDir: string;
|
|
52
|
+
buildFile: string;
|
|
53
|
+
nativeOut: string;
|
|
54
|
+
devUrl: string;
|
|
55
|
+
withBrotli: boolean;
|
|
56
|
+
embedAssets: boolean;
|
|
57
|
+
backendScript?: string;
|
|
58
|
+
logLevel?: "error" | "warn" | "info" | "debug" | "trace";
|
|
59
|
+
config: ResolvedZappConfig;
|
|
60
|
+
}) => {
|
|
61
|
+
process.stdout.write(`[zapp] starting dev orchestration (${preferredJsTool()})\n`);
|
|
62
|
+
if (withBrotli && !embedAssets) {
|
|
63
|
+
process.stdout.write("[zapp] note: --brotli has no effect without --embed-assets\n");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await runGenerate({ root, frontendDir });
|
|
67
|
+
|
|
68
|
+
const vite = embedAssets ? null : spawnPackageScript("dev", { cwd: frontendDir });
|
|
69
|
+
let app: any = null;
|
|
70
|
+
let shuttingDown = false;
|
|
71
|
+
|
|
72
|
+
const shutdown = (reason: "user" | "app-exit" | "error" = "error") => {
|
|
73
|
+
if (shuttingDown) return;
|
|
74
|
+
shuttingDown = true;
|
|
75
|
+
if (reason === "user") {
|
|
76
|
+
process.stdout.write("\n[zapp] gracefully exiting...\n");
|
|
77
|
+
} else if (reason === "app-exit") {
|
|
78
|
+
process.stdout.write("[zapp] app exited, cleaning up...\n");
|
|
79
|
+
}
|
|
80
|
+
killChild(app);
|
|
81
|
+
killChild(vite);
|
|
82
|
+
setTimeout(() => process.exit(0), 1500);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
process.on("SIGINT", () => shutdown("user"));
|
|
86
|
+
process.on("SIGTERM", () => shutdown("user"));
|
|
87
|
+
process.on("SIGHUP", () => shutdown("user"));
|
|
88
|
+
|
|
89
|
+
if (process.platform === "win32" && process.stdin.isTTY) {
|
|
90
|
+
const rl = createInterface({ input: process.stdin });
|
|
91
|
+
rl.on("SIGINT", () => shutdown("user"));
|
|
92
|
+
rl.on("close", () => shutdown("user"));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const assetDir = path.join(frontendDir, "dist");
|
|
97
|
+
if (embedAssets) {
|
|
98
|
+
process.stdout.write("[zapp] dev embedded mode: building static frontend assets\n");
|
|
99
|
+
await runPackageScript("build", { cwd: frontendDir });
|
|
100
|
+
} else {
|
|
101
|
+
await waitForUrl(devUrl, 30000);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const backendScriptPath = await resolveAndBundleBackend({ root, frontendDir, backendScript });
|
|
105
|
+
|
|
106
|
+
const buildConfigFile = await generateBuildConfigZc({
|
|
107
|
+
root,
|
|
108
|
+
mode: embedAssets ? "dev-embedded" : "dev",
|
|
109
|
+
assetDir,
|
|
110
|
+
devUrl,
|
|
111
|
+
backendScriptPath,
|
|
112
|
+
logLevel,
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await mkdir(path.dirname(nativeOut), { recursive: true });
|
|
116
|
+
const needsQjs = await buildFileNeedsQjs(buildFile);
|
|
117
|
+
const qjsLib = needsQjs ? await ensureQjsLib(root, "dev") : null;
|
|
118
|
+
const zcArgs = ["build", buildFile, buildConfigFile, "-DZAPP_BUILD_DEV", "--debug", ...nativeIncludeArgs()];
|
|
119
|
+
const manifest = embedAssets
|
|
120
|
+
? await buildAssetManifest({ assetDir, withBrotli })
|
|
121
|
+
: { v: 1, generatedAt: new Date().toISOString(), assets: [] as any[], embedded: false };
|
|
122
|
+
const assetsFile = await generateAssetsZc(root, manifest, assetDir);
|
|
123
|
+
zcArgs.push(assetsFile);
|
|
124
|
+
// On Windows, embed the application manifest for comctl32 v6
|
|
125
|
+
if (process.platform === "win32") {
|
|
126
|
+
const manifestSrc = path.join(root, "config", "windows", "app.manifest");
|
|
127
|
+
if (existsSync(manifestSrc)) {
|
|
128
|
+
const buildDir = path.join(root, ".zapp", "build");
|
|
129
|
+
await mkdir(buildDir, { recursive: true });
|
|
130
|
+
const rcPath = path.join(buildDir, "app.rc");
|
|
131
|
+
await Bun.write(rcPath, `1 24 "${manifestSrc.replace(/\\/g, "/")}"\n`);
|
|
132
|
+
const resPath = path.join(buildDir, "app_manifest.o");
|
|
133
|
+
await runCmd("windres", [rcPath, "-O", "coff", "-o", resPath]);
|
|
134
|
+
zcArgs.push(resPath);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
zcArgs.push("-o", nativeOut);
|
|
139
|
+
if (qjsLib) {
|
|
140
|
+
zcArgs.push("-L", path.dirname(qjsLib), "-lqjs");
|
|
141
|
+
}
|
|
142
|
+
await runCmd("zc", zcArgs, { cwd: root, env: { ZAPP_NATIVE: resolveNativeDir() } });
|
|
143
|
+
app = spawnStreaming(nativeOut, [], {
|
|
144
|
+
cwd: root,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
app.exited.then((code: number | null) => {
|
|
148
|
+
if (!shuttingDown) {
|
|
149
|
+
shutdown("app-exit");
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
vite?.exited.then(() => {
|
|
153
|
+
if (!shuttingDown) {
|
|
154
|
+
shutdown("error");
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
} catch (error) {
|
|
158
|
+
shutdown("error");
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await new Promise(() => {});
|
|
163
|
+
return path.resolve(root);
|
|
164
|
+
};
|
package/src/generate.ts
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
|
|
5
|
+
type ServiceMethod = {
|
|
6
|
+
name: string;
|
|
7
|
+
args: { name: string; type: string }[];
|
|
8
|
+
returnType: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type ServiceDef = {
|
|
12
|
+
name: string;
|
|
13
|
+
methods: ServiceMethod[];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const ZEN_TO_TS_TYPES: Record<string, string> = {
|
|
17
|
+
string: "string",
|
|
18
|
+
int: "number",
|
|
19
|
+
float: "number",
|
|
20
|
+
double: "number",
|
|
21
|
+
bool: "boolean",
|
|
22
|
+
void: "void",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function mapType(zenType: string): string {
|
|
26
|
+
return ZEN_TO_TS_TYPES[zenType.trim()] ?? "unknown";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Scans .zc files for service_add registrations and extracts method signatures.
|
|
31
|
+
*
|
|
32
|
+
* Looks for patterns like:
|
|
33
|
+
* app.service.add("name", handler_fn);
|
|
34
|
+
*
|
|
35
|
+
* Then finds the corresponding function definition:
|
|
36
|
+
* fn handler_fn(app: App*, args: string) -> string { ... }
|
|
37
|
+
*/
|
|
38
|
+
async function scanServices(srcDir: string): Promise<ServiceDef[]> {
|
|
39
|
+
const services: ServiceDef[] = [];
|
|
40
|
+
const files: string[] = [];
|
|
41
|
+
|
|
42
|
+
async function walk(dir: string) {
|
|
43
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
44
|
+
for (const entry of entries) {
|
|
45
|
+
if (entry.name.startsWith(".") || entry.name === "vendor") continue;
|
|
46
|
+
const full = path.join(dir, entry.name);
|
|
47
|
+
if (entry.isDirectory()) {
|
|
48
|
+
await walk(full);
|
|
49
|
+
} else if (entry.name.endsWith(".zc")) {
|
|
50
|
+
files.push(full);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
await walk(srcDir);
|
|
56
|
+
|
|
57
|
+
const allContent: { file: string; content: string }[] = [];
|
|
58
|
+
for (const file of files) {
|
|
59
|
+
const content = await fs.readFile(file, "utf8");
|
|
60
|
+
allContent.push({ file, content });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Find service.add("name", handler) registrations
|
|
64
|
+
const addPattern = /\.service\.add\(\s*"([^"]+)"\s*,\s*(\w+)\s*\)/g;
|
|
65
|
+
const registrations: { serviceName: string; handlerName: string }[] = [];
|
|
66
|
+
|
|
67
|
+
for (const { content } of allContent) {
|
|
68
|
+
let match;
|
|
69
|
+
while ((match = addPattern.exec(content)) !== null) {
|
|
70
|
+
registrations.push({ serviceName: match[1], handlerName: match[2] });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// For each registration, find the function signature
|
|
75
|
+
for (const { serviceName, handlerName } of registrations) {
|
|
76
|
+
const fnPattern = new RegExp(
|
|
77
|
+
`fn\\s+${handlerName}\\s*\\(([^)]*)\\)\\s*->\\s*(\\w+)`,
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
let found = false;
|
|
81
|
+
for (const { content } of allContent) {
|
|
82
|
+
const fnMatch = fnPattern.exec(content);
|
|
83
|
+
if (!fnMatch) continue;
|
|
84
|
+
|
|
85
|
+
const rawArgs = fnMatch[1];
|
|
86
|
+
const returnType = mapType(fnMatch[2]);
|
|
87
|
+
|
|
88
|
+
const args: { name: string; type: string }[] = [];
|
|
89
|
+
for (const part of rawArgs.split(",")) {
|
|
90
|
+
const trimmed = part.trim();
|
|
91
|
+
if (!trimmed) continue;
|
|
92
|
+
const [name, type] = trimmed.split(":").map((s) => s.trim());
|
|
93
|
+
if (name === "app" || type === "App*") continue;
|
|
94
|
+
args.push({ name, type: mapType(type) });
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
services.push({
|
|
98
|
+
name: serviceName,
|
|
99
|
+
methods: [{ name: serviceName, args, returnType }],
|
|
100
|
+
});
|
|
101
|
+
found = true;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!found) {
|
|
106
|
+
process.stderr.write(
|
|
107
|
+
`[zapp] warning: could not find function '${handlerName}' for service '${serviceName}'\n`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return services;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function generateBindingFile(service: ServiceDef): string {
|
|
116
|
+
const lines: string[] = [
|
|
117
|
+
`// Auto-generated by \`zapp generate\`. Do not edit.`,
|
|
118
|
+
`import { Services } from "@zapp/runtime";`,
|
|
119
|
+
``,
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const className = service.name.charAt(0).toUpperCase() + service.name.slice(1);
|
|
123
|
+
|
|
124
|
+
lines.push(`export class ${className} {`);
|
|
125
|
+
for (const method of service.methods) {
|
|
126
|
+
const params = method.args
|
|
127
|
+
.map((a) => `${a.name}: ${a.type}`)
|
|
128
|
+
.join(", ");
|
|
129
|
+
const argsExpr = method.args.length === 0
|
|
130
|
+
? "{}"
|
|
131
|
+
: method.args.length === 1
|
|
132
|
+
? method.args[0].name
|
|
133
|
+
: `{ ${method.args.map((a) => a.name).join(", ")} }`;
|
|
134
|
+
|
|
135
|
+
lines.push(
|
|
136
|
+
` static async ${method.name}(${params}): Promise<${method.returnType}> {`,
|
|
137
|
+
);
|
|
138
|
+
lines.push(
|
|
139
|
+
` return Services.invoke<${method.returnType}>("${method.name}", ${argsExpr});`,
|
|
140
|
+
);
|
|
141
|
+
lines.push(` }`);
|
|
142
|
+
}
|
|
143
|
+
lines.push(`}`);
|
|
144
|
+
lines.push(``);
|
|
145
|
+
|
|
146
|
+
return lines.join("\n");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function runGenerate({
|
|
150
|
+
root,
|
|
151
|
+
outDir,
|
|
152
|
+
frontendDir,
|
|
153
|
+
}: {
|
|
154
|
+
root: string;
|
|
155
|
+
outDir?: string;
|
|
156
|
+
frontendDir?: string;
|
|
157
|
+
}) {
|
|
158
|
+
const base = frontendDir ?? root;
|
|
159
|
+
const srcDir = path.join(base, "src");
|
|
160
|
+
const hasSrcDir = await fs.stat(srcDir).then(() => true, () => false);
|
|
161
|
+
const targetDir = outDir
|
|
162
|
+
? path.resolve(root, outDir)
|
|
163
|
+
: path.join(hasSrcDir ? srcDir : base, "generated");
|
|
164
|
+
|
|
165
|
+
process.stdout.write(`[zapp] scanning for service registrations...\n`);
|
|
166
|
+
const zappDir = path.join(root, "zapp");
|
|
167
|
+
const scanDir = await fs.stat(zappDir).then(() => zappDir, () => root);
|
|
168
|
+
const services = await scanServices(scanDir);
|
|
169
|
+
|
|
170
|
+
if (services.length === 0) {
|
|
171
|
+
process.stdout.write(
|
|
172
|
+
`[zapp] no service registrations found. Nothing to generate.\n`,
|
|
173
|
+
);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
178
|
+
|
|
179
|
+
const indexExports: string[] = [];
|
|
180
|
+
for (const service of services) {
|
|
181
|
+
const className =
|
|
182
|
+
service.name.charAt(0).toUpperCase() + service.name.slice(1);
|
|
183
|
+
const fileName = `${className}.ts`;
|
|
184
|
+
const filePath = path.join(targetDir, fileName);
|
|
185
|
+
const content = generateBindingFile(service);
|
|
186
|
+
await fs.writeFile(filePath, content, "utf8");
|
|
187
|
+
process.stdout.write(`[zapp] generated ${path.relative(root, filePath)}\n`);
|
|
188
|
+
indexExports.push(`export { ${className} } from "./${className}";`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const indexPath = path.join(targetDir, "index.ts");
|
|
192
|
+
await fs.writeFile(
|
|
193
|
+
indexPath,
|
|
194
|
+
`// Auto-generated by \`zapp generate\`. Do not edit.\n${indexExports.join("\n")}\n`,
|
|
195
|
+
"utf8",
|
|
196
|
+
);
|
|
197
|
+
process.stdout.write(
|
|
198
|
+
`[zapp] generated ${services.length} binding(s) in ${path.relative(root, targetDir)}/\n`,
|
|
199
|
+
);
|
|
200
|
+
}
|
package/src/icons.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { mkdir, rm } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { runCmd } from "./common";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* macOS icon sizes for iconset.
|
|
8
|
+
* Each entry: [size, scale] → produces icon_{size}x{size}{@{scale}x}.png
|
|
9
|
+
*/
|
|
10
|
+
const ICNS_SIZES: [number, number][] = [
|
|
11
|
+
[16, 1], [16, 2],
|
|
12
|
+
[32, 1], [32, 2],
|
|
13
|
+
[128, 1], [128, 2],
|
|
14
|
+
[256, 1], [256, 2],
|
|
15
|
+
[512, 1], [512, 2],
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generate .icns from a PNG source using sips + iconutil (macOS only).
|
|
20
|
+
*/
|
|
21
|
+
export async function generateIcns(pngPath: string, outputDir: string): Promise<string | null> {
|
|
22
|
+
if (process.platform !== "darwin") return null;
|
|
23
|
+
if (!existsSync(pngPath)) {
|
|
24
|
+
console.warn(`[zapp] icon source not found: ${pngPath}`);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const iconsetDir = path.join(outputDir, "AppIcon.iconset");
|
|
29
|
+
await mkdir(iconsetDir, { recursive: true });
|
|
30
|
+
|
|
31
|
+
// Generate all required sizes
|
|
32
|
+
for (const [size, scale] of ICNS_SIZES) {
|
|
33
|
+
const pixels = size * scale;
|
|
34
|
+
const suffix = scale > 1 ? `@${scale}x` : "";
|
|
35
|
+
const filename = `icon_${size}x${size}${suffix}.png`;
|
|
36
|
+
const outPath = path.join(iconsetDir, filename);
|
|
37
|
+
try {
|
|
38
|
+
await runCmd("sips", ["-z", String(pixels), String(pixels), pngPath, "--out", outPath]);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
console.warn(`[zapp] failed to resize icon to ${pixels}x${pixels}: ${err}`);
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Convert iconset to icns
|
|
46
|
+
const icnsPath = path.join(outputDir, "AppIcon.icns");
|
|
47
|
+
try {
|
|
48
|
+
await runCmd("iconutil", ["-c", "icns", iconsetDir, "-o", icnsPath]);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.warn(`[zapp] iconutil failed: ${err}`);
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Clean up iconset folder
|
|
55
|
+
await rm(iconsetDir, { recursive: true, force: true });
|
|
56
|
+
|
|
57
|
+
return icnsPath;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Compile a .icon folder (macOS Tahoe liquid glass) to Assets.car using actool.
|
|
62
|
+
* Requires Xcode 26 command line tools.
|
|
63
|
+
*/
|
|
64
|
+
export async function compileIconAsset(iconFolder: string, outputDir: string): Promise<string | null> {
|
|
65
|
+
if (process.platform !== "darwin") return null;
|
|
66
|
+
if (!existsSync(iconFolder)) {
|
|
67
|
+
console.warn(`[zapp] .icon folder not found: ${iconFolder}`);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
await runCmd("actool", [
|
|
73
|
+
"--compile", outputDir,
|
|
74
|
+
"--platform", "macosx",
|
|
75
|
+
"--minimum-deployment-target", "26.0",
|
|
76
|
+
iconFolder,
|
|
77
|
+
]);
|
|
78
|
+
const carPath = path.join(outputDir, "Assets.car");
|
|
79
|
+
if (existsSync(carPath)) {
|
|
80
|
+
return carPath;
|
|
81
|
+
}
|
|
82
|
+
console.warn("[zapp] actool did not produce Assets.car");
|
|
83
|
+
return null;
|
|
84
|
+
} catch (err) {
|
|
85
|
+
console.warn(`[zapp] actool failed (requires Xcode 26): ${err}`);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Generate .ico from a PNG source for Windows.
|
|
92
|
+
* Tries ImageMagick first, falls back to a basic single-size copy.
|
|
93
|
+
*/
|
|
94
|
+
export async function generateIco(pngPath: string, outputPath: string): Promise<string | null> {
|
|
95
|
+
if (!existsSync(pngPath)) {
|
|
96
|
+
console.warn(`[zapp] icon source not found: ${pngPath}`);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Try ImageMagick (magick or convert)
|
|
101
|
+
for (const cmd of ["magick", "convert"]) {
|
|
102
|
+
try {
|
|
103
|
+
await runCmd(cmd, [
|
|
104
|
+
pngPath,
|
|
105
|
+
"-define", "icon:auto-resize=256,128,64,48,32,16",
|
|
106
|
+
outputPath,
|
|
107
|
+
]);
|
|
108
|
+
if (existsSync(outputPath)) return outputPath;
|
|
109
|
+
} catch {
|
|
110
|
+
// Try next command
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.warn("[zapp] ImageMagick not found — cannot generate .ico. Install ImageMagick for Windows icon support.");
|
|
115
|
+
return null;
|
|
116
|
+
}
|
package/src/init.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { spawnStreaming } from "./common";
|
|
3
|
+
import { mkdir } from "node:fs/promises";
|
|
4
|
+
|
|
5
|
+
export const runInit = async ({
|
|
6
|
+
root,
|
|
7
|
+
name,
|
|
8
|
+
template,
|
|
9
|
+
}: {
|
|
10
|
+
root: string;
|
|
11
|
+
name: string;
|
|
12
|
+
template: string;
|
|
13
|
+
}) => {
|
|
14
|
+
const projectDir = path.resolve(root, name);
|
|
15
|
+
const zappDir = path.join(projectDir, "zapp");
|
|
16
|
+
const configDir = path.join(projectDir, "config");
|
|
17
|
+
const darwinConfigDir = path.join(configDir, "darwin");
|
|
18
|
+
const windowsConfigDir = path.join(configDir, "windows");
|
|
19
|
+
|
|
20
|
+
console.log(`Scaffolding Zapp project in ${projectDir}...`);
|
|
21
|
+
|
|
22
|
+
await mkdir(projectDir, { recursive: true });
|
|
23
|
+
|
|
24
|
+
console.log(`Creating Vite project with template: ${template}...`);
|
|
25
|
+
await spawnStreaming("bun", ["create", "vite", ".", "--template", template], { cwd: projectDir }).exited;
|
|
26
|
+
|
|
27
|
+
await mkdir(zappDir, { recursive: true });
|
|
28
|
+
await mkdir(darwinConfigDir, { recursive: true });
|
|
29
|
+
await mkdir(windowsConfigDir, { recursive: true });
|
|
30
|
+
|
|
31
|
+
// Add Zapp dependencies to package.json
|
|
32
|
+
const pkgPath = path.join(projectDir, "package.json");
|
|
33
|
+
let pkgObj: Record<string, unknown> = {};
|
|
34
|
+
try {
|
|
35
|
+
const pkgFile = Bun.file(pkgPath);
|
|
36
|
+
if (await pkgFile.exists()) {
|
|
37
|
+
pkgObj = JSON.parse(await pkgFile.text());
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
console.error(`Warning: Could not read ${pkgPath}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const devDeps = (pkgObj.devDependencies ?? {}) as Record<string, string>;
|
|
44
|
+
devDeps["@zapp/cli"] = "latest";
|
|
45
|
+
devDeps["@zapp/vite"] = "latest";
|
|
46
|
+
pkgObj.devDependencies = devDeps;
|
|
47
|
+
|
|
48
|
+
const deps = (pkgObj.dependencies ?? {}) as Record<string, string>;
|
|
49
|
+
deps["@zapp/runtime"] = "latest";
|
|
50
|
+
pkgObj.dependencies = deps;
|
|
51
|
+
|
|
52
|
+
await Bun.write(pkgPath, JSON.stringify(pkgObj, null, 2));
|
|
53
|
+
|
|
54
|
+
// --- Zen-C entry point ---
|
|
55
|
+
await Bun.write(path.join(zappDir, "app.zc"), `import "app/app.zc";
|
|
56
|
+
|
|
57
|
+
fn on_ready(id: int, handle: void*) -> void {
|
|
58
|
+
Window{id: id, handle: handle}.show();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fn run_app() -> int {
|
|
62
|
+
let config = AppConfig{
|
|
63
|
+
name: "${name}",
|
|
64
|
+
applicationShouldTerminateAfterLastWindowClosed: true,
|
|
65
|
+
webContentInspectable: -1, // -1 = inherit from build (dev=on, prod=off)
|
|
66
|
+
maxWorkers: 0,
|
|
67
|
+
qjsStackSize: 0,
|
|
68
|
+
};
|
|
69
|
+
let app = App::new(config);
|
|
70
|
+
|
|
71
|
+
let opts = window_options_default("${name}");
|
|
72
|
+
opts.visible = false;
|
|
73
|
+
let win = app.window.create(&opts);
|
|
74
|
+
win.on_ready(on_ready);
|
|
75
|
+
|
|
76
|
+
return app.run();
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
|
|
80
|
+
// --- Zapp config ---
|
|
81
|
+
await Bun.write(path.join(zappDir, "zapp.config.ts"), `import { defineConfig } from "@zapp/cli/config";
|
|
82
|
+
|
|
83
|
+
export default defineConfig({
|
|
84
|
+
name: "${name}",
|
|
85
|
+
identifier: "com.zapp.${name.toLowerCase().replace(/[^a-z0-9]/g, "")}",
|
|
86
|
+
version: "0.1.0",
|
|
87
|
+
});
|
|
88
|
+
`);
|
|
89
|
+
|
|
90
|
+
// --- Build entry ---
|
|
91
|
+
await Bun.write(path.join(zappDir, "build.zc"), `// --- Platform Tags ---
|
|
92
|
+
//> macos: define: apple
|
|
93
|
+
//> windows: define: windows
|
|
94
|
+
|
|
95
|
+
// --- macOS Directives ---
|
|
96
|
+
//> macos: framework: Cocoa
|
|
97
|
+
//> macos: framework: WebKit
|
|
98
|
+
//> macos: framework: CoreFoundation
|
|
99
|
+
//> macos: framework: JavaScriptCore
|
|
100
|
+
//> macos: framework: Security
|
|
101
|
+
//> macos: link: -lcompression
|
|
102
|
+
//> macos: cflags: -fobjc-arc -x objective-c
|
|
103
|
+
// To use QuickJS instead of JSC on macOS, uncomment:
|
|
104
|
+
// //> macos: define: ZAPP_WORKER_ENGINE_QJS
|
|
105
|
+
|
|
106
|
+
// --- Windows Directives ---
|
|
107
|
+
//> windows: cflags: -DUNICODE -D_UNICODE -DCINTERFACE -DCOBJMACROS
|
|
108
|
+
//> windows: link: -lole32 -lshell32 -luuid -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshlwapi
|
|
109
|
+
//> windows: link: -lwinhttp -lbcrypt -ladvapi32 -lrpcrt4 -lcrypt32 -lversion
|
|
110
|
+
// Uncomment to enable Zapp Workers on Windows (adds ~760 KB):
|
|
111
|
+
// //> windows: define: ZAPP_WORKER_ENGINE_QJS
|
|
112
|
+
|
|
113
|
+
import "app.zc";
|
|
114
|
+
|
|
115
|
+
fn main() -> int {
|
|
116
|
+
return run_app();
|
|
117
|
+
}
|
|
118
|
+
`);
|
|
119
|
+
|
|
120
|
+
// --- macOS Info.plist ---
|
|
121
|
+
await Bun.write(path.join(darwinConfigDir, "Info.plist"), `<?xml version="1.0" encoding="UTF-8"?>
|
|
122
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
123
|
+
<plist version="1.0">
|
|
124
|
+
<dict>
|
|
125
|
+
<key>CFBundleName</key>
|
|
126
|
+
<string>${name}</string>
|
|
127
|
+
<key>CFBundleIdentifier</key>
|
|
128
|
+
<string>com.zapp.${name.toLowerCase().replace(/[^a-z0-9]/g, "")}</string>
|
|
129
|
+
<key>CFBundleVersion</key>
|
|
130
|
+
<string>1.0.0</string>
|
|
131
|
+
<key>CFBundleShortVersionString</key>
|
|
132
|
+
<string>1.0.0</string>
|
|
133
|
+
<key>CFBundlePackageType</key>
|
|
134
|
+
<string>APPL</string>
|
|
135
|
+
<key>LSMinimumSystemVersion</key>
|
|
136
|
+
<string>13.0</string>
|
|
137
|
+
<key>NSHighResolutionCapable</key>
|
|
138
|
+
<true/>
|
|
139
|
+
</dict>
|
|
140
|
+
</plist>
|
|
141
|
+
`);
|
|
142
|
+
|
|
143
|
+
// --- Windows app.manifest ---
|
|
144
|
+
await Bun.write(path.join(windowsConfigDir, "app.manifest"), `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
145
|
+
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
|
146
|
+
<assemblyIdentity
|
|
147
|
+
type="win32"
|
|
148
|
+
name="com.zapp.${name.toLowerCase().replace(/[^a-z0-9]/g, "")}"
|
|
149
|
+
version="1.0.0.0"
|
|
150
|
+
/>
|
|
151
|
+
<description>${name}</description>
|
|
152
|
+
|
|
153
|
+
<!-- Enable visual styles (modern controls) -->
|
|
154
|
+
<dependency>
|
|
155
|
+
<dependentAssembly>
|
|
156
|
+
<assemblyIdentity
|
|
157
|
+
type="win32"
|
|
158
|
+
name="Microsoft.Windows.Common-Controls"
|
|
159
|
+
version="6.0.0.0"
|
|
160
|
+
processorArchitecture="*"
|
|
161
|
+
publicKeyToken="6595b64144ccf1df"
|
|
162
|
+
language="*"
|
|
163
|
+
/>
|
|
164
|
+
</dependentAssembly>
|
|
165
|
+
</dependency>
|
|
166
|
+
|
|
167
|
+
<!-- High-DPI awareness (Per-Monitor V2) -->
|
|
168
|
+
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
|
169
|
+
<windowsSettings>
|
|
170
|
+
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2,PerMonitor</dpiAwareness>
|
|
171
|
+
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
|
172
|
+
</windowsSettings>
|
|
173
|
+
</application>
|
|
174
|
+
|
|
175
|
+
<!-- Declare supported OS versions -->
|
|
176
|
+
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
|
177
|
+
<application>
|
|
178
|
+
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> <!-- Windows 10/11 -->
|
|
179
|
+
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /> <!-- Windows 8.1 -->
|
|
180
|
+
</application>
|
|
181
|
+
</compatibility>
|
|
182
|
+
</assembly>
|
|
183
|
+
`);
|
|
184
|
+
|
|
185
|
+
console.log(`\nProject ${name} scaffolded successfully!`);
|
|
186
|
+
console.log(`Next steps:`);
|
|
187
|
+
console.log(` cd ${name}`);
|
|
188
|
+
console.log(` bun install`);
|
|
189
|
+
console.log(` zapp dev`);
|
|
190
|
+
};
|