@flighthq/host-web 0.4.0-edge.1908.751021c

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 (165) hide show
  1. package/dist/contract.d.ts +32 -0
  2. package/dist/contract.d.ts.map +1 -0
  3. package/dist/contract.js +32 -0
  4. package/dist/contract.js.map +1 -0
  5. package/dist/enableHostWeb.d.ts +2 -0
  6. package/dist/enableHostWeb.d.ts.map +1 -0
  7. package/dist/enableHostWeb.js +47 -0
  8. package/dist/enableHostWeb.js.map +1 -0
  9. package/dist/index.d.ts +32 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +32 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/webAccessibility.d.ts +3 -0
  14. package/dist/webAccessibility.d.ts.map +1 -0
  15. package/dist/webAccessibility.js +12 -0
  16. package/dist/webAccessibility.js.map +1 -0
  17. package/dist/webApp.d.ts +3 -0
  18. package/dist/webApp.d.ts.map +1 -0
  19. package/dist/webApp.js +156 -0
  20. package/dist/webApp.js.map +1 -0
  21. package/dist/webClipboard.d.ts +3 -0
  22. package/dist/webClipboard.d.ts.map +1 -0
  23. package/dist/webClipboard.js +132 -0
  24. package/dist/webClipboard.js.map +1 -0
  25. package/dist/webConnectivity.d.ts +3 -0
  26. package/dist/webConnectivity.d.ts.map +1 -0
  27. package/dist/webConnectivity.js +58 -0
  28. package/dist/webConnectivity.js.map +1 -0
  29. package/dist/webCursor.d.ts +3 -0
  30. package/dist/webCursor.d.ts.map +1 -0
  31. package/dist/webCursor.js +8 -0
  32. package/dist/webCursor.js.map +1 -0
  33. package/dist/webDevice.d.ts +3 -0
  34. package/dist/webDevice.d.ts.map +1 -0
  35. package/dist/webDevice.js +12 -0
  36. package/dist/webDevice.js.map +1 -0
  37. package/dist/webDialog.d.ts +3 -0
  38. package/dist/webDialog.d.ts.map +1 -0
  39. package/dist/webDialog.js +47 -0
  40. package/dist/webDialog.js.map +1 -0
  41. package/dist/webFilesystem.d.ts +3 -0
  42. package/dist/webFilesystem.d.ts.map +1 -0
  43. package/dist/webFilesystem.js +12 -0
  44. package/dist/webFilesystem.js.map +1 -0
  45. package/dist/webGeolocation.d.ts +3 -0
  46. package/dist/webGeolocation.d.ts.map +1 -0
  47. package/dist/webGeolocation.js +58 -0
  48. package/dist/webGeolocation.js.map +1 -0
  49. package/dist/webGlyphRasterizer.d.ts +5 -0
  50. package/dist/webGlyphRasterizer.d.ts.map +1 -0
  51. package/dist/webGlyphRasterizer.js +101 -0
  52. package/dist/webGlyphRasterizer.js.map +1 -0
  53. package/dist/webHaptics.d.ts +3 -0
  54. package/dist/webHaptics.d.ts.map +1 -0
  55. package/dist/webHaptics.js +12 -0
  56. package/dist/webHaptics.js.map +1 -0
  57. package/dist/webImage.d.ts +3 -0
  58. package/dist/webImage.d.ts.map +1 -0
  59. package/dist/webImage.js +26 -0
  60. package/dist/webImage.js.map +1 -0
  61. package/dist/webKeyboard.d.ts +3 -0
  62. package/dist/webKeyboard.d.ts.map +1 -0
  63. package/dist/webKeyboard.js +12 -0
  64. package/dist/webKeyboard.js.map +1 -0
  65. package/dist/webLifecycle.d.ts +3 -0
  66. package/dist/webLifecycle.d.ts.map +1 -0
  67. package/dist/webLifecycle.js +12 -0
  68. package/dist/webLifecycle.js.map +1 -0
  69. package/dist/webLoop.d.ts +3 -0
  70. package/dist/webLoop.d.ts.map +1 -0
  71. package/dist/webLoop.js +38 -0
  72. package/dist/webLoop.js.map +1 -0
  73. package/dist/webMediasession.d.ts +3 -0
  74. package/dist/webMediasession.d.ts.map +1 -0
  75. package/dist/webMediasession.js +51 -0
  76. package/dist/webMediasession.js.map +1 -0
  77. package/dist/webMenu.d.ts +3 -0
  78. package/dist/webMenu.d.ts.map +1 -0
  79. package/dist/webMenu.js +31 -0
  80. package/dist/webMenu.js.map +1 -0
  81. package/dist/webNotification.d.ts +3 -0
  82. package/dist/webNotification.d.ts.map +1 -0
  83. package/dist/webNotification.js +85 -0
  84. package/dist/webNotification.js.map +1 -0
  85. package/dist/webPermissions.d.ts +3 -0
  86. package/dist/webPermissions.d.ts.map +1 -0
  87. package/dist/webPermissions.js +37 -0
  88. package/dist/webPermissions.js.map +1 -0
  89. package/dist/webPlatform.d.ts +3 -0
  90. package/dist/webPlatform.d.ts.map +1 -0
  91. package/dist/webPlatform.js +12 -0
  92. package/dist/webPlatform.js.map +1 -0
  93. package/dist/webPower.d.ts +3 -0
  94. package/dist/webPower.d.ts.map +1 -0
  95. package/dist/webPower.js +217 -0
  96. package/dist/webPower.js.map +1 -0
  97. package/dist/webProtocol.d.ts +3 -0
  98. package/dist/webProtocol.d.ts.map +1 -0
  99. package/dist/webProtocol.js +78 -0
  100. package/dist/webProtocol.js.map +1 -0
  101. package/dist/webScreen.d.ts +3 -0
  102. package/dist/webScreen.d.ts.map +1 -0
  103. package/dist/webScreen.js +12 -0
  104. package/dist/webScreen.js.map +1 -0
  105. package/dist/webSensors.d.ts +3 -0
  106. package/dist/webSensors.d.ts.map +1 -0
  107. package/dist/webSensors.js +12 -0
  108. package/dist/webSensors.js.map +1 -0
  109. package/dist/webShare.d.ts +3 -0
  110. package/dist/webShare.d.ts.map +1 -0
  111. package/dist/webShare.js +33 -0
  112. package/dist/webShare.js.map +1 -0
  113. package/dist/webShell.d.ts +3 -0
  114. package/dist/webShell.d.ts.map +1 -0
  115. package/dist/webShell.js +51 -0
  116. package/dist/webShell.js.map +1 -0
  117. package/dist/webStatusbar.d.ts +3 -0
  118. package/dist/webStatusbar.d.ts.map +1 -0
  119. package/dist/webStatusbar.js +52 -0
  120. package/dist/webStatusbar.js.map +1 -0
  121. package/dist/webStorage.d.ts +3 -0
  122. package/dist/webStorage.d.ts.map +1 -0
  123. package/dist/webStorage.js +12 -0
  124. package/dist/webStorage.js.map +1 -0
  125. package/dist/webWebcam.d.ts +3 -0
  126. package/dist/webWebcam.d.ts.map +1 -0
  127. package/dist/webWebcam.js +12 -0
  128. package/dist/webWebcam.js.map +1 -0
  129. package/dist/webWindow.d.ts +3 -0
  130. package/dist/webWindow.d.ts.map +1 -0
  131. package/dist/webWindow.js +135 -0
  132. package/dist/webWindow.js.map +1 -0
  133. package/package.json +76 -0
  134. package/src/enableHostWeb.test.ts +12 -0
  135. package/src/evidence.test.ts +172 -0
  136. package/src/webAccessibility.test.ts +22 -0
  137. package/src/webApp.test.ts +22 -0
  138. package/src/webClipboard.test.ts +22 -0
  139. package/src/webConnectivity.test.ts +22 -0
  140. package/src/webCursor.test.ts +26 -0
  141. package/src/webDevice.test.ts +22 -0
  142. package/src/webDialog.test.ts +22 -0
  143. package/src/webFilesystem.test.ts +22 -0
  144. package/src/webGeolocation.test.ts +22 -0
  145. package/src/webGlyphRasterizer.test.ts +153 -0
  146. package/src/webHaptics.test.ts +22 -0
  147. package/src/webImage.test.ts +22 -0
  148. package/src/webKeyboard.test.ts +22 -0
  149. package/src/webLifecycle.test.ts +22 -0
  150. package/src/webLoop.test.ts +123 -0
  151. package/src/webMediasession.test.ts +22 -0
  152. package/src/webMenu.test.ts +22 -0
  153. package/src/webNotification.test.ts +22 -0
  154. package/src/webPermissions.test.ts +22 -0
  155. package/src/webPlatform.test.ts +22 -0
  156. package/src/webPower.test.ts +22 -0
  157. package/src/webProtocol.test.ts +22 -0
  158. package/src/webScreen.test.ts +22 -0
  159. package/src/webSensors.test.ts +22 -0
  160. package/src/webShare.test.ts +22 -0
  161. package/src/webShell.test.ts +22 -0
  162. package/src/webStatusbar.test.ts +22 -0
  163. package/src/webStorage.test.ts +22 -0
  164. package/src/webWebcam.test.ts +22 -0
  165. package/src/webWindow.test.ts +22 -0
@@ -0,0 +1,51 @@
1
+ import { installShellHostBackend, observeShellHostResult } from '@flighthq/shell/contract';
2
+ export function enableHostWebShell() {
3
+ if (_enabled)
4
+ return;
5
+ _enabled = true;
6
+ const backend = {
7
+ beep() { },
8
+ async moveItemsToTrash() {
9
+ return [];
10
+ },
11
+ async moveToTrash() {
12
+ return false;
13
+ },
14
+ async openExternal(url) {
15
+ if (typeof window === 'undefined' || typeof window.open !== 'function') {
16
+ observeShellHostResult('openExternal', false);
17
+ return false;
18
+ }
19
+ try {
20
+ const result = window.open(url, '_blank', 'noopener') !== null;
21
+ observeShellHostResult('openExternal', result);
22
+ return result;
23
+ }
24
+ catch {
25
+ observeShellHostResult('openExternal', false);
26
+ return false;
27
+ }
28
+ },
29
+ async openPath() {
30
+ return false;
31
+ },
32
+ async openPathResult() {
33
+ return 'unavailable on web';
34
+ },
35
+ async readShortcutLink() {
36
+ return null;
37
+ },
38
+ async showItemInFolder() {
39
+ return false;
40
+ },
41
+ async writeShortcutLink() {
42
+ return false;
43
+ },
44
+ };
45
+ installShellHostBackend(backend);
46
+ }
47
+ export function resetHostWebShellForTest() {
48
+ _enabled = false;
49
+ }
50
+ let _enabled = false;
51
+ //# sourceMappingURL=webShell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webShell.js","sourceRoot":"","sources":["../src/webShell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAG3F,MAAM,UAAU,kBAAkB;IAChC,IAAI,QAAQ;QAAE,OAAO;IACrB,QAAQ,GAAG,IAAI,CAAC;IAChB,MAAM,OAAO,GAAiB;QAC5B,IAAI,KAAI,CAAC;QACT,KAAK,CAAC,gBAAgB;YACpB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,KAAK,CAAC,WAAW;YACf,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,CAAC,YAAY,CAAC,GAAG;YACpB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACvE,sBAAsB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;gBAC9C,OAAO,KAAK,CAAC;YACf,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC,KAAK,IAAI,CAAC;gBAC/D,sBAAsB,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;gBAC/C,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,sBAAsB,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;gBAC9C,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,KAAK,CAAC,QAAQ;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,CAAC,cAAc;YAClB,OAAO,oBAAoB,CAAC;QAC9B,CAAC;QACD,KAAK,CAAC,gBAAgB;YACpB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,CAAC,gBAAgB;YACpB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,CAAC,iBAAiB;YACrB,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;IACF,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC;AAED,IAAI,QAAQ,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function enableHostWebStatusBar(): void;
2
+ export declare function resetHostWebStatusBarForTest(): void;
3
+ //# sourceMappingURL=webStatusbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webStatusbar.d.ts","sourceRoot":"","sources":["../src/webStatusbar.ts"],"names":[],"mappings":"AAOA,wBAAgB,sBAAsB,IAAI,IAAI,CA2C7C;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
@@ -0,0 +1,52 @@
1
+ import { installStatusBarHostBackend, observeStatusBarHostResult, packedRgbaToHexColor, } from '@flighthq/statusbar/contract';
2
+ export function enableHostWebStatusBar() {
3
+ if (_enabled)
4
+ return;
5
+ _enabled = true;
6
+ const backend = {
7
+ getInfo(out) {
8
+ out.color = 0;
9
+ out.height = -1;
10
+ out.overlaysContent = false;
11
+ out.style = 'default';
12
+ out.visible = true;
13
+ return out;
14
+ },
15
+ setBackgroundColor(color) {
16
+ try {
17
+ if (typeof document === 'undefined') {
18
+ observeStatusBarHostResult('setBackgroundColor', false);
19
+ return;
20
+ }
21
+ const head = document.head;
22
+ if (head === null || head === undefined) {
23
+ observeStatusBarHostResult('setBackgroundColor', false);
24
+ return;
25
+ }
26
+ let meta = head.querySelector('meta[name="theme-color"]');
27
+ if (meta === null) {
28
+ meta = document.createElement('meta');
29
+ meta.setAttribute('name', 'theme-color');
30
+ head.appendChild(meta);
31
+ }
32
+ meta.setAttribute('content', packedRgbaToHexColor(color));
33
+ observeStatusBarHostResult('setBackgroundColor', true);
34
+ }
35
+ catch {
36
+ observeStatusBarHostResult('setBackgroundColor', false);
37
+ }
38
+ },
39
+ setOverlaysContent() { },
40
+ setStyle() { },
41
+ setVisible() { },
42
+ subscribe() {
43
+ return () => { };
44
+ },
45
+ };
46
+ installStatusBarHostBackend(backend);
47
+ }
48
+ export function resetHostWebStatusBarForTest() {
49
+ _enabled = false;
50
+ }
51
+ let _enabled = false;
52
+ //# sourceMappingURL=webStatusbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webStatusbar.js","sourceRoot":"","sources":["../src/webStatusbar.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,UAAU,sBAAsB;IACpC,IAAI,QAAQ;QAAE,OAAO;IACrB,QAAQ,GAAG,IAAI,CAAC;IAChB,MAAM,OAAO,GAAqB;QAChC,OAAO,CAAC,GAAkB;YACxB,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAChB,GAAG,CAAC,eAAe,GAAG,KAAK,CAAC;YAC5B,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC;YACtB,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;YACnB,OAAO,GAAG,CAAC;QACb,CAAC;QACD,kBAAkB,CAAC,KAAa;YAC9B,IAAI,CAAC;gBACH,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;oBACpC,0BAA0B,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;oBACxD,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;gBAC3B,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACxC,0BAA0B,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;oBACxD,OAAO;gBACT,CAAC;gBACD,IAAI,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC;gBAC1D,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;oBAClB,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;oBACtC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;oBACzC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;gBACD,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;gBAC1D,0BAA0B,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBACP,0BAA0B,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,kBAAkB,KAAU,CAAC;QAC7B,QAAQ,KAAU,CAAC;QACnB,UAAU,KAAU,CAAC;QACrB,SAAS;YACP,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;QAClB,CAAC;KACF,CAAC;IACF,2BAA2B,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC;AAED,IAAI,QAAQ,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function enableHostWebStorage(): void;
2
+ export declare function resetHostWebStorageForTest(): void;
3
+ //# sourceMappingURL=webStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webStorage.d.ts","sourceRoot":"","sources":["../src/webStorage.ts"],"names":[],"mappings":"AAEA,wBAAgB,oBAAoB,IAAI,IAAI,CAI3C;AAED,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -0,0 +1,12 @@
1
+ import { createWebStorageBackend, installStorageHostBackend } from '@flighthq/storage/contract';
2
+ export function enableHostWebStorage() {
3
+ if (_enabled)
4
+ return;
5
+ _enabled = true;
6
+ installStorageHostBackend(createWebStorageBackend());
7
+ }
8
+ export function resetHostWebStorageForTest() {
9
+ _enabled = false;
10
+ }
11
+ let _enabled = false;
12
+ //# sourceMappingURL=webStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webStorage.js","sourceRoot":"","sources":["../src/webStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEhG,MAAM,UAAU,oBAAoB;IAClC,IAAI,QAAQ;QAAE,OAAO;IACrB,QAAQ,GAAG,IAAI,CAAC;IAChB,yBAAyB,CAAC,uBAAuB,EAAE,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,0BAA0B;IACxC,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC;AAED,IAAI,QAAQ,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function enableHostWebWebcam(): void;
2
+ export declare function resetHostWebWebcamForTest(): void;
3
+ //# sourceMappingURL=webWebcam.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webWebcam.d.ts","sourceRoot":"","sources":["../src/webWebcam.ts"],"names":[],"mappings":"AAEA,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
@@ -0,0 +1,12 @@
1
+ import { createWebWebcamBackend, installWebcamHostBackend } from '@flighthq/webcam/contract';
2
+ export function enableHostWebWebcam() {
3
+ if (_enabled)
4
+ return;
5
+ _enabled = true;
6
+ installWebcamHostBackend(createWebWebcamBackend());
7
+ }
8
+ export function resetHostWebWebcamForTest() {
9
+ _enabled = false;
10
+ }
11
+ let _enabled = false;
12
+ //# sourceMappingURL=webWebcam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webWebcam.js","sourceRoot":"","sources":["../src/webWebcam.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AAE7F,MAAM,UAAU,mBAAmB;IACjC,IAAI,QAAQ;QAAE,OAAO;IACrB,QAAQ,GAAG,IAAI,CAAC;IAChB,wBAAwB,CAAC,sBAAsB,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,QAAQ,GAAG,KAAK,CAAC;AACnB,CAAC;AAED,IAAI,QAAQ,GAAG,KAAK,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function enableHostWebWindow(): void;
2
+ export declare function resetHostWebWindowForTest(): void;
3
+ //# sourceMappingURL=webWindow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webWindow.d.ts","sourceRoot":"","sources":["../src/webWindow.ts"],"names":[],"mappings":"AAGA,wBAAgB,mBAAmB,IAAI,IAAI,CAwH1C;AAED,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
@@ -0,0 +1,135 @@
1
+ import { installWindowHostBackend, observeWindowHostResult } from '@flighthq/application/contract';
2
+ export function enableHostWebWindow() {
3
+ if (_enabled)
4
+ return;
5
+ _enabled = true;
6
+ const backend = {
7
+ center(win) {
8
+ if (typeof window === 'undefined' || typeof window.moveTo !== 'function' || typeof screen === 'undefined')
9
+ return;
10
+ try {
11
+ window.moveTo(Math.round((screen.availWidth - win.width) / 2), Math.round((screen.availHeight - win.height) / 2));
12
+ observeWindowHostResult('center', true);
13
+ }
14
+ catch {
15
+ observeWindowHostResult('center', false);
16
+ }
17
+ },
18
+ close() {
19
+ if (typeof window !== 'undefined' && typeof window.close === 'function') {
20
+ try {
21
+ window.close();
22
+ observeWindowHostResult('close', true);
23
+ }
24
+ catch {
25
+ observeWindowHostResult('close', false);
26
+ }
27
+ }
28
+ },
29
+ flashWindowFrame() { },
30
+ focus() {
31
+ if (typeof window !== 'undefined' && typeof window.focus === 'function') {
32
+ window.focus();
33
+ observeWindowHostResult('focus', true);
34
+ }
35
+ },
36
+ getBounds(win, out) {
37
+ if (typeof window === 'undefined') {
38
+ out.x = win.x;
39
+ out.y = win.y;
40
+ out.width = win.width;
41
+ out.height = win.height;
42
+ observeWindowHostResult('getBounds', true);
43
+ return out;
44
+ }
45
+ out.x = window.screenX ?? win.x;
46
+ out.y = window.screenY ?? win.y;
47
+ out.width = window.innerWidth ?? win.width;
48
+ out.height = window.innerHeight ?? win.height;
49
+ observeWindowHostResult('getBounds', true);
50
+ return out;
51
+ },
52
+ hide() { },
53
+ maximize() { },
54
+ minimize() { },
55
+ open() {
56
+ const result = typeof window !== 'undefined';
57
+ observeWindowHostResult('open', result);
58
+ return result;
59
+ },
60
+ requestAttention() { },
61
+ restore() { },
62
+ setAlwaysOnTop() { },
63
+ setContentProtection() { },
64
+ setFullscreen(_win, fullscreen) {
65
+ if (typeof document === 'undefined')
66
+ return;
67
+ try {
68
+ if (fullscreen)
69
+ void document.documentElement.requestFullscreen?.();
70
+ else
71
+ void document.exitFullscreen?.();
72
+ observeWindowHostResult('setFullscreen', true);
73
+ }
74
+ catch {
75
+ observeWindowHostResult('setFullscreen', false);
76
+ }
77
+ },
78
+ setHasShadow() { },
79
+ setIcon(_win, icon) {
80
+ if (typeof document === 'undefined')
81
+ return;
82
+ let link = document.querySelector('link[rel="icon"]');
83
+ if (link === null) {
84
+ link = document.createElement('link');
85
+ link.rel = 'icon';
86
+ document.head.appendChild(link);
87
+ }
88
+ link.href = icon;
89
+ observeWindowHostResult('setIcon', true);
90
+ },
91
+ setMaximumSize() { },
92
+ setMenuBarVisible() { },
93
+ setMinimumSize() { },
94
+ setOpacity() { },
95
+ setParent() { },
96
+ setPosition(_win, x, y) {
97
+ if (typeof window !== 'undefined' && typeof window.moveTo === 'function') {
98
+ try {
99
+ window.moveTo(x, y);
100
+ observeWindowHostResult('setPosition', true);
101
+ }
102
+ catch {
103
+ observeWindowHostResult('setPosition', false);
104
+ }
105
+ }
106
+ },
107
+ setProgress() { },
108
+ setResizable() { },
109
+ setSize(_win, width, height) {
110
+ if (typeof window !== 'undefined' && typeof window.resizeTo === 'function') {
111
+ try {
112
+ window.resizeTo(width, height);
113
+ observeWindowHostResult('setSize', true);
114
+ }
115
+ catch {
116
+ observeWindowHostResult('setSize', false);
117
+ }
118
+ }
119
+ },
120
+ setSkipTaskbar() { },
121
+ setTitle(_win, title) {
122
+ if (typeof document !== 'undefined') {
123
+ document.title = title;
124
+ observeWindowHostResult('setTitle', true);
125
+ }
126
+ },
127
+ show() { },
128
+ };
129
+ installWindowHostBackend(backend);
130
+ }
131
+ export function resetHostWebWindowForTest() {
132
+ _enabled = false;
133
+ }
134
+ let _enabled = false;
135
+ //# sourceMappingURL=webWindow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webWindow.js","sourceRoot":"","sources":["../src/webWindow.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@flighthq/host-web",
3
+ "version": "0.4.0-edge.1908.751021c",
4
+ "author": "Joshua Granick and other contributors",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/flighthq/flight.git",
9
+ "directory": "packages/host-web"
10
+ },
11
+ "type": "module",
12
+ "main": "dist/index.js",
13
+ "types": "dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "default": "./dist/index.js"
18
+ },
19
+ "./contract": {
20
+ "types": "./dist/contract.d.ts",
21
+ "default": "./dist/contract.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "src/**/*.test.ts",
27
+ "!dist/**/*.test.js",
28
+ "!dist/**/*.test.d.ts",
29
+ "!dist/**/*.test.js.map",
30
+ "!dist/**/*.test.d.ts.map"
31
+ ],
32
+ "scripts": {
33
+ "build": "tsc -b",
34
+ "clean": "tsc -b --clean",
35
+ "test": "vitest run --config vitest.config.ts",
36
+ "test:watch": "vitest --watch --config vitest.config.ts",
37
+ "prepack": "npm run clean && npm run clean:dist && npm run build",
38
+ "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
+ },
40
+ "dependencies": {
41
+ "@flighthq/accessibility": "0.4.0-edge.1908.751021c",
42
+ "@flighthq/app": "0.4.0-edge.1908.751021c",
43
+ "@flighthq/application": "0.4.0-edge.1908.751021c",
44
+ "@flighthq/clipboard": "0.4.0-edge.1908.751021c",
45
+ "@flighthq/connectivity": "0.4.0-edge.1908.751021c",
46
+ "@flighthq/device": "0.4.0-edge.1908.751021c",
47
+ "@flighthq/dialog": "0.4.0-edge.1908.751021c",
48
+ "@flighthq/filesystem": "0.4.0-edge.1908.751021c",
49
+ "@flighthq/geolocation": "0.4.0-edge.1908.751021c",
50
+ "@flighthq/glyphatlas": "0.4.0-edge.1908.751021c",
51
+ "@flighthq/haptics": "0.4.0-edge.1908.751021c",
52
+ "@flighthq/image": "0.4.0-edge.1908.751021c",
53
+ "@flighthq/keyboard": "0.4.0-edge.1908.751021c",
54
+ "@flighthq/lifecycle": "0.4.0-edge.1908.751021c",
55
+ "@flighthq/mediasession": "0.4.0-edge.1908.751021c",
56
+ "@flighthq/menu": "0.4.0-edge.1908.751021c",
57
+ "@flighthq/notification": "0.4.0-edge.1908.751021c",
58
+ "@flighthq/permissions": "0.4.0-edge.1908.751021c",
59
+ "@flighthq/platform": "0.4.0-edge.1908.751021c",
60
+ "@flighthq/power": "0.4.0-edge.1908.751021c",
61
+ "@flighthq/protocol": "0.4.0-edge.1908.751021c",
62
+ "@flighthq/screen": "0.4.0-edge.1908.751021c",
63
+ "@flighthq/sensors": "0.4.0-edge.1908.751021c",
64
+ "@flighthq/share": "0.4.0-edge.1908.751021c",
65
+ "@flighthq/shell": "0.4.0-edge.1908.751021c",
66
+ "@flighthq/statusbar": "0.4.0-edge.1908.751021c",
67
+ "@flighthq/storage": "0.4.0-edge.1908.751021c",
68
+ "@flighthq/types": "0.4.0-edge.1908.751021c",
69
+ "@flighthq/webcam": "0.4.0-edge.1908.751021c"
70
+ },
71
+ "devDependencies": {
72
+ "typescript": "^5.3.0"
73
+ },
74
+ "description": "Web host backend: installs browser-specific implementations of Flight capability seams (Canvas glyph rasterizer, DOM cursor)",
75
+ "sideEffects": false
76
+ }
@@ -0,0 +1,12 @@
1
+ import { enableHostWeb } from './enableHostWeb';
2
+
3
+ describe('enableHostWeb', () => {
4
+ it('does not throw on first call', () => {
5
+ expect(() => enableHostWeb()).not.toThrow();
6
+ });
7
+
8
+ it('is idempotent', () => {
9
+ enableHostWeb();
10
+ expect(() => enableHostWeb()).not.toThrow();
11
+ });
12
+ });
@@ -0,0 +1,172 @@
1
+ import { existsSync, readFileSync, readdirSync } from 'fs';
2
+ import { resolve } from 'path';
3
+ import type { OutputChunk, RollupOutput } from 'rollup';
4
+ import { build } from 'vite';
5
+ import { describe, expect, it } from 'vitest';
6
+ import { gzipSync } from 'zlib';
7
+
8
+ const ROOT = resolve(__dirname, '../../..');
9
+ const EVIDENCE_DIR = resolve(__dirname, '../evidence');
10
+
11
+ interface CapabilityEntry {
12
+ readonly fixture: string;
13
+ readonly modulePattern: string;
14
+ }
15
+
16
+ const CAPABILITIES: readonly CapabilityEntry[] = [
17
+ { fixture: 'cursor', modulePattern: 'webCursor' },
18
+ { fixture: 'glyph', modulePattern: 'webGlyphRasterizer' },
19
+ { fixture: 'loop', modulePattern: 'webLoop' },
20
+ ];
21
+
22
+ interface FixtureResult {
23
+ modules: string[];
24
+ rawBytes: number;
25
+ gzipBytes: number;
26
+ code: string;
27
+ }
28
+
29
+ function resolveWorkspaceAliases(): Record<string, string> {
30
+ const packagesDir = resolve(ROOT, 'packages');
31
+ const alias: Record<string, string> = {};
32
+ const entries = readdirSync(packagesDir, { withFileTypes: true });
33
+ for (const entry of entries) {
34
+ if (!entry.isDirectory()) continue;
35
+ const pkgJsonPath = resolve(packagesDir, entry.name, 'package.json');
36
+ if (!existsSync(pkgJsonPath)) continue;
37
+ const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));
38
+ if (typeof pkgJson.name === 'string') {
39
+ alias[pkgJson.name] = resolve(packagesDir, entry.name, 'src');
40
+ }
41
+ }
42
+ return alias;
43
+ }
44
+
45
+ async function buildFixture(name: string): Promise<FixtureResult> {
46
+ const entry = resolve(EVIDENCE_DIR, `${name}.ts`);
47
+ const alias = resolveWorkspaceAliases();
48
+
49
+ const result = (await build({
50
+ configFile: false,
51
+ root: EVIDENCE_DIR,
52
+ logLevel: 'silent',
53
+ resolve: { alias },
54
+ build: {
55
+ write: false,
56
+ minify: false,
57
+ target: 'esnext',
58
+ sourcemap: false,
59
+ rollupOptions: {
60
+ input: entry,
61
+ output: { format: 'es' },
62
+ },
63
+ },
64
+ })) as RollupOutput;
65
+
66
+ const chunks = result.output.filter((o): o is OutputChunk => o.type === 'chunk');
67
+ const mainChunk = chunks.find((c) => c.isEntry) ?? chunks[0];
68
+ const allModules = new Set<string>();
69
+ for (const chunk of chunks) {
70
+ for (const id of Object.keys(chunk.modules)) {
71
+ allModules.add(id);
72
+ }
73
+ }
74
+
75
+ const code = mainChunk.code;
76
+ const rawBytes = Buffer.byteLength(code, 'utf-8');
77
+ const gzipBytes = gzipSync(code).byteLength;
78
+
79
+ return {
80
+ code,
81
+ gzipBytes,
82
+ modules: [...allModules].map((id) => id.replace(ROOT + '/', '')),
83
+ rawBytes,
84
+ };
85
+ }
86
+
87
+ function sourceModules(modules: readonly string[]): string[] {
88
+ return modules.filter((m) => !m.includes('/evidence/'));
89
+ }
90
+
91
+ function hasHostWebModule(modules: readonly string[]): boolean {
92
+ return sourceModules(modules).some((m) => m.includes('packages/host-web/'));
93
+ }
94
+
95
+ function hasCapabilityModule(modules: readonly string[], pattern: string): boolean {
96
+ return sourceModules(modules).some((m) => m.includes(pattern));
97
+ }
98
+
99
+ describe('evidence: tree-shaking isolation', () => {
100
+ const results = new Map<string, FixtureResult>();
101
+
102
+ async function getFixture(name: string): Promise<FixtureResult> {
103
+ let result = results.get(name);
104
+ if (result === undefined) {
105
+ result = await buildFixture(name);
106
+ results.set(name, result);
107
+ }
108
+ return result;
109
+ }
110
+
111
+ it('control fixture contains zero host-web modules', async () => {
112
+ const { modules } = await getFixture('control');
113
+ expect(hasHostWebModule(modules)).toBe(false);
114
+ });
115
+
116
+ it('capability fixture contains zero host-web modules', async () => {
117
+ const { modules } = await getFixture('capability');
118
+ expect(sourceModules(modules).length).toBeGreaterThan(0);
119
+ expect(hasHostWebModule(modules)).toBe(false);
120
+ });
121
+
122
+ for (const cap of CAPABILITIES) {
123
+ for (const other of CAPABILITIES) {
124
+ if (other === cap) continue;
125
+ it(`${cap.fixture} fixture excludes ${other.fixture} modules`, async () => {
126
+ const { modules } = await getFixture(cap.fixture);
127
+ expect(sourceModules(modules).length).toBeGreaterThan(0);
128
+ expect(hasHostWebModule(modules)).toBe(true);
129
+ expect(hasCapabilityModule(modules, other.modulePattern)).toBe(false);
130
+ });
131
+ }
132
+ }
133
+
134
+ it('combined module set is within the union of individual capabilities', async () => {
135
+ const individualResults = await Promise.all(CAPABILITIES.map((cap) => getFixture(cap.fixture)));
136
+ const combinedResult = await getFixture('combined');
137
+ const union = new Set(individualResults.flatMap((r) => sourceModules(r.modules)));
138
+ const outsideUnion = sourceModules(combinedResult.modules).filter((m) => !union.has(m));
139
+ expect(outsideUnion).toEqual([]);
140
+ });
141
+
142
+ it('normalized subadditivity: S(combined) + (N-1)*S(control) <= sum(S(individual))', async () => {
143
+ const control = await getFixture('control');
144
+ const combined = await getFixture('combined');
145
+ const individualResults = await Promise.all(CAPABILITIES.map((cap) => getFixture(cap.fixture)));
146
+ const n = CAPABILITIES.length;
147
+
148
+ for (const [name, fixture] of CAPABILITIES.map((cap, i) => [cap.fixture, individualResults[i]] as const)) {
149
+ const rawDelta = fixture.rawBytes - control.rawBytes;
150
+ const gzipDelta = fixture.gzipBytes - control.gzipBytes;
151
+ console.log(
152
+ `${name}: raw=${fixture.rawBytes} (${rawDelta >= 0 ? '+' : ''}${rawDelta}), ` +
153
+ `gzip=${fixture.gzipBytes} (${gzipDelta >= 0 ? '+' : ''}${gzipDelta})`,
154
+ );
155
+ }
156
+ console.log(`combined: raw=${combined.rawBytes}, gzip=${combined.gzipBytes}`);
157
+ console.log(`control: raw=${control.rawBytes}, gzip=${control.gzipBytes}`);
158
+
159
+ const sumRaw = individualResults.reduce((s, r) => s + r.rawBytes, 0);
160
+ const sumGzip = individualResults.reduce((s, r) => s + r.gzipBytes, 0);
161
+
162
+ for (const cap of CAPABILITIES) {
163
+ const individual = individualResults[CAPABILITIES.indexOf(cap)];
164
+ expect(individual.rawBytes).toBeGreaterThan(control.rawBytes);
165
+ }
166
+
167
+ expect(combined.rawBytes).toBeGreaterThan(Math.max(...individualResults.map((r) => r.rawBytes)));
168
+
169
+ expect(combined.rawBytes + (n - 1) * control.rawBytes).toBeLessThanOrEqual(sumRaw);
170
+ expect(combined.gzipBytes + (n - 1) * control.gzipBytes).toBeLessThanOrEqual(sumGzip);
171
+ });
172
+ });
@@ -0,0 +1,22 @@
1
+ import { enableHostWebAccessibility, resetHostWebAccessibilityForTest } from './webAccessibility';
2
+
3
+ describe('enableHostWebAccessibility', () => {
4
+ afterEach(() => resetHostWebAccessibilityForTest());
5
+
6
+ it('does not throw on first call', () => {
7
+ expect(() => enableHostWebAccessibility()).not.toThrow();
8
+ });
9
+
10
+ it('is idempotent', () => {
11
+ enableHostWebAccessibility();
12
+ expect(() => enableHostWebAccessibility()).not.toThrow();
13
+ });
14
+ });
15
+
16
+ describe('resetHostWebAccessibilityForTest', () => {
17
+ it('allows re-enabling after reset', () => {
18
+ enableHostWebAccessibility();
19
+ resetHostWebAccessibilityForTest();
20
+ expect(() => enableHostWebAccessibility()).not.toThrow();
21
+ });
22
+ });
@@ -0,0 +1,22 @@
1
+ import { enableHostWebApp, resetHostWebAppForTest } from './webApp';
2
+
3
+ describe('enableHostWebApp', () => {
4
+ afterEach(() => resetHostWebAppForTest());
5
+
6
+ it('does not throw on first call', () => {
7
+ expect(() => enableHostWebApp()).not.toThrow();
8
+ });
9
+
10
+ it('is idempotent', () => {
11
+ enableHostWebApp();
12
+ expect(() => enableHostWebApp()).not.toThrow();
13
+ });
14
+ });
15
+
16
+ describe('resetHostWebAppForTest', () => {
17
+ it('allows re-enabling after reset', () => {
18
+ enableHostWebApp();
19
+ resetHostWebAppForTest();
20
+ expect(() => enableHostWebApp()).not.toThrow();
21
+ });
22
+ });
@@ -0,0 +1,22 @@
1
+ import { enableHostWebClipboard, resetHostWebClipboardForTest } from './webClipboard';
2
+
3
+ describe('enableHostWebClipboard', () => {
4
+ afterEach(() => resetHostWebClipboardForTest());
5
+
6
+ it('does not throw on first call', () => {
7
+ expect(() => enableHostWebClipboard()).not.toThrow();
8
+ });
9
+
10
+ it('is idempotent', () => {
11
+ enableHostWebClipboard();
12
+ expect(() => enableHostWebClipboard()).not.toThrow();
13
+ });
14
+ });
15
+
16
+ describe('resetHostWebClipboardForTest', () => {
17
+ it('allows re-enabling after reset', () => {
18
+ enableHostWebClipboard();
19
+ resetHostWebClipboardForTest();
20
+ expect(() => enableHostWebClipboard()).not.toThrow();
21
+ });
22
+ });