@nan0web/ui 1.0.2 → 1.0.4

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.
Files changed (58) hide show
  1. package/README.md +19 -54
  2. package/package.json +21 -17
  3. package/src/App/Core/CoreApp.js +14 -19
  4. package/src/App/Core/UI.js +4 -50
  5. package/src/App/Core/Widget.js +4 -6
  6. package/src/App/User/Command/Message.js +23 -37
  7. package/src/App/User/Command/index.js +3 -8
  8. package/src/App/User/UserApp.js +32 -27
  9. package/src/App/User/UserUI.js +4 -4
  10. package/src/App/User/index.js +0 -6
  11. package/src/App/index.js +0 -3
  12. package/src/README.md.js +33 -57
  13. package/src/StdIn.js +12 -15
  14. package/src/View/View.js +5 -5
  15. package/src/core/Error/index.js +9 -0
  16. package/src/core/Form/Form.js +43 -23
  17. package/src/core/Form/Input.js +16 -7
  18. package/src/core/Form/Message.js +6 -8
  19. package/src/core/InputAdapter.js +6 -2
  20. package/src/core/Message/Message.js +109 -19
  21. package/src/core/Message/OutputMessage.js +8 -8
  22. package/src/core/Message/index.js +3 -4
  23. package/src/core/Stream.js +10 -10
  24. package/src/core/UiAdapter.js +189 -0
  25. package/src/core/index.js +5 -6
  26. package/src/index.js +5 -4
  27. package/types/App/Core/CoreApp.d.ts +9 -9
  28. package/types/App/Core/UI.d.ts +5 -15
  29. package/types/App/Core/Widget.d.ts +7 -8
  30. package/types/App/User/Command/Message.d.ts +15 -29
  31. package/types/App/User/Command/Options.d.ts +9 -2
  32. package/types/App/User/Command/index.d.ts +3 -7
  33. package/types/App/User/UserApp.d.ts +19 -9
  34. package/types/App/User/UserUI.d.ts +0 -9
  35. package/types/App/User/index.d.ts +0 -4
  36. package/types/App/index.d.ts +1 -3
  37. package/types/Frame/Frame.d.ts +5 -5
  38. package/types/StdIn.d.ts +13 -13
  39. package/types/View/View.d.ts +9 -9
  40. package/types/core/Error/index.d.ts +6 -0
  41. package/types/core/Form/Form.d.ts +14 -11
  42. package/types/core/Form/Input.d.ts +20 -7
  43. package/types/core/Form/Message.d.ts +5 -4
  44. package/types/core/InputAdapter.d.ts +2 -0
  45. package/types/core/Intent.d.ts +91 -0
  46. package/types/core/Message/InputMessage.d.ts +5 -5
  47. package/types/core/Message/Message.d.ts +58 -15
  48. package/types/core/Message/OutputMessage.d.ts +4 -4
  49. package/types/core/Message/index.d.ts +3 -4
  50. package/types/core/Stream.d.ts +5 -4
  51. package/types/core/StreamEntry.d.ts +1 -1
  52. package/types/core/UiAdapter.d.ts +104 -0
  53. package/types/core/index.d.ts +3 -3
  54. package/types/index.d.ts +5 -4
  55. package/src/App/Command/Options.js +0 -78
  56. package/src/App/Command/index.js +0 -9
  57. package/src/App/User/Command/Options.js +0 -48
  58. package/src/core/Message/InputMessage.js +0 -119
@@ -1,11 +1,33 @@
1
- export default UIMessage;
2
1
  /**
3
- * Base UI message class.
2
+ * @typedef {Object} MessageBodySchema
3
+ * @property {boolean} [required]
4
+ * @property {string} [help]
5
+ * @property {RegExp} [pattern]
6
+ * @property {string[]} [options]
7
+ * @property {*} [defaultValue]
8
+ * @property {Function} [validate]
9
+ */
10
+ /**
11
+ * Base message class for UI communications.
12
+ * A message holds structured data (body) defined by a static Body class.
13
+ * It can represent commands, forms, alerts, or any UI unit.
14
+ *
15
+ * @class UiMessage
16
+ * @extends Message
4
17
  *
5
- * @class UIMessage
6
- * @extends BaseMessage
18
+ * @example
19
+ * class UserLoginMessage extends UiMessage {
20
+ * static Body = class {
21
+ * static username = { required: true, help: "Enter username" }
22
+ * static password = { required: true, type: "password" }
23
+ * constructor({ username = "", password = "" }) {
24
+ * this.username = username
25
+ * this.password = password
26
+ * }
27
+ * }
28
+ * }
7
29
  */
8
- declare class UIMessage extends BaseMessage {
30
+ export default class UiMessage extends Message {
9
31
  static TYPES: {
10
32
  TEXT: string;
11
33
  FORM: string;
@@ -18,14 +40,22 @@ declare class UIMessage extends BaseMessage {
18
40
  NAVIGATION: string;
19
41
  };
20
42
  /**
21
- * Creates a UIMessage instance from plain data.
43
+ * Creates a UiMessage instance from plain data.
22
44
  *
23
45
  * @param {Object} data - Message data.
24
- * @returns {UIMessage}
46
+ * @returns {UiMessage}
47
+ */
48
+ static from(data: any): UiMessage;
49
+ /**
50
+ * Initializes body from input using static Body schema.
51
+ *
52
+ * @param {Object} input - Input object.
53
+ * @param {Function} BodyClass - Static body class with defaults and schema.
54
+ * @returns {Object} Parsed body.
25
55
  */
26
- static from(data: any): UIMessage;
56
+ static parseBody(input: any, BodyClass: Function): any;
27
57
  /**
28
- * Creates a UIMessage.
58
+ * Creates a UiMessage.
29
59
  *
30
60
  * @param {Object} [input={}] - Message properties.
31
61
  */
@@ -35,16 +65,29 @@ declare class UIMessage extends BaseMessage {
35
65
  /** @type {string} */
36
66
  id: string;
37
67
  /**
38
- * Checks if the message type is valid.
68
+ * Validates the message body against its schema.
39
69
  *
40
- * @returns {boolean}
70
+ * NOTE: The signature must exactly match `Message.validate` – it returns a
71
+ * `Map<string,string>` regardless of the generic type, otherwise TypeScript
72
+ * reports incompatibility with the base class.
73
+ *
74
+ * @param {any} [body=this.body] - Optional body to validate.
75
+ * @returns {Map<string,string>} Map of validation errors, empty if valid.
41
76
  */
42
- isValidType(): boolean;
77
+ validate(body?: any): Map<string, string>;
43
78
  /**
44
- * Checks whether the message contains any body content.
79
+ * Checks if the message type is valid.
45
80
  *
46
81
  * @returns {boolean}
47
82
  */
48
- isEmpty(): boolean;
83
+ isValidType(): boolean;
49
84
  }
50
- import { Message as BaseMessage } from "@nan0web/co";
85
+ export type MessageBodySchema = {
86
+ required?: boolean | undefined;
87
+ help?: string | undefined;
88
+ pattern?: RegExp | undefined;
89
+ options?: string[] | undefined;
90
+ defaultValue?: any;
91
+ validate?: Function | undefined;
92
+ };
93
+ import { Message } from "@nan0web/co";
@@ -2,9 +2,9 @@
2
2
  * OutputMessage – message sent from the system to the UI.
3
3
  *
4
4
  * @class OutputMessage
5
- * @extends UIMessage
5
+ * @extends UiMessage
6
6
  */
7
- export default class OutputMessage extends UIMessage {
7
+ export default class OutputMessage extends UiMessage {
8
8
  static PRIORITY: {
9
9
  LOW: number;
10
10
  NORMAL: number;
@@ -27,7 +27,7 @@ export default class OutputMessage extends UIMessage {
27
27
  /** @type {number} */
28
28
  priority: number;
29
29
  /** @param {string[]|string} value */
30
- set content(arg: string[]);
30
+ set content(value: string[] | string);
31
31
  /** @returns {string[]} */
32
32
  get content(): string[];
33
33
  /** @returns {number} */
@@ -50,4 +50,4 @@ export default class OutputMessage extends UIMessage {
50
50
  */
51
51
  toJSON(): any;
52
52
  }
53
- import UIMessage from "./Message.js";
53
+ import UiMessage from "./Message.js";
@@ -1,5 +1,4 @@
1
- export default UIMessage;
2
- import UIMessage from "./Message.js";
3
- import InputMessage from "./InputMessage.js";
1
+ export default UiMessage;
2
+ import UiMessage from "./Message.js";
4
3
  import OutputMessage from "./OutputMessage.js";
5
- export { UIMessage, InputMessage, OutputMessage };
4
+ export { UiMessage, OutputMessage };
@@ -1,5 +1,6 @@
1
+ export { StreamEntry };
1
2
  /**
2
- * Agnostic UI stream for processing progress.
3
+ * Agnostic UI stream for processing progress using async generators.
3
4
  *
4
5
  * @class UIStream
5
6
  */
@@ -13,15 +14,15 @@ export default class UIStream {
13
14
  */
14
15
  static createProcessor(signal: AbortSignal, processorFn: () => Promise<StreamEntry>): () => AsyncGenerator<StreamEntry>;
15
16
  /**
16
- * Runs a generator with progress callbacks and abort handling.
17
+ * Runs an async generator with progress callbacks and abort handling.
17
18
  *
18
19
  * @param {AbortSignal} signal - Abort signal.
19
- * @param {Function} generator - Function returning an async iterator.
20
+ * @param {() => AsyncGenerator<StreamEntry>} generatorFn - Function that returns an async generator.
20
21
  * @param {Function} [onProgress] - Called with (progress, item).
21
22
  * @param {Function} [onError] - Called with (errorMessage, item).
22
23
  * @param {Function} [onComplete] - Called with (item) when done.
23
24
  * @returns {Promise<void>}
24
25
  */
25
- static process(signal: AbortSignal, generator: Function, onProgress?: Function | undefined, onError?: Function | undefined, onComplete?: Function | undefined): Promise<void>;
26
+ static process(signal: AbortSignal, generatorFn: () => AsyncGenerator<StreamEntry>, onProgress?: Function, onError?: Function, onComplete?: Function): Promise<void>;
26
27
  }
27
28
  import StreamEntry from "./StreamEntry.js";
@@ -21,7 +21,7 @@ export default class StreamEntry {
21
21
  done?: boolean | undefined;
22
22
  cancelled?: boolean | undefined;
23
23
  error?: string | undefined;
24
- } | undefined);
24
+ });
25
25
  /**
26
26
  * The value of the stream entry.
27
27
  * @type {any}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Generates a UIForm from a static Body schema.
3
+ *
4
+ * @param {Function} BodyClass - Class defining field schema.
5
+ * @param {Object} [options={}] - Generation options.
6
+ * @param {Object} [options.initialState={}] - Pre-filled form values.
7
+ * @param {Function} [options.t] - Optional translation function.
8
+ * @returns {UIForm} Form instance ready for input.
9
+ */
10
+ export function generateForm(BodyClass: Function, options?: {
11
+ initialState?: any;
12
+ t?: Function | undefined;
13
+ }): UIForm;
14
+ /**
15
+ * Unified UI Adapter that handles both input and output operations.
16
+ * It manages user interactions and rendering of messages, forms, and progress.
17
+ *
18
+ * @class UiAdapter
19
+ * @extends EventProcessor
20
+ *
21
+ * @example
22
+ * const adapter = new UiAdapter()
23
+ * adapter.output = new View()
24
+ *
25
+ * const result = await adapter.requireInput(new LoginMessage())
26
+ * console.log(result) // { username: "user", password: "pass" }
27
+ */
28
+ export default class UiAdapter extends EventProcessor {
29
+ static CancelError: typeof CancelError;
30
+ /** @returns {typeof CancelError} */
31
+ get CancelError(): typeof CancelError;
32
+ /** @type {OutputAdapter | null} Output interface for rendering */
33
+ output: OutputAdapter | null;
34
+ /**
35
+ * Starts listening for input and emits an `input` event.
36
+ *
37
+ * @returns {void}
38
+ */
39
+ start(): void;
40
+ /**
41
+ * Stops listening for input and output streams.
42
+ * Default implementation does nothing; override in subclasses to perform cleanup.
43
+ *
44
+ * @returns {void}
45
+ */
46
+ stop(): void;
47
+ /**
48
+ * Checks whether the adapter is ready to receive input.
49
+ *
50
+ * @returns {boolean} Always true in base class; override for specific checks.
51
+ */
52
+ isReady(): boolean;
53
+ /**
54
+ * Helper to ask a question.
55
+ * Must be implemented by subclasses.
56
+ *
57
+ * @param {string} question - Question to ask the user.
58
+ * @returns {Promise<string>} User's response.
59
+ * @throws {Error} If not implemented in subclass.
60
+ */
61
+ ask(question: string): Promise<string>;
62
+ /**
63
+ * Generic selection prompt.
64
+ * Must be implemented by subclasses.
65
+ *
66
+ * @param {object} config - Selection configuration.
67
+ * @param {string[]} [config.options=[]] - List of options to choose from.
68
+ * @returns {Promise<{ index: number, value: string | null }>} Selected option.
69
+ * @throws {Error} If not implemented in subclass.
70
+ */
71
+ select(config: {
72
+ options?: string[] | undefined;
73
+ }): Promise<{
74
+ index: number;
75
+ value: string | null;
76
+ }>;
77
+ /**
78
+ * Ensures a message's body is fully and validly filled.
79
+ * Generates a form from the message's static Body schema,
80
+ * then iteratively collects input until all fields are valid or cancelled.
81
+ *
82
+ * @template {UIMessage} T
83
+ * @param {T} msg - Message instance needing input.
84
+ * @returns {Promise<T['body']>} Updated and validated message body.
85
+ *
86
+ * @example
87
+ * const body = await adapter.requireInput(new LoginMessage({ body: { username: "user" } }))
88
+ * // → prompts for password, returns { username: "user", password: "..." }
89
+ */
90
+ requireInput<T extends UIMessage>(msg: T): Promise<T["body"]>;
91
+ /**
92
+ * Renders a message to the user interface.
93
+ * Must be implemented by subclasses.
94
+ *
95
+ * @param {UIMessage} message - Message to render.
96
+ * @emits rendered
97
+ * @throws {Error} If not implemented in subclass.
98
+ */
99
+ render(message: UIMessage): void;
100
+ }
101
+ import UIForm from "./Form/Form.js";
102
+ import EventProcessor from "@nan0web/event/oop";
103
+ import CancelError from "./Error/CancelError.js";
104
+ import UIMessage from "./Message/Message.js";
@@ -1,9 +1,9 @@
1
1
  export { default as InputAdapter } from "./InputAdapter.js";
2
2
  export { default as OutputAdapter } from "./OutputAdapter.js";
3
3
  export { default as UIStream } from "./Stream.js";
4
- export { default as UIMessage } from "./Message/Message.js";
5
- export { default as InputMessage } from "./Message/InputMessage.js";
6
- export { default as OutputMessage } from "./Message/OutputMessage.js";
4
+ export { default as UiMessage } from "./Message/Message.js";
7
5
  export { default as FormMessage } from "./Form/Message.js";
8
6
  export { default as FormInput } from "./Form/Input.js";
9
7
  export { default as UIForm } from "./Form/Form.js";
8
+ export { default as UiAdapter } from "./UiAdapter.js";
9
+ export { default as Error, CancelError } from "./Error/index.js";
package/types/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  export { default as FormMessage } from "./core/Form/Message.js";
2
2
  export { default as FormInput } from "./core/Form/Input.js";
3
3
  export { default as InputAdapter } from "./core/InputAdapter.js";
4
- export { default as InputMessage } from "./core/Message/InputMessage.js";
5
4
  export { default as OutputAdapter } from "./core/OutputAdapter.js";
6
5
  export { default as OutputMessage } from "./core/Message/OutputMessage.js";
7
- export { default as UIForm } from "./core/Form/Form.js";
8
- export { default as UIMessage } from "./core/Message/Message.js";
9
- export { default as UIStream } from "./core/Stream.js";
6
+ export { default as UiForm } from "./core/Form/Form.js";
7
+ export { default as UiMessage } from "./core/Message/Message.js";
8
+ export { default as UiStream } from "./core/Stream.js";
9
+ export { default as UiAdapter } from "./core/UiAdapter.js";
10
10
  import Frame from "./Frame/Frame.js";
11
11
  import FrameProps from "./Frame/Props.js";
12
12
  import Locale from "./Locale.js";
@@ -18,3 +18,4 @@ import Model from "./Model/index.js";
18
18
  import Component from "./Component/index.js";
19
19
  import App from "./App/index.js";
20
20
  export { Frame, FrameProps, Locale, StdIn, StdOut, View, RenderOptions, Model, Component, App };
21
+ export { default as Error, CancelError } from "./core/Error/index.js";
@@ -1,78 +0,0 @@
1
- /**
2
- * Represents command options with default values.
3
- * Provides utilities for handling command line options.
4
- */
5
- class CommandOptions {
6
- /**
7
- * Default option values.
8
- * @type {object}
9
- * @property {boolean} help - Whether help is requested
10
- * @property {string} cwd - Current working directory
11
- */
12
- static DEFAULTS = {
13
- help: false,
14
- cwd: "",
15
- }
16
-
17
- /** @type {boolean} Whether help is requested */
18
- help
19
-
20
- /** @type {string} Current working directory */
21
- cwd
22
-
23
- /**
24
- * Creates a new CommandOptions instance.
25
- * @param {object} props - The properties for command options
26
- * @param {boolean} [props.help=false] - Whether help is requested
27
- * @param {string} [props.cwd=""] - Current working directory
28
- */
29
- constructor(props = {}) {
30
- const {
31
- help = CommandOptions.DEFAULTS.help,
32
- cwd = CommandOptions.DEFAULTS.cwd,
33
- } = props
34
- this.help = Boolean(help)
35
- this.cwd = String(cwd)
36
- }
37
-
38
- /** @type {Record<string, any>} */
39
- get DEFAULTS() {
40
- return /** @type {typeof CommandOptions} */ (this.constructor).DEFAULTS
41
- }
42
-
43
- /**
44
- * Checks if all options have their default values.
45
- * @returns {boolean} True if all options are at their default values, false otherwise
46
- */
47
- get empty() {
48
- return Object.entries(this).every(
49
- ([key, value]) => CommandOptions.DEFAULTS[key] === value
50
- )
51
- }
52
-
53
- /**
54
- * Converts the options to a string representation.
55
- * @returns {string} String representation of the options or "<no options>" if none set
56
- */
57
- toString() {
58
- const opts = Object.entries(this).map(([key, value]) => {
59
- if (this.DEFAULTS[key] === value) return false
60
- const prefix = true === value ? "--" : "-"
61
- return `${prefix}${key}${value ? ` ${value}` : ""}`
62
- }).filter(Boolean)
63
- if (0 === opts.length) return "<no options>"
64
- return opts.join(" ")
65
- }
66
-
67
- /**
68
- * Creates a CommandOptions instance from the given props.
69
- * @param {CommandOptions|object} props - The properties to create from
70
- * @returns {CommandOptions} A CommandOptions instance
71
- */
72
- static from(props) {
73
- if (props instanceof CommandOptions) return props
74
- return new this(props)
75
- }
76
- }
77
-
78
- export default CommandOptions
@@ -1,9 +0,0 @@
1
- import { CommandMessage } from "@nan0web/co"
2
- import CommandOptions from "./Options.js"
3
-
4
- export { CommandMessage, CommandOptions }
5
-
6
- export default {
7
- Message: CommandMessage,
8
- Options: CommandOptions,
9
- }
@@ -1,48 +0,0 @@
1
- import CommandOptions from "../../Command/Options.js"
2
-
3
- /**
4
- * Extends CommandOptions to include user-specific options.
5
- */
6
- class UserAppCommandOptions extends CommandOptions {
7
- /**
8
- * Default option values including inherited ones.
9
- * @type {object}
10
- * @property {boolean} help - Whether help is requested
11
- * @property {string} cwd - Current working directory
12
- * @property {string} user - User name
13
- */
14
- static DEFAULTS = {
15
- ...CommandOptions.DEFAULTS,
16
- user: "",
17
- }
18
-
19
- /** @type {string} User name */
20
- user
21
-
22
- /**
23
- * Creates a new UserAppCommandOptions instance.
24
- * @param {object} props - Options properties
25
- * @param {boolean} [props.help=false] - Whether help is requested
26
- * @param {string} [props.cwd=""] - Current working directory
27
- * @param {string} [props.user=""] - User name
28
- */
29
- constructor(props = {}) {
30
- const {
31
- user = UserAppCommandOptions.DEFAULTS.user,
32
- } = props
33
- super(props)
34
- this.user = String(user)
35
- }
36
-
37
- /**
38
- * Creates a UserAppCommandOptions instance from the given props.
39
- * @param {UserAppCommandOptions|object} props - The properties to create from
40
- * @returns {UserAppCommandOptions} A UserAppCommandOptions instance
41
- */
42
- static from(props) {
43
- if (props instanceof UserAppCommandOptions) return props
44
- return new this(props)
45
- }
46
- }
47
-
48
- export default UserAppCommandOptions
@@ -1,119 +0,0 @@
1
- import { notEmpty } from "@nan0web/types"
2
- import { Message } from "@nan0web/co"
3
-
4
- /** @typedef {Message | string | null} InputMessageValue */
5
-
6
- /**
7
- * Represents a message input with value, options, and metadata.
8
- */
9
- export default class InputMessage {
10
- static ESCAPE = String.fromCharCode(27)
11
- /** @type {InputMessageValue} Input value */
12
- value
13
-
14
- /** @type {string[]} Available options for this input */
15
- options
16
-
17
- /** @type {boolean} Whether this input is waiting for response */
18
- waiting
19
-
20
- /** @type {number} Timestamp when input was created */
21
- #time
22
-
23
- /**
24
- * Creates a new InputMessage instance.
25
- * @param {object} props - Input message properties
26
- * @param {InputMessageValue} [props.value=""] - Input value
27
- * @param {string[]|string} [props.options=[]] - Available options
28
- * @param {boolean} [props.waiting=false] - Waiting state flag
29
- * @param {boolean} [props.escaped=false] - Sets value to escape when true
30
- */
31
- constructor(props = {}) {
32
- if ("string" === typeof props) {
33
- props = { value: props }
34
- }
35
- const {
36
- value = "",
37
- waiting = false,
38
- options = [],
39
- escaped = false,
40
- } = props
41
- this.#time = Date.now()
42
- this.waiting = Boolean(waiting)
43
-
44
- // Properly handle string options by converting to array
45
- this.options = Array.isArray(options) ? options.map(String) : [String(options)]
46
- this.value = String(value)
47
- if (!this.value && escaped) {
48
- this.value = this.ESCAPE
49
- }
50
- }
51
-
52
- /**
53
- * Checks if the input value is empty.
54
- * @returns {boolean} True if value is empty or null, false otherwise
55
- */
56
- get empty() {
57
- return null === this.value || 0 === String(this.value).length
58
- }
59
-
60
- /**
61
- * Gets the timestamp when input was created.
62
- * @returns {number} Creation timestamp
63
- */
64
- get time() {
65
- return this.#time
66
- }
67
-
68
- /**
69
- * Returns the escape value.
70
- * @returns {string}
71
- */
72
- get ESCAPE() {
73
- return /** @type {typeof InputMessage} */ (this.constructor).ESCAPE
74
- }
75
-
76
- /**
77
- * Checks if the input is an escape sequence.
78
- * @returns {boolean} True if input value is escape sequence, false otherwise
79
- */
80
- get escaped() {
81
- return this.ESCAPE === this.value
82
- }
83
-
84
- /**
85
- * Validates if the input has a non-empty value.
86
- * @returns {boolean} True if input is valid, false otherwise
87
- */
88
- get isValid() {
89
- // An input is valid only if it has a non-empty value and is not an escape sequence
90
- return notEmpty(this.value) && this.value !== this.ESCAPE
91
- }
92
-
93
- /**
94
- * Converts the input to a plain object representation.
95
- * @returns {object} Object with all properties including timestamp
96
- */
97
- toObject() {
98
- return { ...this, time: this.time }
99
- }
100
-
101
- /**
102
- * Converts the input to a string representation including timestamp.
103
- * @returns {string} String representation with timestamp and value
104
- */
105
- toString() {
106
- const date = new Date(this.time)
107
- return `${date.toISOString().split(".")[0]} ${this.value}`
108
- }
109
-
110
- /**
111
- * Creates an InputMessage instance from the given value.
112
- * @param {InputMessage|object|string} value - The value to create from
113
- * @returns {InputMessage} An InputMessage instance
114
- */
115
- static from(value) {
116
- if (value instanceof InputMessage) return value
117
- return new this(value)
118
- }
119
- }