@flighthq/lifecycle 0.5.0-next.1944.cd6b6e7 → 0.5.1-edge.638.d4dbd4e

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/lifecycle`. The `@fl
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/lifecycle@0.5.0-next.1944.cd6b6e7](https://github.com/flighthq/flight/tree/cd6b6e71eb472b3a4249830a7743333f019fa7b7/packages/lifecycle)
17
- - [License](https://github.com/flighthq/flight/blob/cd6b6e71eb472b3a4249830a7743333f019fa7b7/LICENSE.md)
16
+ - [Source for @flighthq/lifecycle@0.5.1-edge.638.d4dbd4e](https://github.com/flighthq/flight/tree/d4dbd4e347dc8be10b180c85a766ab50333dcb51/packages/lifecycle)
17
+ - [License](https://github.com/flighthq/flight/blob/d4dbd4e347dc8be10b180c85a766ab50333dcb51/LICENSE.md)
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { explainLifecycleBackend, attachAppLifecycle, createAppLifecycle, detachAppLifecycle, disposeAppLifecycle, getAppLaunchKind, getAppLifecycleState, isAppActive, isAppBackground, isAppInactive, requestAppBack, } from './contract';
1
+ export { attachAppLifecycle, createAppLifecycle, detachAppLifecycle, disposeAppLifecycle, getAppLaunchKind, getAppLifecycleState, isAppActive, isAppBackground, isAppInactive, requestAppBack, } from './contract';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { explainLifecycleBackend, attachAppLifecycle, createAppLifecycle, detachAppLifecycle, disposeAppLifecycle, getAppLaunchKind, getAppLifecycleState, isAppActive, isAppBackground, isAppInactive, requestAppBack, } from './contract';
1
+ export { attachAppLifecycle, createAppLifecycle, detachAppLifecycle, disposeAppLifecycle, getAppLaunchKind, getAppLifecycleState, isAppActive, isAppBackground, isAppInactive, requestAppBack, } from './contract';
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,eAAe,EACf,aAAa,EACb,cAAc,GACf,MAAM,YAAY,CAAC"}
@@ -1,20 +1,16 @@
1
- import type { BackendExplanation } from '@flighthq/types/contract';
2
- import type { AppLaunchKind, AppLifecycle, AppLifecycleState, LifecycleBackend } from '@flighthq/types/contract';
3
- export declare function attachAppLifecycle(app: AppLifecycle): void;
1
+ import type { BackendOperationExplanation, LifecycleOperation } from '@flighthq/types/contract';
2
+ import type { AppLaunchKind, HasSystemLifecycle, AppLifecycle, AppLifecycleState, LifecycleBackend } from '@flighthq/types/contract';
3
+ export declare function attachAppLifecycle(host: HasSystemLifecycle, app: AppLifecycle): void;
4
4
  export declare function createAppLifecycle(): AppLifecycle;
5
5
  export declare function createWebLifecycleBackend(): LifecycleBackend;
6
6
  export declare function detachAppLifecycle(app: AppLifecycle): void;
7
7
  export declare function disposeAppLifecycle(app: AppLifecycle): void;
8
- export declare function explainLifecycleBackend(): BackendExplanation;
9
- export declare function getAppLaunchKind(): AppLaunchKind;
10
- export declare function getAppLifecycleState(): AppLifecycleState;
11
- export declare function getLifecycleBackend(): LifecycleBackend;
12
- export declare function installLifecycleHostBackend(backend: LifecycleBackend): void;
13
- export declare function isAppActive(): boolean;
14
- export declare function isAppBackground(): boolean;
15
- export declare function isAppInactive(): boolean;
16
- export declare function observeLifecycleHostResult(operation: string, succeeded: boolean): void;
8
+ export declare function explainLifecycleOperation(host: HasSystemLifecycle, operation: LifecycleOperation): BackendOperationExplanation;
9
+ export declare function getAppLaunchKind(host: HasSystemLifecycle): AppLaunchKind;
10
+ export declare function getAppLifecycleState(host: HasSystemLifecycle): AppLifecycleState;
11
+ export declare function hasLifecycleOperation(host: HasSystemLifecycle, operation: LifecycleOperation): boolean;
12
+ export declare function isAppActive(host: HasSystemLifecycle): boolean;
13
+ export declare function isAppBackground(host: HasSystemLifecycle): boolean;
14
+ export declare function isAppInactive(host: HasSystemLifecycle): boolean;
17
15
  export declare function requestAppBack(app: AppLifecycle): boolean;
18
- export declare function resetLifecycleBackendForTest(): void;
19
- export declare function setLifecycleBackend(backend: LifecycleBackend | null): void;
20
16
  //# sourceMappingURL=lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,iBAAiB,EAEjB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAYlC,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAqC1D;AAGD,wBAAgB,kBAAkB,IAAI,YAAY,CAUjD;AAmBD,wBAAgB,yBAAyB,IAAI,gBAAgB,CA4E5D;AAGD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAM1D;AAID,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAG3D;AAED,wBAAgB,uBAAuB,IAAI,kBAAkB,CAa5D;AAMD,wBAAgB,gBAAgB,IAAI,aAAa,CAGhD;AAGD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAExD;AAED,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAM3E;AAGD,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAGD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAID,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAKtF;AAOD,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAGzD;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAKnD;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAE1E"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAChG,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EAEjB,gBAAgB,EACjB,MAAM,0BAA0B,CAAC;AAYlC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI,CAqCpF;AAGD,wBAAgB,kBAAkB,IAAI,YAAY,CAUjD;AAmBD,wBAAgB,yBAAyB,IAAI,gBAAgB,CA4E5D;AAGD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAM1D;AAID,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAG3D;AAQD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,kBAAkB,GAC5B,2BAA2B,CAG7B;AAMD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,aAAa,CAGxE;AAGD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,CAEhF;AAGD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,kBAAkB,EAAE,SAAS,EAAE,kBAAkB,GAAG,OAAO,CAEtG;AAGD,wBAAgB,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAE7D;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAEjE;AAID,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAE/D;AAOD,wBAAgB,cAAc,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAGzD"}
package/dist/lifecycle.js CHANGED
@@ -9,9 +9,9 @@ import { createSignal, emitSignal } from '@flighthq/signals/contract';
9
9
  // whether the derived state changed. onResume/onPause are deduped edges: 'active'→non-'active'
10
10
  // fires onPause (including the interruption edge 'active'→'inactive'); non-'active'→'active' fires
11
11
  // onResume. The 'inactive'→'background' and reverse transitions do not fire onPause/onResume again.
12
- export function attachAppLifecycle(app) {
12
+ export function attachAppLifecycle(host, app) {
13
13
  detachAppLifecycle(app);
14
- const backend = getLifecycleBackend();
14
+ const backend = host.system.lifecycle;
15
15
  let previous = backend.getState();
16
16
  const unsubscribeState = backend.subscribe(() => {
17
17
  const state = backend.getState();
@@ -173,61 +173,44 @@ export function disposeAppLifecycle(app) {
173
173
  detachAppLifecycle(app);
174
174
  _savedState.delete(app);
175
175
  }
176
- export function explainLifecycleBackend() {
177
- if (_custom !== null) {
178
- return { conflict: _hostConflict, layer: 'custom', operation: null, viability: 'unobserved' };
179
- }
180
- if (_host !== null) {
181
- return {
182
- conflict: _hostConflict,
183
- layer: 'host',
184
- operation: _hostObservation !== null ? _hostObservation.operation : null,
185
- viability: _hostObservation !== null ? _hostObservation.viability : 'unobserved',
186
- };
187
- }
188
- return { conflict: false, layer: 'host-not-enabled', operation: null, viability: 'unobserved' };
176
+ // Which layer implements `operation`, and whether anything real does — the per-operation answer
177
+ // `explainLifecycleBackend` cannot give: that one reports a backend is installed, this one reports whether
178
+ // THIS operation on it is a genuine implementation or the sentinel standing in.
179
+ //
180
+ // ★ The sentinel is deliberately not consulted. It answers every operation, so counting it would make
181
+ // this report `true` for everything and say nothing at all.
182
+ export function explainLifecycleOperation(host, operation) {
183
+ const implemented = typeof host.system.lifecycle[operation] === 'function';
184
+ return { implemented, layer: implemented ? 'host' : 'sentinel', operation };
189
185
  }
190
186
  // Returns the kind of launch — 'cold' (fresh process) or 'warm' (resumed from background). The web
191
187
  // backend approximates this via PerformanceNavigationTiming.type ('back_forward' → 'warm', all
192
188
  // others → 'cold'). Returns 'warm' as a safe fallback when the backend does not implement
193
189
  // getLaunchKind (legacy or minimal backends that pre-date the optional method).
194
- export function getAppLaunchKind() {
195
- const backend = getLifecycleBackend();
190
+ export function getAppLaunchKind(host) {
191
+ const backend = host.system.lifecycle;
196
192
  return backend.getLaunchKind !== undefined ? backend.getLaunchKind() : 'warm';
197
193
  }
198
194
  // Returns the current application lifecycle state from the active backend.
199
- export function getAppLifecycleState() {
200
- return getLifecycleBackend().getState();
195
+ export function getAppLifecycleState(host) {
196
+ return host.system.lifecycle.getState();
201
197
  }
202
- export function getLifecycleBackend() {
203
- return _custom ?? _host ?? _sentinel;
204
- }
205
- export function installLifecycleHostBackend(backend) {
206
- if (_host !== null) {
207
- if (_host !== backend)
208
- _hostConflict = true;
209
- return;
210
- }
211
- _host = backend;
198
+ // Whether a real backend implements `operation`, as opposed to the sentinel answering for it.
199
+ export function hasLifecycleOperation(host, operation) {
200
+ return explainLifecycleOperation(host, operation).implemented;
212
201
  }
213
202
  // Returns true when the application is in the 'active' state (visible and focused).
214
- export function isAppActive() {
215
- return getLifecycleBackend().getState() === 'active';
203
+ export function isAppActive(host) {
204
+ return host.system.lifecycle.getState() === 'active';
216
205
  }
217
206
  // Returns true when the application is in the 'background' state (hidden/suspended).
218
- export function isAppBackground() {
219
- return getLifecycleBackend().getState() === 'background';
207
+ export function isAppBackground(host) {
208
+ return host.system.lifecycle.getState() === 'background';
220
209
  }
221
210
  // Returns true when the application is in the 'inactive' state (visible but not focused —
222
211
  // e.g. app switcher, control-center overlay, incoming call).
223
- export function isAppInactive() {
224
- return getLifecycleBackend().getState() === 'inactive';
225
- }
226
- export function observeLifecycleHostResult(operation, succeeded) {
227
- _hostObservation = {
228
- operation,
229
- viability: succeeded ? 'available' : 'runtime-api-unavailable',
230
- };
212
+ export function isAppInactive(host) {
213
+ return host.system.lifecycle.getState() === 'inactive';
231
214
  }
232
215
  // Emits app.onBackButton and returns whether the back action may proceed. Returns false when a
233
216
  // listener vetoed by calling cancelSignal(app.onBackButton), meaning the listener handled
@@ -238,33 +221,6 @@ export function requestAppBack(app) {
238
221
  emitSignal(app.onBackButton);
239
222
  return app.onBackButton.data?.cancelled !== true;
240
223
  }
241
- export function resetLifecycleBackendForTest() {
242
- _custom = null;
243
- _host = null;
244
- _hostConflict = false;
245
- _hostObservation = null;
246
- }
247
- export function setLifecycleBackend(backend) {
248
- _custom = backend;
249
- }
250
224
  const _savedState = new WeakMap();
251
- const _sentinel = {
252
- getState() {
253
- return 'active';
254
- },
255
- getLaunchKind() {
256
- return 'cold';
257
- },
258
- subscribe() {
259
- return () => { };
260
- },
261
- subscribeMemoryWarning() {
262
- return () => { };
263
- },
264
- };
265
225
  const _subscriptions = new WeakMap();
266
- let _custom = null;
267
- let _host = null;
268
- let _hostConflict = false;
269
- let _hostObservation = null;
270
226
  //# sourceMappingURL=lifecycle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAUtE,kGAAkG;AAClG,kGAAkG;AAClG,6FAA6F;AAC7F,oGAAoG;AACpG,qFAAqF;AACrF,EAAE;AACF,6FAA6F;AAC7F,+FAA+F;AAC/F,mGAAmG;AACnG,oGAAoG;AACpG,MAAM,UAAU,kBAAkB,CAAC,GAAiB;IAClD,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,IAAI,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAElC,MAAM,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;QAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QACjC,UAAU,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,KAAK,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAChD,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACzB,oCAAoC;YACpC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,UAAU,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACvD,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACxB,mEAAmE;YACnE,MAAM,QAAQ,GAA4B,EAAE,CAAC;YAC7C,UAAU,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;YACtC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC;QACD,QAAQ,GAAG,KAAK,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,IAAI,iBAA2C,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAC9C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAwB,EAAE,EAAE;YACpE,UAAU,CAAC,GAAG,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE;QAC3B,gBAAgB,EAAE,CAAC;QACnB,iBAAiB,EAAE,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,kBAAkB;IAChC,OAAO;QACL,aAAa,EAAE,YAAY,EAAE;QAC7B,QAAQ,EAAE,YAAY,EAAE;QACxB,OAAO,EAAE,YAAY,EAAE;QACvB,YAAY,EAAE,YAAY,EAAE;QAC5B,eAAe,EAAE,YAAY,EAAE;QAC/B,WAAW,EAAE,YAAY,EAAE;QAC3B,cAAc,EAAE,YAAY,EAAE;KAC/B,CAAC;AACJ,CAAC;AAED,oGAAoG;AACpG,iCAAiC;AACjC,uDAAuD;AACvD,wGAAwG;AACxG,kEAAkE;AAClE,oGAAoG;AACpG,EAAE;AACF,qFAAqF;AACrF,kGAAkG;AAClG,oFAAoF;AACpF,iGAAiG;AACjG,8FAA8F;AAC9F,EAAE;AACF,gGAAgG;AAChG,kGAAkG;AAClG,qGAAqG;AACrG,qGAAqG;AACrG,MAAM,UAAU,yBAAyB;IACvC,IAAI,cAAc,GAAG,OAAO,QAAQ,KAAK,WAAW,CAAC;IACrD,OAAO;QACL,QAAQ;YACN,IAAI,OAAO,QAAQ,KAAK,WAAW;gBAAE,OAAO,QAAQ,CAAC;YACrD,IAAI,QAAQ,CAAC,MAAM;gBAAE,OAAO,YAAY,CAAC;YACzC,OAAO,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QAChD,CAAC;QACD,SAAS,CAAC,QAAoB;YAC5B,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,WAAW;gBAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;YACtF,4CAA4C;YAC5C,cAAc,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,cAAc,GAAG,IAAI,CAAC;gBACtB,QAAQ,EAAE,CAAC;YACb,CAAC,CAAC;YACF,MAAM,MAAM,GAAG,GAAG,EAAE;gBAClB,cAAc,GAAG,KAAK,CAAC;gBACvB,QAAQ,EAAE,CAAC;YACb,CAAC,CAAC;YACF,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;YACxD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC9C,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC9C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC1C,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACxC,OAAO,GAAG,EAAE;gBACV,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;gBAC3D,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBACjD,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBACjD,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC7C,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC,CAAC;QACJ,CAAC;QACD,aAAa;YACX,+FAA+F;YAC/F,4FAA4F;YAC5F,yFAAyF;YACzF,6EAA6E;YAC7E,IAAI,OAAO,WAAW,KAAK,WAAW;gBAAE,OAAO,MAAM,CAAC;YACtD,MAAM,OAAO,GAAG,WAAW,CAAC,gBAAgB,CAAC,YAAY,CAAkC,CAAC;YAC5F,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc;gBAAE,OAAO,MAAM,CAAC;YAC5E,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,sBAAsB,CAAC,QAA4C;YACjE,0FAA0F;YAC1F,8FAA8F;YAC9F,6FAA6F;YAC7F,4FAA4F;YAC5F,qEAAqE;YACrE,IAAI,OAAO,MAAM,KAAK,WAAW;gBAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;YACnD,yFAAyF;YACzF,4FAA4F;YAC5F,mFAAmF;YACnF,MAAM,UAAU,GAAG,CAAC,CAAQ,EAAE,EAAE;gBAC9B,MAAM,MAAM,GAAI,CAAwC,CAAC,MAAM,CAAC;gBAChE,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAC;gBAClC,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;oBAC5B,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACvB,CAAC;qBAAM,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;oBACnC,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACvB,CAAC;qBAAM,CAAC;oBACN,4EAA4E;oBAC5E,QAAQ,CAAC,UAAU,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC,CAAC;YACF,MAAM,kBAAkB,GAAG,GAAG,EAAE;gBAC9B,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACrB,CAAC,CAAC;YACF,MAAM,CAAC,gBAAgB,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;YACvD,MAAM,CAAC,gBAAgB,CAAC,0BAA0B,EAAE,kBAAkB,CAAC,CAAC;YACxE,OAAO,GAAG,EAAE;gBACV,MAAM,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;gBAC1D,MAAM,CAAC,mBAAmB,CAAC,0BAA0B,EAAE,kBAAkB,CAAC,CAAC;YAC7E,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,kBAAkB,CAAC,GAAiB;IAClD,MAAM,WAAW,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5C,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,WAAW,EAAE,CAAC;QACd,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,kGAAkG;AAClG,qCAAqC;AACrC,MAAM,UAAU,mBAAmB,CAAC,GAAiB;IACnD,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxB,WAAW,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;IAChG,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,QAAQ,EAAE,aAAa;YACvB,KAAK,EAAE,MAAM;YACb,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;YACxE,SAAS,EAAE,gBAAgB,KAAK,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY;SACjF,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AAClG,CAAC;AAED,mGAAmG;AACnG,+FAA+F;AAC/F,0FAA0F;AAC1F,gFAAgF;AAChF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,OAAO,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAChF,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,oBAAoB;IAClC,OAAO,mBAAmB,EAAE,CAAC,QAAQ,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,IAAI,KAAK,IAAI,SAAS,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,OAAyB;IACnE,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,IAAI,KAAK,KAAK,OAAO;YAAE,aAAa,GAAG,IAAI,CAAC;QAC5C,OAAO;IACT,CAAC;IACD,KAAK,GAAG,OAAO,CAAC;AAClB,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,WAAW;IACzB,OAAO,mBAAmB,EAAE,CAAC,QAAQ,EAAE,KAAK,QAAQ,CAAC;AACvD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,eAAe;IAC7B,OAAO,mBAAmB,EAAE,CAAC,QAAQ,EAAE,KAAK,YAAY,CAAC;AAC3D,CAAC;AAED,0FAA0F;AAC1F,6DAA6D;AAC7D,MAAM,UAAU,aAAa;IAC3B,OAAO,mBAAmB,EAAE,CAAC,QAAQ,EAAE,KAAK,UAAU,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,SAAiB,EAAE,SAAkB;IAC9E,gBAAgB,GAAG;QACjB,SAAS;QACT,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,yBAAyB;KAC/D,CAAC;AACJ,CAAC;AAED,+FAA+F;AAC/F,0FAA0F;AAC1F,kGAAkG;AAClG,+FAA+F;AAC/F,4CAA4C;AAC5C,MAAM,UAAU,cAAc,CAAC,GAAiB;IAC9C,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7B,OAAO,GAAG,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO,GAAG,IAAI,CAAC;IACf,KAAK,GAAG,IAAI,CAAC;IACb,aAAa,GAAG,KAAK,CAAC;IACtB,gBAAgB,GAAG,IAAI,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAgC;IAClE,OAAO,GAAG,OAAO,CAAC;AACpB,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,OAAO,EAAyC,CAAC;AACzE,MAAM,SAAS,GAAqB;IAClC,QAAQ;QACN,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,aAAa;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,SAAS;QACP,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;IACD,sBAAsB;QACpB,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC;CACF,CAAC;AACF,MAAM,cAAc,GAAG,IAAI,OAAO,EAA4B,CAAC;AAC/D,IAAI,OAAO,GAA4B,IAAI,CAAC;AAC5C,IAAI,KAAK,GAA4B,IAAI,CAAC;AAC1C,IAAI,aAAa,GAAG,KAAK,CAAC;AAC1B,IAAI,gBAAgB,GAAqF,IAAI,CAAC"}
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/lifecycle",
3
- "version": "0.5.0-next.1944.cd6b6e7",
3
+ "version": "0.5.1-edge.638.d4dbd4e",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,8 +38,8 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/signals": "0.5.0-next.1944.cd6b6e7",
42
- "@flighthq/types": "0.5.0-next.1944.cd6b6e7"
41
+ "@flighthq/signals": "0.5.1-edge.638.d4dbd4e",
42
+ "@flighthq/types": "0.5.1-edge.638.d4dbd4e"
43
43
  },
44
44
  "devDependencies": {
45
45
  "typescript": "^5.3.0"
@@ -1,5 +1,11 @@
1
1
  import { cancelSignal, connectSignal } from '@flighthq/signals/contract';
2
- import type { AppLifecycleState, AppMemoryPressure, LifecycleBackend } from '@flighthq/types/contract';
2
+ import type {
3
+ HasSystemLifecycle,
4
+ AppLifecycleState,
5
+ AppMemoryPressure,
6
+ LifecycleBackend,
7
+ LifecycleOperation,
8
+ } from '@flighthq/types/contract';
3
9
 
4
10
  import {
5
11
  attachAppLifecycle,
@@ -7,18 +13,14 @@ import {
7
13
  createWebLifecycleBackend,
8
14
  detachAppLifecycle,
9
15
  disposeAppLifecycle,
16
+ explainLifecycleOperation,
10
17
  getAppLaunchKind,
11
18
  getAppLifecycleState,
12
- getLifecycleBackend,
19
+ hasLifecycleOperation,
13
20
  isAppActive,
14
21
  isAppBackground,
15
22
  isAppInactive,
16
23
  requestAppBack,
17
- setLifecycleBackend,
18
- explainLifecycleBackend,
19
- installLifecycleHostBackend,
20
- observeLifecycleHostResult,
21
- resetLifecycleBackendForTest,
22
24
  } from './lifecycle';
23
25
 
24
26
  type FakeBackend = LifecycleBackend & {
@@ -27,6 +29,10 @@ type FakeBackend = LifecycleBackend & {
27
29
  fireMemory: (level: AppMemoryPressure) => void;
28
30
  };
29
31
 
32
+ function hostOf(backend: LifecycleBackend): HasSystemLifecycle {
33
+ return { system: { lifecycle: backend } } as HasSystemLifecycle;
34
+ }
35
+
30
36
  function fakeBackend(): FakeBackend {
31
37
  let stateListener: (() => void) | null = null;
32
38
  let memoryListener: ((level: AppMemoryPressure) => void) | null = null;
@@ -56,18 +62,16 @@ function fakeBackend(): FakeBackend {
56
62
  };
57
63
  }
58
64
 
59
- afterEach(() => setLifecycleBackend(null));
60
-
61
65
  describe('attachAppLifecycle', () => {
62
66
  it('emits onPause and onStateChange when leaving active for background', () => {
63
67
  const backend = fakeBackend();
64
- setLifecycleBackend(backend);
68
+ const host = hostOf(backend);
65
69
  const app = createAppLifecycle();
66
70
  let changes = 0;
67
71
  let pauses = 0;
68
72
  connectSignal(app.onStateChange, () => changes++);
69
73
  connectSignal(app.onPause, () => pauses++);
70
- attachAppLifecycle(app);
74
+ attachAppLifecycle(host, app);
71
75
  backend.state = 'background';
72
76
  backend.fire();
73
77
  expect(changes).toBe(1);
@@ -76,11 +80,11 @@ describe('attachAppLifecycle', () => {
76
80
 
77
81
  it('emits onPause when leaving active for inactive', () => {
78
82
  const backend = fakeBackend();
79
- setLifecycleBackend(backend);
83
+ const host = hostOf(backend);
80
84
  const app = createAppLifecycle();
81
85
  let pauses = 0;
82
86
  connectSignal(app.onPause, () => pauses++);
83
- attachAppLifecycle(app);
87
+ attachAppLifecycle(host, app);
84
88
  backend.state = 'inactive';
85
89
  backend.fire();
86
90
  expect(pauses).toBe(1);
@@ -89,11 +93,11 @@ describe('attachAppLifecycle', () => {
89
93
  it('does not double-fire onPause for inactive → background', () => {
90
94
  const backend = fakeBackend();
91
95
  backend.state = 'inactive';
92
- setLifecycleBackend(backend);
96
+ const host = hostOf(backend);
93
97
  const app = createAppLifecycle();
94
98
  let pauses = 0;
95
99
  connectSignal(app.onPause, () => pauses++);
96
- attachAppLifecycle(app);
100
+ attachAppLifecycle(host, app);
97
101
  backend.state = 'background';
98
102
  backend.fire();
99
103
  // inactive → background should not re-fire onPause (already paused)
@@ -103,11 +107,11 @@ describe('attachAppLifecycle', () => {
103
107
  it('emits onResume when returning to active from background', () => {
104
108
  const backend = fakeBackend();
105
109
  backend.state = 'background';
106
- setLifecycleBackend(backend);
110
+ const host = hostOf(backend);
107
111
  const app = createAppLifecycle();
108
112
  let resumes = 0;
109
113
  connectSignal(app.onResume, () => resumes++);
110
- attachAppLifecycle(app);
114
+ attachAppLifecycle(host, app);
111
115
  backend.state = 'active';
112
116
  backend.fire();
113
117
  expect(resumes).toBe(1);
@@ -116,11 +120,11 @@ describe('attachAppLifecycle', () => {
116
120
  it('emits onResume when returning to active from inactive', () => {
117
121
  const backend = fakeBackend();
118
122
  backend.state = 'inactive';
119
- setLifecycleBackend(backend);
123
+ const host = hostOf(backend);
120
124
  const app = createAppLifecycle();
121
125
  let resumes = 0;
122
126
  connectSignal(app.onResume, () => resumes++);
123
- attachAppLifecycle(app);
127
+ attachAppLifecycle(host, app);
124
128
  backend.state = 'active';
125
129
  backend.fire();
126
130
  expect(resumes).toBe(1);
@@ -128,12 +132,12 @@ describe('attachAppLifecycle', () => {
128
132
 
129
133
  it('is idempotent — re-attaching tears down the prior subscription', () => {
130
134
  const backend = fakeBackend();
131
- setLifecycleBackend(backend);
135
+ const host = hostOf(backend);
132
136
  const app = createAppLifecycle();
133
137
  let changes = 0;
134
138
  connectSignal(app.onStateChange, () => changes++);
135
- attachAppLifecycle(app);
136
- attachAppLifecycle(app);
139
+ attachAppLifecycle(host, app);
140
+ attachAppLifecycle(host, app);
137
141
  backend.state = 'background';
138
142
  backend.fire();
139
143
  // Only one subscription should be active.
@@ -142,14 +146,14 @@ describe('attachAppLifecycle', () => {
142
146
 
143
147
  it('emits onSaveState when leaving active', () => {
144
148
  const backend = fakeBackend();
145
- setLifecycleBackend(backend);
149
+ const host = hostOf(backend);
146
150
  const app = createAppLifecycle();
147
151
  let saved = false;
148
152
  connectSignal(app.onSaveState, (bag) => {
149
153
  bag['key'] = 'value';
150
154
  saved = true;
151
155
  });
152
- attachAppLifecycle(app);
156
+ attachAppLifecycle(host, app);
153
157
  backend.state = 'background';
154
158
  backend.fire();
155
159
  expect(saved).toBe(true);
@@ -157,7 +161,7 @@ describe('attachAppLifecycle', () => {
157
161
 
158
162
  it('emits onRestoreState with saved bag when returning to active', () => {
159
163
  const backend = fakeBackend();
160
- setLifecycleBackend(backend);
164
+ const host = hostOf(backend);
161
165
  const app = createAppLifecycle();
162
166
  connectSignal(app.onSaveState, (bag) => {
163
167
  bag['x'] = 42;
@@ -166,7 +170,7 @@ describe('attachAppLifecycle', () => {
166
170
  connectSignal(app.onRestoreState, (state) => {
167
171
  restored = state;
168
172
  });
169
- attachAppLifecycle(app);
173
+ attachAppLifecycle(host, app);
170
174
  // Transition away to trigger save.
171
175
  backend.state = 'background';
172
176
  backend.fire();
@@ -179,11 +183,11 @@ describe('attachAppLifecycle', () => {
179
183
 
180
184
  it('subscribes to memory warnings when backend supports it', () => {
181
185
  const backend = fakeBackend();
182
- setLifecycleBackend(backend);
186
+ const host = hostOf(backend);
183
187
  const app = createAppLifecycle();
184
188
  const levels: AppMemoryPressure[] = [];
185
189
  connectSignal(app.onMemoryWarning, (level) => levels.push(level));
186
- attachAppLifecycle(app);
190
+ attachAppLifecycle(host, app);
187
191
  backend.fireMemory('critical');
188
192
  expect(levels).toEqual(['critical']);
189
193
  });
@@ -197,11 +201,11 @@ describe('attachAppLifecycle', () => {
197
201
  const states: AppLifecycleState[] = ['active', 'inactive', 'background'];
198
202
  for (let trial = 0; trial < 200; trial++) {
199
203
  const backend = fakeBackend();
200
- setLifecycleBackend(backend);
204
+ const host = hostOf(backend);
201
205
  const app = createAppLifecycle();
202
206
  let changes = 0;
203
207
  connectSignal(app.onStateChange, () => changes++);
204
- attachAppLifecycle(app);
208
+ attachAppLifecycle(host, app);
205
209
  const fireCount = 1 + Math.floor(Math.random() * 30);
206
210
  for (let i = 0; i < fireCount; i++) {
207
211
  backend.state = states[Math.floor(Math.random() * states.length)];
@@ -219,13 +223,13 @@ describe('attachAppLifecycle', () => {
219
223
  const backend = fakeBackend();
220
224
  const start = states[Math.floor(Math.random() * states.length)];
221
225
  backend.state = start;
222
- setLifecycleBackend(backend);
226
+ const host = hostOf(backend);
223
227
  const app = createAppLifecycle();
224
228
  let pauses = 0;
225
229
  let resumes = 0;
226
230
  connectSignal(app.onPause, () => pauses++);
227
231
  connectSignal(app.onResume, () => resumes++);
228
- attachAppLifecycle(app);
232
+ attachAppLifecycle(host, app);
229
233
 
230
234
  // Drive a random storm while computing the expected edge counts from an independent model:
231
235
  // a pause edge is every 'active' → non-'active' transition, a resume edge every
@@ -255,7 +259,7 @@ describe('attachAppLifecycle', () => {
255
259
  for (let trial = 0; trial < 100; trial++) {
256
260
  const backend = fakeBackend();
257
261
  backend.state = 'active';
258
- setLifecycleBackend(backend);
262
+ const host = hostOf(backend);
259
263
  const app = createAppLifecycle();
260
264
  let changes = 0;
261
265
  let pauses = 0;
@@ -263,7 +267,7 @@ describe('attachAppLifecycle', () => {
263
267
  connectSignal(app.onStateChange, () => changes++);
264
268
  connectSignal(app.onPause, () => pauses++);
265
269
  connectSignal(app.onResume, () => resumes++);
266
- attachAppLifecycle(app);
270
+ attachAppLifecycle(host, app);
267
271
  const fireCount = 1 + Math.floor(Math.random() * 30);
268
272
  for (let i = 0; i < fireCount; i++) backend.fire();
269
273
  expect(changes).toBe(fireCount);
@@ -282,13 +286,13 @@ describe('attachAppLifecycle', () => {
282
286
  for (let trial = 0; trial < 200; trial++) {
283
287
  const backend = fakeBackend();
284
288
  backend.state = states[Math.floor(Math.random() * states.length)];
285
- setLifecycleBackend(backend);
289
+ const host = hostOf(backend);
286
290
  const app = createAppLifecycle();
287
291
  let pauses = 0;
288
292
  let resumes = 0;
289
293
  connectSignal(app.onPause, () => pauses++);
290
294
  connectSignal(app.onResume, () => resumes++);
291
- attachAppLifecycle(app);
295
+ attachAppLifecycle(host, app);
292
296
  const fireCount = 1 + Math.floor(Math.random() * 30);
293
297
  for (let i = 0; i < fireCount; i++) {
294
298
  backend.state = states[Math.floor(Math.random() * states.length)];
@@ -398,11 +402,11 @@ describe('createWebLifecycleBackend', () => {
398
402
  describe('detachAppLifecycle', () => {
399
403
  it('stops further delivery', () => {
400
404
  const backend = fakeBackend();
401
- setLifecycleBackend(backend);
405
+ const host = hostOf(backend);
402
406
  const app = createAppLifecycle();
403
407
  let changes = 0;
404
408
  connectSignal(app.onStateChange, () => changes++);
405
- attachAppLifecycle(app);
409
+ attachAppLifecycle(host, app);
406
410
  detachAppLifecycle(app);
407
411
  backend.fire();
408
412
  expect(changes).toBe(0);
@@ -417,58 +421,62 @@ describe('detachAppLifecycle', () => {
417
421
  describe('disposeAppLifecycle', () => {
418
422
  it('detaches the subscription', () => {
419
423
  const backend = fakeBackend();
420
- setLifecycleBackend(backend);
424
+ const host = hostOf(backend);
421
425
  const app = createAppLifecycle();
422
- attachAppLifecycle(app);
426
+ attachAppLifecycle(host, app);
423
427
  expect(() => disposeAppLifecycle(app)).not.toThrow();
424
428
  });
425
429
 
426
430
  it('stops delivery after dispose', () => {
427
431
  const backend = fakeBackend();
428
- setLifecycleBackend(backend);
432
+ const host = hostOf(backend);
429
433
  const app = createAppLifecycle();
430
434
  let changes = 0;
431
435
  connectSignal(app.onStateChange, () => changes++);
432
- attachAppLifecycle(app);
436
+ attachAppLifecycle(host, app);
433
437
  disposeAppLifecycle(app);
434
438
  backend.fire();
435
439
  expect(changes).toBe(0);
436
440
  });
437
441
  });
438
442
 
439
- describe('explainLifecycleBackend', () => {
440
- afterEach(() => resetLifecycleBackendForTest());
441
-
442
- it('reports host-not-enabled when no backend is installed', () => {
443
- resetLifecycleBackendForTest();
444
- const explanation = explainLifecycleBackend();
445
- expect(explanation.layer).toBe('host-not-enabled');
446
- expect(explanation.conflict).toBe(false);
447
- expect(explanation.viability).toBe('unobserved');
448
- });
449
-
450
- it('reports custom layer when a custom backend is set', () => {
451
- setLifecycleBackend(fakeBackend());
452
- expect(explainLifecycleBackend().layer).toBe('custom');
443
+ describe('explainLifecycleOperation', () => {
444
+ // The sentinel is gone with the ambient resolver: a host either carries a provider that implements
445
+ // the operation or it does not, and "not implemented" is now a fact about THAT host rather than
446
+ // about a process-wide fallback that answered everything.
447
+ it('reports the host provider as implementing what it provides', () => {
448
+ const host = hostOf(fakeBackend());
449
+ expect(explainLifecycleOperation(host, 'getState')).toEqual({
450
+ implemented: true,
451
+ layer: 'host',
452
+ operation: 'getState',
453
+ });
453
454
  });
454
455
 
455
- it('reports host layer when a host backend is installed', () => {
456
- installLifecycleHostBackend(fakeBackend());
457
- expect(explainLifecycleBackend().layer).toBe('host');
456
+ it('reports an operation the host provider omits as unimplemented', () => {
457
+ const host = hostOf({ getState: () => 'active', subscribe: () => () => {} } as LifecycleBackend);
458
+ expect(explainLifecycleOperation(host, 'getLaunchKind')).toEqual({
459
+ implemented: false,
460
+ layer: 'sentinel',
461
+ operation: 'getLaunchKind',
462
+ });
458
463
  });
459
464
 
460
- it('reports conflict when two different host backends are installed', () => {
461
- installLifecycleHostBackend(fakeBackend());
462
- installLifecycleHostBackend(fakeBackend());
463
- expect(explainLifecycleBackend().conflict).toBe(true);
465
+ // Two hosts, two answers for the same operation — impossible before the migration, because one
466
+ // process-wide backend answered for every caller.
467
+ it('answers per host rather than process-wide', () => {
468
+ const rich = hostOf(fakeBackend());
469
+ const bare = hostOf({ getState: () => 'active', subscribe: () => () => {} } as LifecycleBackend);
470
+ expect(explainLifecycleOperation(rich, 'subscribeMemoryWarning').implemented).toBe(true);
471
+ expect(explainLifecycleOperation(bare, 'subscribeMemoryWarning').implemented).toBe(false);
464
472
  });
465
473
  });
466
474
 
467
475
  describe('getAppLaunchKind', () => {
468
476
  it("returns 'warm' when backend does not implement getLaunchKind", () => {
469
477
  const backend = fakeBackend();
470
- setLifecycleBackend(backend);
471
- expect(getAppLaunchKind()).toBe('warm');
478
+ const host = hostOf(backend);
479
+ expect(getAppLaunchKind(host)).toBe('warm');
472
480
  });
473
481
 
474
482
  it('delegates to backend.getLaunchKind when present', () => {
@@ -477,8 +485,8 @@ describe('getAppLaunchKind', () => {
477
485
  subscribe: () => () => {},
478
486
  getLaunchKind: () => 'cold',
479
487
  };
480
- setLifecycleBackend(backend);
481
- expect(getAppLaunchKind()).toBe('cold');
488
+ const host = hostOf(backend);
489
+ expect(getAppLaunchKind(host)).toBe('cold');
482
490
  });
483
491
  });
484
492
 
@@ -486,33 +494,20 @@ describe('getAppLifecycleState', () => {
486
494
  it('reads from the active backend', () => {
487
495
  const backend = fakeBackend();
488
496
  backend.state = 'inactive';
489
- setLifecycleBackend(backend);
490
- expect(getAppLifecycleState()).toBe('inactive');
497
+ const host = hostOf(backend);
498
+ expect(getAppLifecycleState(host)).toBe('inactive');
491
499
  });
492
500
  });
493
501
 
494
- describe('getLifecycleBackend', () => {
495
- it('falls back to a web backend', () => {
496
- expect(getLifecycleBackend()).not.toBeNull();
502
+ describe('hasLifecycleOperation', () => {
503
+ it('agrees with explainLifecycleOperation for the same host', () => {
504
+ const host = hostOf(fakeBackend());
505
+ expect(hasLifecycleOperation(host, 'getState')).toBe(explainLifecycleOperation(host, 'getState').implemented);
497
506
  });
498
- });
499
-
500
- describe('installLifecycleHostBackend', () => {
501
- afterEach(() => resetLifecycleBackendForTest());
502
507
 
503
- it('installs a host backend that getLifecycleBackend returns', () => {
504
- const backend = fakeBackend();
505
- installLifecycleHostBackend(backend);
506
- expect(getLifecycleBackend()).toBe(backend);
507
- });
508
-
509
- it('is first-host-wins: a second different backend sets conflict', () => {
510
- const first = fakeBackend();
511
- const second = fakeBackend();
512
- installLifecycleHostBackend(first);
513
- installLifecycleHostBackend(second);
514
- expect(getLifecycleBackend()).toBe(first);
515
- expect(explainLifecycleBackend().conflict).toBe(true);
508
+ it('is false for an operation the host provider omits', () => {
509
+ const host = hostOf({ getState: () => 'active', subscribe: () => () => {} } as LifecycleBackend);
510
+ expect(hasLifecycleOperation(host, 'getLaunchKind')).toBe(false);
516
511
  });
517
512
  });
518
513
 
@@ -520,22 +515,22 @@ describe('isAppActive', () => {
520
515
  it("returns true when state is 'active'", () => {
521
516
  const backend = fakeBackend();
522
517
  backend.state = 'active';
523
- setLifecycleBackend(backend);
524
- expect(isAppActive()).toBe(true);
518
+ const host = hostOf(backend);
519
+ expect(isAppActive(host)).toBe(true);
525
520
  });
526
521
 
527
522
  it("returns false when state is 'background'", () => {
528
523
  const backend = fakeBackend();
529
524
  backend.state = 'background';
530
- setLifecycleBackend(backend);
531
- expect(isAppActive()).toBe(false);
525
+ const host = hostOf(backend);
526
+ expect(isAppActive(host)).toBe(false);
532
527
  });
533
528
 
534
529
  it("returns false when state is 'inactive'", () => {
535
530
  const backend = fakeBackend();
536
531
  backend.state = 'inactive';
537
- setLifecycleBackend(backend);
538
- expect(isAppActive()).toBe(false);
532
+ const host = hostOf(backend);
533
+ expect(isAppActive(host)).toBe(false);
539
534
  });
540
535
  });
541
536
 
@@ -543,49 +538,44 @@ describe('isAppBackground', () => {
543
538
  it("returns true when state is 'background'", () => {
544
539
  const backend = fakeBackend();
545
540
  backend.state = 'background';
546
- setLifecycleBackend(backend);
547
- expect(isAppBackground()).toBe(true);
541
+ const host = hostOf(backend);
542
+ expect(isAppBackground(host)).toBe(true);
548
543
  });
549
544
 
550
545
  it("returns false when state is 'active'", () => {
551
546
  const backend = fakeBackend();
552
547
  backend.state = 'active';
553
- setLifecycleBackend(backend);
554
- expect(isAppBackground()).toBe(false);
548
+ const host = hostOf(backend);
549
+ expect(isAppBackground(host)).toBe(false);
555
550
  });
556
551
  });
557
552
 
553
+ // Per-operation availability for LifecycleBackend. The operations below are the ones the interface declares
554
+ // OPTIONAL, so a host that omits them is compliant rather than broken — that is the absence-of-an-export
555
+ // ruling, and this is the query that makes it observable.
556
+ const OPTIONAL_OPERATIONS: readonly LifecycleOperation[] = ['getLaunchKind', 'subscribeMemoryWarning'];
557
+
558
+ // A host implementing only the REQUIRED members — partial support declared by absence.
559
+ function partialBackend(): LifecycleBackend {
560
+ return {
561
+ getState: (() => undefined) as never,
562
+ subscribe: (() => undefined) as never,
563
+ } as LifecycleBackend;
564
+ }
565
+
558
566
  describe('isAppInactive', () => {
559
567
  it("returns true when state is 'inactive'", () => {
560
568
  const backend = fakeBackend();
561
569
  backend.state = 'inactive';
562
- setLifecycleBackend(backend);
563
- expect(isAppInactive()).toBe(true);
570
+ const host = hostOf(backend);
571
+ expect(isAppInactive(host)).toBe(true);
564
572
  });
565
573
 
566
574
  it("returns false when state is 'active'", () => {
567
575
  const backend = fakeBackend();
568
576
  backend.state = 'active';
569
- setLifecycleBackend(backend);
570
- expect(isAppInactive()).toBe(false);
571
- });
572
- });
573
-
574
- describe('observeLifecycleHostResult', () => {
575
- afterEach(() => resetLifecycleBackendForTest());
576
-
577
- it('records a successful observation', () => {
578
- installLifecycleHostBackend(fakeBackend());
579
- observeLifecycleHostResult('getState', true);
580
- const explanation = explainLifecycleBackend();
581
- expect(explanation.operation).toBe('getState');
582
- expect(explanation.viability).toBe('available');
583
- });
584
-
585
- it('records a failed observation', () => {
586
- installLifecycleHostBackend(fakeBackend());
587
- observeLifecycleHostResult('getState', false);
588
- expect(explainLifecycleBackend().viability).toBe('runtime-api-unavailable');
577
+ const host = hostOf(backend);
578
+ expect(isAppInactive(host)).toBe(false);
589
579
  });
590
580
  });
591
581
 
@@ -609,23 +599,3 @@ describe('requestAppBack', () => {
609
599
  expect(fired).toBe(1);
610
600
  });
611
601
  });
612
-
613
- describe('resetLifecycleBackendForTest', () => {
614
- it('clears all backend slots', () => {
615
- setLifecycleBackend(fakeBackend());
616
- installLifecycleHostBackend(fakeBackend());
617
- observeLifecycleHostResult('getState', true);
618
- resetLifecycleBackendForTest();
619
- expect(explainLifecycleBackend().layer).toBe('host-not-enabled');
620
- expect(explainLifecycleBackend().conflict).toBe(false);
621
- expect(explainLifecycleBackend().viability).toBe('unobserved');
622
- });
623
- });
624
-
625
- describe('setLifecycleBackend', () => {
626
- it('clears back to the web fallback when passed null', () => {
627
- setLifecycleBackend(fakeBackend());
628
- setLifecycleBackend(null);
629
- expect(getLifecycleBackend()).not.toBeNull();
630
- });
631
- });
@@ -0,0 +1,57 @@
1
+ import type { AppLifecycleState, HasSystemLifecycle, LifecycleBackend } from '@flighthq/types/contract';
2
+
3
+ import { getAppLaunchKind, getAppLifecycleState, isAppActive, isAppBackground, isAppInactive } from './lifecycle';
4
+
5
+ function hostWith(backend: Partial<LifecycleBackend>): HasSystemLifecycle {
6
+ return { system: { lifecycle: backend as LifecycleBackend } } as HasSystemLifecycle;
7
+ }
8
+
9
+ function stateHost(state: AppLifecycleState): HasSystemLifecycle {
10
+ return hostWith({ getState: () => state, subscribe: () => () => {} });
11
+ }
12
+
13
+ describe('getAppLaunchKind', () => {
14
+ it('reads the launch kind from the host it is given', () => {
15
+ expect(getAppLaunchKind(hostWith({ getState: () => 'active', getLaunchKind: () => 'warm' }))).toBe('warm');
16
+ });
17
+
18
+ // getLaunchKind is optional on the backend; a provider without it must not throw.
19
+ it('falls back to warm when the provider does not implement it', () => {
20
+ expect(getAppLaunchKind(stateHost('active'))).toBe('warm');
21
+ });
22
+ });
23
+
24
+ describe('getAppLifecycleState', () => {
25
+ it('reads the state from the host it is given', () => {
26
+ expect(getAppLifecycleState(stateHost('background'))).toBe('background');
27
+ });
28
+
29
+ // Two hosts, two answers, no ambient selection in between. This is the property the migration is
30
+ // for: before it, both calls resolved one process-wide backend and the second host was unreachable.
31
+ it('keeps two hosts independent', () => {
32
+ expect(getAppLifecycleState(stateHost('active'))).toBe('active');
33
+ expect(getAppLifecycleState(stateHost('inactive'))).toBe('inactive');
34
+ });
35
+ });
36
+
37
+ describe('isAppActive', () => {
38
+ it('reports active only for the active state', () => {
39
+ expect(isAppActive(stateHost('active'))).toBe(true);
40
+ expect(isAppActive(stateHost('inactive'))).toBe(false);
41
+ expect(isAppActive(stateHost('background'))).toBe(false);
42
+ });
43
+ });
44
+
45
+ describe('isAppBackground', () => {
46
+ it('reports background only for the background state', () => {
47
+ expect(isAppBackground(stateHost('background'))).toBe(true);
48
+ expect(isAppBackground(stateHost('active'))).toBe(false);
49
+ });
50
+ });
51
+
52
+ describe('isAppInactive', () => {
53
+ it('reports inactive only for the inactive state', () => {
54
+ expect(isAppInactive(stateHost('inactive'))).toBe(true);
55
+ expect(isAppInactive(stateHost('active'))).toBe(false);
56
+ });
57
+ });