@deck-shelves/host 1.3.2 → 1.4.1

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/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/contract/index.ts
4
- var HOST_API_VERSION = "1.2.0";
4
+ var HOST_API_VERSION = "1.3.0";
5
5
  var INJECTED_HOST_GLOBAL = "__SHELVES_HOST__";
6
6
  var FORCE_OWNER_GLOBAL = "__SHELVES_FORCE_OWNER__";
7
7
  var OWNER_GLOBAL = "__DECK_SHELVES_OWNER__";
package/dist/index.d.cts CHANGED
@@ -23,9 +23,11 @@
23
23
  * npm release version. Bump semver here on shape changes: MINOR for additive,
24
24
  * backward-compatible members (a new optional namespace / field); MAJOR on a
25
25
  * breaking change. 1.2.0 added the optional `updates` namespace and the
26
- * optional `React`/`ReactDOM`/`jsx` UI-surface members.
26
+ * optional `React`/`ReactDOM`/`jsx` UI-surface members. 1.3.0 added the optional
27
+ * `api.handshake()` + `HostHandshake`, `lifecycle.teardown()`, and the
28
+ * `routes.addPatch`/`removePatch` route-patch members.
27
29
  */
28
- declare const HOST_API_VERSION: "1.2.0";
30
+ declare const HOST_API_VERSION: "1.3.0";
29
31
  interface PluginDescriptor {
30
32
  name: string;
31
33
  version: string;
@@ -38,6 +40,14 @@ interface HostLifecycle {
38
40
  register(plugin: PluginDescriptor): Disposable;
39
41
  onMount(cb: () => void): void;
40
42
  onUnmount(cb: () => void): void;
43
+ /**
44
+ * Dispose the CURRENT bundle instance: runs every `onUnmount` handler once and
45
+ * clears them. The host calls this before it hot-swaps a new bundle in place, so
46
+ * two instances never both own the Home. Optional (feature-detected) — a bundle
47
+ * needing clean re-eval should register real teardown in `onUnmount`.
48
+ * Returns the number of handlers run.
49
+ */
50
+ teardown?(): number;
41
51
  }
42
52
  /** Generic RPC channel into the host backend. Each host routes it to the
43
53
  * plugin's data backend through its own transport (an in-process bridge, a
@@ -45,9 +55,30 @@ interface HostLifecycle {
45
55
  interface HostRpc {
46
56
  call<Req = unknown, Res = unknown>(method: string, args?: Req): Promise<Res>;
47
57
  }
58
+ /**
59
+ * Transforms an existing route's props. Receives a shallow copy of the route's
60
+ * props and returns a partial override (today only `children` is honored); a
61
+ * missing/void return leaves the route untouched.
62
+ */
63
+ type RoutePatch = (props: {
64
+ path?: string;
65
+ children?: unknown;
66
+ [key: string]: unknown;
67
+ }) => {
68
+ children?: unknown;
69
+ } | void;
48
70
  interface HostRoutes {
49
71
  /** Register a full-page route; returns a disposer that removes it. */
50
72
  register(path: string, component: () => unknown): Disposable;
73
+ /**
74
+ * Patch an existing route (the host's own or a coexisting loader's) in place —
75
+ * e.g. wrap the Home to inject shelves. Returns the same `patch` so the caller
76
+ * can pair it with `removePatch`. Optional (feature-detected): hosts on a
77
+ * contract below 1.3.0 do not implement it.
78
+ */
79
+ addPatch?(path: string, patch: RoutePatch): RoutePatch;
80
+ /** Remove a patch previously added with {@link addPatch}. Optional. */
81
+ removePatch?(path: string, patch: RoutePatch): RoutePatch;
51
82
  }
52
83
  interface ToastOptions {
53
84
  title?: string;
@@ -242,6 +273,22 @@ interface HostApi {
242
273
  /** Optional self-update surface; present only on hosts that can obtain and
243
274
  * apply an update themselves (see `HostUpdates`). */
244
275
  readonly updates?: HostUpdates;
276
+ /** Optional handshake: identifies the host and the capabilities it implements,
277
+ * so a bundle can adapt (and skip feature-detecting each member). Present on
278
+ * hosts that support it; absent hosts are read via direct feature detection. */
279
+ handshake?(): HostHandshake;
280
+ }
281
+ /** What {@link HostApi.handshake} reports: who is hosting, its versions, and a
282
+ * flat map of capability flags the bundle can branch on. `hostKind` is an opaque
283
+ * host-chosen label (see {@link HostOwnerKind}); the contract names no host. */
284
+ interface HostHandshake {
285
+ readonly hostKind: HostOwnerKind;
286
+ /** The host's own product version (e.g. the daemon version). */
287
+ readonly hostVersion: string;
288
+ /** The contract version the host implements ({@link HOST_API_VERSION}). */
289
+ readonly hostApiVersion: string;
290
+ /** Feature flags, e.g. `{ teardown: true, selfUpdate: true, nativeQam: true }`. */
291
+ readonly capabilities: Readonly<Record<string, boolean>>;
245
292
  }
246
293
  /** An owner label is an opaque, host-chosen string; the contract never enumerates
247
294
  concrete names (that would bake a host/loader identity into the boundary). */
@@ -324,4 +371,4 @@ declare global {
324
371
  }
325
372
  }
326
373
 
327
- export { type Disposable, FORCE_OWNER_GLOBAL, HOST_API_VERSION, type HostApi, type HostLifecycle, type HostMainMenu, type HostNotifications, type HostOwnerKind, type HostOwnerMetadata, type HostQam, type HostRoutes, type HostRpc, type HostUi, type HostUpdates, INJECTED_HOST_GLOBAL, type MainMenuEntry, OWNER_GLOBAL, OWNER_METADATA_GLOBAL, type PlatformApi, type PlatformAppMeta, type PlatformCollection, type PlatformTab, type PluginDescriptor, type QamPanel, type ShelfSource, type ShelvesHostGlobal, type ToastOptions, getInjectedHost, isForcedOwner, readForcedOwner, readOwner };
374
+ export { type Disposable, FORCE_OWNER_GLOBAL, HOST_API_VERSION, type HostApi, type HostHandshake, type HostLifecycle, type HostMainMenu, type HostNotifications, type HostOwnerKind, type HostOwnerMetadata, type HostQam, type HostRoutes, type HostRpc, type HostUi, type HostUpdates, INJECTED_HOST_GLOBAL, type MainMenuEntry, OWNER_GLOBAL, OWNER_METADATA_GLOBAL, type PlatformApi, type PlatformAppMeta, type PlatformCollection, type PlatformTab, type PluginDescriptor, type QamPanel, type RoutePatch, type ShelfSource, type ShelvesHostGlobal, type ToastOptions, getInjectedHost, isForcedOwner, readForcedOwner, readOwner };
package/dist/index.d.ts CHANGED
@@ -23,9 +23,11 @@
23
23
  * npm release version. Bump semver here on shape changes: MINOR for additive,
24
24
  * backward-compatible members (a new optional namespace / field); MAJOR on a
25
25
  * breaking change. 1.2.0 added the optional `updates` namespace and the
26
- * optional `React`/`ReactDOM`/`jsx` UI-surface members.
26
+ * optional `React`/`ReactDOM`/`jsx` UI-surface members. 1.3.0 added the optional
27
+ * `api.handshake()` + `HostHandshake`, `lifecycle.teardown()`, and the
28
+ * `routes.addPatch`/`removePatch` route-patch members.
27
29
  */
28
- declare const HOST_API_VERSION: "1.2.0";
30
+ declare const HOST_API_VERSION: "1.3.0";
29
31
  interface PluginDescriptor {
30
32
  name: string;
31
33
  version: string;
@@ -38,6 +40,14 @@ interface HostLifecycle {
38
40
  register(plugin: PluginDescriptor): Disposable;
39
41
  onMount(cb: () => void): void;
40
42
  onUnmount(cb: () => void): void;
43
+ /**
44
+ * Dispose the CURRENT bundle instance: runs every `onUnmount` handler once and
45
+ * clears them. The host calls this before it hot-swaps a new bundle in place, so
46
+ * two instances never both own the Home. Optional (feature-detected) — a bundle
47
+ * needing clean re-eval should register real teardown in `onUnmount`.
48
+ * Returns the number of handlers run.
49
+ */
50
+ teardown?(): number;
41
51
  }
42
52
  /** Generic RPC channel into the host backend. Each host routes it to the
43
53
  * plugin's data backend through its own transport (an in-process bridge, a
@@ -45,9 +55,30 @@ interface HostLifecycle {
45
55
  interface HostRpc {
46
56
  call<Req = unknown, Res = unknown>(method: string, args?: Req): Promise<Res>;
47
57
  }
58
+ /**
59
+ * Transforms an existing route's props. Receives a shallow copy of the route's
60
+ * props and returns a partial override (today only `children` is honored); a
61
+ * missing/void return leaves the route untouched.
62
+ */
63
+ type RoutePatch = (props: {
64
+ path?: string;
65
+ children?: unknown;
66
+ [key: string]: unknown;
67
+ }) => {
68
+ children?: unknown;
69
+ } | void;
48
70
  interface HostRoutes {
49
71
  /** Register a full-page route; returns a disposer that removes it. */
50
72
  register(path: string, component: () => unknown): Disposable;
73
+ /**
74
+ * Patch an existing route (the host's own or a coexisting loader's) in place —
75
+ * e.g. wrap the Home to inject shelves. Returns the same `patch` so the caller
76
+ * can pair it with `removePatch`. Optional (feature-detected): hosts on a
77
+ * contract below 1.3.0 do not implement it.
78
+ */
79
+ addPatch?(path: string, patch: RoutePatch): RoutePatch;
80
+ /** Remove a patch previously added with {@link addPatch}. Optional. */
81
+ removePatch?(path: string, patch: RoutePatch): RoutePatch;
51
82
  }
52
83
  interface ToastOptions {
53
84
  title?: string;
@@ -242,6 +273,22 @@ interface HostApi {
242
273
  /** Optional self-update surface; present only on hosts that can obtain and
243
274
  * apply an update themselves (see `HostUpdates`). */
244
275
  readonly updates?: HostUpdates;
276
+ /** Optional handshake: identifies the host and the capabilities it implements,
277
+ * so a bundle can adapt (and skip feature-detecting each member). Present on
278
+ * hosts that support it; absent hosts are read via direct feature detection. */
279
+ handshake?(): HostHandshake;
280
+ }
281
+ /** What {@link HostApi.handshake} reports: who is hosting, its versions, and a
282
+ * flat map of capability flags the bundle can branch on. `hostKind` is an opaque
283
+ * host-chosen label (see {@link HostOwnerKind}); the contract names no host. */
284
+ interface HostHandshake {
285
+ readonly hostKind: HostOwnerKind;
286
+ /** The host's own product version (e.g. the daemon version). */
287
+ readonly hostVersion: string;
288
+ /** The contract version the host implements ({@link HOST_API_VERSION}). */
289
+ readonly hostApiVersion: string;
290
+ /** Feature flags, e.g. `{ teardown: true, selfUpdate: true, nativeQam: true }`. */
291
+ readonly capabilities: Readonly<Record<string, boolean>>;
245
292
  }
246
293
  /** An owner label is an opaque, host-chosen string; the contract never enumerates
247
294
  concrete names (that would bake a host/loader identity into the boundary). */
@@ -324,4 +371,4 @@ declare global {
324
371
  }
325
372
  }
326
373
 
327
- export { type Disposable, FORCE_OWNER_GLOBAL, HOST_API_VERSION, type HostApi, type HostLifecycle, type HostMainMenu, type HostNotifications, type HostOwnerKind, type HostOwnerMetadata, type HostQam, type HostRoutes, type HostRpc, type HostUi, type HostUpdates, INJECTED_HOST_GLOBAL, type MainMenuEntry, OWNER_GLOBAL, OWNER_METADATA_GLOBAL, type PlatformApi, type PlatformAppMeta, type PlatformCollection, type PlatformTab, type PluginDescriptor, type QamPanel, type ShelfSource, type ShelvesHostGlobal, type ToastOptions, getInjectedHost, isForcedOwner, readForcedOwner, readOwner };
374
+ export { type Disposable, FORCE_OWNER_GLOBAL, HOST_API_VERSION, type HostApi, type HostHandshake, type HostLifecycle, type HostMainMenu, type HostNotifications, type HostOwnerKind, type HostOwnerMetadata, type HostQam, type HostRoutes, type HostRpc, type HostUi, type HostUpdates, INJECTED_HOST_GLOBAL, type MainMenuEntry, OWNER_GLOBAL, OWNER_METADATA_GLOBAL, type PlatformApi, type PlatformAppMeta, type PlatformCollection, type PlatformTab, type PluginDescriptor, type QamPanel, type RoutePatch, type ShelfSource, type ShelvesHostGlobal, type ToastOptions, getInjectedHost, isForcedOwner, readForcedOwner, readOwner };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/contract/index.ts
2
- var HOST_API_VERSION = "1.2.0";
2
+ var HOST_API_VERSION = "1.3.0";
3
3
  var INJECTED_HOST_GLOBAL = "__SHELVES_HOST__";
4
4
  var FORCE_OWNER_GLOBAL = "__SHELVES_FORCE_OWNER__";
5
5
  var OWNER_GLOBAL = "__DECK_SHELVES_OWNER__";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deck-shelves/host",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "description": "Deck Shelves host contract — the HostApi types all host adapters and the bundle build against.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -32,12 +32,14 @@
32
32
  "lint:fix": "eslint --fix \"src/**/*.ts\"",
33
33
  "test": "vitest run",
34
34
  "test:watch": "vitest",
35
+ "api:check": "pnpm run build && node scripts/check-api.mjs check",
36
+ "api:update": "pnpm run build && node scripts/check-api.mjs update",
35
37
  "check": "pnpm run typecheck && pnpm run lint && pnpm run test",
36
38
  "dev:check": "pnpm run check",
37
39
  "clean": "node scripts/clean.mjs",
38
- "release:dry": "pnpm run clean && pnpm run check && pnpm run build && pnpm pack --dry-run",
39
- "release:local": "pnpm run clean && pnpm run check && pnpm run build && pnpm pack",
40
- "prepublishOnly": "pnpm run clean && pnpm run check && pnpm run build"
40
+ "release:dry": "pnpm run clean && pnpm run check && pnpm run build && node scripts/check-api.mjs check && pnpm pack --dry-run",
41
+ "release:local": "pnpm run clean && pnpm run check && pnpm run build && node scripts/check-api.mjs check && pnpm pack",
42
+ "prepublishOnly": "pnpm run clean && pnpm run check && pnpm run build && node scripts/check-api.mjs check"
41
43
  },
42
44
  "keywords": [
43
45
  "deck-shelves",