@agentshouse/app-bridge 0.1.0-alpha.8 → 0.1.0-alpha.9

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
@@ -17,6 +17,14 @@ port's one listener. It carries six families:
17
17
  absolute path, carries its current address as the return target, and the page
18
18
  returns there when it completes. An App names an address House gave it in a
19
19
  reading and composes none.
20
+ - **Installation** - `install()` offers the page as a Home-screen app. Where the
21
+ browser has an install prompt ready the shell shows it and the call resolves
22
+ `'accepted'` or `'dismissed'` with the User's choice, spending that prompt;
23
+ otherwise, as on every iPhone and iPad, it resolves `'manual'` and the App
24
+ shows its own instructions. A prompt the browser refuses to show, as for a
25
+ call made without a click, rejects with the browser's own `DOMException`
26
+ and stays ready. Call it from a click. The standard
27
+ `display-mode: standalone` media query tells the App it runs installed.
20
28
  - **Status** - the App reference the Runtime port is attached under, sync
21
29
  state, credential state, release availability and observed failure, `ga`:
22
30
  whether the page measures and the visitor's stored analytics choice, and
@@ -105,4 +113,5 @@ records in `consents` each
105
113
  choice leaves, records in `tabs` each `setTab` the shell would take and ignores
106
114
  any other, answers a release code read from the `sources` it was given, or
107
115
  `null`, answers `readScreenshot` from the `screenshots` it was given by App
108
- reference, and attaches a Runtime port.
116
+ reference, answers every `install()` `'manual'`, as a browser with no install
117
+ prompt does, and attaches a Runtime port.
@@ -13,6 +13,7 @@ export interface HouseImageCopy {
13
13
  readonly name: string;
14
14
  readonly media_type: string;
15
15
  }
16
+ type HouseInstallation = 'accepted' | 'dismissed' | 'manual';
16
17
  export interface HouseBridge {
17
18
  readonly runtime: Promise<HouseMessagePort>;
18
19
  address(): string | null;
@@ -20,6 +21,7 @@ export interface HouseBridge {
20
21
  push(address: string): Promise<string>;
21
22
  replace(address: string): Promise<string>;
22
23
  ceremony(path: string): Promise<never>;
24
+ install(): Promise<HouseInstallation>;
23
25
  setTab(tab: HouseTab): void;
24
26
  readAttachment(room: string, attachment: string): Promise<HouseImageCopy | null>;
25
27
  sourceTop(app: string, release?: string): Promise<HouseSourceTop | HouseSourceRefusal | null>;
@@ -30,3 +32,4 @@ export interface HouseBridge {
30
32
  gaConsent(choice: HouseGaChoice): void;
31
33
  }
32
34
  export declare function connectHouseBridge(source?: Promise<HouseBridgePort>): HouseBridge;
35
+ export {};
@@ -35,6 +35,8 @@ export function connectHouseBridge(source = heldBridge()) {
35
35
  let nextAttachment = 0;
36
36
  const sources = new Map();
37
37
  let nextSource = 0;
38
+ const installations = new Map();
39
+ let nextInstallation = 0;
38
40
  const screenshots = new Map();
39
41
  let nextScreenshot = 0;
40
42
  const addressListeners = new Set();
@@ -92,6 +94,20 @@ export function connectHouseBridge(source = heldBridge()) {
92
94
  pending.resolve(answer.image ?? null);
93
95
  return;
94
96
  }
97
+ if (data.house === 'install') {
98
+ const answer = data;
99
+ if (typeof answer.id !== 'number')
100
+ return;
101
+ const pending = installations.get(answer.id);
102
+ if (pending === undefined)
103
+ return;
104
+ installations.delete(answer.id);
105
+ if (answer.outcome !== undefined)
106
+ pending.resolve(answer.outcome);
107
+ else
108
+ pending.reject(new DOMException(answer.refusal?.message, answer.refusal?.name));
109
+ return;
110
+ }
95
111
  if (data.house === 'source') {
96
112
  const answer = data;
97
113
  if (typeof answer.id !== 'number')
@@ -167,6 +183,13 @@ export function connectHouseBridge(source = heldBridge()) {
167
183
  send({ house: 'ceremony', path });
168
184
  return pending.promise;
169
185
  },
186
+ install() {
187
+ const pending = settled();
188
+ const id = ++nextInstallation;
189
+ installations.set(id, pending.settle);
190
+ send({ house: 'install', id });
191
+ return pending.promise;
192
+ },
170
193
  setTab(tab) {
171
194
  send({ house: 'tab', title: tab.title, icon: tab.icon });
172
195
  },
@@ -79,6 +79,9 @@ export function createHouseBridgeTestHost(options = {}) {
79
79
  else if (data.house === 'ceremony') {
80
80
  ceremony(data.path);
81
81
  }
82
+ else if (data.house === 'install') {
83
+ deliver({ house: 'install', id: data.id, outcome: 'manual' });
84
+ }
82
85
  else if (data.house === 'tab') {
83
86
  const change = tabChange(data);
84
87
  if (change !== null)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentshouse/app-bridge",
3
- "version": "0.1.0-alpha.8",
4
- "description": "Renderer-side client of the agents.house App bridge: navigation, the tab title and icon, ceremonies, status, Site image reads, App release code and App screenshot reads, with an in-page test host.",
3
+ "version": "0.1.0-alpha.9",
4
+ "description": "Renderer-side client of the agents.house App bridge: navigation, the tab title and icon, ceremonies, installation, status, Site image reads, App release code and App screenshot reads, with an in-page test host.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "sideEffects": false,