@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
@@ -0,0 +1,550 @@
1
+ //> macos: framework: WebKit
2
+ //> macos: framework: Cocoa
3
+ //> macos: framework: Security
4
+ //> macos: link: -lcompression
5
+
6
+ import "./window.zc";
7
+ import "./webview_bootstrap.zc";
8
+
9
+ include <stdlib.h>
10
+ include <string.h>
11
+ include <stdbool.h>
12
+
13
+ raw {
14
+ #ifdef __APPLE__
15
+ #include <Cocoa/Cocoa.h>
16
+ #include <WebKit/WebKit.h>
17
+ #include <dispatch/dispatch.h>
18
+ #include <compression.h>
19
+ #ifndef ZAPP_EMBEDDED_ASSET_STRUCT_DEFINED
20
+ #define ZAPP_EMBEDDED_ASSET_STRUCT_DEFINED 1
21
+ struct ZappEmbeddedAsset {
22
+ char* path;
23
+ uint8_t* data;
24
+ int len;
25
+ bool is_brotli;
26
+ int uncompressed_len;
27
+ };
28
+ #endif
29
+ extern struct ZappEmbeddedAsset zapp_embedded_assets[];
30
+ extern int zapp_embedded_assets_count;
31
+
32
+ extern void* app_get_active(void);
33
+ extern char* app_get_bootstrap_name(void);
34
+ extern bool app_get_bootstrap_application_should_terminate_after_last_window_closed(void);
35
+ extern bool app_get_bootstrap_web_content_inspectable(void);
36
+ extern int app_get_bootstrap_max_workers(void);
37
+ extern void zapp_handle_message(void* app_ptr, char* msg_c);
38
+ extern const char* zapp_darwin_webview_bootstrap_script(void);
39
+ extern char* service_get_bindings_manifest_json(void);
40
+ extern const char* zapp_build_asset_root(void);
41
+ extern const char* zapp_build_initial_url(void);
42
+ extern int zapp_build_is_dev_mode(void);
43
+ extern int zapp_build_use_embedded_assets(void);
44
+
45
+ static NSString* zapp_escape_js_string(const char* raw) {
46
+ if (!raw) return @"";
47
+ NSString* s = [NSString stringWithUTF8String:raw];
48
+ s = [s stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
49
+ s = [s stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
50
+ s = [s stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"];
51
+ s = [s stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"];
52
+ return s;
53
+ }
54
+
55
+ static NSString* zapp_mime_for_path(NSString* path) {
56
+ NSString* lower = [path lowercaseString];
57
+ if ([lower hasSuffix:@".html"]) return @"text/html; charset=utf-8";
58
+ if ([lower hasSuffix:@".js"] || [lower hasSuffix:@".mjs"]) return @"application/javascript; charset=utf-8";
59
+ if ([lower hasSuffix:@".css"]) return @"text/css; charset=utf-8";
60
+ if ([lower hasSuffix:@".json"]) return @"application/json; charset=utf-8";
61
+ if ([lower hasSuffix:@".svg"]) return @"image/svg+xml";
62
+ if ([lower hasSuffix:@".png"]) return @"image/png";
63
+ if ([lower hasSuffix:@".jpg"] || [lower hasSuffix:@".jpeg"]) return @"image/jpeg";
64
+ if ([lower hasSuffix:@".woff2"]) return @"font/woff2";
65
+ if ([lower hasSuffix:@".map"]) return @"application/json; charset=utf-8";
66
+ return @"application/octet-stream";
67
+ }
68
+
69
+ static NSString* zapp_asset_root_path(void) {
70
+ const char* configuredRoot = zapp_build_asset_root();
71
+ if (configuredRoot && configuredRoot[0] != '\0') {
72
+ return [NSString stringWithUTF8String:configuredRoot];
73
+ }
74
+ return [[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:@"example/frontend/dist"];
75
+ }
76
+
77
+ static NSMutableDictionary<NSString*, NSMutableDictionary*>* zapp_sync_waits = nil;
78
+ static NSMutableDictionary<NSString*, NSMutableArray<NSString*>*>* zapp_sync_queues = nil;
79
+ extern void zapp_darwin_worker_dispatch_sync_result(const char* worker_id, const char* payload_json);
80
+
81
+ static void zapp_sync_ensure_state(void) {
82
+ if (zapp_sync_waits == nil) {
83
+ zapp_sync_waits = [NSMutableDictionary dictionary];
84
+ }
85
+ if (zapp_sync_queues == nil) {
86
+ zapp_sync_queues = [NSMutableDictionary dictionary];
87
+ }
88
+ }
89
+
90
+ static void zapp_sync_remove_wait_from_queue(NSString* key, NSString* requestId) {
91
+ if (key == nil || requestId == nil) return;
92
+ NSMutableArray<NSString*>* queue = [zapp_sync_queues objectForKey:key];
93
+ if (queue == nil) return;
94
+ [queue removeObject:requestId];
95
+ if ([queue count] == 0) {
96
+ [zapp_sync_queues removeObjectForKey:key];
97
+ }
98
+ }
99
+
100
+ static void zapp_dispatch_sync_result_to_webviews(const char* payload_json) {
101
+ NSString* payload = zapp_escape_js_string(payload_json);
102
+ NSString* js = [NSString stringWithFormat:
103
+ @"(function(){const b=globalThis[Symbol.for('zapp.bridge')];if(b&&typeof b.dispatchSyncResult==='function'){b.dispatchSyncResult('%@');}})();",
104
+ payload
105
+ ];
106
+ for (NSWindow* window in [NSApp windows]) {
107
+ NSView* content = [window contentView];
108
+ if ([content isKindOfClass:[WKWebView class]]) {
109
+ WKWebView* webview = (WKWebView*)content;
110
+ [webview evaluateJavaScript:js completionHandler:nil];
111
+ }
112
+ }
113
+ }
114
+
115
+ static void zapp_sync_dispatch_result(NSString* requestId, BOOL ok, NSString* status, NSString* targetWorkerId) {
116
+ if (requestId == nil || [requestId length] == 0) return;
117
+ NSString* safeStatus = ([status isKindOfClass:[NSString class]] && [status length] > 0) ? status : @"notified";
118
+ NSString* payload = [NSString stringWithFormat:
119
+ @"{\"id\":\"%@\",\"ok\":%@,\"status\":\"%@\"}",
120
+ requestId,
121
+ ok ? @"true" : @"false",
122
+ safeStatus
123
+ ];
124
+ if ([targetWorkerId isKindOfClass:[NSString class]] && [targetWorkerId length] > 0) {
125
+ zapp_darwin_worker_dispatch_sync_result([targetWorkerId UTF8String], [payload UTF8String]);
126
+ return;
127
+ }
128
+ zapp_dispatch_sync_result_to_webviews([payload UTF8String]);
129
+ }
130
+
131
+ static NSURL* zapp_initial_url(void) {
132
+ const char* configuredUrl = zapp_build_initial_url();
133
+ if (configuredUrl && configuredUrl[0] != '\0') {
134
+ return [NSURL URLWithString:[NSString stringWithUTF8String:configuredUrl]];
135
+ }
136
+ return [NSURL URLWithString:@"zapp://index.html"];
137
+ }
138
+
139
+ @interface ZappAssetSchemeHandler : NSObject <WKURLSchemeHandler>
140
+ @end
141
+
142
+ @implementation ZappAssetSchemeHandler
143
+ - (void)webView:(WKWebView*)webView startURLSchemeTask:(id<WKURLSchemeTask>)task {
144
+ (void)webView;
145
+ NSURL* url = [task request].URL;
146
+ NSString* host = url.host ?: @"";
147
+ NSString* path = url.path ?: @"/";
148
+ NSString* assetRoot = zapp_asset_root_path();
149
+
150
+ // Map custom scheme URLs to dist files:
151
+ // - zapp://index.html -> index.html
152
+ // - zapp://index.html/assets/a.css -> assets/a.css
153
+ // - zapp://app/index.html -> index.html
154
+ // - zapp://app/assets/a.css -> assets/a.css
155
+ NSString* rel = path;
156
+ if ((rel.length == 0 || [rel isEqualToString:@"/"]) && host.length > 0) {
157
+ rel = [@"/" stringByAppendingString:host];
158
+ } else if (host.length > 0 && ![host isEqualToString:@"app"]) {
159
+ // Some URLs encode the html file in host and real path in pathname.
160
+ // For asset paths, ignore host and keep only pathname.
161
+ if ([path hasPrefix:@"/assets/"]) {
162
+ rel = path;
163
+ }
164
+ }
165
+ if ([rel isEqualToString:@"/"] || rel.length == 0) {
166
+ rel = @"/index.html";
167
+ }
168
+ while ([rel hasPrefix:@"/"]) rel = [rel substringFromIndex:1];
169
+
170
+ NSString* lookupPath = [@"/" stringByAppendingString:rel];
171
+ if (zapp_build_use_embedded_assets() != 0 && zapp_embedded_assets_count > 0) {
172
+ bool foundEmbedded = false;
173
+ for (int i = 0; i < zapp_embedded_assets_count; i++) {
174
+ NSString* assetPath = [NSString stringWithUTF8String:zapp_embedded_assets[i].path];
175
+ if ([assetPath isEqualToString:lookupPath]) {
176
+ NSData* data = nil;
177
+ if (zapp_embedded_assets[i].is_brotli) {
178
+ uint8_t* out_buf = malloc(zapp_embedded_assets[i].uncompressed_len);
179
+ size_t decoded_size = compression_decode_buffer(out_buf, zapp_embedded_assets[i].uncompressed_len,
180
+ zapp_embedded_assets[i].data, zapp_embedded_assets[i].len,
181
+ NULL, COMPRESSION_BROTLI);
182
+ if (decoded_size > 0) {
183
+ data = [NSData dataWithBytesNoCopy:out_buf length:decoded_size freeWhenDone:YES];
184
+ } else {
185
+ free(out_buf);
186
+ data = [NSData data];
187
+ }
188
+ } else {
189
+ data = [NSData dataWithBytesNoCopy:(void*)zapp_embedded_assets[i].data length:zapp_embedded_assets[i].len freeWhenDone:NO];
190
+ }
191
+
192
+ NSMutableDictionary* headers = [NSMutableDictionary dictionaryWithDictionary:@{
193
+ @"Content-Type": zapp_mime_for_path(lookupPath),
194
+ @"Cross-Origin-Opener-Policy": @"same-origin",
195
+ @"Cross-Origin-Embedder-Policy": @"require-corp",
196
+ @"Cross-Origin-Resource-Policy": @"same-origin",
197
+ @"Cache-Control": @"no-cache"
198
+ }];
199
+
200
+ NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
201
+ initWithURL:url
202
+ statusCode:200
203
+ HTTPVersion:@"HTTP/1.1"
204
+ headerFields:headers];
205
+ [task didReceiveResponse:response];
206
+ [task didReceiveData:data];
207
+ [task didFinish];
208
+ return;
209
+ }
210
+ }
211
+ BOOL isAssetRequest = [rel hasPrefix:@"assets/"] || [rel hasPrefix:@"zapp-workers/"];
212
+ if (!isAssetRequest && !foundEmbedded) {
213
+ for (int i = 0; i < zapp_embedded_assets_count; i++) {
214
+ NSString* assetPath = [NSString stringWithUTF8String:zapp_embedded_assets[i].path];
215
+ if ([assetPath isEqualToString:@"/index.html"]) {
216
+ NSData* data = nil;
217
+ if (zapp_embedded_assets[i].is_brotli) {
218
+ uint8_t* out_buf = malloc(zapp_embedded_assets[i].uncompressed_len);
219
+ size_t decoded_size = compression_decode_buffer(out_buf, zapp_embedded_assets[i].uncompressed_len,
220
+ zapp_embedded_assets[i].data, zapp_embedded_assets[i].len,
221
+ NULL, COMPRESSION_BROTLI);
222
+ if (decoded_size > 0) {
223
+ data = [NSData dataWithBytesNoCopy:out_buf length:decoded_size freeWhenDone:YES];
224
+ } else {
225
+ free(out_buf);
226
+ data = [NSData data];
227
+ }
228
+ } else {
229
+ data = [NSData dataWithBytesNoCopy:(void*)zapp_embedded_assets[i].data length:zapp_embedded_assets[i].len freeWhenDone:NO];
230
+ }
231
+
232
+ NSMutableDictionary* headers = [NSMutableDictionary dictionaryWithDictionary:@{
233
+ @"Content-Type": zapp_mime_for_path(@"/index.html"),
234
+ @"Cross-Origin-Opener-Policy": @"same-origin",
235
+ @"Cross-Origin-Embedder-Policy": @"require-corp",
236
+ @"Cross-Origin-Resource-Policy": @"same-origin",
237
+ @"Cache-Control": @"no-cache"
238
+ }];
239
+
240
+ NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
241
+ initWithURL:url
242
+ statusCode:200
243
+ HTTPVersion:@"HTTP/1.1"
244
+ headerFields:headers];
245
+ [task didReceiveResponse:response];
246
+ [task didReceiveData:data];
247
+ [task didFinish];
248
+ return;
249
+ }
250
+ }
251
+ }
252
+ }
253
+
254
+ NSString* full = [assetRoot stringByAppendingPathComponent:rel];
255
+ if ([[NSFileManager defaultManager] fileExistsAtPath:full] == NO) {
256
+ BOOL isAssetRequest = [rel hasPrefix:@"assets/"] || [rel hasPrefix:@"zapp-workers/"];
257
+ if (!isAssetRequest) {
258
+ NSString* fallback = [assetRoot stringByAppendingPathComponent:@"index.html"];
259
+ if ([[NSFileManager defaultManager] fileExistsAtPath:fallback]) {
260
+ full = fallback;
261
+ }
262
+ }
263
+ if ([[NSFileManager defaultManager] fileExistsAtPath:full] == NO) {
264
+ NSData* empty = [NSData data];
265
+ NSHTTPURLResponse* notFound = [[NSHTTPURLResponse alloc]
266
+ initWithURL:url
267
+ statusCode:404
268
+ HTTPVersion:@"HTTP/1.1"
269
+ headerFields:@{ @"Content-Type": @"text/plain; charset=utf-8" }];
270
+ [task didReceiveResponse:notFound];
271
+ [task didReceiveData:empty];
272
+ [task didFinish];
273
+ return;
274
+ }
275
+ }
276
+
277
+ NSData* data = [NSData dataWithContentsOfFile:full];
278
+ if (!data) data = [NSData data];
279
+ NSDictionary* headers = @{
280
+ @"Content-Type": zapp_mime_for_path(full),
281
+ @"Cross-Origin-Opener-Policy": @"same-origin",
282
+ @"Cross-Origin-Embedder-Policy": @"require-corp",
283
+ @"Cross-Origin-Resource-Policy": @"same-origin",
284
+ @"Cache-Control": @"no-cache"
285
+ };
286
+ NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc]
287
+ initWithURL:url
288
+ statusCode:200
289
+ HTTPVersion:@"HTTP/1.1"
290
+ headerFields:headers];
291
+ [task didReceiveResponse:response];
292
+ [task didReceiveData:data];
293
+ [task didFinish];
294
+ }
295
+
296
+ - (void)webView:(WKWebView*)webView stopURLSchemeTask:(id<WKURLSchemeTask>)task {
297
+ (void)webView;
298
+ (void)task;
299
+ }
300
+ @end
301
+
302
+ @interface ZappMsgHandler : NSObject <WKScriptMessageHandler>
303
+ @end
304
+
305
+ @implementation ZappMsgHandler
306
+ - (void)userContentController:(WKUserContentController*)ucc didReceiveScriptMessage:(WKScriptMessage*)msg {
307
+ (void)ucc;
308
+ id body = [msg body];
309
+ if (![body isKindOfClass:[NSString class]]) return;
310
+ const char* raw_msg = [(NSString*)body UTF8String];
311
+ if (!raw_msg) return;
312
+ char* msg_copy = strdup(raw_msg);
313
+ if (!msg_copy) return;
314
+ void* app_ptr = app_get_active();
315
+ if (app_ptr != NULL) {
316
+ zapp_handle_message(app_ptr, msg_copy);
317
+ }
318
+ free(msg_copy);
319
+ }
320
+ @end
321
+
322
+ void zapp_dispatch_invoke_result(char* request_id, char* payload_json) {
323
+ (void)request_id;
324
+ NSString* payload = zapp_escape_js_string(payload_json);
325
+ NSString* js = [NSString stringWithFormat:
326
+ @"(function(){const b=globalThis[Symbol.for('zapp.bridge')];if(b&&typeof b.dispatchInvokeResult==='function'){b.dispatchInvokeResult('%@');}})();",
327
+ payload];
328
+ for (NSWindow* window in [NSApp windows]) {
329
+ NSView* content = [window contentView];
330
+ if ([content isKindOfClass:[WKWebView class]]) {
331
+ WKWebView* webview = (WKWebView*)content;
332
+ [webview evaluateJavaScript:js completionHandler:nil];
333
+ }
334
+ }
335
+ }
336
+
337
+ void platform_sync_handle_bridge(char* action, char* payload_json) {
338
+ if (action == NULL || payload_json == NULL) return;
339
+ NSString* actionStr = [NSString stringWithUTF8String:action];
340
+ NSString* payload = [NSString stringWithUTF8String:payload_json];
341
+ if (![actionStr isKindOfClass:[NSString class]] || ![payload isKindOfClass:[NSString class]]) return;
342
+
343
+ NSData* payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
344
+ if (payloadData == nil) return;
345
+ id rawObj = [NSJSONSerialization JSONObjectWithData:payloadData options:0 error:nil];
346
+ if (![rawObj isKindOfClass:[NSDictionary class]]) return;
347
+ NSDictionary* body = (NSDictionary*)rawObj;
348
+
349
+ zapp_sync_ensure_state();
350
+
351
+ if ([actionStr isEqualToString:@"wait"]) {
352
+ NSString* requestId = [body objectForKey:@"id"];
353
+ NSString* key = [body objectForKey:@"key"];
354
+ NSNumber* timeoutNumber = [body objectForKey:@"timeoutMs"];
355
+ NSString* targetWorkerId = [body objectForKey:@"targetWorkerId"];
356
+ if (![requestId isKindOfClass:[NSString class]] || [requestId length] == 0) return;
357
+ if (![key isKindOfClass:[NSString class]] || [key length] == 0) return;
358
+ if ([zapp_sync_waits objectForKey:requestId] != nil) return;
359
+
360
+ NSInteger timeoutMs = 30000;
361
+ if ([timeoutNumber respondsToSelector:@selector(integerValue)]) {
362
+ timeoutMs = [timeoutNumber integerValue];
363
+ }
364
+ if (timeoutMs < 1) timeoutMs = 1;
365
+ if (timeoutMs > 300000) timeoutMs = 300000;
366
+
367
+ NSMutableDictionary* waitObj = [NSMutableDictionary dictionary];
368
+ [waitObj setObject:key forKey:@"key"];
369
+ if ([targetWorkerId isKindOfClass:[NSString class]] && [targetWorkerId length] > 0) {
370
+ [waitObj setObject:targetWorkerId forKey:@"targetWorkerId"];
371
+ }
372
+ [zapp_sync_waits setObject:waitObj forKey:requestId];
373
+
374
+ NSMutableArray<NSString*>* queue = [zapp_sync_queues objectForKey:key];
375
+ if (queue == nil) {
376
+ queue = [NSMutableArray array];
377
+ [zapp_sync_queues setObject:queue forKey:key];
378
+ }
379
+ [queue addObject:requestId];
380
+
381
+ if ([timeoutNumber respondsToSelector:@selector(integerValue)]) {
382
+ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)timeoutMs * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
383
+ NSDictionary* existing = [zapp_sync_waits objectForKey:requestId];
384
+ if (existing == nil) return;
385
+ NSString* existingKey = [existing objectForKey:@"key"];
386
+ NSString* existingTargetWorkerId = [existing objectForKey:@"targetWorkerId"];
387
+ [zapp_sync_waits removeObjectForKey:requestId];
388
+ zapp_sync_remove_wait_from_queue(existingKey, requestId);
389
+ zapp_sync_dispatch_result(requestId, YES, @"timed-out", existingTargetWorkerId);
390
+ });
391
+ }
392
+ return;
393
+ }
394
+
395
+ if ([actionStr isEqualToString:@"notify"]) {
396
+ NSString* key = [body objectForKey:@"key"];
397
+ NSNumber* countNumber = [body objectForKey:@"count"];
398
+ if (![key isKindOfClass:[NSString class]] || [key length] == 0) return;
399
+ NSInteger count = 1;
400
+ if ([countNumber respondsToSelector:@selector(integerValue)]) {
401
+ count = [countNumber integerValue];
402
+ }
403
+ if (count < 1) count = 1;
404
+ if (count > 65535) count = 65535;
405
+
406
+ NSMutableArray<NSString*>* queue = [zapp_sync_queues objectForKey:key];
407
+ if (queue == nil || [queue count] == 0) return;
408
+
409
+ NSInteger delivered = 0;
410
+ while (delivered < count && [queue count] > 0) {
411
+ NSString* requestId = queue[0];
412
+ [queue removeObjectAtIndex:0];
413
+ NSDictionary* existing = [zapp_sync_waits objectForKey:requestId];
414
+ if (existing == nil) continue;
415
+ NSString* existingTargetWorkerId = [existing objectForKey:@"targetWorkerId"];
416
+ [zapp_sync_waits removeObjectForKey:requestId];
417
+ zapp_sync_dispatch_result(requestId, YES, @"notified", existingTargetWorkerId);
418
+ delivered += 1;
419
+ }
420
+ if ([queue count] == 0) {
421
+ [zapp_sync_queues removeObjectForKey:key];
422
+ }
423
+ return;
424
+ }
425
+
426
+ if ([actionStr isEqualToString:@"cancel"]) {
427
+ NSString* requestId = [body objectForKey:@"id"];
428
+ if (![requestId isKindOfClass:[NSString class]] || [requestId length] == 0) return;
429
+ NSDictionary* existing = [zapp_sync_waits objectForKey:requestId];
430
+ if (existing == nil) return;
431
+ NSString* existingKey = [existing objectForKey:@"key"];
432
+ NSString* existingTargetWorkerId = [existing objectForKey:@"targetWorkerId"];
433
+ [zapp_sync_waits removeObjectForKey:requestId];
434
+ zapp_sync_remove_wait_from_queue(existingKey, requestId);
435
+ zapp_sync_dispatch_result(requestId, YES, @"cancelled", existingTargetWorkerId);
436
+ }
437
+ }
438
+
439
+ // Custom WKWebView subclass for drag region support
440
+ @interface ZappWebView : WKWebView
441
+ @property (nonatomic, assign) BOOL inDragRegion;
442
+ @end
443
+
444
+ @implementation ZappWebView
445
+ - (instancetype)initWithFrame:(NSRect)frame configuration:(WKWebViewConfiguration*)config {
446
+ self = [super initWithFrame:frame configuration:config];
447
+ if (self) { _inDragRegion = NO; }
448
+ return self;
449
+ }
450
+ - (void)mouseDown:(NSEvent*)event {
451
+ if (self.inDragRegion) {
452
+ [self.window performWindowDragWithEvent:event];
453
+ return;
454
+ }
455
+ [super mouseDown:event];
456
+ }
457
+ // Allow the window to be moved when clicking drag regions
458
+ - (BOOL)mouseDownCanMoveWindow {
459
+ return self.inDragRegion;
460
+ }
461
+ @end
462
+
463
+ void zapp_darwin_webview_create(void* window_ptr, bool inspectable) {
464
+ NSWindow* window = (__bridge NSWindow*)window_ptr;
465
+ NSView* hostView = [window contentView];
466
+ NSRect bounds = [hostView bounds];
467
+ WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init];
468
+ ZappAssetSchemeHandler* schemeHandler = [[ZappAssetSchemeHandler alloc] init];
469
+ [config setURLSchemeHandler:schemeHandler forURLScheme:@"zapp"];
470
+ WKUserContentController* ucc = [[WKUserContentController alloc] init];
471
+ NSString* ownerId = [NSString stringWithFormat:@"owner-%p", window];
472
+ NSString* windowId = [NSString stringWithFormat:@"win-%p", window];
473
+ const char* bindingsRaw = service_get_bindings_manifest_json();
474
+ NSString* bindingsJson = zapp_escape_js_string(bindingsRaw);
475
+
476
+ const char* bootstrapName = app_get_bootstrap_name();
477
+ NSString* appName = bootstrapName != NULL
478
+ ? [NSString stringWithUTF8String:bootstrapName]
479
+ : @"Zapp App";
480
+ BOOL applicationShouldTerminateAfterLastWindowClosed =
481
+ app_get_bootstrap_application_should_terminate_after_last_window_closed() ? YES : NO;
482
+ BOOL webContentInspectable =
483
+ app_get_bootstrap_web_content_inspectable() ? YES : NO;
484
+ int maxWorkers = app_get_bootstrap_max_workers();
485
+ appName = [appName stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
486
+ appName = [appName stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"];
487
+ NSString* appConfigScript = [NSString stringWithFormat:
488
+ @"(function(){globalThis[Symbol.for('zapp.bootstrapConfig')]={name:'%@',applicationShouldTerminateAfterLastWindowClosed:%@,webContentInspectable:%@,maxWorkers:%d};})();",
489
+ appName,
490
+ applicationShouldTerminateAfterLastWindowClosed ? @"true" : @"false",
491
+ webContentInspectable ? @"true" : @"false",
492
+ maxWorkers
493
+ ];
494
+ WKUserScript* appConfigUserScript = [[WKUserScript alloc]
495
+ initWithSource:appConfigScript
496
+ injectionTime:WKUserScriptInjectionTimeAtDocumentStart
497
+ forMainFrameOnly:NO];
498
+ [ucc addUserScript:appConfigUserScript];
499
+
500
+ NSString* bindingsScript = [NSString stringWithFormat:
501
+ @"(function(){globalThis[Symbol.for('zapp.bindingsManifest')]='%@';})();",
502
+ bindingsJson
503
+ ];
504
+ WKUserScript* bindingsUserScript = [[WKUserScript alloc]
505
+ initWithSource:bindingsScript
506
+ injectionTime:WKUserScriptInjectionTimeAtDocumentStart
507
+ forMainFrameOnly:NO];
508
+ [ucc addUserScript:bindingsUserScript];
509
+
510
+ NSString* ownerScript = [NSString stringWithFormat:
511
+ @"(function(){globalThis[Symbol.for('zapp.ownerId')]='%@';})();",
512
+ ownerId
513
+ ];
514
+ WKUserScript* ownerUserScript = [[WKUserScript alloc]
515
+ initWithSource:ownerScript
516
+ injectionTime:WKUserScriptInjectionTimeAtDocumentStart
517
+ forMainFrameOnly:NO];
518
+ [ucc addUserScript:ownerUserScript];
519
+
520
+ NSString* windowIdScript = [NSString stringWithFormat:
521
+ @"(function(){globalThis[Symbol.for('zapp.windowId')]='%@';})();",
522
+ windowId
523
+ ];
524
+ WKUserScript* windowIdUserScript = [[WKUserScript alloc]
525
+ initWithSource:windowIdScript
526
+ injectionTime:WKUserScriptInjectionTimeAtDocumentStart
527
+ forMainFrameOnly:NO];
528
+ [ucc addUserScript:windowIdUserScript];
529
+
530
+ NSString* bootstrap = [NSString stringWithUTF8String:zapp_darwin_webview_bootstrap_script()];
531
+ WKUserScript* userScript = [[WKUserScript alloc]
532
+ initWithSource:bootstrap
533
+ injectionTime:WKUserScriptInjectionTimeAtDocumentStart
534
+ forMainFrameOnly:NO];
535
+ [ucc addUserScript:userScript];
536
+
537
+ ZappMsgHandler* handler = [[ZappMsgHandler alloc] init];
538
+ [ucc addScriptMessageHandler:handler name:@"zapp"];
539
+ [config setUserContentController:ucc];
540
+ [[config preferences] setValue:@YES forKey:@"developerExtrasEnabled"];
541
+ ZappWebView* webview = [[ZappWebView alloc] initWithFrame:bounds configuration:config];
542
+ [webview setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
543
+ [webview setInspectable:inspectable ? YES : NO];
544
+ NSURL* url = zapp_initial_url();
545
+ [webview loadRequest:[NSURLRequest requestWithURL:url]];
546
+
547
+ [window setContentView:webview];
548
+ }
549
+ #endif
550
+ }
@@ -0,0 +1,9 @@
1
+ // AUTO-GENERATED FILE. DO NOT EDIT.
2
+ // Source of truth: `packages/bootstrap/src/webview.ts`
3
+ // Generated: `2026-03-22T07:58:05.467Z`
4
+
5
+ raw {
6
+ const char* zapp_darwin_webview_bootstrap_script(void) {
7
+ return "(()=>{var{defineProperty:_,getOwnPropertyNames:o,getOwnPropertyDescriptor:s}=Object,d=Object.prototype.hasOwnProperty;var S=new WeakMap,n=(H)=>{var Q=S.get(H),$;if(Q)return Q;if(Q=_({},\"__esModule\",{value:!0}),H&&typeof H===\"object\"||typeof H===\"function\")o(H).map((K)=>!d.call(Q,K)&&_(Q,K,{get:()=>H[K],enumerable:!($=s(H,K))||$.enumerable}));return S.set(H,Q),Q};var GH={},L=globalThis,h=L.__zapp,W=h&&typeof h===\"object\"?h:{},v=()=>{if(L.__zapp===W)return;L.__zapp=W;try{Object.defineProperty(L,\"__zapp\",{value:W,enumerable:!0,configurable:!1,writable:!1})}catch{}},k=Symbol.for(\"zapp.bridge\"),M=Symbol.for(\"zapp.bootstrapConfig\"),w=Symbol.for(\"zapp.ownerId\"),x=L,B=(H)=>{let Q=x[k]?\?{},$=Object.assign({},Q,H);Object.defineProperty(x,k,{value:$,enumerable:!1,configurable:!0,writable:!1})},X={},Y={},O=0;B({_listeners:Y,_lastId:O});var D=X.__ctxId?\?=`ctx-${Date.now()}-${Math.random().toString(36).slice(2)}`,R=X.__pendingInvokes=X.__pendingInvokes?\?{},C=X.__pendingSyncWaits=X.__pendingSyncWaits?\?{},I=X.__invokeSeq?\?0,m=1,a=131072,y=x[M]==null?null:{name:x[M].name,applicationShouldTerminateAfterLastWindowClosed:x[M].applicationShouldTerminateAfterLastWindowClosed,webContentInspectable:x[M].webContentInspectable,maxWorkers:x[M].maxWorkers};try{delete x[M]}catch{}var u=(H)=>typeof H===\"string\"?H:JSON.stringify(H?\?{}),A=(H,Q,$)=>{v();let K=L.webkit?.messageHandlers?.zapp;if(!K?.postMessage)return!1;return K.postMessage(`${H}\n${Q}\n${u($)}`),!0};X.invoke=(H,Q)=>new Promise(($,K)=>{let J=typeof H===\"string\"?H.trim():\"\";if(!J){K(Error(\"Service method must be a non-empty string.\"));return}if(u(Q).length>a){K(Error(\"Service payload exceeds max size.\"));return}let G=`${D}:inv-${++I}`;X.__invokeSeq=I;let f={v:m,id:G,method:J,args:Q,meta:{sourceCtxId:D}},F=setTimeout(()=>{delete R[G],K(Error(\"Service invocation timed out.\"))},15000);if(R[G]={resolve:$,reject:K,timeout:F},!A(\"invoke_rpc\",J,f))clearTimeout(F),delete R[G],K(Error(\"Native invoke transport unavailable.\"))});var b=()=>{let H=Error(\"Sync wait aborted.\");return H.name=\"AbortError\",H};X.syncWait=(H,Q=30000,$)=>new Promise((K,J)=>{let V=typeof H===\"string\"?H.trim():\"\";if(!V){J(Error(\"Sync key must be a non-empty string.\"));return}if($?.aborted){J(b());return}let G=`${D}:sync-${Date.now()}-${Math.random().toString(36).slice(2)}`,f=Q==null||Number.isNaN(Number(Q))?null:Math.floor(Number(Q)),F=f==null?null:Math.max(1,Math.min(300000,f)),z={id:G,key:V,timeoutMs:F,meta:{sourceCtxId:D}},Z=F==null?void 0:setTimeout(()=>{delete C[G],J(Error(\"Sync wait transport timed out.\"))},F+5000);if(C[G]={resolve:K,reject:J,timeout:Z},!A(\"sync\",\"wait\",z)){if(Z)clearTimeout(Z);delete C[G],J(Error(\"Native sync transport unavailable.\"));return}if($){let N=()=>{let T=C[G];if(!T)return;if(T.timeout)clearTimeout(T.timeout);delete C[G],A(\"sync\",\"cancel\",{id:G,meta:{sourceCtxId:D}}),J(b())};$.addEventListener(\"abort\",N,{once:!0})}});X.syncNotify=(H,Q=1)=>{let $=typeof H===\"string\"?H.trim():\"\";if(!$)return!1;let K=Math.max(1,Math.min(65535,Math.floor(Q)));return A(\"sync\",\"notify\",{key:$,count:K,meta:{sourceCtxId:D}})};X.syncCancel=(H)=>{let Q=typeof H===\"string\"?H.trim():\"\";if(!Q)return!1;return A(\"sync\",\"cancel\",{id:Q,meta:{sourceCtxId:D}})};X.emit=(H,Q)=>A(\"emit\",H,{__zapp_internal_meta:{sourceCtxId:D},data:Q});X.onEvent=(H,Q)=>{let $=++O;return(Y[H]?\?=[]).push({id:$,fn:Q}),$};X.offEvent=(H,Q)=>{let $=Y[H]?\?[];Y[H]=$.filter((K)=>K.id!==Q)};X.onceEvent=(H,Q)=>{let $=++O;return(Y[H]?\?=[]).push({id:$,fn:Q,once:!0}),$};X.offAllEvents=(H)=>{if(H)delete Y[H];else Object.keys(Y).forEach((Q)=>delete Y[Q])};var t=(H)=>{let Q=H.pathname.split(\".\").pop()?.toLowerCase();if(Q!==\"ts\"&&Q!==\"tsx\")return H.toString();let $=(Z)=>{let U=Z.startsWith(\"/\")?Z:`/${Z}`;if(H.protocol===\"zapp:\")return`zapp://app${U}`;return new URL(U,H).toString()},K=x[Symbol.for(\"zapp.workerManifest\")],J=H.pathname.split(\"/\").pop()?\?\"worker.ts\",V=`./${J}`;if(K){let Z=K[V]?\?K[J];if(typeof Z===\"string\"&&Z.length>0)return $(Z)}let G=H.pathname.split(\"/\"),z=`/zapp-workers/${(G[G.length-1]?\?\"worker.ts\").replace(/\\.[^.]+$/,\"\")}.mjs`;return $(z)},r=(H)=>H instanceof URL?t(H):H;if(!X.workerBridge){let H={},Q=0,$=x[w],K=typeof $===\"string\"&&$.length>0?$:`owner-${Date.now()}-${Math.random().toString(36).slice(2)}`;try{delete x[w]}catch{}let J=[],V=(F)=>{return H[F]?\?={message:[],error:[],close:[]},H[F]},G=(F,z,Z)=>{let U=(E)=>{queueMicrotask(E)};if(F===\"close\"){let E=H[z];U(()=>{if(E)for(let i of E.close)try{i(Z)}catch{}X.workerBridge?.terminateWorker(z)});return}let N=H[z];if(!N)return;let T=Z;if(typeof Z===\"string\")try{T=JSON.parse(Z)}catch{}let j=F===\"error\"?N.error:N.message;U(()=>{for(let E of j)try{E(T)}catch{}})};X.__workerBridgeDispatch=G,B({dispatchWorkerBridge:G}),X.workerBridge={createWorker(F,z){let Z=Boolean(z?.shared),U=`${K}:${D}:zw-${++Q}`;return V(U),J.push(U),A(\"worker\",\"create\",{id:U,scriptUrl:F,ownerId:K,shared:Z}),U},postToWorker(F,z){A(\"worker\",\"post\",{id:F,data:z,ownerId:K})},terminateWorker(F){A(\"worker\",\"terminate\",{id:F,ownerId:K}),J=J.filter((z)=>z!==F),delete H[F]},subscribe(F,z,Z,U){let N=V(F);if(z)N.message.push(z);if(Z)N.error.push(Z);if(U)N.close.push(U);return()=>{let T=H[F];if(!T)return;if(z)T.message=T.message.filter((j)=>j!==z);if(Z)T.error=T.error.filter((j)=>j!==Z);if(U)T.close=T.close.filter((j)=>j!==U)}}};let f=()=>{if(!J.length)return;A(\"worker\",\"reset_owner\",{ownerId:K}),J=[];for(let F of Object.keys(H))delete H[F]};B({resetOwnerWorkers:f,createWorker:X.workerBridge.createWorker.bind(X.workerBridge),postToWorker:X.workerBridge.postToWorker.bind(X.workerBridge),terminateWorker:X.workerBridge.terminateWorker.bind(X.workerBridge),subscribeWorker:X.workerBridge.subscribe.bind(X.workerBridge),resolveWorkerScriptURL:r}),L.addEventListener(\"beforeunload\",f),L.addEventListener(\"pagehide\",f)}var q={},e=0,HH=(H)=>new Promise((Q,$)=>{let K=`${D}:win-${++e}`,J=setTimeout(()=>{delete q[K],$(Error(\"Window creation timed out.\"))},15000);q[K]={resolve:Q,reject:$,timeout:J},A(\"window\",\"create\",{requestId:K,options:H})}),QH=(H,Q,$)=>{A(\"window\",Q,{windowId:H,...$})},$H=(H,Q)=>{A(\"app\",H,Q?\?{})},KH=(H)=>{let Q=H;if(typeof H===\"string\")try{Q=JSON.parse(H)}catch{return}if(!Q||typeof Q!==\"object\")return;let $=Q;if(typeof $.requestId!==\"string\")return;let K=q[$.requestId];if(!K)return;if(clearTimeout(K.timeout),delete q[$.requestId],$.ok===!1)K.reject(Error($.error?\?\"Window creation failed.\"));else K.resolve({id:$.id?\?\"\"})},l=(H,Q,$)=>{v();let K={windowId:H,timestamp:Date.now()};if($)try{let V=JSON.parse($);if(V.width||V.height)K.size={width:V.width?\?0,height:V.height?\?0};if(V.x!==void 0||V.y!==void 0)K.position={x:V.x?\?0,y:V.y?\?0}}catch{}let J=(V)=>{let G=Y[V];if(!G||G.length===0)return;let f=[];for(let F of G){try{F.fn(K)}catch{}if(!F.once)f.push(F)}if(f.length>0)Y[V]=f;else delete Y[V]};J(`__zapp_window:${H}:${Q}`),J(`window:${Q}`)};B({windowCreate:HH,windowAction:QH,appAction:$H,dispatchWindowResult:KH,dispatchWindowEvent:l,_emit:X.emit,_onEvent:X.onEvent,_onceEvent:X.onceEvent,_offEvent:X.offEvent,_offAllEvents:X.offAllEvents});W.invoke=X.invoke;W.emit=X.emit;W.on=(H,Q)=>{let $=X.onEvent?.(H,Q)?\?0;return()=>X.offEvent?.(H,$)};var XH=(H,Q)=>{v();let $=Q;if(typeof Q===\"string\"){let V=Q.trim();if(V.startsWith(\"{\")&&V.endsWith(\"}\")||V.startsWith(\"[\")&&V.endsWith(\"]\"))try{$=JSON.parse(Q)}catch{}}if($&&typeof $===\"object\"){let V=$;if(V.__zapp_internal_meta?.sourceCtxId===D)return;if(Object.prototype.hasOwnProperty.call(V,\"data\"))$=V.data}let K=Y[H]?\?[],J=[];for(let V of K){try{V.fn($)}catch{}if(!V.once)J.push(V)}if(J.length>0)Y[H]=J;else delete Y[H]},JH=(H)=>{let Q=H;if(typeof H===\"string\")try{Q=JSON.parse(H)}catch{return}if(!Q||typeof Q!==\"object\")return;let $=Q;if(typeof $.id!==\"string\"||$.id.length===0)return;let K=R[$.id];if(!K)return;if(clearTimeout(K.timeout),delete R[$.id],$.ok){K.resolve($.result);return}let J=$.error?.code?\?\"INTERNAL_ERROR\",V=$.error?.message?\?\"Service invocation failed\";K.reject(Error(`${J}: ${V}`))},VH=(H)=>{let Q=H;if(typeof H===\"string\")try{Q=JSON.parse(H)}catch{return}if(!Q||typeof Q!==\"object\")return;let $=Q;if(typeof $.id!==\"string\"||$.id.length===0)return;let K=C[$.id];if(!K)return;if(K.timeout)clearTimeout(K.timeout);if(delete C[$.id],!$.ok){K.reject(Error(\"Sync wait failed.\"));return}if($.status===\"cancelled\"){K.reject(b());return}K.resolve($.status===\"timed-out\"?\"timed-out\":\"notified\")},FH=(H)=>{let Q=H;if(typeof H===\"string\")try{Q=JSON.parse(H)}catch{return}if(!Q||typeof Q!==\"object\")return;let $=Q;if(typeof $.requestId!==\"string\")return;let K=`__zapp:dialog:${$.requestId}`,J=Y[K];if(J){for(let V of J)try{V.fn($)}catch{}delete Y[K]}};B({dispatchInvokeResult:JH,dispatchSyncResult:VH,dispatchDialogResult:FH,deliverEvent:XH,getConfig:()=>y==null?null:{...y},invoke:async(H)=>{let Q=H;if(!Q||typeof Q!==\"object\")throw Error(\"Invalid invoke request\");if(typeof Q.method!==\"string\")throw Error(\"Invalid service method\");let $=await X.invoke?.(Q.method,Q.args);return{v:m,id:Q.id,ok:!0,result:$}},getServiceBindings:()=>{let H=x[Symbol.for(\"zapp.bindingsManifest\")];if(typeof H!==\"string\")return null;return H},syncWait:async(H)=>{let Q=H;return X.syncWait?.(Q?.key?\?\"\",Q?.timeoutMs===void 0?30000:Q.timeoutMs,Q?.signal)?\?Promise.reject(Error(\"Sync unavailable\"))},syncNotify:(H)=>{let Q=H;return X.syncNotify?.(Q?.key?\?\"\",Q?.count?\?1)?\?!1},syncCancel:(H)=>{let Q=H;return X.syncCancel?.(Q?.id?\?\"\")?\?!1}});Object.defineProperties(W,{invoke:{value:X.invoke,enumerable:!0,configurable:!1,writable:!1},syncWait:{value:X.syncWait,enumerable:!0,configurable:!1,writable:!1},syncNotify:{value:X.syncNotify,enumerable:!0,configurable:!1,writable:!1},syncCancel:{value:X.syncCancel,enumerable:!0,configurable:!1,writable:!1},emit:{value:X.emit,enumerable:!0,configurable:!1,writable:!1},on:{value:W.on,enumerable:!0,configurable:!1,writable:!1}});Object.freeze(W);if(typeof document<\"u\"){let H=()=>{if(!document.head)return;let Q=document.createElement(\"meta\");Q.httpEquiv=\"Content-Security-Policy\",Q.content=\"default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; img-src 'self' data: blob:;\",document.head.insertBefore(Q,document.head.firstChild)};if(document.head)H();else document.addEventListener(\"DOMContentLoaded\",H,{once:!0})}v();var p=Symbol.for(\"zapp.windowId\"),c=Symbol.for(\"zapp.windowReady\"),P=L,g=()=>{if(P[c])return;P[c]=!0;let H=P[p],Q=L.webkit?.messageHandlers?.zapp;if(Q?.postMessage){let $=JSON.stringify({windowId:H?\?\"unknown\"});Q.postMessage(`window\nready\n${$}`)}l(H?\?\"unknown\",\"ready\")};if(typeof document<\"u\"){if(document.addEventListener(\"DOMContentLoaded\",g,{once:!0}),document.readyState!==\"loading\")g();let H=($)=>{let K=$;while(K){if(K.hasAttribute?.(\"data-zapp-drag-region\"))return!0;let J=K.tagName;if(J===\"BUTTON\"||J===\"INPUT\"||J===\"SELECT\"||J===\"TEXTAREA\"||J===\"A\")return!1;K=K.parentElement}return!1},Q=!1;document.addEventListener(\"mousemove\",($)=>{let K=H($.target);if(K!==Q)Q=K,A(\"window\",\"setDragRegion\",{windowId:P[p]?\?\"unknown\",drag:K})})}})();\n";
8
+ }
9
+ }