sparkbun 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 (131) hide show
  1. package/bin/sparkbun.cjs +18 -0
  2. package/dist-linux-arm64/bsdiff +0 -0
  3. package/dist-linux-arm64/bspatch +0 -0
  4. package/dist-linux-arm64/libElectrobunCore.so +0 -0
  5. package/dist-linux-arm64/libNativeWrapper.so +0 -0
  6. package/dist-linux-arm64/libasar.so +0 -0
  7. package/dist-linux-x64/bsdiff +0 -0
  8. package/dist-linux-x64/bspatch +0 -0
  9. package/dist-linux-x64/libElectrobunCore.so +0 -0
  10. package/dist-linux-x64/libNativeWrapper.so +0 -0
  11. package/dist-linux-x64/libasar.so +0 -0
  12. package/dist-macos-arm64/bsdiff +0 -0
  13. package/dist-macos-arm64/bspatch +0 -0
  14. package/dist-macos-arm64/libElectrobunCore.dylib +0 -0
  15. package/dist-macos-arm64/libNativeWrapper.dylib +0 -0
  16. package/dist-macos-arm64/libasar.dylib +0 -0
  17. package/dist-macos-arm64/libwebgpu_dawn.dylib +0 -0
  18. package/dist-macos-arm64/preload-full.js +885 -0
  19. package/dist-macos-arm64/preload-sandboxed.js +111 -0
  20. package/dist-macos-arm64/process_helper +0 -0
  21. package/dist-win-x64/ElectrobunCore.dll +0 -0
  22. package/dist-win-x64/WebView2Loader.dll +0 -0
  23. package/dist-win-x64/bsdiff.exe +0 -0
  24. package/dist-win-x64/bspatch.exe +0 -0
  25. package/dist-win-x64/libNativeWrapper.dll +0 -0
  26. package/dist-win-x64/zig-asar/arm64/libasar.dll +0 -0
  27. package/dist-win-x64/zig-asar/x64/libasar.dll +0 -0
  28. package/package.json +47 -0
  29. package/scripts/build-and-upload-artifacts.js +207 -0
  30. package/scripts/gen-webgpu-ffi.mjs +162 -0
  31. package/scripts/install-windows-deps.ps1 +80 -0
  32. package/scripts/package-release.js +237 -0
  33. package/scripts/push-version.js +84 -0
  34. package/scripts/update-bun-version.ts +122 -0
  35. package/scripts/update-cef-version.ts +145 -0
  36. package/src/browser/builtinrpcSchema.ts +19 -0
  37. package/src/browser/global.d.ts +36 -0
  38. package/src/browser/index.ts +234 -0
  39. package/src/browser/webviewtag.ts +88 -0
  40. package/src/browser/wgputag.ts +48 -0
  41. package/src/bun/SparkBunConfig.ts +497 -0
  42. package/src/bun/__tests__/ffi-contract.test.ts +105 -0
  43. package/src/bun/core/ApplicationMenu.ts +70 -0
  44. package/src/bun/core/BrowserView.ts +416 -0
  45. package/src/bun/core/BrowserWindow.ts +396 -0
  46. package/src/bun/core/BuildConfig.ts +71 -0
  47. package/src/bun/core/ContextMenu.ts +75 -0
  48. package/src/bun/core/GpuWindow.ts +289 -0
  49. package/src/bun/core/Paths.ts +5 -0
  50. package/src/bun/core/Socket.ts +22 -0
  51. package/src/bun/core/Tray.ts +197 -0
  52. package/src/bun/core/Updater.ts +1131 -0
  53. package/src/bun/core/Utils.ts +487 -0
  54. package/src/bun/core/WGPUView.ts +167 -0
  55. package/src/bun/core/menuRoles.ts +181 -0
  56. package/src/bun/events/ApplicationEvents.ts +22 -0
  57. package/src/bun/events/event.ts +27 -0
  58. package/src/bun/events/eventEmitter.ts +45 -0
  59. package/src/bun/events/trayEvents.ts +11 -0
  60. package/src/bun/events/webviewEvents.ts +39 -0
  61. package/src/bun/events/windowEvents.ts +23 -0
  62. package/src/bun/index.ts +120 -0
  63. package/src/bun/preload/.generated/compiled.ts +2 -0
  64. package/src/bun/preload/build.ts +65 -0
  65. package/src/bun/preload/dragRegions.ts +41 -0
  66. package/src/bun/preload/encryption.ts +86 -0
  67. package/src/bun/preload/events.ts +171 -0
  68. package/src/bun/preload/globals.d.ts +45 -0
  69. package/src/bun/preload/index-sandboxed.ts +28 -0
  70. package/src/bun/preload/index.ts +77 -0
  71. package/src/bun/preload/internalRpc.ts +80 -0
  72. package/src/bun/preload/overlaySync.ts +107 -0
  73. package/src/bun/preload/webviewTag.ts +451 -0
  74. package/src/bun/preload/wgpuTag.ts +246 -0
  75. package/src/bun/proc/linux.md +43 -0
  76. package/src/bun/proc/native.ts +3253 -0
  77. package/src/bun/webGPU.ts +346 -0
  78. package/src/bun/webgpuAdapter.ts +3011 -0
  79. package/src/cli/bun.lockb +0 -0
  80. package/src/cli/index.ts +4653 -0
  81. package/src/cli/package-lock.json +81 -0
  82. package/src/cli/package.json +11 -0
  83. package/src/cli/templates/embedded.ts +2 -0
  84. package/src/core/build.zig +16 -0
  85. package/src/core/main.zig +3378 -0
  86. package/src/extractor/build.zig +22 -0
  87. package/src/installer/installer-template.ts +216 -0
  88. package/src/launcher/main.ts +221 -0
  89. package/src/native/build/libNativeWrapper.so +0 -0
  90. package/src/native/linux/build/nativeWrapper.o +0 -0
  91. package/src/native/linux/cef_loader.cpp +110 -0
  92. package/src/native/linux/cef_loader.h +28 -0
  93. package/src/native/linux/cef_process_helper_linux.cpp +160 -0
  94. package/src/native/linux/nativeWrapper.cpp +11768 -0
  95. package/src/native/macos/cef_process_helper_mac.cc +160 -0
  96. package/src/native/macos/nativeWrapper.mm +9172 -0
  97. package/src/native/shared/accelerator_parser.h +72 -0
  98. package/src/native/shared/app_paths.h +110 -0
  99. package/src/native/shared/asar.h +35 -0
  100. package/src/native/shared/cache_migration.h +244 -0
  101. package/src/native/shared/callbacks.h +57 -0
  102. package/src/native/shared/cef_response_filter.h +189 -0
  103. package/src/native/shared/chromium_flags.h +181 -0
  104. package/src/native/shared/config.h +66 -0
  105. package/src/native/shared/download_event.h +197 -0
  106. package/src/native/shared/ffi_helpers.h +139 -0
  107. package/src/native/shared/glob_match.h +59 -0
  108. package/src/native/shared/json_menu_parser.h +223 -0
  109. package/src/native/shared/mime_types.h +101 -0
  110. package/src/native/shared/navigation_rules.h +98 -0
  111. package/src/native/shared/partition_context.h +137 -0
  112. package/src/native/shared/pending_resize_queue.h +45 -0
  113. package/src/native/shared/permissions.h +118 -0
  114. package/src/native/shared/permissions_cef.h +74 -0
  115. package/src/native/shared/preload_script.h +71 -0
  116. package/src/native/shared/shutdown_guard.h +134 -0
  117. package/src/native/shared/thread_safe_map.h +138 -0
  118. package/src/native/shared/webview_storage.h +91 -0
  119. package/src/native/win/cef_process_helper_win.cpp +143 -0
  120. package/src/native/win/dcomp_compositor.h +352 -0
  121. package/src/native/win/nativeWrapper.cpp +12434 -0
  122. package/src/npmbin/index.js +34 -0
  123. package/src/shared/bun-version.ts +3 -0
  124. package/src/shared/cef-version.ts +5 -0
  125. package/src/shared/naming.test.ts +327 -0
  126. package/src/shared/naming.ts +188 -0
  127. package/src/shared/platform.ts +48 -0
  128. package/src/shared/rpc.ts +541 -0
  129. package/src/shared/sparkbun-version.ts +2 -0
  130. package/src/types/three.d.ts +1 -0
  131. package/tsconfig.json +31 -0
@@ -0,0 +1,497 @@
1
+ /**
2
+ * SparkBun configuration type definitions
3
+ * Used in sparkbun.config.ts files
4
+ */
5
+
6
+ /**
7
+ * Bun.build() options that can be passed through to the bundler.
8
+ * Excludes options that are controlled by SparkBun (entrypoints, outdir, target).
9
+ * See https://bun.sh/docs/bundler for full documentation.
10
+ */
11
+ type BunBuildOptions = Omit<
12
+ Parameters<typeof Bun.build>[0],
13
+ "entrypoints" | "outdir" | "target"
14
+ >;
15
+
16
+ export interface SparkBunConfig {
17
+ /**
18
+ * Application metadata configuration
19
+ */
20
+ app: {
21
+ /**
22
+ * The display name of your application
23
+ */
24
+ name: string;
25
+
26
+ /**
27
+ * Unique identifier for your application (e.g., "com.example.myapp")
28
+ * Used for platform-specific identifiers
29
+ */
30
+ identifier: string;
31
+
32
+ /**
33
+ * Application version string (e.g., "1.0.0")
34
+ */
35
+ version: string;
36
+
37
+ /**
38
+ * Optional description of the application
39
+ */
40
+ description?: string;
41
+
42
+ /**
43
+ * Publisher/company name (e.g., "My Company")
44
+ * Used in Windows file properties and installer metadata
45
+ */
46
+ publisher?: string;
47
+
48
+ /**
49
+ * Copyright notice (e.g., "Copyright 2026 My Company")
50
+ * Used in Windows file properties
51
+ */
52
+ copyright?: string;
53
+
54
+ /**
55
+ * Custom URL schemes to register for deep linking (e.g., ["myapp", "myapp-dev"])
56
+ * This allows your app to be opened via URLs like myapp://some/path
57
+ *
58
+ * Platform support:
59
+ * - macOS: Fully supported. App must be in /Applications folder for registration to work.
60
+ * - Windows: Not yet supported
61
+ * - Linux: Not yet supported
62
+ *
63
+ * To handle incoming URLs, listen for the "open-url" event:
64
+ * ```typescript
65
+ * SparkBun.events.on("open-url", (e) => {
66
+ * console.log("Opened with URL:", e.data.url);
67
+ * });
68
+ * ```
69
+ */
70
+ urlSchemes?: string[];
71
+
72
+ /**
73
+ * File type associations for the application.
74
+ * Registers document types so the OS can open files with your app
75
+ * (e.g., double-click in Finder, "Open With" menu, drag-to-dock).
76
+ *
77
+ * Platform support:
78
+ * - macOS: Fully supported. Generates CFBundleDocumentTypes in Info.plist.
79
+ * - Windows/Linux: Not yet supported.
80
+ *
81
+ * Files arrive as file:// URLs via the existing "open-url" event:
82
+ * ```typescript
83
+ * SparkBun.events.on("open-url", (e) => {
84
+ * if (e.data.url.startsWith("file://")) {
85
+ * console.log("Opened file:", e.data.url);
86
+ * }
87
+ * });
88
+ * ```
89
+ */
90
+ fileAssociations?: Array<{
91
+ /** File extensions without the leading dot (e.g., ["dotlock", "json"]) */
92
+ ext: string[];
93
+ /** Human-readable name for this file type (e.g., "DotLock Document") */
94
+ name: string;
95
+ /** The app's role for this file type. @default "Viewer" */
96
+ role?: "Editor" | "Viewer" | "Shell" | "None";
97
+ /**
98
+ * Path to an .icns file for this document type (macOS only).
99
+ * The file is automatically copied into the app bundle's Resources folder
100
+ * during the build. Only the filename (without path) is written to Info.plist.
101
+ */
102
+ icon?: string;
103
+ }>;
104
+ };
105
+
106
+ /**
107
+ * Build configuration options
108
+ */
109
+ build?: {
110
+ /**
111
+ * Bun process build configuration.
112
+ * Accepts all Bun.build() options (plugins, sourcemap, minify, define, etc.)
113
+ * in addition to the entrypoint. See https://bun.sh/docs/bundler
114
+ */
115
+ bun?: {
116
+ /**
117
+ * Entry point for the main Bun process
118
+ * @default "src/bun/index.ts"
119
+ */
120
+ entrypoint?: string;
121
+ } & BunBuildOptions;
122
+
123
+ /**
124
+ * Browser view build configurations.
125
+ * Each view accepts all Bun.build() options (plugins, sourcemap, minify, define, etc.)
126
+ * in addition to the entrypoint. See https://bun.sh/docs/bundler
127
+ */
128
+ views?: {
129
+ [viewName: string]: {
130
+ /**
131
+ * Entry point for this view's TypeScript code
132
+ */
133
+ entrypoint: string;
134
+ } & BunBuildOptions;
135
+ };
136
+
137
+ /**
138
+ * Files to copy directly to the build output
139
+ * Key is source path, value is destination path
140
+ */
141
+ copy?: {
142
+ [sourcePath: string]: string;
143
+ };
144
+ /**
145
+ * Output folder for built application
146
+ * @default "build"
147
+ */
148
+ buildFolder?: string;
149
+
150
+ /**
151
+ * Output folder for distribution artifacts
152
+ * @default "artifacts"
153
+ */
154
+ artifactFolder?: string;
155
+
156
+ /**
157
+ * Build targets to compile for
158
+ * Can be "current", "all", or comma-separated list like "macos-arm64,win-x64"
159
+ */
160
+ targets?: string;
161
+
162
+ /**
163
+ * Override the CEF (Chromium Embedded Framework) version.
164
+ * Format: "CEF_VERSION+chromium-CHROMIUM_VERSION"
165
+ * Example: "144.0.11+ge135be2+chromium-144.0.7559.97"
166
+ *
167
+ * Check the sparkbun-cef-compat compatibility matrix for tested combinations
168
+ * before overriding. Using an untested version may cause runtime issues.
169
+ * @default Uses the version bundled with this SparkBun release
170
+ */
171
+ cefVersion?: string;
172
+
173
+ /**
174
+ * Override the Dawn (WebGPU) version.
175
+ * Format: semver string (e.g., "0.2.3") or tag (e.g., "v0.2.3-beta.0")
176
+ *
177
+ * This downloads the specified sparkbun-dawn release and uses it
178
+ * instead of the latest release.
179
+ * @default Uses the latest sparkbun-dawn release
180
+ */
181
+ wgpuVersion?: string;
182
+
183
+ /**
184
+ * Override the Bun runtime version.
185
+ * Format: semver string (e.g., "1.4.2")
186
+ *
187
+ * This downloads the specified Bun version from GitHub releases and uses it
188
+ * instead of the version bundled with this SparkBun release.
189
+ * @default Uses the version bundled with this SparkBun release
190
+ */
191
+ bunVersion?: string;
192
+
193
+ /**
194
+ * Locales to include in the ICU data file (Linux/Windows only).
195
+ * Set to '*' to include all locales, or specify a subset like ['en', 'de']
196
+ * to reduce app size. Has no effect on macOS (uses system ICU).
197
+ * @default '*'
198
+ */
199
+ locales?: string[] | "*";
200
+
201
+ /**
202
+ * Additional file or directory paths to watch for changes during `sparkbun dev --watch`.
203
+ * Paths are relative to the project root.
204
+ * Useful for files that affect your build but aren't listed as entrypoints or copy sources.
205
+ */
206
+ watch?: string[];
207
+
208
+ /**
209
+ * Glob patterns for files that should not trigger a rebuild when changed.
210
+ * Patterns are matched against project-relative paths.
211
+ * The `build/`, `artifacts/`, and `node_modules/` directories are always ignored automatically.
212
+ */
213
+ watchIgnore?: string[];
214
+
215
+ /**
216
+ * macOS-specific build configuration
217
+ */
218
+ mac?: {
219
+ /**
220
+ * Enable code signing for macOS builds
221
+ * @default false
222
+ */
223
+ codesign?: boolean;
224
+
225
+ /**
226
+ * Create a DMG artifact for macOS builds.
227
+ * Disable this for local prototype builds that only need the app bundle and update archive.
228
+ * @default true
229
+ */
230
+ createDmg?: boolean;
231
+
232
+ /**
233
+ * Enable notarization for macOS builds (requires codesign)
234
+ * @default false
235
+ */
236
+ notarize?: boolean;
237
+
238
+ /**
239
+ * Bundle CEF (Chromium Embedded Framework) instead of using system WebView
240
+ * @default false
241
+ */
242
+ bundleCEF?: boolean;
243
+
244
+ /**
245
+ * Bundle Dawn (WebGPU) for GPU-native rendering
246
+ * @default false
247
+ */
248
+ bundleWGPU?: boolean;
249
+
250
+ /**
251
+ * Default renderer for webviews when not explicitly specified
252
+ * @default 'native'
253
+ */
254
+ defaultRenderer?: "native" | "cef";
255
+
256
+ /**
257
+ * Custom Chromium command-line flags to pass to CEF during initialization.
258
+ * Keys are flag names without the "--" prefix.
259
+ * - `true` — add a switch-only flag
260
+ * - `"value"` — add a flag with a value
261
+ * - `false` — remove a default flag set by SparkBun
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * chromiumFlags: {
266
+ * "disable-gpu": false, // remove SparkBun's default --disable-gpu
267
+ * "remote-debugging-port": "9333", // --remote-debugging-port=9333
268
+ * }
269
+ * ```
270
+ */
271
+ chromiumFlags?: Record<string, string | boolean>;
272
+
273
+ /**
274
+ * macOS entitlements for code signing
275
+ */
276
+ entitlements?: Record<string, boolean | string | string[]>;
277
+
278
+ /**
279
+ * Path to .iconset folder or .icon file (from Icon Composer)
280
+ * containing app icons.
281
+ *
282
+ * - `.iconset` folders are converted to .icns via iconutil
283
+ * (requires Command Line Tools)
284
+ * - `.icon` files are compiled via actool, producing Assets.car
285
+ * for Liquid Glass on macOS 26+ and a .icns fallback for older
286
+ * macOS versions (requires Xcode)
287
+ *
288
+ * @default "icon.iconset"
289
+ */
290
+ icons?: string;
291
+ };
292
+
293
+ /**
294
+ * Windows-specific build configuration
295
+ */
296
+ win?: {
297
+ /**
298
+ * Bundle CEF (Chromium Embedded Framework) instead of using WebView2
299
+ * @default false
300
+ */
301
+ bundleCEF?: boolean;
302
+
303
+ /**
304
+ * Bundle Dawn (WebGPU) for GPU-native rendering
305
+ * @default false
306
+ */
307
+ bundleWGPU?: boolean;
308
+
309
+ /**
310
+ * Default renderer for webviews when not explicitly specified
311
+ * @default 'native'
312
+ */
313
+ defaultRenderer?: "native" | "cef";
314
+
315
+ /**
316
+ * Custom Chromium command-line flags to pass to CEF during initialization.
317
+ * Keys are flag names without the "--" prefix.
318
+ * - `true` — add a switch-only flag
319
+ * - `"value"` — add a flag with a value
320
+ * - `false` — remove a default flag set by SparkBun
321
+ *
322
+ * @example
323
+ * ```typescript
324
+ * chromiumFlags: {
325
+ * "disable-gpu": false, // remove SparkBun's default --disable-gpu
326
+ * "remote-debugging-port": "9333", // --remote-debugging-port=9333
327
+ * }
328
+ * ```
329
+ */
330
+ chromiumFlags?: Record<string, string | boolean>;
331
+
332
+ /**
333
+ * Path to application icon (.ico format)
334
+ * Used for the installer/extractor wrapper, desktop shortcuts, and taskbar
335
+ * Should include multiple sizes (16x16, 32x32, 48x48, 256x256) for best results
336
+ * @example "assets/icon.ico"
337
+ */
338
+ icon?: string;
339
+
340
+ /**
341
+ * Request administrator privileges on launch.
342
+ * The app will check for admin at startup and re-launch itself
343
+ * elevated via UAC if needed.
344
+ * @default false
345
+ */
346
+ requireAdmin?: boolean;
347
+ };
348
+
349
+ /**
350
+ * Linux-specific build configuration
351
+ */
352
+ linux?: {
353
+ /**
354
+ * Bundle CEF (Chromium Embedded Framework) instead of using GTKWebKit
355
+ * Recommended on Linux for advanced layer compositing features
356
+ * @default false
357
+ */
358
+ bundleCEF?: boolean;
359
+
360
+ /**
361
+ * Bundle Dawn (WebGPU) for GPU-native rendering
362
+ * @default false
363
+ */
364
+ bundleWGPU?: boolean;
365
+
366
+ /**
367
+ * Default renderer for webviews when not explicitly specified
368
+ * @default 'native'
369
+ */
370
+ defaultRenderer?: "native" | "cef";
371
+
372
+ /**
373
+ * Custom Chromium command-line flags to pass to CEF during initialization.
374
+ * Keys are flag names without the "--" prefix.
375
+ * - `true` — add a switch-only flag
376
+ * - `"value"` — add a flag with a value
377
+ * - `false` — remove a default flag set by SparkBun
378
+ *
379
+ * @example
380
+ * ```typescript
381
+ * chromiumFlags: {
382
+ * "disable-gpu": false, // remove SparkBun's default --disable-gpu
383
+ * "remote-debugging-port": "9333", // --remote-debugging-port=9333
384
+ * }
385
+ * ```
386
+ */
387
+ chromiumFlags?: Record<string, string | boolean>;
388
+
389
+ /**
390
+ * Path to application icon (PNG format recommended)
391
+ * Used for desktop entries, window icons, and taskbar
392
+ * Should be at least 256x256 pixels for best results
393
+ * @example "assets/icon.png"
394
+ */
395
+ icon?: string;
396
+
397
+ /**
398
+ * Request root privileges on launch.
399
+ * The app will check for root at startup and re-launch itself
400
+ * via pkexec if needed.
401
+ * @default false
402
+ */
403
+ requireAdmin?: boolean;
404
+
405
+ /**
406
+ * Create a .deb package for Debian/Ubuntu.
407
+ * @default false
408
+ */
409
+ createDeb?: boolean;
410
+
411
+ /**
412
+ * System library dependencies for the .deb package.
413
+ * @default ["libwebkit2gtk-4.1-0", "libgtk-3-0t64", "libsoup-3.0-0", "libjavascriptcoregtk-4.1-0", "libayatana-appindicator3-1", "libgdk-pixbuf-2.0-0"]
414
+ */
415
+ debDependencies?: string[];
416
+
417
+ /**
418
+ * Package maintainer for the .deb control file.
419
+ * @example "Your Name <you@example.com>"
420
+ */
421
+ debMaintainer?: string;
422
+
423
+ /**
424
+ * Install prefix for the .deb package.
425
+ * @default "/opt/<AppNameNoSpaces>"
426
+ */
427
+ installDir?: string;
428
+
429
+ /**
430
+ * Desktop entry category.
431
+ * @default "Utility;Application;"
432
+ */
433
+ category?: string;
434
+ };
435
+ };
436
+
437
+ /**
438
+ * Runtime behaviour configuration.
439
+ * These values are copied into build.json and available to the Bun process at runtime.
440
+ * You can add arbitrary keys here and access them via BuildConfig.
441
+ */
442
+ runtime?: {
443
+ /**
444
+ * Quit the application when the last BrowserWindow is closed.
445
+ * @default true
446
+ */
447
+ exitOnLastWindowClosed?: boolean;
448
+
449
+ [key: string]: unknown;
450
+ };
451
+
452
+ /**
453
+ * Build scripts configuration
454
+ */
455
+ scripts?: {
456
+ /**
457
+ * Script to run before the build starts
458
+ * Can be a path to a script file
459
+ */
460
+ preBuild?: string;
461
+
462
+ /**
463
+ * Script to run after build completes
464
+ * Can be a path to a script file
465
+ */
466
+ postBuild?: string;
467
+
468
+ /**
469
+ * Script to run after the app is wrapped (macOS .app bundle created)
470
+ * Can be a path to a script file
471
+ */
472
+ postWrap?: string;
473
+
474
+ /**
475
+ * Script to run after packaging is complete
476
+ * Can be a path to a script file
477
+ */
478
+ postPackage?: string;
479
+ };
480
+
481
+ /**
482
+ * Release and distribution configuration
483
+ */
484
+ release?: {
485
+ /**
486
+ * Base URL for artifact distribution (e.g., S3 bucket, GitHub Releases)
487
+ * Used for auto-updates and patch generation
488
+ */
489
+ baseUrl?: string;
490
+ /**
491
+ * Generate delta patch files by diffing against the previous release.
492
+ * Disable to skip patch generation for local canary/stable testing.
493
+ * @default true
494
+ */
495
+ generatePatch?: boolean;
496
+ };
497
+ }
@@ -0,0 +1,105 @@
1
+ // Contract tests for the bun:ffi APIs that sparkbun depends on.
2
+ //
3
+ // Bun bumps don't usually break sparkbun, but when they do, the breakage
4
+ // almost always lives in this surface — JSCallback marshaling, FFIType
5
+ // encoding, dlopen behavior. These tests are a tripwire: if a new Bun release
6
+ // breaks any of them, we want to know before cutting a sparkbun release,
7
+ // not after a user reports a crash.
8
+ //
9
+ // Skipped on Windows for now since the bun-check workflow runs on Linux and
10
+ // the system library paths differ. If we add a Windows runner later, switch
11
+ // the libc path resolution to include msvcrt/ucrtbase.
12
+
13
+ import { describe, expect, it } from "bun:test";
14
+ import {
15
+ CString,
16
+ FFIType,
17
+ JSCallback,
18
+ dlopen,
19
+ ptr,
20
+ toArrayBuffer,
21
+ type Pointer,
22
+ } from "bun:ffi";
23
+
24
+ const isUnix =
25
+ process.platform === "darwin" || process.platform === "linux";
26
+
27
+ const libcPath =
28
+ process.platform === "darwin" ? "libSystem.B.dylib" : "libc.so.6";
29
+
30
+ (isUnix ? describe : describe.skip)(
31
+ "bun:ffi contract used by sparkbun",
32
+ () => {
33
+ it("dlopen + FFIType.cstring + FFIType.u64 (strlen)", () => {
34
+ const lib = dlopen(libcPath, {
35
+ strlen: {
36
+ args: [FFIType.cstring],
37
+ returns: FFIType.u64,
38
+ },
39
+ });
40
+
41
+ const len = lib.symbols.strlen(
42
+ new TextEncoder().encode("hello\0"),
43
+ );
44
+ expect(Number(len)).toBe(5);
45
+
46
+ lib.close();
47
+ });
48
+
49
+ it("ptr + toArrayBuffer round-trip", () => {
50
+ const src = new Uint8Array([1, 2, 3, 4, 5]);
51
+ const back = new Uint8Array(
52
+ toArrayBuffer(ptr(src), 0, src.byteLength),
53
+ );
54
+ expect(Array.from(back)).toEqual([1, 2, 3, 4, 5]);
55
+ });
56
+
57
+ it("CString reads null-terminated bytes", () => {
58
+ const buf = new Uint8Array([72, 105, 33, 0]); // "Hi!\0"
59
+ const s = new CString(ptr(buf));
60
+ expect(s.toString()).toBe("Hi!");
61
+ });
62
+
63
+ it("JSCallback: native invokes JS via function pointer (qsort)", () => {
64
+ const lib = dlopen(libcPath, {
65
+ qsort: {
66
+ args: [
67
+ FFIType.ptr,
68
+ FFIType.u64,
69
+ FFIType.u64,
70
+ FFIType.function,
71
+ ],
72
+ returns: FFIType.void,
73
+ },
74
+ });
75
+
76
+ let comparisonCount = 0;
77
+ const compare = new JSCallback(
78
+ (aPtr: Pointer, bPtr: Pointer) => {
79
+ comparisonCount++;
80
+ const a = new Int32Array(toArrayBuffer(aPtr, 0, 4))[0]!;
81
+ const b = new Int32Array(toArrayBuffer(bPtr, 0, 4))[0]!;
82
+ return a - b;
83
+ },
84
+ {
85
+ args: [FFIType.ptr, FFIType.ptr],
86
+ returns: FFIType.i32,
87
+ },
88
+ );
89
+
90
+ const arr = new Int32Array([5, 2, 8, 1, 3]);
91
+ lib.symbols.qsort(
92
+ ptr(arr),
93
+ BigInt(arr.length),
94
+ 4n,
95
+ compare.ptr,
96
+ );
97
+
98
+ expect(Array.from(arr)).toEqual([1, 2, 3, 5, 8]);
99
+ expect(comparisonCount).toBeGreaterThan(0);
100
+
101
+ compare.close();
102
+ lib.close();
103
+ });
104
+ },
105
+ );
@@ -0,0 +1,70 @@
1
+ import { ffi, type ApplicationMenuItemConfig } from "../proc/native";
2
+ import sparkBunEventEmitter from "../events/eventEmitter";
3
+ import { roleLabelMap } from "./menuRoles";
4
+
5
+ type NonDividerMenuItem = {
6
+ type?: "normal";
7
+ label?: string;
8
+ tooltip?: string;
9
+ action?: string;
10
+ role?: string;
11
+ data?: unknown;
12
+ submenu?: Array<ApplicationMenuItemConfig>;
13
+ enabled?: boolean;
14
+ checked?: boolean;
15
+ hidden?: boolean;
16
+ accelerator?: string;
17
+ };
18
+
19
+ export const setApplicationMenu = (menu: Array<ApplicationMenuItemConfig>) => {
20
+ const menuWithDefaults = menuConfigWithDefaults(menu);
21
+ ffi.request.setApplicationMenu({
22
+ menuConfig: JSON.stringify(menuWithDefaults),
23
+ });
24
+ };
25
+
26
+ export const on = (
27
+ name: "application-menu-clicked",
28
+ handler: (event: unknown) => void,
29
+ ) => {
30
+ const specificName = `${name}`;
31
+ sparkBunEventEmitter.on(specificName, handler);
32
+ };
33
+
34
+ const menuConfigWithDefaults = (
35
+ menu: Array<ApplicationMenuItemConfig>,
36
+ ): Array<ApplicationMenuItemConfig> => {
37
+ return menu.map((item) => {
38
+ if (item.type === "divider" || item.type === "separator") {
39
+ return { type: "divider" } as const;
40
+ } else {
41
+ const menuItem = item as NonDividerMenuItem;
42
+ // Use shared serialization method
43
+ const actionWithDataId = ffi.internal.serializeMenuAction(
44
+ menuItem.action || "",
45
+ menuItem.data,
46
+ );
47
+
48
+ return {
49
+ label:
50
+ menuItem.label ||
51
+ roleLabelMap[menuItem.role as keyof typeof roleLabelMap] ||
52
+ "",
53
+ type: menuItem.type || "normal",
54
+ // application menus can either have an action or a role. not both.
55
+ ...(menuItem.role
56
+ ? { role: menuItem.role }
57
+ : { action: actionWithDataId }),
58
+ // default enabled to true unless explicitly set to false
59
+ enabled: menuItem.enabled === false ? false : true,
60
+ checked: Boolean(menuItem.checked),
61
+ hidden: Boolean(menuItem.hidden),
62
+ tooltip: menuItem.tooltip || undefined,
63
+ accelerator: menuItem.accelerator || undefined,
64
+ ...(menuItem.submenu
65
+ ? { submenu: menuConfigWithDefaults(menuItem.submenu) }
66
+ : {}),
67
+ };
68
+ }
69
+ });
70
+ };