@monimesl/dot-service 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/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Page, c as PageHost, d as PageOptions, f as State, h as definePage, i as Mutation, l as PageId, m as StateUpdate, n as ActionContext, o as PageContext, p as StateChanges, r as DeepReadonly, s as PageDefinition, t as Action, u as PageNavigation } from "./page-DdIm6Q9h.js";
1
+ import { a as Page, c as PageHost, d as PageOptions, f as State, h as definePage, i as Mutation, l as PageId, m as StateUpdate, n as ActionContext, o as PageContext, p as StateChanges, r as DeepReadonly, s as PageDefinition, t as Action, u as PageNavigation } from "./page-Xn5DL6zY.js";
2
2
  import { AppState, ColorScheme, DotEvent, DotEvent as DotEvent$1, DotHooks, DotHooks as DotHooks$1, EventEmitter, HostCaller, HostLayerMessages, LogicLayerMessages, MessageChannel, Navigation, NavigationBarOptions, PageConfigs, PageConfigs as PageConfigs$1, PageHooks, PageLaunchOptions, PageLaunchOptions as PageLaunchOptions$1, PageState, PageState as PageState$1, SystemContext, SystemContext as SystemContext$1, TabBarOptions, Theme, Theme as Theme$1, Transport, Transport as Transport$1, UILayerMessages, createEvent, hostTransport } from "@monimesl/dot-core";
3
3
  //#region src/service.d.ts
4
4
  type ServiceChannel = MessageChannel<LogicLayerMessages, UILayerMessages & HostLayerMessages>;
@@ -55,9 +55,6 @@ export declare class Service implements DotContext {
55
55
  }
56
56
  //#endregion
57
57
  //#region src/plugins/logger.d.ts
58
- /**
59
- * Logs page lifecycle, events, state changes, and errors.
60
- */
61
58
  export declare function logger(options?: {
62
59
  log: (...args: unknown[]) => void;
63
60
  logError: (...args: unknown[]) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/service.ts","../src/plugins/logger.ts","../src/index.ts"],"mappings":";;;KA6BY,iBAAiB,eAC3B,oBACA,kBAAkB;UAGH;EACf;EAEA,SAAS,MAAM;EAEf,WAAW,MAAM;EAEjB,SAAS,MAAM;EAEf,SAAS,MAAM;EAGf,SAAS,MAAM,MAAM,YAAY;EAGjC,MAAM,MAAM,MAAM,iBAAiB,OAAO;EAG1C,SAAS,MAAM,MAAM,OAAO;EAG5B,MAAM,gBAAgB;;UAGP;WACN;EAET,MAAM,SAAS;;UAGA;WACN,OAAO;WACP,eAAe;EAExB,SAAS,OAAO;;UAGD;WACN,QAAQ;WACR,mBAAmB;WACnB;WAEA,UAAU;WACV,QAAQ,QAAQ,cAAY,SAAS;;wBAGhC,UAAU,KAAK,gBAAgB;UAI9B;EACf,WAAW;EACX,MAAM,QAAQ;EACd,OAAO,eAAe;EACtB;;qBAIW,mBAAmB;;WACrB,SAAS;WACT,OAAK,aAAA;EAUF,cAAE,WAAW,OAAO,KAAU,UAAkB;EAuC5D,IAAI,QAAQ;EAKZ;MAcI,SAAS;MAIT,iBAAiB;EAIrB,SAAS,OAAO;EAKhB,QAAQ,qBAAqB;WASpB,UAAU;EAGnB,SAAS,oBAAoB,YAAY,UAAS,sBAAyB;EAU3E,aAAa,aAAa,eAAe;EAqEzC,WAAW;EAmBX,YAAY,MAAM,eAAe;;;;;;;wBCxRnB,OACd;EACE,SAAS;EACT,cAAc;IAKf;;;wBCmCa,cAAc,SAAS,iBAAiB;wBAUxC,WAAW,SAAS,KAAK,+BAA+B"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/service.ts","../src/plugins/logger.ts","../src/index.ts"],"mappings":";;;KA6BY,iBAAiB,eAC3B,oBACA,kBAAkB;UAGH;EACf;EAEA,SAAS,MAAM;EAEf,WAAW,MAAM;EAEjB,SAAS,MAAM;EAEf,SAAS,MAAM;EAGf,SAAS,MAAM,MAAM,YAAY;EAGjC,MAAM,MAAM,MAAM,iBAAiB,OAAO;EAG1C,SAAS,MAAM,MAAM,OAAO;EAG5B,MAAM,gBAAgB;;UAGP;WACN;EAET,MAAM,SAAS;;UAGA;WACN,OAAO;WACP,eAAe;EAExB,SAAS,OAAO;;UAGD;WACN,QAAQ;WACR,mBAAmB;WACnB;WAEA,UAAU;WACV,QAAQ,QAAQ,cAAY,SAAS;;wBAGhC,UAAU,KAAK,gBAAgB;UAI9B;EACf,WAAW;EACX,MAAM,QAAQ;EACd,OAAO,eAAe;EACtB;;qBAIW,mBAAmB;;WACrB,SAAS;WACT,OAAK,aAAA;EAUF,cAAE,WAAW,OAAO,KAAU,UAAkB;EAuC5D,IAAI,QAAQ;EAKZ;MAaI,SAAS;MAIT,iBAAiB;EAIrB,SAAS,OAAO;EAKhB,QAAQ,qBAAqB;WASpB,UAAU;EAGnB,SAAS,oBAAoB,YAAY,UAAS,sBAAyB;EAU3E,aAAa,aAAa,eAAe;EAgEzC,WAAW;EAmBX,YAAY,MAAM,eAAe;;;;wBCpRnB,OACd;EACE,SAAS;EACT,cAAc;IAKf;;;wBCqCa,cAAc,SAAS,iBAAiB;wBAUxC,WAAW,SAAS,KAAK,+BAA+B"}
package/dist/index.js CHANGED
@@ -1,9 +1,6 @@
1
- import { i as definePage, n as defineDot, r as Page, t as Service } from "./service-BNdw42QP.js";
1
+ import { i as definePage, n as defineDot, r as Page, t as Service } from "./service-CHUmeUjF.js";
2
2
  import { connectHost, createEvent, hostTransport, hostTransport as hostTransport$1 } from "@monimesl/dot-core";
3
3
  //#region src/plugins/logger.ts
4
- /**
5
- * Logs page lifecycle, events, state changes, and errors.
6
- */
7
4
  function logger(options = {
8
5
  log: console.debug,
9
6
  logError: console.error
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["hostTransport"],"sources":["../src/plugins/logger.ts","../src/index.ts"],"sourcesContent":["import type { ServicePlugin } from '../service';\n\n/**\n * Logs page lifecycle, events, state changes, and errors.\n */\nexport function logger(\n options: {\n log: (...args: unknown[]) => void;\n logError: (...args: unknown[]) => void;\n } = {\n log: console.debug,\n logError: console.error,\n },\n): ServicePlugin {\n const { log, logError } = options;\n return {\n name: 'logger',\n setup({ hooks }) {\n hooks.on('pageLoad', (page) => log(`[dot] load ${page.id}#${page.instanceId}`, page.state));\n hooks.on('pageUnload', (page) => log(`[dot] unload ${page.id}#${page.instanceId}`));\n hooks.on('event', (page, handler, event) => log(`[dot] ${page.id} ${handler}`, event));\n hooks.on('navigate', (page, navigation) => log(`[dot] ${page.id} navigate`, navigation));\n hooks.on('setState', (page, patch) => log(`[dot] ${page.id} setState`, patch));\n hooks.on('error', (error) => logError('[dot] error', error));\n },\n };\n}\n","import { connectHost, hostTransport } from '@monimesl/dot-core';\n\nimport type { ServiceOptions } from './service';\nimport { Service } from './service';\n\nexport { Page, definePage } from './page';\nexport type {\n Action,\n ActionContext,\n DeepReadonly,\n Mutation,\n PageContext,\n PageDefinition,\n PageHost,\n PageId,\n PageNavigation,\n PageOptions,\n State,\n StateChanges,\n StateUpdate,\n} from './page';\nexport { Service, defineDot } from './service';\nexport type {\n DotContext,\n DotDefinition,\n ServiceHooks,\n ServiceOptions,\n ServicePlugin,\n ServiceChannel,\n} from './service';\nexport { logger } from './plugins/logger';\nexport { createEvent, hostTransport } from '@monimesl/dot-core';\nexport type {\n ColorScheme,\n DotEvent,\n DotHooks,\n NavigationBarOptions,\n PageConfigs,\n PageState,\n PageHooks,\n PageLaunchOptions,\n AppState,\n SystemContext,\n TabBarOptions,\n Theme,\n Transport,\n} from '@monimesl/dot-core';\n\nexport function createService(options: ServiceOptions): Service {\n const service = new Service(options);\n service.start();\n return service;\n}\n\n// Where the running service is found by the next build of the dot, run in the same engine.\nconst RUNNING_SERVICE = Symbol.for('dot.service');\n\n// Starts the service, or hands a newer build's pages to the one already running, as a hot reload does.\nexport function runService(options: Omit<ServiceOptions, 'transport'>): Service {\n const scope = globalThis as unknown as Record<symbol, Service | undefined>;\n const running = scope[RUNNING_SERVICE];\n if (running) {\n // The new build has its own copy of the host connection, which its code's `dash` calls use.\n connectHost(running.callHost);\n running.replacePages(options.pages);\n return running;\n }\n const service = createService({ ...options, transport: hostTransport() });\n scope[RUNNING_SERVICE] = service;\n return service;\n}\n"],"mappings":";;;;;;AAKA,SAAgB,OACd,UAGI;CACF,KAAK,QAAQ;CACb,UAAU,QAAQ;AACpB,GACe;CACf,MAAM,EAAE,KAAK,aAAa;CAC1B,OAAO;EACL,MAAM;EACN,MAAM,EAAE,SAAS;GACf,MAAM,GAAG,aAAa,SAAS,IAAI,cAAc,KAAK,GAAG,GAAG,KAAK,cAAc,KAAK,KAAK,CAAC;GAC1F,MAAM,GAAG,eAAe,SAAS,IAAI,gBAAgB,KAAK,GAAG,GAAG,KAAK,YAAY,CAAC;GAClF,MAAM,GAAG,UAAU,MAAM,SAAS,UAAU,IAAI,SAAS,KAAK,GAAG,GAAG,WAAW,KAAK,CAAC;GACrF,MAAM,GAAG,aAAa,MAAM,eAAe,IAAI,SAAS,KAAK,GAAG,YAAY,UAAU,CAAC;GACvF,MAAM,GAAG,aAAa,MAAM,UAAU,IAAI,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC;GAC7E,MAAM,GAAG,UAAU,UAAU,SAAS,eAAe,KAAK,CAAC;EAC7D;CACF;AACF;;;ACsBA,SAAgB,cAAc,SAAkC;CAC9D,MAAM,UAAU,IAAI,QAAQ,OAAO;CACnC,QAAQ,MAAM;CACd,OAAO;AACT;AAGA,MAAM,kBAAkB,OAAO,IAAI,aAAa;AAGhD,SAAgB,WAAW,SAAqD;CAC9E,MAAM,QAAQ;CACd,MAAM,UAAU,MAAM;CACtB,IAAI,SAAS;EAEX,YAAY,QAAQ,QAAQ;EAC5B,QAAQ,aAAa,QAAQ,KAAK;EAClC,OAAO;CACT;CACA,MAAM,UAAU,cAAc;EAAE,GAAG;EAAS,WAAWA,gBAAc;CAAE,CAAC;CACxE,MAAM,mBAAmB;CACzB,OAAO;AACT"}
1
+ {"version":3,"file":"index.js","names":["hostTransport"],"sources":["../src/plugins/logger.ts","../src/index.ts"],"sourcesContent":["import type { ServicePlugin } from '../service';\n\n// Logs page lifecycle, events, state changes, and errors.\nexport function logger(\n options: {\n log: (...args: unknown[]) => void;\n logError: (...args: unknown[]) => void;\n } = {\n log: console.debug,\n logError: console.error,\n },\n): ServicePlugin {\n const { log, logError } = options;\n return {\n name: 'logger',\n setup({ hooks }) {\n hooks.on('pageLoad', (page) => log(`[dot] load ${page.id}#${page.instanceId}`, page.state));\n hooks.on('pageUnload', (page) => log(`[dot] unload ${page.id}#${page.instanceId}`));\n hooks.on('event', (page, handler, event) => log(`[dot] ${page.id} ${handler}`, event));\n hooks.on('navigate', (page, navigation) => log(`[dot] ${page.id} navigate`, navigation));\n hooks.on('setState', (page, patch) => log(`[dot] ${page.id} setState`, patch));\n hooks.on('error', (error) => logError('[dot] error', error));\n },\n };\n}\n","import { connectHost, hostTransport } from '@monimesl/dot-core';\n\nimport type { ServiceOptions } from './service';\nimport { Service } from './service';\n\nexport { Page, definePage } from './page';\nexport type {\n Action,\n ActionContext,\n DeepReadonly,\n Mutation,\n PageContext,\n PageDefinition,\n PageHost,\n PageId,\n PageNavigation,\n PageOptions,\n State,\n StateChanges,\n StateUpdate,\n} from './page';\nexport { Service, defineDot } from './service';\nexport type {\n DotContext,\n DotDefinition,\n ServiceHooks,\n ServiceOptions,\n ServicePlugin,\n ServiceChannel,\n} from './service';\nexport { logger } from './plugins/logger';\nexport { createEvent, hostTransport } from '@monimesl/dot-core';\nexport type {\n ColorScheme,\n DotEvent,\n DotHooks,\n NavigationBarOptions,\n PageConfigs,\n PageState,\n PageHooks,\n PageLaunchOptions,\n AppState,\n SystemContext,\n TabBarOptions,\n Theme,\n Transport,\n} from '@monimesl/dot-core';\n\nexport function createService(options: ServiceOptions): Service {\n const service = new Service(options);\n service.start();\n return service;\n}\n\n// Where the running service is found by the next build of the dot, run in the same engine.\nconst RUNNING_SERVICE = Symbol.for('dot.service');\n\n// Starts the service, or hands a newer build's pages to the one already running, as a hot reload does.\nexport function runService(options: Omit<ServiceOptions, 'transport'>): Service {\n const scope = globalThis as unknown as Record<symbol, Service | undefined>;\n const running = scope[RUNNING_SERVICE];\n if (running) {\n // The new build has its own copy of the host connection, which its code's `dash` calls use.\n connectHost(running.callHost);\n running.replacePages(options.pages);\n return running;\n }\n const service = createService({ ...options, transport: hostTransport() });\n scope[RUNNING_SERVICE] = service;\n return service;\n}\n"],"mappings":";;;AAGA,SAAgB,OACd,UAGI;CACF,KAAK,QAAQ;CACb,UAAU,QAAQ;AACpB,GACe;CACf,MAAM,EAAE,KAAK,aAAa;CAC1B,OAAO;EACL,MAAM;EACN,MAAM,EAAE,SAAS;GACf,MAAM,GAAG,aAAa,SAAS,IAAI,cAAc,KAAK,GAAG,GAAG,KAAK,cAAc,KAAK,KAAK,CAAC;GAC1F,MAAM,GAAG,eAAe,SAAS,IAAI,gBAAgB,KAAK,GAAG,GAAG,KAAK,YAAY,CAAC;GAClF,MAAM,GAAG,UAAU,MAAM,SAAS,UAAU,IAAI,SAAS,KAAK,GAAG,GAAG,WAAW,KAAK,CAAC;GACrF,MAAM,GAAG,aAAa,MAAM,eAAe,IAAI,SAAS,KAAK,GAAG,YAAY,UAAU,CAAC;GACvF,MAAM,GAAG,aAAa,MAAM,UAAU,IAAI,SAAS,KAAK,GAAG,YAAY,KAAK,CAAC;GAC7E,MAAM,GAAG,UAAU,UAAU,SAAS,eAAe,KAAK,CAAC;EAC7D;CACF;AACF;;;ACwBA,SAAgB,cAAc,SAAkC;CAC9D,MAAM,UAAU,IAAI,QAAQ,OAAO;CACnC,QAAQ,MAAM;CACd,OAAO;AACT;AAGA,MAAM,kBAAkB,OAAO,IAAI,aAAa;AAGhD,SAAgB,WAAW,SAAqD;CAC9E,MAAM,QAAQ;CACd,MAAM,UAAU,MAAM;CACtB,IAAI,SAAS;EAEX,YAAY,QAAQ,QAAQ;EAC5B,QAAQ,aAAa,QAAQ,KAAK;EAClC,OAAO;CACT;CACA,MAAM,UAAU,cAAc;EAAE,GAAG;EAAS,WAAWA,gBAAc;CAAE,CAAC;CACxE,MAAM,mBAAmB;CACzB,OAAO;AACT"}
@@ -79,7 +79,6 @@ declare class Page<S extends PageState = PageState> {
79
79
  get barChanges(): PageBars;
80
80
  setNavigationBar(options: NavigationBarOptions): void;
81
81
  setTabBar(options: TabBarOptions): void;
82
- handlers(): string[];
83
82
  setState(update: StateUpdate<S>): void;
84
83
  mutate(name: string, event?: DotEvent): void;
85
84
  act(name: string, event?: DotEvent): Promise<void>;
@@ -89,4 +88,4 @@ declare class Page<S extends PageState = PageState> {
89
88
  }
90
89
  //#endregion
91
90
  export { Page as a, PageHost as c, PageOptions as d, State as f, definePage as h, Mutation as i, PageId as l, StateUpdate as m, ActionContext as n, PageContext as o, StateChanges as p, DeepReadonly as r, PageDefinition as s, Action as t, PageNavigation as u };
92
- //# sourceMappingURL=page-DdIm6Q9h.d.ts.map
91
+ //# sourceMappingURL=page-Xn5DL6zY.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"page-DdIm6Q9h.d.ts","names":[],"sources":["../src/page.ts"],"mappings":";;;QAqBQ;YAEI;;KAKA,gBAAgB,uCAExB,cAAc;UAED;EACf,KAAK,MAAM,QAAQ,UAAU;EAE7B,QAAQ,MAAM,QAAQ,UAAU;EAEhC,MAAM,MAAM,QAAQ,UAAU;EAE9B,KAAK;;KAGK,aAAa,KAAK,eAAc,6BACxC,IACA,+BACc,WAAW,IAAI,aAAa,EAAE,SAC1C;KAEM,MAAM,KAAK,aAAa;KAExB,aAAa,KAAK,QAAQ,MAAM;KAEhC,YAAY,KAAK,aAAa,OAAO,OAAO,MAAM,OAAO,aAAa;KAItE,SAAS;EACnB,SAAS,OAAO,MAAM,IAAI,OAAO,WAAW,aAAa;;KAG/C,OAAO;EACjB,OAAO,OAAO,MAAM,IAAI,OAAO,kBAAkB;;KAI9C,UAAU,KAAK,YAAW,iBAAiB,YAAY,iBAAgB;UAE3D,YAAY,UAAU,WAAW,IAAI;WAC3C;WACA;WACA,OAAO,MAAM;WAEb,MAAM;EAEf,SAAS,QAAQ,YAAY;EAG7B,iBAAiB,SAAS;EAG1B,UAAU,SAAS;WAEV,uBAAuB,WAAW,SAAS,OAAO,UAAU,GAAG;WAC/D,qBAAqB,WAAW,SAAS,OAAO,UAAU,GAAG,QAAQ;;UAG/D,cAAc,UAAU,WAAW,IAAI,YAAY,YAAY,GAAG,IAAI;WAC5E,YAAY;;UAGN,YAAY,UAAU,WAAW,IAAI;EACpD;EACA,cAAc;EAGd,UAAU;EACV,QAAQ,QAAQ,aAAa,SAAS,YAAY,GAAG,IAAI;EACzD,YAAY,KAAK;EACjB,UAAU,KAAK,SAAS,cAAc,GAAG,IAAI;;UAG9B,eAAe,UAAU,YAAY;WAC3C;WACA,cAAc;WACd,UAAU;WACV,QAAQ,QAAQ;WAChB,YAAY,SAAS,eAAe,SAAS;WAC7C,UAAU,SAAS,eAAe,OAAO;;iBAGpC,WACd,UAAU,WACV,WAAW,eAAe,SAAS,KACnC,WAAW,eAAe,OAAO,KACjC,SAAS,YAAY,GAAG,IAAI,MAAM,eAAe;UAIlC;EACf,OAAO,MAAM,MAAM,OAAO;EAG1B,SAAS,MAAM;WAGN,aAAa;EAEtB,SAAS,MAAM,MAAM,YAAY;WAExB;;UAIM,aAAa;WACnB,OAAO,MAAM;WACb,YAAY;;KAGlB,UAAU,KAAK,eAAe,SAAS;KACvC,QAAQ,KAAK,eAAe,OAAO;cAI3B,KAAK,UAAU,YAAY;;WAC7B;WACA;WACA,SAAS,YAAY,GAAG,UAAU,IAAI,QAAQ;WAC9C,eAAe,cAAc,GAAG,UAAU,IAAI,QAAQ;WAMtD,MAAM;EAMb,YAAA,oBACA,YACA,YAAY,eAAe,IAC3B,MAAM,UACN,WAAW,aAAa;MAiCtB,SAAS,MAAM;MAIf,QAAQ;MAIR,cAAc;EAIlB,iBAAiB,SAAS;EAU1B,UAAU,SAAS;EAUnB;EAKA,SAAS,QAAQ,YAAY;EAqB7B,OAAO,cAAc,QAAQ;EAQvB,IAAI,cAAc,QAAQ,WAAW;EAS3C,SAAS,cAAc,OAAO,WAAW;EAanC,UAAU,gBAAgB,WAC9B,UAAU,MACP,MAAM,WAAW,UAAU,MAC7B;EASH"}
1
+ {"version":3,"file":"page-Xn5DL6zY.d.ts","names":[],"sources":["../src/page.ts"],"mappings":";;;QAqBQ;YAEI;;KAKA,gBAAgB,uCAExB,cAAc;UAED;EACf,KAAK,MAAM,QAAQ,UAAU;EAE7B,QAAQ,MAAM,QAAQ,UAAU;EAEhC,MAAM,MAAM,QAAQ,UAAU;EAE9B,KAAK;;KAGK,aAAa,KAAK,eAAc,6BACxC,IACA,+BACc,WAAW,IAAI,aAAa,EAAE,SAC1C;KAEM,MAAM,KAAK,aAAa;KAExB,aAAa,KAAK,QAAQ,MAAM;KAEhC,YAAY,KAAK,aAAa,OAAO,OAAO,MAAM,OAAO,aAAa;KAItE,SAAS;EACnB,SAAS,OAAO,MAAM,IAAI,OAAO,WAAW,aAAa;;KAG/C,OAAO;EACjB,OAAO,OAAO,MAAM,IAAI,OAAO,kBAAkB;;KAI9C,UAAU,KAAK,YAAW,iBAAiB,YAAY,iBAAgB;UAE3D,YAAY,UAAU,WAAW,IAAI;WAC3C;WACA;WACA,OAAO,MAAM;WAEb,MAAM;EAEf,SAAS,QAAQ,YAAY;EAG7B,iBAAiB,SAAS;EAG1B,UAAU,SAAS;WAEV,uBAAuB,WAAW,SAAS,OAAO,UAAU,GAAG;WAC/D,qBAAqB,WAAW,SAAS,OAAO,UAAU,GAAG,QAAQ;;UAG/D,cAAc,UAAU,WAAW,IAAI,YAAY,YAAY,GAAG,IAAI;WAC5E,YAAY;;UAGN,YAAY,UAAU,WAAW,IAAI;EACpD;EACA,cAAc;EAGd,UAAU;EACV,QAAQ,QAAQ,aAAa,SAAS,YAAY,GAAG,IAAI;EACzD,YAAY,KAAK;EACjB,UAAU,KAAK,SAAS,cAAc,GAAG,IAAI;;UAG9B,eAAe,UAAU,YAAY;WAC3C;WACA,cAAc;WACd,UAAU;WACV,QAAQ,QAAQ;WAChB,YAAY,SAAS,eAAe,SAAS;WAC7C,UAAU,SAAS,eAAe,OAAO;;iBAGpC,WACd,UAAU,WACV,WAAW,eAAe,SAAS,KACnC,WAAW,eAAe,OAAO,KACjC,SAAS,YAAY,GAAG,IAAI,MAAM,eAAe;UAIlC;EACf,OAAO,MAAM,MAAM,OAAO;EAG1B,SAAS,MAAM;WAGN,aAAa;EAEtB,SAAS,MAAM,MAAM,YAAY;WAExB;;UAIM,aAAa;WACnB,OAAO,MAAM;WACb,YAAY;;KAGlB,UAAU,KAAK,eAAe,SAAS;KACvC,QAAQ,KAAK,eAAe,OAAO;cAI3B,KAAK,UAAU,YAAY;;WAC7B;WACA;WACA,SAAS,YAAY,GAAG,UAAU,IAAI,QAAQ;WAC9C,eAAe,cAAc,GAAG,UAAU,IAAI,QAAQ;WAMtD,MAAM;EAMb,YAAA,oBACA,YACA,YAAY,eAAe,IAC3B,MAAM,UACN,WAAW,aAAa;MAiCtB,SAAS,MAAM;MAIf,QAAQ;MAIR,cAAc;EAIlB,iBAAiB,SAAS;EAU1B,UAAU,SAAS;EAUnB,SAAS,QAAQ,YAAY;EAqB7B,OAAO,cAAc,QAAQ;EAQvB,IAAI,cAAc,QAAQ,WAAW;EAS3C,SAAS,cAAc,OAAO,WAAW;EAanC,UAAU,gBAAgB,WAC9B,UAAU,MACP,MAAM,WAAW,UAAU,MAC7B;EASH"}
@@ -115,10 +115,6 @@ var Page = class {
115
115
  };
116
116
  this.#host.showBars(this);
117
117
  }
118
- handlers() {
119
- const { mutations = {}, actions = {} } = this.#definition;
120
- return [...Object.keys(mutations), ...Object.keys(actions)];
121
- }
122
118
  setState(update) {
123
119
  if (this.#closed) return;
124
120
  const changes = typeof update === "function" ? update(this.#state) : update;
@@ -241,7 +237,7 @@ function mapNames(record, create) {
241
237
  function deepFreeze(value) {
242
238
  if (typeof value === "object" && value !== null && !Object.isFrozen(value)) {
243
239
  Object.freeze(value);
244
- Object.values(value).forEach(deepFreeze);
240
+ for (const child of Object.values(value)) deepFreeze(child);
245
241
  }
246
242
  return value;
247
243
  }
@@ -348,23 +344,16 @@ var Service = class {
348
344
  const definition = definitions[page.id];
349
345
  if (!definition) continue;
350
346
  page.close();
351
- if (!(JSON.stringify(previous[page.id]?.initialState) !== JSON.stringify(definition.initialState))) {
347
+ if (JSON.stringify(previous[page.id]?.initialState) !== JSON.stringify(definition.initialState)) {
348
+ const options = this.#stack.pages.find((entry) => entry.instanceId === instanceId)?.options;
349
+ this.loadPage(instanceId, page.id, options);
350
+ } else {
352
351
  const kept = this.#createPage(instanceId, page.id, {
353
352
  state: page.state,
354
353
  barChanges: page.barChanges
355
354
  });
356
355
  this.#sendBars(kept);
357
- continue;
358
356
  }
359
- const restarted = this.#createPage(instanceId, page.id);
360
- this.channel.send("initPageState", {
361
- instanceId,
362
- state: restarted.state
363
- });
364
- this.#sendBars(restarted);
365
- this.hooks.emit("pageLoad", restarted);
366
- const options = this.#stack.pages.find((entry) => entry.instanceId === instanceId)?.options ?? {};
367
- this.reportError(restarted.lifecycle("onLoad", options), instanceId);
368
357
  }
369
358
  }
370
359
  #createPage(instanceId, id, restored) {
@@ -381,7 +370,7 @@ var Service = class {
381
370
  navigate: (page, navigation) => {
382
371
  if (navigation.action !== "back") this.#definition(navigation.page);
383
372
  const { pages, limit } = this.#stack;
384
- if (navigation.action === "push" && pages.length >= limit) throw new Error(`Cannot open "${navigation.page}": ${limit} pages are already open. Use replace or back.`);
373
+ if (navigation.action === "push" && pages.length >= limit) throw new Error(`Can't open "${navigation.page}": ${limit} pages are already open. Use replace or back.`);
385
374
  this.hooks.emit("navigate", page, navigation);
386
375
  this.channel.send("navigate", {
387
376
  ...navigation,
@@ -436,4 +425,4 @@ function instanceIdOf(message) {
436
425
  //#endregion
437
426
  export { definePage as i, defineDot as n, Page as r, Service as t };
438
427
 
439
- //# sourceMappingURL=service-BNdw42QP.js.map
428
+ //# sourceMappingURL=service-CHUmeUjF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service-CHUmeUjF.js","names":[],"sources":["../src/host-calls.ts","../src/page.ts","../src/service.ts"],"sourcesContent":["import type {\n HostCallOptions,\n HostRequest,\n HostResult,\n LogicLayerMessages,\n} from '@monimesl/dot-core';\nimport { HostError, createHostRequest } from '@monimesl/dot-core';\n\nimport type { ServiceChannel } from './service';\n\ninterface WaitingCall {\n readonly method: string;\n resolve(value: unknown): void;\n reject(error: HostError): void;\n}\n\n// Calls to the host that are waiting for their `hostResult`.\nexport class HostCalls {\n readonly #channel: ServiceChannel;\n readonly #waiting = new Map<number, WaitingCall>();\n #nextId = 1;\n\n constructor(channel: ServiceChannel) {\n this.#channel = channel;\n channel.handle('hostResult', (result) => this.#settle(result));\n }\n\n call(method: string, params: unknown, options: HostCallOptions): HostRequest<unknown> {\n const id = this.#nextId++;\n const promise = new Promise<unknown>((resolve, reject) => {\n this.#waiting.set(id, { method, resolve, reject });\n });\n const message: LogicLayerMessages['hostCall'] = { id, method, params };\n if (options.timeout !== undefined) {\n message.timeout = options.timeout;\n }\n this.#channel.send('hostCall', message);\n return createHostRequest(promise, () => this.#cancel(id));\n }\n\n #cancel(id: number): void {\n const call = this.#waiting.get(id);\n if (!call) {\n return;\n }\n this.#waiting.delete(id);\n this.#channel.send('hostCancel', { id });\n call.reject(new HostError('cancelled', `\"${call.method}\" was cancelled`));\n }\n\n #settle(result: HostResult): void {\n const call = this.#waiting.get(result.id);\n // A call cancelled here may still get the host's late answer, which no one wants any more.\n if (!call) {\n return;\n }\n this.#waiting.delete(result.id);\n if ('error' in result) {\n call.reject(new HostError(result.error.code, result.error.message));\n } else {\n call.resolve(result.value);\n }\n }\n}\n","import type {\n DotEvent,\n Navigation,\n NavigationBarOptions,\n PageBars,\n PageConfigs,\n PageHooks,\n PageLaunchOptions,\n PageState,\n TabBarOptions,\n} from '@monimesl/dot-core';\nimport {\n applyChanges,\n checkConfigs,\n checkNavigationBar,\n checkTabBar,\n mergeConfigs,\n} from '@monimesl/dot-core';\nimport type { Dash, DashRequest } from '@monimesl/dot-dash';\nimport { dash, tracked } from '@monimesl/dot-dash';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface DotPageIds {}\n}\n\n// Any string until `.dot/pages.d.ts` lists the dot's pages; the brackets stop TypeScript from\n// applying the condition to each id separately.\nexport type PageId = [keyof DotPageIds] extends [never]\n ? string\n : Extract<keyof DotPageIds, string>;\n\nexport interface PageNavigation {\n push(page: PageId, options?: PageLaunchOptions): void;\n\n replace(page: PageId, options?: PageLaunchOptions): void;\n\n reset(page: PageId, options?: PageLaunchOptions): void;\n\n back(delta?: number): void;\n}\n\nexport type DeepReadonly<T> = T extends (...args: never[]) => unknown\n ? T\n : T extends object\n ? { readonly [K in keyof T]: DeepReadonly<T[K]> }\n : T;\n\nexport type State<S> = DeepReadonly<S>;\n\nexport type StateChanges<S> = Partial<State<S>>;\n\nexport type StateUpdate<S> = StateChanges<S> | ((state: State<S>) => StateChanges<S> | undefined);\n\n// Declared as methods, whose parameters TypeScript checks loosely, so a handler may narrow its\n// event, e.g. `(state, event: DotEvent<{ size: number }>) => ...`.\nexport type Mutation<S> = {\n mutation(state: State<S>, event: DotEvent): StateChanges<S> | undefined;\n}['mutation'];\n\nexport type Action<S> = {\n action(state: State<S>, event: DotEvent): void | Promise<void>;\n}['action'];\n\n// A handler's parameters after `state`: what calling it from another handler takes.\ntype EventArgs<F> = F extends (state: never, ...rest: infer R) => unknown ? R : never;\n\nexport interface PageContext<S extends PageState, Mu, Ac> {\n readonly id: string;\n readonly instanceId: number;\n readonly state: State<S>;\n // Dash, whose calls still running when the page closes are cancelled.\n readonly dash: Dash;\n\n setState(update: StateUpdate<S>): void;\n\n // Changes what Dash's navigation bar shows over this page, from what definePage set.\n setNavigationBar(options: NavigationBarOptions): void;\n\n // Hides or shows Dash's tab bar while this page shows.\n setTabBar(options: TabBarOptions): void;\n\n readonly mutations: { readonly [K in keyof Mu]: (...event: EventArgs<Mu[K]>) => void };\n readonly actions: { readonly [K in keyof Ac]: (...event: EventArgs<Ac[K]>) => Promise<void> };\n}\n\nexport interface ActionContext<S extends PageState, Mu, Ac> extends PageContext<S, Mu, Ac> {\n readonly navigation: PageNavigation;\n}\n\nexport interface PageOptions<S extends PageState, Mu, Ac> {\n id?: string;\n initialState: S;\n // What Dash's bars show while this page shows, over defineDot's configs; `setNavigationBar` and\n // `setTabBar` change them.\n configs?: PageConfigs;\n hooks?: Partial<PageHooks> & ThisType<PageContext<S, Mu, Ac>>;\n mutations?: Mu & ThisType<void>;\n actions?: Ac & ThisType<ActionContext<S, Mu, Ac>>;\n}\n\nexport interface PageDefinition<S extends PageState = PageState> {\n readonly id?: string;\n readonly initialState: S;\n readonly configs?: PageConfigs;\n readonly hooks?: Partial<PageHooks>;\n readonly mutations?: Readonly<Record<string, Mutation<S>>>;\n readonly actions?: Readonly<Record<string, Action<S>>>;\n}\n\nexport function definePage<\n S extends PageState,\n Mu extends Record<string, Mutation<S>>,\n Ac extends Record<string, Action<S>>,\n>(options: PageOptions<S, Mu, Ac>): PageDefinition<S> {\n return options;\n}\n\nexport interface PageHost {\n commit(page: Page, patch: PageState): void;\n\n // The page's bars changed.\n showBars(page: Page): void;\n\n // defineDot's configs, which the page's own override.\n readonly dotConfigs?: PageConfigs | undefined;\n\n navigate(page: Page, navigation: Navigation): void;\n\n readonly strict?: boolean;\n}\n\n// What a page that goes on from an earlier one, as after a hot reload, starts with.\nexport interface RestoredPage<S> {\n readonly state: State<S>;\n readonly barChanges: PageBars;\n}\n\ntype Mutations<S> = Record<string, Mutation<S>>;\ntype Actions<S> = Record<string, Action<S>>;\ntype MutationCalls<S extends PageState> = PageContext<S, Mutations<S>, Actions<S>>['mutations'];\ntype ActionCalls<S extends PageState> = PageContext<S, Mutations<S>, Actions<S>>['actions'];\n\nexport class Page<S extends PageState = PageState> {\n readonly id: string;\n readonly instanceId: number;\n readonly context: PageContext<S, Mutations<S>, Actions<S>>;\n readonly actionContext: ActionContext<S, Mutations<S>, Actions<S>>;\n readonly #definition: PageDefinition<S>;\n readonly #host: PageHost;\n #state: State<S>;\n #closed = false;\n readonly #calls = new Set<DashRequest<unknown>>();\n readonly dash: Dash = tracked(dash, (request) => this.#track(request));\n #previousHook: Promise<unknown> = Promise.resolve();\n // What the page changed in its bars while running, over its configs.\n #barChanges: PageBars;\n\n constructor(\n instanceId: number,\n id: string,\n definition: PageDefinition<S>,\n host: PageHost,\n restored?: RestoredPage<S>,\n ) {\n this.id = id;\n this.instanceId = instanceId;\n this.#definition = definition;\n this.#host = host;\n const state = restored\n ? restored.state\n : (JSON.parse(JSON.stringify(definition.initialState)) as State<S>);\n this.#state = this.#freeze(state);\n this.#barChanges = restored?.barChanges ?? { navigationBar: {}, tabBar: {} };\n checkConfigs(definition.configs ?? {});\n\n const { mutations = {}, actions = {} } = definition;\n const clash = Object.keys(mutations).find((name) => name in actions);\n if (clash) {\n throw new Error(`Page \"${id}\": \"${clash}\" is both a mutation and an action`);\n }\n\n const mutationCalls = mapNames(\n mutations,\n (name) => (event?: DotEvent) => this.mutate(name, event),\n );\n const actionCalls = mapNames(actions, (name) => (event?: DotEvent) => this.act(name, event));\n this.context = new HookContext(this, mutationCalls, actionCalls);\n this.actionContext = new HandlerContext(\n this,\n mutationCalls,\n actionCalls,\n this.#createNavigation(),\n );\n }\n\n get state(): State<S> {\n return this.#state;\n }\n\n get bars(): PageBars {\n return mergeConfigs(this.#host.dotConfigs, this.#definition.configs, this.#barChanges);\n }\n\n get barChanges(): PageBars {\n return this.#barChanges;\n }\n\n setNavigationBar(options: NavigationBarOptions): void {\n checkNavigationBar(options);\n if (this.#closed) {\n return;\n }\n const navigationBar = { ...this.#barChanges.navigationBar, ...options };\n this.#barChanges = { ...this.#barChanges, navigationBar };\n this.#host.showBars(this as Page);\n }\n\n setTabBar(options: TabBarOptions): void {\n checkTabBar(options);\n if (this.#closed) {\n return;\n }\n const tabBar = { ...this.#barChanges.tabBar, ...options };\n this.#barChanges = { ...this.#barChanges, tabBar };\n this.#host.showBars(this as Page);\n }\n\n setState(update: StateUpdate<S>): void {\n if (this.#closed) {\n return;\n }\n const changes = typeof update === 'function' ? update(this.#state) : update;\n if (changes === undefined) {\n return;\n }\n const next = applyChanges(this.#state, changes);\n const patch: PageState = {};\n for (const key of Object.keys(next) as (keyof State<S> & string)[]) {\n if (next[key] !== this.#state[key]) {\n patch[key] = next[key];\n }\n }\n this.#state = this.#freeze(next);\n if (Object.keys(patch).length > 0) {\n this.#host.commit(this as Page, patch);\n }\n }\n\n mutate(name: string, event?: DotEvent): void {\n const mutation = this.#definition.mutations?.[name];\n if (!mutation) {\n throw new Error(`Page \"${this.id}\" has no mutation \"${name}\"`);\n }\n this.#runMutation(mutation, event);\n }\n\n async act(name: string, event?: DotEvent): Promise<void> {\n const action = this.#definition.actions?.[name];\n if (!action) {\n throw new Error(`Page \"${this.id}\" has no action \"${name}\"`);\n }\n await this.#runAction(action, event);\n }\n\n // Runs the mutation or action named by a view event. A mutation is done when this returns.\n dispatch(name: string, event: DotEvent): Promise<void> {\n const action = this.#definition.actions?.[name];\n if (action) {\n return this.#runAction(action, event);\n }\n const mutation = this.#definition.mutations?.[name];\n if (!mutation) {\n throw new Error(`Page \"${this.id}\" has no mutation or action \"${name}\"`);\n }\n this.#runMutation(mutation, event);\n return Promise.resolve();\n }\n\n async lifecycle<K extends keyof PageHooks>(\n hookName: K,\n ...args: Parameters<PageHooks[K]>\n ): Promise<void> {\n const hook = this.#definition.hooks?.[hookName] as\n ((...hookArgs: Parameters<PageHooks[K]>) => unknown) | undefined;\n // Hooks run one at a time, in call order; a failed hook does not block the next one.\n const run = this.#previousHook.then(() => hook?.call(this.context, ...args));\n this.#previousHook = run.catch(() => {});\n await run;\n }\n\n close(): void {\n this.#closed = true;\n for (const request of this.#calls) {\n request.cancel();\n }\n this.#calls.clear();\n }\n\n #track(request: DashRequest<unknown>): void {\n if (this.#closed) {\n return;\n }\n this.#calls.add(request);\n const forget = () => this.#calls.delete(request);\n void request.then(forget, forget);\n }\n\n // Handlers called from other handlers may leave out the event, so it can be undefined here.\n #runMutation(mutation: Mutation<S>, event: DotEvent | undefined): void {\n this.setState((state) => mutation(state, event as DotEvent));\n }\n\n async #runAction(action: Action<S>, event: DotEvent | undefined): Promise<void> {\n await action.call(this.actionContext, this.#state, event as DotEvent);\n }\n\n #createNavigation(): PageNavigation {\n return {\n push: (page, options = {}) => this.#navigate({ action: 'push', page, options }),\n replace: (page, options = {}) => this.#navigate({ action: 'replace', page, options }),\n reset: (page, options = {}) => this.#navigate({ action: 'reset', page, options }),\n back: (delta = 1) => this.#navigate({ action: 'back', delta }),\n };\n }\n\n #navigate(navigation: Navigation): void {\n if (!this.#closed) {\n this.#host.navigate(this as Page, navigation);\n }\n }\n\n #freeze(state: State<S>): State<S> {\n return this.#host.strict ? deepFreeze(state) : state;\n }\n}\n\n// What hooks get as `this`. `setState` is bound, so a hook may destructure it.\nclass HookContext<S extends PageState> implements PageContext<S, Mutations<S>, Actions<S>> {\n readonly id: string;\n readonly instanceId: number;\n readonly mutations: MutationCalls<S>;\n readonly actions: ActionCalls<S>;\n readonly dash: Dash;\n readonly #page: Page<S>;\n\n constructor(page: Page<S>, mutations: MutationCalls<S>, actions: ActionCalls<S>) {\n this.id = page.id;\n this.instanceId = page.instanceId;\n this.dash = page.dash;\n this.mutations = mutations;\n this.actions = actions;\n this.#page = page;\n }\n\n get state(): State<S> {\n return this.#page.state;\n }\n\n readonly setState = (update: StateUpdate<S>): void => {\n this.#page.setState(update);\n };\n\n readonly setNavigationBar = (options: NavigationBarOptions): void => {\n this.#page.setNavigationBar(options);\n };\n\n readonly setTabBar = (options: TabBarOptions): void => {\n this.#page.setTabBar(options);\n };\n}\n\n// What actions get as `this`: the hook context plus navigation.\nclass HandlerContext<S extends PageState>\n extends HookContext<S>\n implements ActionContext<S, Mutations<S>, Actions<S>>\n{\n readonly navigation: PageNavigation;\n\n constructor(\n page: Page<S>,\n mutations: MutationCalls<S>,\n actions: ActionCalls<S>,\n navigation: PageNavigation,\n ) {\n super(page, mutations, actions);\n this.navigation = navigation;\n }\n}\n\nfunction mapNames<T>(\n record: Readonly<Record<string, unknown>>,\n create: (name: string) => T,\n): Record<string, T> {\n return Object.fromEntries(Object.keys(record).map((name) => [name, create(name)]));\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value === 'object' && value !== null && !Object.isFrozen(value)) {\n Object.freeze(value);\n for (const child of Object.values(value)) {\n deepFreeze(child);\n }\n }\n return value;\n}\n","import type {\n DotHooks,\n DotEvent,\n Envelope,\n HostCaller,\n HostLayerMessages,\n LogicLayerMessages,\n Navigation,\n PageConfigs,\n PageLaunchOptions,\n PageState,\n SystemContext,\n Theme,\n Transport,\n UILayerMessages,\n} from '@monimesl/dot-core';\nimport {\n DEFAULT_SYSTEM_CONTEXT,\n checkConfigs,\n connectHost,\n EventEmitter,\n MAX_STACK_DEPTH,\n MessageChannel,\n} from '@monimesl/dot-core';\n\nimport { HostCalls } from './host-calls';\nimport type { PageDefinition, RestoredPage } from './page';\nimport { Page } from './page';\n\nexport type ServiceChannel = MessageChannel<\n LogicLayerMessages,\n UILayerMessages & HostLayerMessages\n>;\n\nexport interface ServiceHooks {\n launch(): void;\n\n pageLoad(page: Page): void;\n\n pageUnload(page: Page): void;\n\n pageShow(page: Page): void;\n\n pageHide(page: Page): void;\n\n // A page asked to navigate; the request is on its way to the view layer.\n navigate(page: Page, navigation: Navigation): void;\n\n // Before a handler runs\n event(page: Page, handler: string, event: DotEvent): void;\n\n // After the state changes, with the changed keys, before they are sent to the view layer\n setState(page: Page, patch: PageState): void;\n\n // The instance is known when the error came from one page.\n error(error: unknown, instanceId: number | undefined): void;\n}\n\nexport interface ServicePlugin {\n readonly name: string;\n\n setup(service: Service): void;\n}\n\nexport interface DotContext {\n readonly theme: Theme;\n readonly systemContext: SystemContext;\n\n setTheme(theme: Theme): void;\n}\n\nexport interface DotDefinition {\n readonly theme?: Theme;\n readonly plugins?: readonly ServicePlugin[];\n readonly pages: readonly [string, ...string[]];\n // What Dash's bars show over every page; each page's configs override them.\n readonly configs?: PageConfigs;\n readonly hooks?: Partial<DotHooks> & ThisType<DotContext>;\n}\n\nexport function defineDot(dot: DotDefinition): DotDefinition {\n return dot;\n}\n\nexport interface ServiceOptions {\n transport: Transport;\n dot?: Partial<DotDefinition>;\n pages: Record<string, PageDefinition>;\n strict?: boolean;\n}\n\n// The logic layer: owns every page's state, runs handlers, and sends state changes to the view layer.\nexport class Service implements DotContext {\n readonly channel: ServiceChannel;\n readonly hooks = new EventEmitter<ServiceHooks>();\n #definitions: Record<string, PageDefinition>;\n readonly #pages = new Map<number, Page>();\n readonly #dot: Partial<DotDefinition>;\n readonly #strict: boolean;\n #theme: Theme;\n #systemContext: SystemContext = DEFAULT_SYSTEM_CONTEXT;\n #stack: HostLayerMessages['syncStack'] = { pages: [], limit: MAX_STACK_DEPTH };\n readonly #hostCalls: HostCalls;\n\n constructor({ transport, pages, dot = {}, strict = false }: ServiceOptions) {\n this.channel = new MessageChannel(transport);\n this.#hostCalls = new HostCalls(this.channel);\n this.#definitions = pages;\n this.#dot = dot;\n this.#strict = strict;\n this.#theme = dot.theme ?? {};\n checkConfigs(dot.configs ?? {});\n\n this.channel.handle('connect', () => this.channel.send('setTheme', { theme: this.#theme }));\n this.channel.handle('syncStack', (stack) => {\n this.#stack = stack;\n });\n this.channel.handle('syncSystemContext', (context) => {\n this.#systemContext = context;\n });\n this.channel.handle('load', ({ instanceId, page, options }) =>\n this.loadPage(instanceId, page, options),\n );\n this.channel.handle('unload', ({ instanceId }) => this.unloadPage(instanceId));\n this.channel.handle('show', ({ instanceId }) => {\n const page = this.getPage(instanceId);\n this.hooks.emit('pageShow', page);\n this.reportError(page.lifecycle('onShow'), instanceId);\n });\n this.channel.handle('hide', ({ instanceId }) => {\n const page = this.getPage(instanceId);\n this.hooks.emit('pageHide', page);\n this.reportError(page.lifecycle('onHide'), instanceId);\n });\n this.channel.handle('event', ({ instanceId, handler, event }) => {\n const page = this.getPage(instanceId);\n this.hooks.emit('event', page, handler, event);\n this.reportError(page.dispatch(handler, event), instanceId);\n });\n\n dot.plugins?.forEach((plugin) => this.use(plugin));\n }\n\n use(plugin: ServicePlugin): this {\n plugin.setup(this);\n return this;\n }\n\n start(): () => void {\n const stopListening = this.channel.listen((error, message) => {\n this.#reportError(error, instanceIdOf(message));\n });\n connectHost(this.callHost);\n this.hooks.emit('launch');\n this.reportError(this.#runLaunchHook());\n return () => {\n stopListening();\n connectHost(null);\n };\n }\n\n get theme(): Theme {\n return this.#theme;\n }\n\n get systemContext(): SystemContext {\n return this.#systemContext;\n }\n\n setTheme(theme: Theme): void {\n this.#theme = theme;\n this.channel.send('setTheme', { theme });\n }\n\n getPage(instanceId: number): Page {\n const page = this.#pages.get(instanceId);\n if (!page) {\n throw new Error(`Page instance ${instanceId} is not loaded`);\n }\n return page;\n }\n\n // Runs a host call, such as `dash.ui.alert`, through this service's channel.\n readonly callHost: HostCaller = (method, params, options) =>\n this.#hostCalls.call(method, params, options);\n\n loadPage(instanceId: number, id: string, options: PageLaunchOptions = {}): Page {\n const page = this.#createPage(instanceId, id);\n this.channel.send('initPageState', { instanceId, state: page.state });\n this.#sendBars(page);\n this.hooks.emit('pageLoad', page);\n this.reportError(page.lifecycle('onLoad', options), instanceId);\n return page;\n }\n\n // Swaps in a newer build's pages, as a hot reload does; a page restarts only if its initialState changed.\n replacePages(definitions: Record<string, PageDefinition>): void {\n const previous = this.#definitions;\n this.#definitions = definitions;\n for (const [instanceId, page] of this.#pages) {\n const definition = definitions[page.id];\n // A page the new build no longer has keeps its old code until it closes.\n if (!definition) {\n continue;\n }\n page.close();\n const initialStateChanged =\n JSON.stringify(previous[page.id]?.initialState) !== JSON.stringify(definition.initialState);\n if (initialStateChanged) {\n // What the page was opened with, for its onLoad to run again.\n const options = this.#stack.pages.find((entry) => entry.instanceId === instanceId)?.options;\n this.loadPage(instanceId, page.id, options);\n } else {\n const kept = this.#createPage(instanceId, page.id, {\n state: page.state,\n barChanges: page.barChanges,\n });\n // The new definePage may set other configs.\n this.#sendBars(kept);\n }\n }\n }\n\n #createPage(instanceId: number, id: string, restored?: RestoredPage<PageState>): Page {\n const page = new Page(\n instanceId,\n id,\n this.#definition(id),\n {\n commit: (page, patch) => {\n this.hooks.emit('setState', page, patch);\n this.channel.send('setPageState', { instanceId: page.instanceId, patchState: patch });\n },\n showBars: (page) => this.#sendBars(page),\n dotConfigs: this.#dot.configs,\n navigate: (page, navigation) => {\n if (navigation.action !== 'back') {\n this.#definition(navigation.page);\n }\n const { pages, limit } = this.#stack;\n if (navigation.action === 'push' && pages.length >= limit) {\n throw new Error(\n `Can't open \"${navigation.page}\": ${limit} pages are already open. Use replace or back.`,\n );\n }\n this.hooks.emit('navigate', page, navigation);\n this.channel.send('navigate', { ...navigation, from: page.instanceId });\n },\n strict: this.#strict,\n },\n restored,\n );\n this.#pages.set(instanceId, page);\n return page;\n }\n\n #sendBars(page: Page): void {\n this.channel.send('pageBars', { instanceId: page.instanceId, ...page.bars });\n }\n\n unloadPage(instanceId: number): void {\n const page = this.#pages.get(instanceId);\n if (!page) {\n return;\n }\n this.#pages.delete(instanceId);\n page.close();\n this.reportError(page.lifecycle('onUnload'), instanceId);\n this.hooks.emit('pageUnload', page);\n }\n\n #definition(id: string): PageDefinition {\n const definition = this.#definitions[id];\n if (!definition) {\n throw new Error(`Unknown page \"${id}\"`);\n }\n return definition;\n }\n\n reportError(work: Promise<void>, instanceId?: number): void {\n work.catch((error: unknown) => {\n this.#reportError(error, instanceId);\n });\n }\n\n async #runLaunchHook(): Promise<void> {\n await this.#dot.hooks?.onLaunch?.call(this);\n }\n\n #reportError(error: unknown, instanceId: number | undefined): void {\n this.hooks.emit('error', error, instanceId);\n const reason = error instanceof Error ? error : new Error(String(error));\n this.#dot.hooks?.onError?.call(this, reason);\n const report: LogicLayerMessages['error'] = { message: reason.message };\n if (instanceId !== undefined) {\n report.instanceId = instanceId;\n }\n this.channel.send('error', report);\n }\n}\n\nfunction instanceIdOf(message: Envelope): number | undefined {\n const payload = message.payload as { instanceId?: unknown } | undefined;\n if (typeof payload?.instanceId === 'number') {\n return payload.instanceId;\n }\n return undefined;\n}\n"],"mappings":"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"}
package/dist/testing.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { f as State, s as PageDefinition } from "./page-DdIm6Q9h.js";
1
+ import { f as State, s as PageDefinition } from "./page-Xn5DL6zY.js";
2
2
  import { DotEvent, Navigation, PageBars, PageLaunchOptions, PageState } from "@monimesl/dot-core";
3
3
  //#region src/testing.d.ts
4
4
  export type TestHost = Readonly<Record<string, (params: never) => unknown>>;
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","names":[],"sources":["../src/testing.ts"],"mappings":";;;YAkBY,WAAW,SAAS,gBAAgB;iBAE/B;EACf;EACA,UAAU;EAEV,OAAO;;iBAGQ;WACN;WACA;;iBAGM,SAAS,UAAU;WACzB,OAAO,MAAM;WACb,kBAAkB;WAClB,sBAAsB;WACtB,oBAAoB;WAEpB,MAAM;EAEf,IAAI,cAAc,mBAAmB;EAErC,SAAS,cAAc,QAAQ,WAAW;EAE1C,QAAQ;EAER,QAAQ;EAER,UAAU;;wBAGU,SAAS,UAAU,WACvC,YAAY,eAAe,MACzB,IAAa,SAAc,SAAa,kBACzC,QAAQ,SAAS"}
1
+ {"version":3,"file":"testing.d.ts","names":[],"sources":["../src/testing.ts"],"mappings":";;;YAqBY,WAAW,SAAS,gBAAgB;iBAE/B;EACf;EACA,UAAU;EAEV,OAAO;;iBAGQ;WACN;WACA;;iBAGM,SAAS,UAAU;WACzB,OAAO,MAAM;WACb,kBAAkB;WAClB,sBAAsB;WACtB,oBAAoB;WAEpB,MAAM;EAEf,IAAI,cAAc,mBAAmB;EAErC,SAAS,cAAc,QAAQ,WAAW;EAE1C,QAAQ;EAER,QAAQ;EAER,UAAU;;wBAGU,SAAS,UAAU,WACvC,YAAY,eAAe,MACzB,IAAa,SAAc,SAAa,kBACzC,QAAQ,SAAS"}
package/dist/testing.js CHANGED
@@ -1,11 +1,10 @@
1
- import { i as definePage, n as defineDot, r as Page } from "./service-BNdw42QP.js";
1
+ import { i as definePage, n as defineDot, r as Page } from "./service-CHUmeUjF.js";
2
2
  import { HostError, connectHost, createEvent, createHostRequest } from "@monimesl/dot-core";
3
3
  //#region src/testing.ts
4
- Object.assign(globalThis, {
5
- definePage,
6
- defineDot,
7
- createEvent
8
- });
4
+ const scope = globalThis;
5
+ scope.definePage = definePage;
6
+ scope.defineDot = defineDot;
7
+ scope.createEvent = createEvent;
9
8
  async function testPage(definition, { id = "test", options = {}, host = {} } = {}) {
10
9
  const patches = [];
11
10
  const navigations = [];
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","names":[],"sources":["../src/testing.ts"],"sourcesContent":["import type {\n DotEvent,\n Navigation,\n PageBars,\n PageLaunchOptions,\n PageState,\n} from '@monimesl/dot-core';\nimport { HostError, connectHost, createEvent, createHostRequest } from '@monimesl/dot-core';\n\nimport type { PageDefinition, State } from './page';\nimport { definePage, Page } from './page';\nimport { defineDot } from './service';\n\n// A dot's code calls these without importing them; the compiler adds the imports when it bundles.\n// Tests import that code directly, so this module provides them, and must be imported first.\nObject.assign(globalThis, { definePage, defineDot, createEvent });\n\n// Fake host methods by name, such as `'dash.ui.alert': () => ({ action: 'ok' })`.\nexport type TestHost = Readonly<Record<string, (params: never) => unknown>>;\n\nexport interface TestPageOptions {\n id?: string;\n options?: PageLaunchOptions;\n // Methods the page may call on the host; any other rejects with `unsupported`.\n host?: TestHost;\n}\n\nexport interface HostCallRecord {\n readonly method: string;\n readonly params: unknown;\n}\n\nexport interface PageTest<S extends PageState> {\n readonly state: State<S>;\n readonly patches: readonly PageState[];\n readonly navigations: readonly Navigation[];\n readonly hostCalls: readonly HostCallRecord[];\n // What Dash's bars show over the page now.\n readonly bars: PageBars;\n\n tap(name: string, detail?: unknown): Promise<void>;\n\n dispatch(name: string, event?: DotEvent): Promise<void>;\n\n show(): Promise<void>;\n\n hide(): Promise<void>;\n\n unload(): Promise<void>;\n}\n\nexport async function testPage<S extends PageState>(\n definition: PageDefinition<S>,\n { id = 'test', options = {}, host = {} }: TestPageOptions = {},\n): Promise<PageTest<S>> {\n const patches: PageState[] = [];\n const navigations: Navigation[] = [];\n const hostCalls: HostCallRecord[] = [];\n connectHost((method, params) => {\n hostCalls.push({ method, params });\n const handler = host[method];\n if (!handler) {\n const error = new HostError('unsupported', `The test gives no host method \"${method}\"`);\n return createHostRequest(Promise.reject(error));\n }\n // Cancelling rejects the call, as it does in a running dot.\n let cancel = () => {};\n const answer = new Promise<unknown>((resolve, reject) => {\n cancel = () => reject(new HostError('cancelled', `\"${method}\" was cancelled`));\n Promise.resolve()\n .then(() => handler(params as never))\n .then(resolve, reject);\n });\n return createHostRequest(answer, () => cancel());\n });\n const page = new Page<S>(1, id, definition, {\n commit: (_page, patch) => patches.push(patch),\n showBars: () => {},\n navigate: (_page, navigation) => navigations.push(navigation),\n strict: true,\n });\n const dispatch = async (name: string, event: DotEvent = createEvent('tap')) => {\n await page.dispatch(name, event);\n };\n\n await page.lifecycle('onLoad', options);\n await page.lifecycle('onShow');\n\n return {\n get state() {\n return page.state;\n },\n get bars() {\n return page.bars;\n },\n patches,\n navigations,\n hostCalls,\n tap: (name, detail = {}) => dispatch(name, createEvent('tap', detail)),\n dispatch,\n show: () => page.lifecycle('onShow'),\n hide: () => page.lifecycle('onHide'),\n unload: async () => {\n page.close();\n await page.lifecycle('onUnload');\n },\n };\n}\n"],"mappings":";;;AAeA,OAAO,OAAO,YAAY;CAAE;CAAY;CAAW;AAAY,CAAC;AAoChE,eAAsB,SACpB,YACA,EAAE,KAAK,QAAQ,UAAU,CAAC,GAAG,OAAO,CAAC,MAAuB,CAAC,GACvC;CACtB,MAAM,UAAuB,CAAC;CAC9B,MAAM,cAA4B,CAAC;CACnC,MAAM,YAA8B,CAAC;CACrC,aAAa,QAAQ,WAAW;EAC9B,UAAU,KAAK;GAAE;GAAQ;EAAO,CAAC;EACjC,MAAM,UAAU,KAAK;EACrB,IAAI,CAAC,SAAS;GACZ,MAAM,QAAQ,IAAI,UAAU,eAAe,kCAAkC,OAAO,EAAE;GACtF,OAAO,kBAAkB,QAAQ,OAAO,KAAK,CAAC;EAChD;EAEA,IAAI,eAAe,CAAC;EACpB,MAAM,SAAS,IAAI,SAAkB,SAAS,WAAW;GACvD,eAAe,OAAO,IAAI,UAAU,aAAa,IAAI,OAAO,gBAAgB,CAAC;GAC7E,QAAQ,QAAQ,CAAC,CACd,WAAW,QAAQ,MAAe,CAAC,CAAC,CACpC,KAAK,SAAS,MAAM;EACzB,CAAC;EACD,OAAO,kBAAkB,cAAc,OAAO,CAAC;CACjD,CAAC;CACD,MAAM,OAAO,IAAI,KAAQ,GAAG,IAAI,YAAY;EAC1C,SAAS,OAAO,UAAU,QAAQ,KAAK,KAAK;EAC5C,gBAAgB,CAAC;EACjB,WAAW,OAAO,eAAe,YAAY,KAAK,UAAU;EAC5D,QAAQ;CACV,CAAC;CACD,MAAM,WAAW,OAAO,MAAc,QAAkB,YAAY,KAAK,MAAM;EAC7E,MAAM,KAAK,SAAS,MAAM,KAAK;CACjC;CAEA,MAAM,KAAK,UAAU,UAAU,OAAO;CACtC,MAAM,KAAK,UAAU,QAAQ;CAE7B,OAAO;EACL,IAAI,QAAQ;GACV,OAAO,KAAK;EACd;EACA,IAAI,OAAO;GACT,OAAO,KAAK;EACd;EACA;EACA;EACA;EACA,MAAM,MAAM,SAAS,CAAC,MAAM,SAAS,MAAM,YAAY,OAAO,MAAM,CAAC;EACrE;EACA,YAAY,KAAK,UAAU,QAAQ;EACnC,YAAY,KAAK,UAAU,QAAQ;EACnC,QAAQ,YAAY;GAClB,KAAK,MAAM;GACX,MAAM,KAAK,UAAU,UAAU;EACjC;CACF;AACF"}
1
+ {"version":3,"file":"testing.js","names":[],"sources":["../src/testing.ts"],"sourcesContent":["import type {\n DotEvent,\n Navigation,\n PageBars,\n PageLaunchOptions,\n PageState,\n} from '@monimesl/dot-core';\nimport { HostError, connectHost, createEvent, createHostRequest } from '@monimesl/dot-core';\n\nimport type { PageDefinition, State } from './page';\nimport { definePage, Page } from './page';\nimport { defineDot } from './service';\n\n// A dot's code calls these without importing them; the compiler adds the imports when it bundles.\n// Tests import that code directly, so this module provides them, and must be imported first.\nconst scope = globalThis as unknown as Record<string, unknown>;\nscope.definePage = definePage;\nscope.defineDot = defineDot;\nscope.createEvent = createEvent;\n\n// Fake host methods by name, such as `'dash.ui.alert': () => ({ action: 'ok' })`.\nexport type TestHost = Readonly<Record<string, (params: never) => unknown>>;\n\nexport interface TestPageOptions {\n id?: string;\n options?: PageLaunchOptions;\n // Methods the page may call on the host; any other rejects with `unsupported`.\n host?: TestHost;\n}\n\nexport interface HostCallRecord {\n readonly method: string;\n readonly params: unknown;\n}\n\nexport interface PageTest<S extends PageState> {\n readonly state: State<S>;\n readonly patches: readonly PageState[];\n readonly navigations: readonly Navigation[];\n readonly hostCalls: readonly HostCallRecord[];\n // What Dash's bars show over the page now.\n readonly bars: PageBars;\n\n tap(name: string, detail?: unknown): Promise<void>;\n\n dispatch(name: string, event?: DotEvent): Promise<void>;\n\n show(): Promise<void>;\n\n hide(): Promise<void>;\n\n unload(): Promise<void>;\n}\n\nexport async function testPage<S extends PageState>(\n definition: PageDefinition<S>,\n { id = 'test', options = {}, host = {} }: TestPageOptions = {},\n): Promise<PageTest<S>> {\n const patches: PageState[] = [];\n const navigations: Navigation[] = [];\n const hostCalls: HostCallRecord[] = [];\n connectHost((method, params) => {\n hostCalls.push({ method, params });\n const handler = host[method];\n if (!handler) {\n const error = new HostError('unsupported', `The test gives no host method \"${method}\"`);\n return createHostRequest(Promise.reject(error));\n }\n // Cancelling rejects the call, as it does in a running dot.\n let cancel = () => {};\n const answer = new Promise<unknown>((resolve, reject) => {\n cancel = () => reject(new HostError('cancelled', `\"${method}\" was cancelled`));\n Promise.resolve()\n .then(() => handler(params as never))\n .then(resolve, reject);\n });\n return createHostRequest(answer, () => cancel());\n });\n const page = new Page<S>(1, id, definition, {\n commit: (_page, patch) => patches.push(patch),\n showBars: () => {},\n navigate: (_page, navigation) => navigations.push(navigation),\n strict: true,\n });\n const dispatch = async (name: string, event: DotEvent = createEvent('tap')) => {\n await page.dispatch(name, event);\n };\n\n await page.lifecycle('onLoad', options);\n await page.lifecycle('onShow');\n\n return {\n get state() {\n return page.state;\n },\n get bars() {\n return page.bars;\n },\n patches,\n navigations,\n hostCalls,\n tap: (name, detail = {}) => dispatch(name, createEvent('tap', detail)),\n dispatch,\n show: () => page.lifecycle('onShow'),\n hide: () => page.lifecycle('onHide'),\n unload: async () => {\n page.close();\n await page.lifecycle('onUnload');\n },\n };\n}\n"],"mappings":";;;AAeA,MAAM,QAAQ;AACd,MAAM,aAAa;AACnB,MAAM,YAAY;AAClB,MAAM,cAAc;AAoCpB,eAAsB,SACpB,YACA,EAAE,KAAK,QAAQ,UAAU,CAAC,GAAG,OAAO,CAAC,MAAuB,CAAC,GACvC;CACtB,MAAM,UAAuB,CAAC;CAC9B,MAAM,cAA4B,CAAC;CACnC,MAAM,YAA8B,CAAC;CACrC,aAAa,QAAQ,WAAW;EAC9B,UAAU,KAAK;GAAE;GAAQ;EAAO,CAAC;EACjC,MAAM,UAAU,KAAK;EACrB,IAAI,CAAC,SAAS;GACZ,MAAM,QAAQ,IAAI,UAAU,eAAe,kCAAkC,OAAO,EAAE;GACtF,OAAO,kBAAkB,QAAQ,OAAO,KAAK,CAAC;EAChD;EAEA,IAAI,eAAe,CAAC;EACpB,MAAM,SAAS,IAAI,SAAkB,SAAS,WAAW;GACvD,eAAe,OAAO,IAAI,UAAU,aAAa,IAAI,OAAO,gBAAgB,CAAC;GAC7E,QAAQ,QAAQ,CAAC,CACd,WAAW,QAAQ,MAAe,CAAC,CAAC,CACpC,KAAK,SAAS,MAAM;EACzB,CAAC;EACD,OAAO,kBAAkB,cAAc,OAAO,CAAC;CACjD,CAAC;CACD,MAAM,OAAO,IAAI,KAAQ,GAAG,IAAI,YAAY;EAC1C,SAAS,OAAO,UAAU,QAAQ,KAAK,KAAK;EAC5C,gBAAgB,CAAC;EACjB,WAAW,OAAO,eAAe,YAAY,KAAK,UAAU;EAC5D,QAAQ;CACV,CAAC;CACD,MAAM,WAAW,OAAO,MAAc,QAAkB,YAAY,KAAK,MAAM;EAC7E,MAAM,KAAK,SAAS,MAAM,KAAK;CACjC;CAEA,MAAM,KAAK,UAAU,UAAU,OAAO;CACtC,MAAM,KAAK,UAAU,QAAQ;CAE7B,OAAO;EACL,IAAI,QAAQ;GACV,OAAO,KAAK;EACd;EACA,IAAI,OAAO;GACT,OAAO,KAAK;EACd;EACA;EACA;EACA;EACA,MAAM,MAAM,SAAS,CAAC,MAAM,SAAS,MAAM,YAAY,OAAO,MAAM,CAAC;EACrE;EACA,YAAY,KAAK,UAAU,QAAQ;EACnC,YAAY,KAAK,UAAU,QAAQ;EACnC,QAAQ,YAAY;GAClB,KAAK,MAAM;GACX,MAAM,KAAK,UAAU,UAAU;EACjC;CACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monimesl/dot-service",
3
- "version": "0.1.0-alpha.8",
3
+ "version": "0.1.0-alpha.9",
4
4
  "description": "Dot logic layer: pages, state and plugins",
5
5
  "type": "module",
6
6
  "repository": {
@@ -30,8 +30,8 @@
30
30
  "main": "./dist/index.js",
31
31
  "types": "./dist/index.d.ts",
32
32
  "dependencies": {
33
- "@monimesl/dot-core": "0.1.0-alpha.8",
34
- "@monimesl/dot-dash": "0.1.0-alpha.8"
33
+ "@monimesl/dot-core": "0.1.0-alpha.9",
34
+ "@monimesl/dot-dash": "0.1.0-alpha.9"
35
35
  },
36
36
  "devDependencies": {
37
37
  "publint": "^0.3.24",
@@ -1 +0,0 @@
1
- {"version":3,"file":"service-BNdw42QP.js","names":[],"sources":["../src/host-calls.ts","../src/page.ts","../src/service.ts"],"sourcesContent":["import type {\n HostCallOptions,\n HostRequest,\n HostResult,\n LogicLayerMessages,\n} from '@monimesl/dot-core';\nimport { HostError, createHostRequest } from '@monimesl/dot-core';\n\nimport type { ServiceChannel } from './service';\n\ninterface WaitingCall {\n readonly method: string;\n resolve(value: unknown): void;\n reject(error: HostError): void;\n}\n\n// Calls to the host that are waiting for their `hostResult`.\nexport class HostCalls {\n readonly #channel: ServiceChannel;\n readonly #waiting = new Map<number, WaitingCall>();\n #nextId = 1;\n\n constructor(channel: ServiceChannel) {\n this.#channel = channel;\n channel.handle('hostResult', (result) => this.#settle(result));\n }\n\n call(method: string, params: unknown, options: HostCallOptions): HostRequest<unknown> {\n const id = this.#nextId++;\n const promise = new Promise<unknown>((resolve, reject) => {\n this.#waiting.set(id, { method, resolve, reject });\n });\n const message: LogicLayerMessages['hostCall'] = { id, method, params };\n if (options.timeout !== undefined) {\n message.timeout = options.timeout;\n }\n this.#channel.send('hostCall', message);\n return createHostRequest(promise, () => this.#cancel(id));\n }\n\n #cancel(id: number): void {\n const call = this.#waiting.get(id);\n if (!call) {\n return;\n }\n this.#waiting.delete(id);\n this.#channel.send('hostCancel', { id });\n call.reject(new HostError('cancelled', `\"${call.method}\" was cancelled`));\n }\n\n #settle(result: HostResult): void {\n const call = this.#waiting.get(result.id);\n // A call cancelled here may still get the host's late answer, which no one wants any more.\n if (!call) {\n return;\n }\n this.#waiting.delete(result.id);\n if ('error' in result) {\n call.reject(new HostError(result.error.code, result.error.message));\n } else {\n call.resolve(result.value);\n }\n }\n}\n","import type {\n DotEvent,\n Navigation,\n NavigationBarOptions,\n PageBars,\n PageConfigs,\n PageHooks,\n PageLaunchOptions,\n PageState,\n TabBarOptions,\n} from '@monimesl/dot-core';\nimport {\n applyChanges,\n checkConfigs,\n checkNavigationBar,\n checkTabBar,\n mergeConfigs,\n} from '@monimesl/dot-core';\nimport type { Dash, DashRequest } from '@monimesl/dot-dash';\nimport { dash, tracked } from '@monimesl/dot-dash';\n\ndeclare global {\n // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n interface DotPageIds {}\n}\n\n// Any string until `.dot/pages.d.ts` lists the dot's pages; the brackets stop TypeScript from\n// applying the condition to each id separately.\nexport type PageId = [keyof DotPageIds] extends [never]\n ? string\n : Extract<keyof DotPageIds, string>;\n\nexport interface PageNavigation {\n push(page: PageId, options?: PageLaunchOptions): void;\n\n replace(page: PageId, options?: PageLaunchOptions): void;\n\n reset(page: PageId, options?: PageLaunchOptions): void;\n\n back(delta?: number): void;\n}\n\nexport type DeepReadonly<T> = T extends (...args: never[]) => unknown\n ? T\n : T extends object\n ? { readonly [K in keyof T]: DeepReadonly<T[K]> }\n : T;\n\nexport type State<S> = DeepReadonly<S>;\n\nexport type StateChanges<S> = Partial<State<S>>;\n\nexport type StateUpdate<S> = StateChanges<S> | ((state: State<S>) => StateChanges<S> | undefined);\n\n// Declared as methods, whose parameters TypeScript checks loosely, so a handler may narrow its\n// event, e.g. `(state, event: DotEvent<{ size: number }>) => ...`.\nexport type Mutation<S> = {\n mutation(state: State<S>, event: DotEvent): StateChanges<S> | undefined;\n}['mutation'];\n\nexport type Action<S> = {\n action(state: State<S>, event: DotEvent): void | Promise<void>;\n}['action'];\n\n// A handler's parameters after `state`: what calling it from another handler takes.\ntype EventArgs<F> = F extends (state: never, ...rest: infer R) => unknown ? R : never;\n\nexport interface PageContext<S extends PageState, Mu, Ac> {\n readonly id: string;\n readonly instanceId: number;\n readonly state: State<S>;\n // Dash, whose calls still running when the page closes are cancelled.\n readonly dash: Dash;\n\n setState(update: StateUpdate<S>): void;\n\n // Changes what Dash's navigation bar shows over this page, from what definePage set.\n setNavigationBar(options: NavigationBarOptions): void;\n\n // Hides or shows Dash's tab bar while this page shows.\n setTabBar(options: TabBarOptions): void;\n\n readonly mutations: { readonly [K in keyof Mu]: (...event: EventArgs<Mu[K]>) => void };\n readonly actions: { readonly [K in keyof Ac]: (...event: EventArgs<Ac[K]>) => Promise<void> };\n}\n\nexport interface ActionContext<S extends PageState, Mu, Ac> extends PageContext<S, Mu, Ac> {\n readonly navigation: PageNavigation;\n}\n\nexport interface PageOptions<S extends PageState, Mu, Ac> {\n id?: string;\n initialState: S;\n // What Dash's bars show while this page shows, over defineDot's configs; `setNavigationBar` and\n // `setTabBar` change them.\n configs?: PageConfigs;\n hooks?: Partial<PageHooks> & ThisType<PageContext<S, Mu, Ac>>;\n mutations?: Mu & ThisType<void>;\n actions?: Ac & ThisType<ActionContext<S, Mu, Ac>>;\n}\n\nexport interface PageDefinition<S extends PageState = PageState> {\n readonly id?: string;\n readonly initialState: S;\n readonly configs?: PageConfigs;\n readonly hooks?: Partial<PageHooks>;\n readonly mutations?: Readonly<Record<string, Mutation<S>>>;\n readonly actions?: Readonly<Record<string, Action<S>>>;\n}\n\nexport function definePage<\n S extends PageState,\n Mu extends Record<string, Mutation<S>>,\n Ac extends Record<string, Action<S>>,\n>(options: PageOptions<S, Mu, Ac>): PageDefinition<S> {\n return options;\n}\n\nexport interface PageHost {\n commit(page: Page, patch: PageState): void;\n\n // The page's bars changed.\n showBars(page: Page): void;\n\n // defineDot's configs, which the page's own override.\n readonly dotConfigs?: PageConfigs | undefined;\n\n navigate(page: Page, navigation: Navigation): void;\n\n readonly strict?: boolean;\n}\n\n// What a page that goes on from an earlier one, as after a hot reload, starts with.\nexport interface RestoredPage<S> {\n readonly state: State<S>;\n readonly barChanges: PageBars;\n}\n\ntype Mutations<S> = Record<string, Mutation<S>>;\ntype Actions<S> = Record<string, Action<S>>;\ntype MutationCalls<S extends PageState> = PageContext<S, Mutations<S>, Actions<S>>['mutations'];\ntype ActionCalls<S extends PageState> = PageContext<S, Mutations<S>, Actions<S>>['actions'];\n\nexport class Page<S extends PageState = PageState> {\n readonly id: string;\n readonly instanceId: number;\n readonly context: PageContext<S, Mutations<S>, Actions<S>>;\n readonly actionContext: ActionContext<S, Mutations<S>, Actions<S>>;\n readonly #definition: PageDefinition<S>;\n readonly #host: PageHost;\n #state: State<S>;\n #closed = false;\n readonly #calls = new Set<DashRequest<unknown>>();\n readonly dash: Dash = tracked(dash, (request) => this.#track(request));\n #previousHook: Promise<unknown> = Promise.resolve();\n // What the page changed in its bars while running, over its configs.\n #barChanges: PageBars;\n\n constructor(\n instanceId: number,\n id: string,\n definition: PageDefinition<S>,\n host: PageHost,\n restored?: RestoredPage<S>,\n ) {\n this.id = id;\n this.instanceId = instanceId;\n this.#definition = definition;\n this.#host = host;\n const state = restored\n ? restored.state\n : (JSON.parse(JSON.stringify(definition.initialState)) as State<S>);\n this.#state = this.#freeze(state);\n this.#barChanges = restored?.barChanges ?? { navigationBar: {}, tabBar: {} };\n checkConfigs(definition.configs ?? {});\n\n const { mutations = {}, actions = {} } = definition;\n const clash = Object.keys(mutations).find((name) => name in actions);\n if (clash) {\n throw new Error(`Page \"${id}\": \"${clash}\" is both a mutation and an action`);\n }\n\n const mutationCalls = mapNames(\n mutations,\n (name) => (event?: DotEvent) => this.mutate(name, event),\n );\n const actionCalls = mapNames(actions, (name) => (event?: DotEvent) => this.act(name, event));\n this.context = new HookContext(this, mutationCalls, actionCalls);\n this.actionContext = new HandlerContext(\n this,\n mutationCalls,\n actionCalls,\n this.#createNavigation(),\n );\n }\n\n get state(): State<S> {\n return this.#state;\n }\n\n get bars(): PageBars {\n return mergeConfigs(this.#host.dotConfigs, this.#definition.configs, this.#barChanges);\n }\n\n get barChanges(): PageBars {\n return this.#barChanges;\n }\n\n setNavigationBar(options: NavigationBarOptions): void {\n checkNavigationBar(options);\n if (this.#closed) {\n return;\n }\n const navigationBar = { ...this.#barChanges.navigationBar, ...options };\n this.#barChanges = { ...this.#barChanges, navigationBar };\n this.#host.showBars(this as Page);\n }\n\n setTabBar(options: TabBarOptions): void {\n checkTabBar(options);\n if (this.#closed) {\n return;\n }\n const tabBar = { ...this.#barChanges.tabBar, ...options };\n this.#barChanges = { ...this.#barChanges, tabBar };\n this.#host.showBars(this as Page);\n }\n\n handlers(): string[] {\n const { mutations = {}, actions = {} } = this.#definition;\n return [...Object.keys(mutations), ...Object.keys(actions)];\n }\n\n setState(update: StateUpdate<S>): void {\n if (this.#closed) {\n return;\n }\n const changes = typeof update === 'function' ? update(this.#state) : update;\n if (changes === undefined) {\n return;\n }\n const next = applyChanges(this.#state, changes);\n const patch: PageState = {};\n for (const key of Object.keys(next) as (keyof State<S> & string)[]) {\n if (next[key] !== this.#state[key]) {\n patch[key] = next[key];\n }\n }\n this.#state = this.#freeze(next);\n if (Object.keys(patch).length > 0) {\n this.#host.commit(this as Page, patch);\n }\n }\n\n mutate(name: string, event?: DotEvent): void {\n const mutation = this.#definition.mutations?.[name];\n if (!mutation) {\n throw new Error(`Page \"${this.id}\" has no mutation \"${name}\"`);\n }\n this.#runMutation(mutation, event);\n }\n\n async act(name: string, event?: DotEvent): Promise<void> {\n const action = this.#definition.actions?.[name];\n if (!action) {\n throw new Error(`Page \"${this.id}\" has no action \"${name}\"`);\n }\n await this.#runAction(action, event);\n }\n\n // Runs the mutation or action named by a view event. A mutation is done when this returns.\n dispatch(name: string, event: DotEvent): Promise<void> {\n const action = this.#definition.actions?.[name];\n if (action) {\n return this.#runAction(action, event);\n }\n const mutation = this.#definition.mutations?.[name];\n if (!mutation) {\n throw new Error(`Page \"${this.id}\" has no mutation or action \"${name}\"`);\n }\n this.#runMutation(mutation, event);\n return Promise.resolve();\n }\n\n async lifecycle<K extends keyof PageHooks>(\n hookName: K,\n ...args: Parameters<PageHooks[K]>\n ): Promise<void> {\n const hook = this.#definition.hooks?.[hookName] as\n ((...hookArgs: Parameters<PageHooks[K]>) => unknown) | undefined;\n // Hooks run one at a time, in call order; a failed hook does not block the next one.\n const run = this.#previousHook.then(() => hook?.call(this.context, ...args));\n this.#previousHook = run.catch(() => {});\n await run;\n }\n\n close(): void {\n this.#closed = true;\n for (const request of this.#calls) {\n request.cancel();\n }\n this.#calls.clear();\n }\n\n #track(request: DashRequest<unknown>): void {\n if (this.#closed) {\n return;\n }\n this.#calls.add(request);\n const forget = () => this.#calls.delete(request);\n void request.then(forget, forget);\n }\n\n // Handlers called from other handlers may leave out the event, so it can be undefined here.\n #runMutation(mutation: Mutation<S>, event: DotEvent | undefined): void {\n this.setState((state) => mutation(state, event as DotEvent));\n }\n\n async #runAction(action: Action<S>, event: DotEvent | undefined): Promise<void> {\n await action.call(this.actionContext, this.#state, event as DotEvent);\n }\n\n #createNavigation(): PageNavigation {\n return {\n push: (page, options = {}) => this.#navigate({ action: 'push', page, options }),\n replace: (page, options = {}) => this.#navigate({ action: 'replace', page, options }),\n reset: (page, options = {}) => this.#navigate({ action: 'reset', page, options }),\n back: (delta = 1) => this.#navigate({ action: 'back', delta }),\n };\n }\n\n #navigate(navigation: Navigation): void {\n if (!this.#closed) {\n this.#host.navigate(this as Page, navigation);\n }\n }\n\n #freeze(state: State<S>): State<S> {\n return this.#host.strict ? deepFreeze(state) : state;\n }\n}\n\n// What hooks get as `this`. `setState` is bound, so a hook may destructure it.\nclass HookContext<S extends PageState> implements PageContext<S, Mutations<S>, Actions<S>> {\n readonly id: string;\n readonly instanceId: number;\n readonly mutations: MutationCalls<S>;\n readonly actions: ActionCalls<S>;\n readonly dash: Dash;\n readonly #page: Page<S>;\n\n constructor(page: Page<S>, mutations: MutationCalls<S>, actions: ActionCalls<S>) {\n this.id = page.id;\n this.instanceId = page.instanceId;\n this.dash = page.dash;\n this.mutations = mutations;\n this.actions = actions;\n this.#page = page;\n }\n\n get state(): State<S> {\n return this.#page.state;\n }\n\n readonly setState = (update: StateUpdate<S>): void => {\n this.#page.setState(update);\n };\n\n readonly setNavigationBar = (options: NavigationBarOptions): void => {\n this.#page.setNavigationBar(options);\n };\n\n readonly setTabBar = (options: TabBarOptions): void => {\n this.#page.setTabBar(options);\n };\n}\n\n// What actions get as `this`: the hook context plus navigation.\nclass HandlerContext<S extends PageState>\n extends HookContext<S>\n implements ActionContext<S, Mutations<S>, Actions<S>>\n{\n readonly navigation: PageNavigation;\n\n constructor(\n page: Page<S>,\n mutations: MutationCalls<S>,\n actions: ActionCalls<S>,\n navigation: PageNavigation,\n ) {\n super(page, mutations, actions);\n this.navigation = navigation;\n }\n}\n\nfunction mapNames<T>(\n record: Readonly<Record<string, unknown>>,\n create: (name: string) => T,\n): Record<string, T> {\n return Object.fromEntries(Object.keys(record).map((name) => [name, create(name)]));\n}\n\nfunction deepFreeze<T>(value: T): T {\n if (typeof value === 'object' && value !== null && !Object.isFrozen(value)) {\n Object.freeze(value);\n Object.values(value).forEach(deepFreeze);\n }\n return value;\n}\n","import type {\n DotHooks,\n DotEvent,\n Envelope,\n HostCaller,\n HostLayerMessages,\n LogicLayerMessages,\n Navigation,\n PageConfigs,\n PageLaunchOptions,\n PageState,\n SystemContext,\n Theme,\n Transport,\n UILayerMessages,\n} from '@monimesl/dot-core';\nimport {\n DEFAULT_SYSTEM_CONTEXT,\n checkConfigs,\n connectHost,\n EventEmitter,\n MAX_STACK_DEPTH,\n MessageChannel,\n} from '@monimesl/dot-core';\n\nimport { HostCalls } from './host-calls';\nimport type { PageDefinition, RestoredPage } from './page';\nimport { Page } from './page';\n\nexport type ServiceChannel = MessageChannel<\n LogicLayerMessages,\n UILayerMessages & HostLayerMessages\n>;\n\nexport interface ServiceHooks {\n launch(): void;\n\n pageLoad(page: Page): void;\n\n pageUnload(page: Page): void;\n\n pageShow(page: Page): void;\n\n pageHide(page: Page): void;\n\n // A page asked to navigate; the request is on its way to the view layer.\n navigate(page: Page, navigation: Navigation): void;\n\n // Before a handler runs\n event(page: Page, handler: string, event: DotEvent): void;\n\n // After the state changes, with the changed keys, before they are sent to the view layer\n setState(page: Page, patch: PageState): void;\n\n // The instance is known when the error came from one page.\n error(error: unknown, instanceId: number | undefined): void;\n}\n\nexport interface ServicePlugin {\n readonly name: string;\n\n setup(service: Service): void;\n}\n\nexport interface DotContext {\n readonly theme: Theme;\n readonly systemContext: SystemContext;\n\n setTheme(theme: Theme): void;\n}\n\nexport interface DotDefinition {\n readonly theme?: Theme;\n readonly plugins?: readonly ServicePlugin[];\n readonly pages: readonly [string, ...string[]];\n // What Dash's bars show over every page; each page's configs override them.\n readonly configs?: PageConfigs;\n readonly hooks?: Partial<DotHooks> & ThisType<DotContext>;\n}\n\nexport function defineDot(dot: DotDefinition): DotDefinition {\n return dot;\n}\n\nexport interface ServiceOptions {\n transport: Transport;\n dot?: Partial<DotDefinition>;\n pages: Record<string, PageDefinition>;\n strict?: boolean;\n}\n\n// The logic layer: owns every page's state, runs handlers, and sends state changes to the view layer.\nexport class Service implements DotContext {\n readonly channel: ServiceChannel;\n readonly hooks = new EventEmitter<ServiceHooks>();\n #definitions: Record<string, PageDefinition>;\n readonly #pages = new Map<number, Page>();\n readonly #dot: Partial<DotDefinition>;\n readonly #strict: boolean;\n #theme: Theme;\n #systemContext: SystemContext = DEFAULT_SYSTEM_CONTEXT;\n #stack: HostLayerMessages['syncStack'] = { pages: [], limit: MAX_STACK_DEPTH };\n readonly #hostCalls: HostCalls;\n\n constructor({ transport, pages, dot = {}, strict = false }: ServiceOptions) {\n this.channel = new MessageChannel(transport);\n this.#hostCalls = new HostCalls(this.channel);\n this.#definitions = pages;\n this.#dot = dot;\n this.#strict = strict;\n this.#theme = dot.theme ?? {};\n checkConfigs(dot.configs ?? {});\n\n this.channel.handle('connect', () => this.channel.send('setTheme', { theme: this.#theme }));\n this.channel.handle('syncStack', (stack) => {\n this.#stack = stack;\n });\n this.channel.handle('syncSystemContext', (context) => {\n this.#systemContext = context;\n });\n this.channel.handle('load', ({ instanceId, page, options }) =>\n this.loadPage(instanceId, page, options),\n );\n this.channel.handle('unload', ({ instanceId }) => this.unloadPage(instanceId));\n this.channel.handle('show', ({ instanceId }) => {\n const page = this.getPage(instanceId);\n this.hooks.emit('pageShow', page);\n this.reportError(page.lifecycle('onShow'), instanceId);\n });\n this.channel.handle('hide', ({ instanceId }) => {\n const page = this.getPage(instanceId);\n this.hooks.emit('pageHide', page);\n this.reportError(page.lifecycle('onHide'), instanceId);\n });\n this.channel.handle('event', ({ instanceId, handler, event }) => {\n const page = this.getPage(instanceId);\n this.hooks.emit('event', page, handler, event);\n this.reportError(page.dispatch(handler, event), instanceId);\n });\n\n dot.plugins?.forEach((plugin) => this.use(plugin));\n }\n\n use(plugin: ServicePlugin): this {\n plugin.setup(this);\n return this;\n }\n\n start(): () => void {\n const stopListening = this.channel.listen((error, message) => {\n this.#reportError(error, instanceIdOf(message));\n });\n // Host calls, such as `dash.ui.alert`, now go through this service's channel.\n connectHost(this.callHost);\n this.hooks.emit('launch');\n this.reportError(this.#runLaunchHook());\n return () => {\n stopListening();\n connectHost(null);\n };\n }\n\n get theme(): Theme {\n return this.#theme;\n }\n\n get systemContext(): SystemContext {\n return this.#systemContext;\n }\n\n setTheme(theme: Theme): void {\n this.#theme = theme;\n this.channel.send('setTheme', { theme });\n }\n\n getPage(instanceId: number): Page {\n const page = this.#pages.get(instanceId);\n if (!page) {\n throw new Error(`Page instance ${instanceId} is not loaded`);\n }\n return page;\n }\n\n // Runs a host call, such as `dash.ui.alert`, through this service's channel.\n readonly callHost: HostCaller = (method, params, options) =>\n this.#hostCalls.call(method, params, options);\n\n loadPage(instanceId: number, id: string, options: PageLaunchOptions = {}): Page {\n const page = this.#createPage(instanceId, id);\n this.channel.send('initPageState', { instanceId, state: page.state });\n this.#sendBars(page);\n this.hooks.emit('pageLoad', page);\n this.reportError(page.lifecycle('onLoad', options), instanceId);\n return page;\n }\n\n // Swaps in a newer build's pages, as a hot reload does; a page restarts only if its initialState changed.\n replacePages(definitions: Record<string, PageDefinition>): void {\n const previous = this.#definitions;\n this.#definitions = definitions;\n for (const [instanceId, page] of this.#pages) {\n const definition = definitions[page.id];\n // A page the new build no longer has keeps its old code until it closes.\n if (!definition) {\n continue;\n }\n page.close();\n const initialStateChanged =\n JSON.stringify(previous[page.id]?.initialState) !== JSON.stringify(definition.initialState);\n if (!initialStateChanged) {\n const kept = this.#createPage(instanceId, page.id, {\n state: page.state,\n barChanges: page.barChanges,\n });\n // The new definePage may set other configs.\n this.#sendBars(kept);\n continue;\n }\n const restarted = this.#createPage(instanceId, page.id);\n this.channel.send('initPageState', { instanceId, state: restarted.state });\n this.#sendBars(restarted);\n this.hooks.emit('pageLoad', restarted);\n // What the page was opened with, for its onLoad to run again.\n const options =\n this.#stack.pages.find((entry) => entry.instanceId === instanceId)?.options ?? {};\n this.reportError(restarted.lifecycle('onLoad', options), instanceId);\n }\n }\n\n #createPage(instanceId: number, id: string, restored?: RestoredPage<PageState>): Page {\n const page = new Page(\n instanceId,\n id,\n this.#definition(id),\n {\n commit: (page, patch) => {\n this.hooks.emit('setState', page, patch);\n this.channel.send('setPageState', { instanceId: page.instanceId, patchState: patch });\n },\n showBars: (page) => this.#sendBars(page),\n dotConfigs: this.#dot.configs,\n navigate: (page, navigation) => {\n if (navigation.action !== 'back') {\n this.#definition(navigation.page);\n }\n const { pages, limit } = this.#stack;\n if (navigation.action === 'push' && pages.length >= limit) {\n throw new Error(\n `Cannot open \"${navigation.page}\": ${limit} pages are already open. Use replace or back.`,\n );\n }\n this.hooks.emit('navigate', page, navigation);\n this.channel.send('navigate', { ...navigation, from: page.instanceId });\n },\n strict: this.#strict,\n },\n restored,\n );\n this.#pages.set(instanceId, page);\n return page;\n }\n\n #sendBars(page: Page): void {\n this.channel.send('pageBars', { instanceId: page.instanceId, ...page.bars });\n }\n\n unloadPage(instanceId: number): void {\n const page = this.#pages.get(instanceId);\n if (!page) {\n return;\n }\n this.#pages.delete(instanceId);\n page.close();\n this.reportError(page.lifecycle('onUnload'), instanceId);\n this.hooks.emit('pageUnload', page);\n }\n\n #definition(id: string): PageDefinition {\n const definition = this.#definitions[id];\n if (!definition) {\n throw new Error(`Unknown page \"${id}\"`);\n }\n return definition;\n }\n\n reportError(work: Promise<void>, instanceId?: number): void {\n work.catch((error: unknown) => {\n this.#reportError(error, instanceId);\n });\n }\n\n async #runLaunchHook(): Promise<void> {\n await this.#dot.hooks?.onLaunch?.call(this);\n }\n\n #reportError(error: unknown, instanceId: number | undefined): void {\n this.hooks.emit('error', error, instanceId);\n const reason = error instanceof Error ? error : new Error(String(error));\n this.#dot.hooks?.onError?.call(this, reason);\n const report: LogicLayerMessages['error'] = { message: reason.message };\n if (instanceId !== undefined) {\n report.instanceId = instanceId;\n }\n this.channel.send('error', report);\n }\n}\n\n// The page instance a channel message was for, if it names one.\nfunction instanceIdOf(message: Envelope): number | undefined {\n const payload = message.payload as { instanceId?: unknown } | undefined;\n if (typeof payload?.instanceId === 'number') {\n return payload.instanceId;\n }\n return undefined;\n}\n"],"mappings":"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"}