@flighthq/host-electron 0.5.1-next.1295.2b6bfa3 → 0.5.1-next.1345.0995dc5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/host-electron`. The
13
13
  This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
14
14
 
15
15
  - [Flight project](https://github.com/flighthq/flight)
16
- - [Source for @flighthq/host-electron@0.5.1-next.1295.2b6bfa3](https://github.com/flighthq/flight/tree/2b6bfa33110e26cbdd959441a6c36a4c78109ab8/packages/host-electron)
17
- - [License](https://github.com/flighthq/flight/blob/2b6bfa33110e26cbdd959441a6c36a4c78109ab8/LICENSE.md)
16
+ - [Source for @flighthq/host-electron@0.5.1-next.1345.0995dc5](https://github.com/flighthq/flight/tree/0995dc5f840e6b57c3e85ecd2123aa798cf60b29/packages/host-electron)
17
+ - [License](https://github.com/flighthq/flight/blob/0995dc5f840e6b57c3e85ecd2123aa798cf60b29/LICENSE.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/host-electron",
3
- "version": "0.5.1-next.1295.2b6bfa3",
3
+ "version": "0.5.1-next.1345.0995dc5",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,25 +38,25 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/entity": "0.5.1-next.1295.2b6bfa3",
42
- "@flighthq/app": "0.5.1-next.1295.2b6bfa3",
43
- "@flighthq/application": "0.5.1-next.1295.2b6bfa3",
44
- "@flighthq/clipboard": "0.5.1-next.1295.2b6bfa3",
45
- "@flighthq/dialog": "0.5.1-next.1295.2b6bfa3",
46
- "@flighthq/ipc": "0.5.1-next.1295.2b6bfa3",
47
- "@flighthq/menu": "0.5.1-next.1295.2b6bfa3",
48
- "@flighthq/notification": "0.5.1-next.1295.2b6bfa3",
49
- "@flighthq/platform": "0.5.1-next.1295.2b6bfa3",
50
- "@flighthq/power": "0.5.1-next.1295.2b6bfa3",
51
- "@flighthq/protocol": "0.5.1-next.1295.2b6bfa3",
52
- "@flighthq/shell": "0.5.1-next.1295.2b6bfa3",
53
- "@flighthq/screen": "0.5.1-next.1295.2b6bfa3",
54
- "@flighthq/shortcut": "0.5.1-next.1295.2b6bfa3",
55
- "@flighthq/signals": "0.5.1-next.1295.2b6bfa3",
56
- "@flighthq/storage": "0.5.1-next.1295.2b6bfa3",
57
- "@flighthq/tray": "0.5.1-next.1295.2b6bfa3",
58
- "@flighthq/types": "0.5.1-next.1295.2b6bfa3",
59
- "@flighthq/updater": "0.5.1-next.1295.2b6bfa3"
41
+ "@flighthq/entity": "0.5.1-next.1345.0995dc5",
42
+ "@flighthq/app": "0.5.1-next.1345.0995dc5",
43
+ "@flighthq/application": "0.5.1-next.1345.0995dc5",
44
+ "@flighthq/clipboard": "0.5.1-next.1345.0995dc5",
45
+ "@flighthq/dialog": "0.5.1-next.1345.0995dc5",
46
+ "@flighthq/ipc": "0.5.1-next.1345.0995dc5",
47
+ "@flighthq/menu": "0.5.1-next.1345.0995dc5",
48
+ "@flighthq/notification": "0.5.1-next.1345.0995dc5",
49
+ "@flighthq/platform": "0.5.1-next.1345.0995dc5",
50
+ "@flighthq/power": "0.5.1-next.1345.0995dc5",
51
+ "@flighthq/protocol": "0.5.1-next.1345.0995dc5",
52
+ "@flighthq/shell": "0.5.1-next.1345.0995dc5",
53
+ "@flighthq/screen": "0.5.1-next.1345.0995dc5",
54
+ "@flighthq/shortcut": "0.5.1-next.1345.0995dc5",
55
+ "@flighthq/signals": "0.5.1-next.1345.0995dc5",
56
+ "@flighthq/storage": "0.5.1-next.1345.0995dc5",
57
+ "@flighthq/tray": "0.5.1-next.1345.0995dc5",
58
+ "@flighthq/types": "0.5.1-next.1345.0995dc5",
59
+ "@flighthq/updater": "0.5.1-next.1345.0995dc5"
60
60
  },
61
61
  "devDependencies": {
62
62
  "typescript": "^5.3.0"
@@ -112,8 +112,7 @@ describe('electronHostApp', () => {
112
112
  it('publishes common application identity, control, and event slots on every profile', async () => {
113
113
  const fake = fakeElectron();
114
114
  const app = electronHostApp(fake.electron, 'linux');
115
- expect(EntityRuntimeKey in app).toBe(true);
116
- expect(Object.keys(app).sort()).toEqual([
115
+ const common = [
117
116
  'allWindowsClosed',
118
117
  'badge',
119
118
  'focus',
@@ -128,7 +127,14 @@ describe('electronHostApp', () => {
128
127
  'secondInstance',
129
128
  'singleInstance',
130
129
  'version',
131
- ]);
130
+ ];
131
+ const profileOnly = [
132
+ ...Object.keys(electronHostApp(fakeElectron().electron, 'macos')),
133
+ ...Object.keys(electronHostApp(fakeElectron().electron, 'windows')),
134
+ ].filter((slot) => !common.includes(slot));
135
+ expect(EntityRuntimeKey in app).toBe(true);
136
+ expect(Object.keys(app)).toEqual(expect.arrayContaining(common));
137
+ expect(Object.keys(app).filter((slot) => profileOnly.includes(slot))).toEqual([]);
132
138
  expect(app.name.getName()).toBe('Flight');
133
139
  expect(app.version.getVersion()).toBe('1.2.3');
134
140
  expect(app.locale.getPreferredSystemLanguages()).toEqual(['en-US', 'fr']);
@@ -100,16 +100,9 @@ describe('electron power slot coverage', () => {
100
100
  });
101
101
 
102
102
  it('drops only the thermal slot when the platform cannot report the level', () => {
103
- const slots = electronHostPower(fakeElectron({ thermal: null }).electron);
104
- expect(Object.keys(slots).sort()).toEqual([
105
- 'batteryHealth',
106
- 'change',
107
- 'idle',
108
- 'keepAwake',
109
- 'sessionLock',
110
- 'status',
111
- 'suspension',
112
- ]);
103
+ const withThermal = Object.keys(electronHostPower(fakeElectron({}).electron)).sort();
104
+ const withoutThermal = Object.keys(electronHostPower(fakeElectron({ thermal: null }).electron)).sort();
105
+ expect(withoutThermal).toEqual(withThermal.filter((slot) => slot !== 'thermal'));
113
106
  });
114
107
 
115
108
  it('declares a teardown obligation on keepAwake alone', () => {
@@ -1,5 +1,6 @@
1
1
  import { getAppName } from '@flighthq/app/contract';
2
2
  import { readClipboardText } from '@flighthq/clipboard/contract';
3
+ import { createHost } from '@flighthq/entity/contract';
3
4
  import { EntityRuntimeKey } from '@flighthq/types/contract';
4
5
  import type { ElectronApi, Entity } from '@flighthq/types/contract';
5
6
 
@@ -180,10 +181,9 @@ function fakeElectron(): ElectronApi {
180
181
  }
181
182
 
182
183
  describe('electronHost', () => {
183
- it('exports exactly the canonical full, 26 group, and supported leaf constructors from both lanes', () => {
184
+ it('exports exactly the canonical full, group, and supported leaf constructors from both lanes', () => {
184
185
  const expected = [...new Set(['electronHost', ...GROUPS.map((entry) => entry[1]), ...LEAVES])].sort();
185
186
  const expectedSurface = [...expected, ...AUXILIARY_EXPORTS].sort();
186
- expect(expected).toHaveLength(116);
187
187
  for (const api of [publicApi, contractApi]) {
188
188
  expect(Object.keys(api).sort()).toEqual(expectedSurface);
189
189
  const names = Object.keys(api)
@@ -205,10 +205,17 @@ describe('electronHost', () => {
205
205
  expectTypeOf<ElectronLeafProvidersAreEntities>().toEqualTypeOf<true>();
206
206
  });
207
207
 
208
- it('constructs all 26 Host groups through explicit canonical boundaries', () => {
208
+ it('constructs every Host group through explicit canonical boundaries', () => {
209
209
  const host = electronHost(fakeElectron(), { platform: 'linux' }) as unknown as Record<string, unknown>;
210
- expect(GROUPS).toHaveLength(26);
211
- expect(Object.keys(host).sort()).toEqual(GROUPS.map((entry) => entry[0]).sort());
210
+ const hostGroups = Object.keys(createHost())
211
+ .filter((key) => key !== String(EntityRuntimeKey))
212
+ .sort();
213
+ expect(GROUPS.map((entry) => entry[0]).sort()).toEqual(hostGroups);
214
+ expect(
215
+ Object.keys(host)
216
+ .filter((key) => key !== String(EntityRuntimeKey))
217
+ .sort(),
218
+ ).toEqual(hostGroups);
212
219
  for (const [path] of GROUPS) expect(host[path], path).not.toBeUndefined();
213
220
  });
214
221
 
@@ -1,3 +1,4 @@
1
+ import { createScreenInfo } from '@flighthq/screen/contract';
1
2
  import type { ScreenInfo, ElectronApi, ElectronDisplay } from '@flighthq/types/contract';
2
3
  import { EntityRuntimeKey } from '@flighthq/types/contract';
3
4
 
@@ -71,7 +72,15 @@ describe('electronHostScreen', () => {
71
72
  scaleFactor: 2,
72
73
  isPrimary: true,
73
74
  });
74
- expect(Object.keys(out).filter((key) => key !== String(EntityRuntimeKey))).toHaveLength(25);
75
+ expect(
76
+ Object.keys(out)
77
+ .filter((key) => key !== String(EntityRuntimeKey))
78
+ .sort(),
79
+ ).toEqual(
80
+ Object.keys(createScreenInfo())
81
+ .filter((key) => key !== String(EntityRuntimeKey))
82
+ .sort(),
83
+ );
75
84
  });
76
85
 
77
86
  it('enumerates all screens marking the primary', () => {
@@ -151,10 +151,10 @@ function trayLeaf(factory: () => object): () => void {
151
151
  }
152
152
 
153
153
  describe('electronHostTray', () => {
154
- it('exposes only the slots supported by the injected OS profile', () => {
154
+ it('exposes the slots supported by the injected OS profile and none exclusive to another', () => {
155
155
  const { electron } = fakeElectron();
156
- expect(Object.keys(electronHostTray(electron, 'linux')).sort()).toEqual(
157
- [
156
+ const supported = {
157
+ linux: [
158
158
  'bounds',
159
159
  'image',
160
160
  'interactionEvents',
@@ -163,10 +163,8 @@ describe('electronHostTray', () => {
163
163
  'menuSelectionEvents',
164
164
  'popupMenu',
165
165
  'tooltip',
166
- ].sort(),
167
- );
168
- expect(Object.keys(electronHostTray(electron, 'macos')).sort()).toEqual(
169
- [
166
+ ],
167
+ macos: [
170
168
  'bounds',
171
169
  'doubleClickPolicy',
172
170
  'dropEvents',
@@ -180,10 +178,8 @@ describe('electronHostTray', () => {
180
178
  'templateImage',
181
179
  'title',
182
180
  'tooltip',
183
- ].sort(),
184
- );
185
- expect(Object.keys(electronHostTray(electron, 'windows')).sort()).toEqual(
186
- [
181
+ ],
182
+ windows: [
187
183
  'balloon',
188
184
  'balloonEvents',
189
185
  'bounds',
@@ -194,8 +190,20 @@ describe('electronHostTray', () => {
194
190
  'menuSelectionEvents',
195
191
  'popupMenu',
196
192
  'tooltip',
197
- ].sort(),
198
- );
193
+ ],
194
+ } as const;
195
+ for (const profile of ['linux', 'macos', 'windows'] as const) {
196
+ const slots = Object.keys(electronHostTray(electron, profile));
197
+ const exclusiveElsewhere: readonly string[] = Object.entries(supported)
198
+ .filter(([other]) => other !== profile)
199
+ .flatMap(([, others]) => others)
200
+ .filter((slot) => !(supported[profile] as readonly string[]).includes(slot));
201
+ expect(slots, profile).toEqual(expect.arrayContaining([...supported[profile]]));
202
+ expect(
203
+ slots.filter((slot) => exclusiveElsewhere.includes(slot)),
204
+ profile,
205
+ ).toEqual([]);
206
+ }
199
207
  });
200
208
 
201
209
  it('constructs the native resource before publishing the Entity', async () => {
@@ -145,44 +145,42 @@ function fakeElectron(): { electron: ElectronApi; created: FakeBrowserWindow[] }
145
145
  beforeEach(() => resetElectronHostWindowForTest());
146
146
 
147
147
  describe('electronHostWindow', () => {
148
- it('adapter-roster axis: publishes all 28 P1 operations without false omissions', () => {
148
+ it('adapter-roster axis: publishes every P1 operation without false omissions', () => {
149
149
  const { electron } = fakeElectron();
150
150
  const backend = electronHostWindow(electron);
151
151
 
152
- expect(
153
- Object.keys(backend)
154
- .filter((operation) => operation !== 'attach')
155
- .sort(),
156
- ).toEqual([
157
- 'center',
158
- 'close',
159
- 'flashWindowFrame',
160
- 'focus',
161
- 'getBounds',
162
- 'hide',
163
- 'maximize',
164
- 'minimize',
165
- 'open',
166
- 'requestAttention',
167
- 'restore',
168
- 'setAlwaysOnTop',
169
- 'setContentProtection',
170
- 'setFullscreen',
171
- 'setHasShadow',
172
- 'setIcon',
173
- 'setMaximumSize',
174
- 'setMenuBarVisible',
175
- 'setMinimumSize',
176
- 'setOpacity',
177
- 'setParent',
178
- 'setPosition',
179
- 'setProgress',
180
- 'setResizable',
181
- 'setSize',
182
- 'setSkipTaskbar',
183
- 'setTitle',
184
- 'show',
185
- ]);
152
+ expect(Object.keys(backend)).toEqual(
153
+ expect.arrayContaining([
154
+ 'center',
155
+ 'close',
156
+ 'flashWindowFrame',
157
+ 'focus',
158
+ 'getBounds',
159
+ 'hide',
160
+ 'maximize',
161
+ 'minimize',
162
+ 'open',
163
+ 'requestAttention',
164
+ 'restore',
165
+ 'setAlwaysOnTop',
166
+ 'setContentProtection',
167
+ 'setFullscreen',
168
+ 'setHasShadow',
169
+ 'setIcon',
170
+ 'setMaximumSize',
171
+ 'setMenuBarVisible',
172
+ 'setMinimumSize',
173
+ 'setOpacity',
174
+ 'setParent',
175
+ 'setPosition',
176
+ 'setProgress',
177
+ 'setResizable',
178
+ 'setSize',
179
+ 'setSkipTaskbar',
180
+ 'setTitle',
181
+ 'show',
182
+ ]),
183
+ );
186
184
  });
187
185
 
188
186
  it('open creates a BrowserWindow and forwards commands to it', () => {