@mak-98/dirvi-app 0.11.0-beta.12 → 0.11.0-beta.14

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.
@@ -1 +1 @@
1
- {"version":3,"file":"init-runtime.d.ts","sourceRoot":"","sources":["../../src/application/init-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;IAE5B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,cAAc,CAAC;CACvC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAuI/C"}
1
+ {"version":3,"file":"init-runtime.d.ts","sourceRoot":"","sources":["../../src/application/init-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAC;IAE5B;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,cAAc,CAAC;CACvC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,IAAI,WAAW,CAsK/C"}
@@ -1 +1 @@
1
- {"version":3,"file":"init-runtime.error.d.ts","sourceRoot":"","sources":["../../src/application/init-runtime.error.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAC5B,kBAAkB,GAClB,eAAe,GACf,eAAe,GACf,sBAAsB,GACtB,4BAA4B,GAC5B,gBAAgB,GAChB,+BAA+B,GAC/B,oBAAoB,GACpB,4BAA4B,GAC5B,oBAAoB,CAAC;AAEzB;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB;gBAA1B,IAAI,EAAE,oBAAoB,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAKzB;AAED,wEAAwE;AACxE,qBAAa,kCAAmC,SAAQ,gBAAgB;;CAOvE;AAED,gFAAgF;AAChF,qBAAa,+BAAgC,SAAQ,gBAAgB;gBACvD,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAG5C;AAED,+CAA+C;AAC/C,qBAAa,6BAA8B,SAAQ,gBAAgB;gBACrD,EAAE,EAAE,MAAM;CAMvB;AAED,wDAAwD;AACxD,qBAAa,mCAAoC,SAAQ,gBAAgB;gBAC3D,IAAI,EAAE,MAAM;CAMzB;AAED,kFAAkF;AAClF,qBAAa,4BAA6B,SAAQ,gBAAgB;;CAOjE;AAED,sFAAsF;AACtF,qBAAa,gCAAiC,SAAQ,gBAAgB;gBACxD,KAAK,EAAE,OAAO;CAO3B;AAED,+EAA+E;AAC/E,qBAAa,+BAAgC,SAAQ,gBAAgB;gBACvD,KAAK,EAAE,OAAO;CAO3B;AAED,6DAA6D;AAC7D,qBAAa,qBAAsB,SAAQ,gBAAgB;;CAO1D;AAED,8DAA8D;AAC9D,qBAAa,4BAA6B,SAAQ,gBAAgB;gBACpD,EAAE,EAAE,MAAM;CAMvB;AAED,iFAAiF;AACjF,qBAAa,yBAA0B,SAAQ,gBAAgB;gBACjD,OAAO,EAAE,MAAM;CAG5B"}
1
+ {"version":3,"file":"init-runtime.error.d.ts","sourceRoot":"","sources":["../../src/application/init-runtime.error.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,MAAM,MAAM,oBAAoB,GAC5B,kBAAkB,GAClB,eAAe,GACf,eAAe,GACf,sBAAsB,GACtB,4BAA4B,GAC5B,gBAAgB,GAChB,+BAA+B,GAC/B,oBAAoB,GACpB,4BAA4B,GAC5B,oBAAoB,CAAC;AAEzB;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAEvC,QAAQ,CAAC,IAAI,EAAE,oBAAoB;gBAA1B,IAAI,EAAE,oBAAoB,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY;CAKzB;AAED,wEAAwE;AACxE,qBAAa,kCAAmC,SAAQ,gBAAgB;;CAOvE;AAED,gFAAgF;AAChF,qBAAa,+BAAgC,SAAQ,gBAAgB;gBACvD,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;CAG5C;AAED,+CAA+C;AAC/C,qBAAa,6BAA8B,SAAQ,gBAAgB;gBACrD,EAAE,EAAE,MAAM;CAMvB;AAED,wDAAwD;AACxD,qBAAa,mCAAoC,SAAQ,gBAAgB;gBAC3D,IAAI,EAAE,MAAM;CAMzB;AAED,kFAAkF;AAClF,qBAAa,4BAA6B,SAAQ,gBAAgB;;CAOjE;AAED,sFAAsF;AACtF,qBAAa,gCAAiC,SAAQ,gBAAgB;gBACxD,KAAK,EAAE,OAAO;CAO3B;AAED,+EAA+E;AAC/E,qBAAa,+BAAgC,SAAQ,gBAAgB;gBACvD,KAAK,EAAE,OAAO;CAO3B;AAED,6DAA6D;AAC7D,qBAAa,qBAAsB,SAAQ,gBAAgB;;CAS1D;AAED,8DAA8D;AAC9D,qBAAa,4BAA6B,SAAQ,gBAAgB;gBACpD,EAAE,EAAE,MAAM;CAMvB;AAED,iFAAiF;AACjF,qBAAa,yBAA0B,SAAQ,gBAAgB;gBACjD,OAAO,EAAE,MAAM;CAG5B"}
@@ -57,7 +57,9 @@ export class InvalidAppPackageReferenceError extends InitRuntimeError {
57
57
  /** Initialization completed without registering any apps. */
58
58
  export class NoAppsRegisteredError extends InitRuntimeError {
59
59
  constructor() {
60
- super('NO_APPS_REGISTERED', 'Initialization did not register any apps. Call dirvi.app.register(id, appReference) at least once in init.mjs.');
60
+ super('NO_APPS_REGISTERED', 'Initialization did not register any apps.' +
61
+ 'Call dirvi.app.register(app) at least once in init.mjs.' +
62
+ 'See /examples/ts-init/ for writing an init.mjs in TypeScript.');
61
63
  }
62
64
  }
63
65
  /** The explicitly selected startup app was not registered. */
@@ -61,18 +61,45 @@ export function createInitRuntime() {
61
61
  },
62
62
  },
63
63
  app: {
64
- register: (id, appReference) => {
64
+ register: (app) => {
65
65
  ensureUnfinished();
66
- validateNonEmptyString(id, 'App ID');
67
- if (registeredApps.has(id)) {
68
- throw new DuplicateAppRegistrationError(id);
66
+ if (typeof app !== 'object' || app === null || Array.isArray(app)) {
67
+ throw new InvalidInitializationValueError('App', 'must be an object');
69
68
  }
69
+ const { id: appId, packRef, ex } = app;
70
+ validateNonEmptyString(appId, 'App ID');
71
+ if (registeredApps.has(appId)) {
72
+ throw new DuplicateAppRegistrationError(appId);
73
+ }
74
+ let appReference;
70
75
  try {
71
- registeredApps.set(id, AppPackageReferenceMethods.parse(appReference));
76
+ appReference = AppPackageReferenceMethods.parse(packRef);
72
77
  }
73
78
  catch (cause) {
74
79
  throw new InvalidAppPackageReferenceError(cause);
75
80
  }
81
+ if (ex !== undefined && !Array.isArray(ex)) {
82
+ throw new InvalidInitializationValueError('Ex commands', 'must be an array');
83
+ }
84
+ const appExCommands = new Map();
85
+ for (const exCommand of ex ?? []) {
86
+ if (typeof exCommand !== 'object' ||
87
+ exCommand === null ||
88
+ Array.isArray(exCommand)) {
89
+ throw new InvalidInitializationValueError('Ex command', 'must be an object');
90
+ }
91
+ const { command, execute } = exCommand;
92
+ validateNonEmptyString(command, 'Ex command name');
93
+ if (typeof execute !== 'function') {
94
+ throw new InvalidExCommandHandlerError();
95
+ }
96
+ if (appExCommands.has(command)) {
97
+ throw new DuplicateExCommandRegistrationError(command);
98
+ }
99
+ appExCommands.set(command, { name: command, execute });
100
+ }
101
+ registeredApps.set(appId, appReference);
102
+ exCommands.set(appId, appExCommands);
76
103
  },
77
104
  initial: (appId) => {
78
105
  ensureUnfinished();
@@ -80,19 +107,6 @@ export function createInitRuntime() {
80
107
  initialAppId = appId;
81
108
  },
82
109
  },
83
- ex: {
84
- register: (name, execute) => {
85
- ensureUnfinished();
86
- validateNonEmptyString(name, 'Ex command name');
87
- if (typeof execute !== 'function') {
88
- throw new InvalidExCommandHandlerError();
89
- }
90
- if (exCommands.has(name)) {
91
- throw new DuplicateExCommandRegistrationError(name);
92
- }
93
- exCommands.set(name, { name, execute });
94
- },
95
- },
96
110
  };
97
111
  /**
98
112
  * === FINISH ================================================================
@@ -125,7 +139,7 @@ export function createInitRuntime() {
125
139
  initial,
126
140
  registered: new Map(registeredApps),
127
141
  },
128
- exCommands: new Map(exCommands),
142
+ exCommands: new Map([...exCommands].map(([appId, commands]) => [appId, new Map(commands)])),
129
143
  };
130
144
  };
131
145
  return {
@@ -4,6 +4,6 @@ import { DirviApi } from 'dirvi-apis';
4
4
  */
5
5
  export type ExCommand = {
6
6
  readonly name: string;
7
- readonly execute: (api: DirviApi) => void | Promise<void>;
7
+ readonly execute: (api: DirviApi, rawArgs: string | undefined) => void | Promise<void>;
8
8
  };
9
9
  //# sourceMappingURL=ex-command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ex-command.d.ts","sourceRoot":"","sources":["../../src/domain/ex-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D,CAAC"}
1
+ {"version":3,"file":"ex-command.d.ts","sourceRoot":"","sources":["../../src/domain/ex-command.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxF,CAAC"}
@@ -17,7 +17,10 @@ export type Initialization = {
17
17
  /** App package references keyed by app ID. */
18
18
  registered: ReadonlyMap<string, AppPackageReference>;
19
19
  };
20
- /** Ex commands registered by the initialization script, keyed by name. */
21
- readonly exCommands: ReadonlyMap<string, ExCommand>;
20
+ /**
21
+ * Ex commands registered by the initialization script, keyed by appId and
22
+ * then command name.
23
+ * */
24
+ readonly exCommands: ReadonlyMap<string, ReadonlyMap<string, ExCommand>>;
22
25
  };
23
26
  //# sourceMappingURL=initialization.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"initialization.d.ts","sourceRoot":"","sources":["../../src/domain/initialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAElC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE;QACZ,wEAAwE;QACxE,OAAO,EAAE,MAAM,CAAC;QAEhB,8CAA8C;QAC9C,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;KACtD,CAAC;IAEF,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACrD,CAAC"}
1
+ {"version":3,"file":"initialization.d.ts","sourceRoot":"","sources":["../../src/domain/initialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAElC,wDAAwD;IACxD,QAAQ,CAAC,GAAG,EAAE;QACZ,wEAAwE;QACxE,OAAO,EAAE,MAAM,CAAC;QAEhB,8CAA8C;QAC9C,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;KACtD,CAAC;IAEF;;;SAGK;IACL,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;CAC1E,CAAC"}
package/dist/ui/App.d.ts CHANGED
@@ -1,12 +1,13 @@
1
- import type { ShellApi } from 'dirvi-apis';
1
+ import { Config, ShellApi } from 'dirvi-apis';
2
2
  import type { AppMethods, EffectToAction, IntentToEffect, Reducer, SerializableKey, State } from 'dirvi-lib';
3
3
  import type { AppScreenRenderer } from './app-screen-renderer.js';
4
- import type { Initialization } from '../domain/initialization.js';
4
+ import { ExCommand } from '../domain/ex-command.js';
5
5
  type AppProps<Id extends SerializableKey, Value, ViewKey = string> = {
6
6
  screenRenderer: AppScreenRenderer;
7
7
  shellApi: ShellApi;
8
8
  appMethods: AppMethods<Id, Value, ViewKey>;
9
- initialization: Initialization;
9
+ exCommands: ReadonlyMap<string, ExCommand>;
10
+ config: Readonly<Config>;
10
11
  initialState: State<Id, Value>;
11
12
  reducer: Reducer<Id, Value>;
12
13
  intentToEffect: IntentToEffect<Id, Value>;
@@ -15,6 +16,6 @@ type AppProps<Id extends SerializableKey, Value, ViewKey = string> = {
15
16
  clipboard?: (value: string) => void;
16
17
  onError?: (error: Error) => void;
17
18
  };
18
- export declare function App<Id extends SerializableKey, Value, ViewKey = string>({ screenRenderer, shellApi, appMethods, initialization, initialState, reducer, intentToEffect, effectToAction, stdout, clipboard, onError, }: AppProps<Id, Value, ViewKey>): import("react").JSX.Element;
19
+ export declare function App<Id extends SerializableKey, Value, ViewKey = string>({ screenRenderer, shellApi, appMethods, exCommands, config, initialState, reducer, intentToEffect, effectToAction, stdout, clipboard, onError, }: AppProps<Id, Value, ViewKey>): import("react").JSX.Element;
19
20
  export {};
20
21
  //# sourceMappingURL=App.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAwB,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EACV,UAAU,EAEV,cAAc,EAEd,cAAc,EAEd,OAAO,EACP,eAAe,EACf,KAAK,EAGN,MAAM,WAAW,CAAC;AAInB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,KAAK,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,IAAI;IACnE,cAAc,EAAE,iBAAiB,CAAC;IAClC,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1C,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,GAAG,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,EACvE,cAAc,EACd,QAAQ,EACR,UAAU,EACV,cAAc,EACd,YAAY,EACZ,OAAO,EACP,cAAc,EACd,cAAc,EACd,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,+BA4V9B"}
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../src/ui/App.tsx"],"names":[],"mappings":"AASA,OAAO,EAAU,MAAM,EAAgB,QAAQ,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EACV,UAAU,EAEV,cAAc,EAEd,cAAc,EAEd,OAAO,EACP,eAAe,EACf,KAAK,EAGN,MAAM,WAAW,CAAC;AAInB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,KAAK,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,IAAI;IACnE,cAAc,EAAE,iBAAiB,CAAC;IAClC,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,YAAY,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5B,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1C,cAAc,EAAE,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC,CAAC;AAEF,wBAAgB,GAAG,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,EACvE,cAAc,EACd,QAAQ,EACR,UAAU,EACV,UAAU,EACV,MAAM,EACN,YAAY,EACZ,OAAO,EACP,cAAc,EACd,cAAc,EACd,MAAM,EACN,SAAS,EACT,OAAO,GACR,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,+BAyV9B"}
package/dist/ui/App.js CHANGED
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useReducer, useRef, useState, } from 'react';
3
3
  import { createFeedbackApi, userInputToIntent } from 'dirvi-lib';
4
4
  import { useView } from './hooks/useView.js';
5
- export function App({ screenRenderer, shellApi, appMethods, initialization, initialState, reducer, intentToEffect, effectToAction, stdout, clipboard, onError, }) {
5
+ export function App({ screenRenderer, shellApi, appMethods, exCommands, config, initialState, reducer, intentToEffect, effectToAction, stdout, clipboard, onError, }) {
6
6
  const ScreenRenderer = screenRenderer;
7
7
  const [state, dispatch] = useReducer(reducer, initialState);
8
8
  const stateRef = useRef(state); // Gives `subscribeToResync` callback a way to
@@ -91,13 +91,13 @@ export function App({ screenRenderer, shellApi, appMethods, initialization, init
91
91
  /** Execute a command, using shell API and app API. */
92
92
  case 'userExCommand': {
93
93
  setInputState(clearInputState);
94
- const command = initialization.exCommands.get(effect.name);
94
+ const command = exCommands.get(effect.name);
95
95
  if (command === undefined) {
96
96
  appApi.addMessage(`Command is no longer registered: ${effect.name}`, 'error');
97
97
  return;
98
98
  }
99
99
  void Promise.resolve()
100
- .then(() => command.execute({ shell: shellApi, app: appApi })) // TODO: Add args
100
+ .then(() => command.execute({ shell: shellApi, app: appApi }, effect.rawArgs))
101
101
  .catch((error) => {
102
102
  const appError = error instanceof Error ? error : new Error(String(error));
103
103
  appApi.addMessage(`Command "${effect.name}" failed: ${appError.message}`, 'error');
@@ -108,10 +108,9 @@ export function App({ screenRenderer, shellApi, appMethods, initialization, init
108
108
  shellApi.quit(effect.exitMessage);
109
109
  return;
110
110
  case 'listApps': {
111
- const appIds = [...initialization.app.registered.keys()];
112
- const lines = appIds.map((id) => `${id}`);
111
+ const appIds = shellApi.listApps();
113
112
  setInputState(clearInputState);
114
- appApi.addMessage(['Apps:', ...lines].join('\n'));
113
+ appApi.addMessage(['Apps:', ...appIds].join('\n'));
115
114
  return;
116
115
  }
117
116
  case 'switchApp':
@@ -226,7 +225,7 @@ export function App({ screenRenderer, shellApi, appMethods, initialization, init
226
225
  appApi.addMessage(effect.message, 'error');
227
226
  return;
228
227
  }
229
- }, [appMethods, effectToAction, navEntry, state, shellApi, initialization.exCommands, initialization.app.registered, appApi, clearInputState]);
228
+ }, [appMethods, effectToAction, navEntry, state, shellApi, appApi, clearInputState, exCommands]);
230
229
  // ===========================================================================
231
230
  // Input hook
232
231
  // ===========================================================================
@@ -245,5 +244,5 @@ export function App({ screenRenderer, shellApi, appMethods, initialization, init
245
244
  // ===========================================================================
246
245
  // Render
247
246
  // ===========================================================================
248
- return (_jsx(ScreenRenderer, { view: view, feedback: feedback, feedbackApi: feedbackApi, config: initialization.config, inputState: inputState, handleInput: handleInput, onRowsChange: handleRowsChange }));
247
+ return (_jsx(ScreenRenderer, { view: view, feedback: feedback, feedbackApi: feedbackApi, config: config, inputState: inputState, handleInput: handleInput, onRowsChange: handleRowsChange }));
249
248
  }
@@ -6,12 +6,13 @@ import type { ShellApi } from 'dirvi-apis';
6
6
  type AppSetupProps<Id extends SerializableKey, Value, ViewKey = string> = {
7
7
  appScreenRenderer: AppScreenRenderer;
8
8
  loadingScreenRenderer: LoadingScreenRenderer;
9
+ appId: string;
9
10
  initialization: Initialization;
10
11
  shellApi: ShellApi;
11
12
  appMethods: AppMethods<Id, Value, ViewKey>;
12
13
  stdout?: (message: string) => void;
13
14
  clipboard?: (value: string) => void;
14
15
  };
15
- export declare function AppSetup<Id extends SerializableKey, Value, ViewKey = string>({ appScreenRenderer, loadingScreenRenderer, initialization, shellApi, appMethods, stdout, clipboard, }: AppSetupProps<Id, Value, ViewKey>): import("react").JSX.Element;
16
+ export declare function AppSetup<Id extends SerializableKey, Value, ViewKey = string>({ appScreenRenderer, loadingScreenRenderer, appId, initialization, shellApi, appMethods, stdout, clipboard, }: AppSetupProps<Id, Value, ViewKey>): import("react").JSX.Element;
16
17
  export {};
17
18
  //# sourceMappingURL=AppSetup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppSetup.d.ts","sourceRoot":"","sources":["../../src/ui/AppSetup.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAqB,eAAe,EAAS,MAAM,WAAW,CAAC;AAOlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,KAAK,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,IAAI;IACxE,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAkBF,wBAAgB,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,EAC5E,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,EACd,QAAQ,EACR,UAAU,EACV,MAAM,EACN,SAAS,GACV,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,+BAmGnC"}
1
+ {"version":3,"file":"AppSetup.d.ts","sourceRoot":"","sources":["../../src/ui/AppSetup.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAqB,eAAe,EAAS,MAAM,WAAW,CAAC;AAOlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAO3C,KAAK,aAAa,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,IAAI;IACxE,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,qBAAqB,EAAE,qBAAqB,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAkBF,wBAAgB,QAAQ,CAAC,EAAE,SAAS,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,EAC5E,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,EACL,cAAc,EACd,QAAQ,EACR,UAAU,EACV,MAAM,EACN,SAAS,GACV,EAAE,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,+BAwGnC"}
@@ -3,7 +3,9 @@ import { useEffect, useMemo, useState } from 'react';
3
3
  import { createTreeMethods } from 'dirvi-lib';
4
4
  import { createEffectToAction, createIntentToEffect, createReducer, } from 'dirvi-lib';
5
5
  import { App } from './App.js';
6
- export function AppSetup({ appScreenRenderer, loadingScreenRenderer, initialization, shellApi, appMethods, stdout, clipboard, }) {
6
+ // TODO Later: configuration watched for changes
7
+ const emptyExCommands = new Map();
8
+ export function AppSetup({ appScreenRenderer, loadingScreenRenderer, appId, initialization, shellApi, appMethods, stdout, clipboard, }) {
7
9
  const [loadState, setLoadState] = useState();
8
10
  useEffect(() => {
9
11
  let mounted = true;
@@ -39,8 +41,9 @@ export function AppSetup({ appScreenRenderer, loadingScreenRenderer, initializat
39
41
  };
40
42
  }, [appMethods]);
41
43
  // --- Pure function deps ---
44
+ const exCommands = useMemo(() => initialization.exCommands.get(appId) ?? emptyExCommands, [initialization.exCommands, appId]);
42
45
  const reducer = useMemo(() => createReducer(appMethods.stateMethods, appMethods.navMethods), [appMethods.stateMethods, appMethods.navMethods]);
43
- const intentToEffect = useMemo(() => createIntentToEffect(new Set(initialization.exCommands.keys()), appMethods.stateMethods), [appMethods.stateMethods, initialization.exCommands]);
46
+ const intentToEffect = useMemo(() => createIntentToEffect(new Set(exCommands.keys()), appMethods.stateMethods), [appMethods.stateMethods, exCommands]);
44
47
  const effectToAction = useMemo(() => createEffectToAction(appMethods.stateMethods, appMethods.navMethods), [appMethods.navMethods, appMethods.stateMethods]);
45
48
  // --- JSX ---
46
49
  const LoadingScreenRenderer = loadingScreenRenderer;
@@ -53,5 +56,5 @@ export function AppSetup({ appScreenRenderer, loadingScreenRenderer, initializat
53
56
  if (loadState.status === 'error') {
54
57
  throw loadState.error;
55
58
  }
56
- return (_jsx(App, { screenRenderer: appScreenRenderer, shellApi: shellApi, appMethods: appMethods, initialization: initialization, initialState: loadState.initialState, reducer: reducer, intentToEffect: intentToEffect, effectToAction: effectToAction, ...(stdout === undefined ? {} : { stdout }), ...(clipboard === undefined ? {} : { clipboard }) }));
59
+ return (_jsx(App, { screenRenderer: appScreenRenderer, shellApi: shellApi, appMethods: appMethods, exCommands: exCommands, config: initialization.config, initialState: loadState.initialState, reducer: reducer, intentToEffect: intentToEffect, effectToAction: effectToAction, ...(stdout === undefined ? {} : { stdout }), ...(clipboard === undefined ? {} : { clipboard }) }));
57
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Shell.d.ts","sourceRoot":"","sources":["../../src/ui/Shell.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAItE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;IACtD,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAE9C,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IAEtC,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,iDAAiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC;AAEF;;GAEG;AACH,wBAAgB,KAAK,CAAC,EACpB,MAAM,EACN,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,MAAM,EACN,SAAS,GACV,EAAE,aAAa,+BAuFf"}
1
+ {"version":3,"file":"Shell.d.ts","sourceRoot":"","sources":["../../src/ui/Shell.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAE1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAItE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAEtB;;OAEG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;OAEG;IACH,QAAQ,CAAC,qBAAqB,EAAE,qBAAqB,CAAC;IACtD,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAE9C,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAC9C,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IAEtC,sDAAsD;IACtD,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,iDAAiD;IACjD,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC;AAEF;;GAEG;AACH,wBAAgB,KAAK,CAAC,EACpB,MAAM,EACN,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,MAAM,EACN,SAAS,GACV,EAAE,aAAa,+BA6Ff"}
package/dist/ui/Shell.js CHANGED
@@ -6,13 +6,14 @@ import { createAppMethodsApplicator } from '../application/create-app-methods.js
6
6
  * Creates `ShellApi` and the `AppMethods` for a selected application.
7
7
  */
8
8
  export function Shell({ onQuit, loadingScreenRenderer, appScreenRenderer, initialAppOptions, initialization, packageLoader, stdout, clipboard, }) {
9
- const [appMethodsApplicator, setAppMethodsApplicator] = useState(undefined);
9
+ const [loadedApp, setLoadedApp] = useState();
10
10
  const [appError, setAppError] = useState(undefined);
11
11
  /**
12
12
  * Create the Shell API, based on given {@link Initialization}.
13
13
  */
14
14
  const shellApi = useMemo(() => {
15
15
  return {
16
+ listApps: () => [...initialization.app.registered.keys()],
16
17
  loadApp: async (appId, input) => {
17
18
  try {
18
19
  const appReference = initialization.app.registered.get(appId);
@@ -25,7 +26,10 @@ export function Shell({ onQuit, loadingScreenRenderer, appScreenRenderer, initia
25
26
  }
26
27
  const appPlugin = await packageLoader.loadAppPlugin(appReference);
27
28
  const loadedAppMethodsApplicator = createAppMethodsApplicator(appPlugin.createAppDefinitionApplicator(input));
28
- setAppMethodsApplicator(() => loadedAppMethodsApplicator);
29
+ setLoadedApp({
30
+ appId,
31
+ appMethodsApplicator: loadedAppMethodsApplicator,
32
+ });
29
33
  return { kind: 'loaded' };
30
34
  }
31
35
  catch (error) {
@@ -61,9 +65,9 @@ export function Shell({ onQuit, loadingScreenRenderer, appScreenRenderer, initia
61
65
  throw appError;
62
66
  }
63
67
  // TODO Later: Loading messages
64
- if (appMethodsApplicator === undefined) {
68
+ if (loadedApp === undefined) {
65
69
  const LoadingScreenRenderer = loadingScreenRenderer;
66
70
  return _jsx(LoadingScreenRenderer, {});
67
71
  }
68
- return appMethodsApplicator((appMethods) => (_jsx(AppSetup, { appScreenRenderer: appScreenRenderer, loadingScreenRenderer: loadingScreenRenderer, initialization: initialization, shellApi: shellApi, appMethods: appMethods, ...(stdout === undefined ? {} : { stdout }), ...(clipboard === undefined ? {} : { clipboard }) })));
72
+ return loadedApp.appMethodsApplicator((appMethods) => (_jsx(AppSetup, { appScreenRenderer: appScreenRenderer, loadingScreenRenderer: loadingScreenRenderer, appId: loadedApp.appId, initialization: initialization, shellApi: shellApi, appMethods: appMethods, ...(stdout === undefined ? {} : { stdout }), ...(clipboard === undefined ? {} : { clipboard }) })));
69
73
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mak-98/dirvi-app",
3
- "version": "0.11.0-beta.12",
3
+ "version": "0.11.0-beta.14",
4
4
  "description": "Shared React application logic for dirvi hosts.",
5
5
  "type": "module",
6
6
  "license": "GPL-3.0-or-later",
@@ -16,8 +16,8 @@
16
16
  "dist"
17
17
  ],
18
18
  "dependencies": {
19
- "dirvi-apis": "0.11.0-beta.12",
20
- "dirvi-lib": "0.11.0-beta.12",
19
+ "dirvi-apis": "0.11.0-beta.14",
20
+ "dirvi-lib": "0.11.0-beta.14",
21
21
  "zod": "^4.4.3"
22
22
  },
23
23
  "peerDependencies": {