@saga-a2ui/core 0.5.6-rc.1 → 0.7.6

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.
@@ -34,7 +34,8 @@ export interface InstanceEvent<Native = unknown> {
34
34
  read(path: string): unknown;
35
35
  }
36
36
 
37
- type NativeOf<Event> = Event extends InstanceEvent<infer Native> ? Native : never;
37
+ type NativeOf<Event> =
38
+ Event extends InstanceEvent<infer Native> ? Native : never;
38
39
 
39
40
  /**
40
41
  * Optional, per binding. `subject` reads, through a supported application or renderer API and not
@@ -71,12 +72,19 @@ export interface InstanceHandle<Events> {
71
72
 
72
73
  export interface InstanceView {
73
74
  /** The one instance with this ID and kind. Throws when there is none or more than one. */
74
- getById<Events>(id: string, kind: ComponentKind<Events>): InstanceHandle<Events>;
75
+ getById<Events>(
76
+ id: string,
77
+ kind: ComponentKind<Events>,
78
+ ): InstanceHandle<Events>;
75
79
  /**
76
80
  * Setup-time discovery: calls `onHandle` once for each present and later instance with this ID
77
81
  * and kind. Unsubscribing stops discovery only. It disposes no binding and removes no callable.
78
82
  */
79
- watchById<Events>(id: string, kind: ComponentKind<Events>, onHandle: (handle: InstanceHandle<Events>) => void): () => void;
83
+ watchById<Events>(
84
+ id: string,
85
+ kind: ComponentKind<Events>,
86
+ onHandle: (handle: InstanceHandle<Events>) => void,
87
+ ): () => void;
80
88
  }
81
89
 
82
90
  export interface OpenInfo<Events> {
@@ -104,14 +112,19 @@ export interface OpenInstance<Events> {
104
112
  * `unbound` when nothing is installed, and `retired` when the instance was retired or is no
105
113
  * longer live. `started` means the callable received the event; a binding that is busy drops it.
106
114
  */
107
- activate<Name extends keyof Events & string>(event: Name, native: NativeOf<Events[Name]>): 'started' | 'unbound' | 'retired';
115
+ activate<Name extends keyof Events & string>(
116
+ event: Name,
117
+ native: NativeOf<Events[Name]>,
118
+ ): 'started' | 'unbound' | 'retired';
108
119
  /**
109
120
  * The binding now attached to one event of this instance, by identity: `undefined` while
110
121
  * nothing is attached, and never a disposed binding. An adapter that captures it with what it
111
122
  * renders can later tell, by reference, that the callable `activate` would reach is no longer
112
123
  * the one that render showed. A rebind on the same handle is a different reference.
113
124
  */
114
- attached<Name extends keyof Events & string>(event: Name): ActionBinding | undefined;
125
+ attached<Name extends keyof Events & string>(
126
+ event: Name,
127
+ ): ActionBinding | undefined;
115
128
  /**
116
129
  * Calls `listener` synchronously after this instance gains or loses an attached binding, and
117
130
  * once when it retires, with the change already visible through `attached`. A listener that
@@ -235,11 +248,15 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
235
248
  for (const binding of [...registration.bindings]) binding.dispose();
236
249
  }
237
250
 
238
- function handleFor<Events>(registration: Registration, record: InstanceRecord): InstanceHandle<Events> {
251
+ function handleFor<Events>(
252
+ registration: Registration,
253
+ record: InstanceRecord,
254
+ ): InstanceHandle<Events> {
239
255
  return {
240
256
  id: record.componentId,
241
257
  dataPath: record.dataPath,
242
- read: (path) => (record.retired || !record.isLive() ? undefined : record.read(path)),
258
+ read: (path) =>
259
+ record.retired || !record.isLive() ? undefined : record.read(path),
243
260
  bindAction<Name extends keyof Events & string>(
244
261
  event: Name,
245
262
  action: ActionDefinition<Events[Name]>,
@@ -247,7 +264,9 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
247
264
  ) {
248
265
  const subject = options?.subject;
249
266
  if (subject !== undefined && typeof subject !== 'function') {
250
- throw new TypeError(`The subject option for '${record.componentId}' must be a function.`);
267
+ throw new TypeError(
268
+ `The subject option for '${record.componentId}' must be a function.`,
269
+ );
251
270
  }
252
271
  // `isLive` is read fresh: the renderer may have dropped this instance's model before it retires the element.
253
272
  if (!registration.active || record.retired || !record.isLive()) {
@@ -257,7 +276,9 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
257
276
  );
258
277
  }
259
278
  if (!record.events.has(event)) {
260
- throw new Error(`The component '${record.componentId}' does not offer the event '${event}'.`);
279
+ throw new Error(
280
+ `The component '${record.componentId}' does not offer the event '${event}'.`,
281
+ );
261
282
  }
262
283
  if (record.slots.has(event)) {
263
284
  throw new Error(
@@ -267,10 +288,12 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
267
288
  }
268
289
  const installation = {};
269
290
  const detach = (): void => {
270
- const detached = record.slots.get(event)?.installation === installation;
291
+ const detached =
292
+ record.slots.get(event)?.installation === installation;
271
293
  if (detached) record.slots.delete(event);
272
294
  registration.bindings.delete(binding);
273
- for (const scope of registration.callbackScopes) scope.delete(binding);
295
+ for (const scope of registration.callbackScopes)
296
+ scope.delete(binding);
274
297
  if (detached) announce(record);
275
298
  };
276
299
  // Throws for a definition `Action` did not build, before anything is installed.
@@ -291,7 +314,10 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
291
314
  dataPath: record.dataPath,
292
315
  native,
293
316
  read(path) {
294
- if (!delivering) throw new Error('read() answers only while the event is being delivered.');
317
+ if (!delivering)
318
+ throw new Error(
319
+ 'read() answers only while the event is being delivered.',
320
+ );
295
321
  return record.read(path);
296
322
  },
297
323
  };
@@ -328,16 +354,31 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
328
354
  }
329
355
  }
330
356
 
331
- function matches(id: string, kind: ComponentKind<unknown>, record: InstanceRecord): boolean {
332
- return !record.retired && record.componentId === id && record.kind === kind && record.isLive();
357
+ function matches(
358
+ id: string,
359
+ kind: ComponentKind<unknown>,
360
+ record: InstanceRecord,
361
+ ): boolean {
362
+ return (
363
+ !record.retired &&
364
+ record.componentId === id &&
365
+ record.kind === kind &&
366
+ record.isLive()
367
+ );
333
368
  }
334
369
 
335
370
  function viewFor(registration: Registration): InstanceView {
336
371
  return {
337
372
  getById(id, kind) {
338
- if (!registration.active) throw new Error(`The setup that asked for '${id}' has ended.`);
339
- const found = [...instances].filter((record) => matches(id, kind, record));
340
- if (found.length === 0) throw new Error(`No rendered instance has the component ID '${id}' and kind '${kind.label}'.`);
373
+ if (!registration.active)
374
+ throw new Error(`The setup that asked for '${id}' has ended.`);
375
+ const found = [...instances].filter((record) =>
376
+ matches(id, kind, record),
377
+ );
378
+ if (found.length === 0)
379
+ throw new Error(
380
+ `No rendered instance has the component ID '${id}' and kind '${kind.label}'.`,
381
+ );
341
382
  if (found.length > 1) {
342
383
  throw new Error(
343
384
  `${found.length} rendered instances have the component ID '${id}' and kind '${kind.label}'. ` +
@@ -347,12 +388,16 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
347
388
  return handleFor(registration, found[0]!);
348
389
  },
349
390
  watchById(id, kind, onHandle) {
350
- if (!registration.active) throw new Error(`The setup that watches '${id}' has ended.`);
391
+ if (!registration.active)
392
+ throw new Error(`The setup that watches '${id}' has ended.`);
351
393
  const watch: Watch = { id, kind, onHandle };
352
394
  registration.watches.add(watch);
353
395
  for (const record of [...instances]) {
354
396
  if (!registration.watches.has(watch)) break;
355
- if (matches(id, kind, record)) runCallback(registration, () => onHandle(handleFor(registration, record)));
397
+ if (matches(id, kind, record))
398
+ runCallback(registration, () =>
399
+ onHandle(handleFor(registration, record)),
400
+ );
356
401
  }
357
402
  return () => {
358
403
  registration.watches.delete(watch);
@@ -397,8 +442,15 @@ export function createInstanceHost(options: InstanceHostOptions): InstanceHost {
397
442
  instances.add(record);
398
443
  for (const registration of [...registrations]) {
399
444
  for (const watch of [...registration.watches]) {
400
- if (record.retired || !registration.watches.has(watch) || !matches(watch.id, watch.kind, record)) continue;
401
- runCallback(registration, () => watch.onHandle(handleFor(registration, record)));
445
+ if (
446
+ record.retired ||
447
+ !registration.watches.has(watch) ||
448
+ !matches(watch.id, watch.kind, record)
449
+ )
450
+ continue;
451
+ runCallback(registration, () =>
452
+ watch.onHandle(handleFor(registration, record)),
453
+ );
402
454
  }
403
455
  }
404
456
  }