@bodhiapp/setup-modal-types 0.0.19 → 0.0.21
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/extension.d.ts +24 -0
- package/{index.ts → dist/index.d.ts} +3 -67
- package/dist/index.js +180 -0
- package/dist/lna.d.ts +56 -0
- package/dist/message-types.d.ts +168 -0
- package/dist/platform.d.ts +32 -0
- package/dist/protocol.d.ts +70 -0
- package/dist/server.d.ts +63 -0
- package/dist/state.d.ts +42 -0
- package/dist/type-guards.d.ts +26 -0
- package/package.json +16 -7
- package/extension.ts +0 -31
- package/lna.ts +0 -75
- package/message-types.ts +0 -185
- package/platform.ts +0 -43
- package/protocol.ts +0 -97
- package/server.ts +0 -82
- package/state.ts +0 -65
- package/type-guards.ts +0 -126
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ExtensionErrorCode = 'ext-not-installed' | 'ext-connection-failed' | 'ext-unsupported-version';
|
|
2
|
+
export declare const EXT_NOT_INSTALLED: ExtensionErrorCode;
|
|
3
|
+
export declare const EXT_CONNECTION_FAILED: ExtensionErrorCode;
|
|
4
|
+
export declare const EXT_UNSUPPORTED_VERSION: ExtensionErrorCode;
|
|
5
|
+
export interface ExtensionStateReady {
|
|
6
|
+
/** Current extension status */
|
|
7
|
+
status: 'ready';
|
|
8
|
+
/** Extension version */
|
|
9
|
+
version: string;
|
|
10
|
+
/** Extension ID (always present when ready) */
|
|
11
|
+
id: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ExtensionStateNotReady {
|
|
14
|
+
/** Current extension status */
|
|
15
|
+
status: 'unreachable' | 'not-installed' | 'unsupported';
|
|
16
|
+
/** Error details */
|
|
17
|
+
error: {
|
|
18
|
+
/** Error message */
|
|
19
|
+
message: string;
|
|
20
|
+
/** Error code */
|
|
21
|
+
code: ExtensionErrorCode;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export type ExtensionState = ExtensionStateReady | ExtensionStateNotReady;
|
|
@@ -4,81 +4,17 @@
|
|
|
4
4
|
* This folder contains all domain and protocol types organized by domain.
|
|
5
5
|
* It is designed to be independent and copyable to other packages.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
// Platform types
|
|
9
7
|
export type { BrowserType, OSType, EnvState, SupportedBrowser, NotSupportedBrowser, Browser, SupportedOS, NotSupportedOS, OS } from './platform';
|
|
10
|
-
|
|
11
|
-
// Extension types
|
|
12
8
|
export type { ExtensionErrorCode, ExtensionStateReady, ExtensionStateNotReady, ExtensionState } from './extension';
|
|
13
9
|
export { EXT_NOT_INSTALLED, EXT_CONNECTION_FAILED, EXT_UNSUPPORTED_VERSION } from './extension';
|
|
14
|
-
|
|
15
|
-
// Server types
|
|
16
10
|
export type { ServerErrorCode, ServerStateReady, ServerStateReachable, ServerStatePending, ServerStateUnreachable, ServerStateError, ServerState } from './server';
|
|
17
|
-
export {
|
|
18
|
-
|
|
19
|
-
SERVER_CONN_REFUSED,
|
|
20
|
-
SERVER_CONN_TIMEOUT,
|
|
21
|
-
SERVER_NOT_FOUND,
|
|
22
|
-
SERVER_NETWORK_UNREACHABLE,
|
|
23
|
-
SERVER_SERVICE_UNAVAILABLE,
|
|
24
|
-
SERVER_UNEXPECTED_ERROR,
|
|
25
|
-
SERVER_IN_SETUP_STATUS,
|
|
26
|
-
SERVER_IN_ADMIN_STATUS,
|
|
27
|
-
} from './server';
|
|
28
|
-
|
|
29
|
-
// LNA types
|
|
30
|
-
export type {
|
|
31
|
-
LnaErrorCode,
|
|
32
|
-
LnaStatePrompt,
|
|
33
|
-
LnaStateSkipped,
|
|
34
|
-
LnaStateGranted,
|
|
35
|
-
LnaStateUnreachable,
|
|
36
|
-
LnaStateDenied,
|
|
37
|
-
LnaStateUnsupported,
|
|
38
|
-
LnaState,
|
|
39
|
-
LnaServerStatePending,
|
|
40
|
-
LnaServerStateReady,
|
|
41
|
-
LnaServerStateSetup,
|
|
42
|
-
LnaServerStateResourceAdmin,
|
|
43
|
-
LnaServerStateError,
|
|
44
|
-
LnaServerState,
|
|
45
|
-
} from './lna';
|
|
11
|
+
export { SERVER_PENDING_EXT_READY, SERVER_CONN_REFUSED, SERVER_CONN_TIMEOUT, SERVER_NOT_FOUND, SERVER_NETWORK_UNREACHABLE, SERVER_SERVICE_UNAVAILABLE, SERVER_UNEXPECTED_ERROR, SERVER_IN_SETUP_STATUS, SERVER_IN_ADMIN_STATUS, } from './server';
|
|
12
|
+
export type { LnaErrorCode, LnaStatePrompt, LnaStateSkipped, LnaStateGranted, LnaStateUnreachable, LnaStateDenied, LnaStateUnsupported, LnaState, LnaServerStatePending, LnaServerStateReady, LnaServerStateSetup, LnaServerStateResourceAdmin, LnaServerStateError, LnaServerState, } from './lna';
|
|
46
13
|
export { LNA_UNREACHABLE, LNA_PERMISSION_DENIED } from './lna';
|
|
47
|
-
|
|
48
|
-
// State types
|
|
49
14
|
export { SetupStep, DEFAULT_USER_CONFIRMATIONS, DEFAULT_SETUP_STATE } from './state';
|
|
50
15
|
export type { SelectedConnection, UserConfirmations, SetupState } from './state';
|
|
51
|
-
|
|
52
|
-
// Protocol types
|
|
53
16
|
export type { RequestId, MessageKind, RequestMessage, ResponseMessage, ErrorMessage, EventMessage, ProtocolMessage } from './protocol';
|
|
54
17
|
export { isRequestMessage, isResponseMessage, isErrorMessage, isEventMessage } from './protocol';
|
|
55
|
-
|
|
56
|
-
// Message types
|
|
57
18
|
export type { MessageTypeRegistry, MessageType, RequestPayload, ResponsePayload, RequestHandlers } from './message-types';
|
|
58
19
|
export { MSG, isMessageType } from './message-types';
|
|
59
|
-
|
|
60
|
-
// Type guards
|
|
61
|
-
export {
|
|
62
|
-
isExtensionStateReady,
|
|
63
|
-
isExtensionStateNotReady,
|
|
64
|
-
isServerStateReady,
|
|
65
|
-
isServerStateReachable,
|
|
66
|
-
isServerStatePending,
|
|
67
|
-
isServerStateUnreachable,
|
|
68
|
-
isServerStateError,
|
|
69
|
-
isLnaStatePrompt,
|
|
70
|
-
isLnaStateSkipped,
|
|
71
|
-
isLnaStateGranted,
|
|
72
|
-
isLnaStateUnreachable,
|
|
73
|
-
isLnaStateDenied,
|
|
74
|
-
isLnaStateUnsupported,
|
|
75
|
-
isLnaServerStatePending,
|
|
76
|
-
isLnaServerStateReady,
|
|
77
|
-
isLnaServerStateSetup,
|
|
78
|
-
isLnaServerStateResourceAdmin,
|
|
79
|
-
isLnaServerStateError,
|
|
80
|
-
isSupportedBrowser,
|
|
81
|
-
isNotSupportedBrowser,
|
|
82
|
-
isSupportedOS,
|
|
83
|
-
isNotSupportedOS,
|
|
84
|
-
} from './type-guards';
|
|
20
|
+
export { isExtensionStateReady, isExtensionStateNotReady, isServerStateReady, isServerStateReachable, isServerStatePending, isServerStateUnreachable, isServerStateError, isLnaStatePrompt, isLnaStateSkipped, isLnaStateGranted, isLnaStateUnreachable, isLnaStateDenied, isLnaStateUnsupported, isLnaServerStatePending, isLnaServerStateReady, isLnaServerStateSetup, isLnaServerStateResourceAdmin, isLnaServerStateError, isSupportedBrowser, isNotSupportedBrowser, isSupportedOS, isNotSupportedOS, } from './type-guards';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const EXT_NOT_INSTALLED = "ext-not-installed";
|
|
2
|
+
const EXT_CONNECTION_FAILED = "ext-connection-failed";
|
|
3
|
+
const EXT_UNSUPPORTED_VERSION = "ext-unsupported-version";
|
|
4
|
+
const SERVER_PENDING_EXT_READY = "server-pending-ext-ready";
|
|
5
|
+
const SERVER_CONN_REFUSED = "server-conn-refused";
|
|
6
|
+
const SERVER_CONN_TIMEOUT = "server-conn-timeout";
|
|
7
|
+
const SERVER_NOT_FOUND = "server-not-found";
|
|
8
|
+
const SERVER_NETWORK_UNREACHABLE = "server-network-unreachable";
|
|
9
|
+
const SERVER_SERVICE_UNAVAILABLE = "server-service-unavailable";
|
|
10
|
+
const SERVER_UNEXPECTED_ERROR = "server-unexpected-error";
|
|
11
|
+
const SERVER_IN_SETUP_STATUS = "server-in-setup-status";
|
|
12
|
+
const SERVER_IN_ADMIN_STATUS = "server-in-admin-status";
|
|
13
|
+
const LNA_UNREACHABLE = "lna-unreachable";
|
|
14
|
+
const LNA_PERMISSION_DENIED = "lna-permission-denied";
|
|
15
|
+
var SetupStep = /* @__PURE__ */ ((SetupStep2) => {
|
|
16
|
+
SetupStep2["PLATFORM_CHECK"] = "platform-check";
|
|
17
|
+
SetupStep2["SERVER_SETUP"] = "server-setup";
|
|
18
|
+
SetupStep2["LNA_SETUP"] = "lna-setup";
|
|
19
|
+
SetupStep2["EXTENSION_SETUP"] = "extension-setup";
|
|
20
|
+
SetupStep2["COMPLETE"] = "complete";
|
|
21
|
+
return SetupStep2;
|
|
22
|
+
})(SetupStep || {});
|
|
23
|
+
const DEFAULT_USER_CONFIRMATIONS = {
|
|
24
|
+
serverInstall: false
|
|
25
|
+
};
|
|
26
|
+
const DEFAULT_SETUP_STATE = {
|
|
27
|
+
extension: { status: "not-installed", error: { message: "Loading...", code: "ext-not-installed" } },
|
|
28
|
+
server: { status: "pending-extension-ready", error: { message: "Loading...", code: "server-pending-ext-ready" } },
|
|
29
|
+
lna: { status: "prompt" },
|
|
30
|
+
lnaServer: { status: "pending-lna-ready" },
|
|
31
|
+
env: { browser: "unknown", os: "unknown" },
|
|
32
|
+
browsers: [],
|
|
33
|
+
os: [],
|
|
34
|
+
userConfirmations: DEFAULT_USER_CONFIRMATIONS,
|
|
35
|
+
selectedConnection: null
|
|
36
|
+
};
|
|
37
|
+
function isRequestMessage(msg) {
|
|
38
|
+
return msg.kind === "request";
|
|
39
|
+
}
|
|
40
|
+
function isResponseMessage(msg) {
|
|
41
|
+
return msg.kind === "response";
|
|
42
|
+
}
|
|
43
|
+
function isErrorMessage(msg) {
|
|
44
|
+
return msg.kind === "error";
|
|
45
|
+
}
|
|
46
|
+
function isEventMessage(msg) {
|
|
47
|
+
return msg.kind === "event";
|
|
48
|
+
}
|
|
49
|
+
const MSG = {
|
|
50
|
+
// Modal lifecycle
|
|
51
|
+
MODAL_READY: "modal:ready",
|
|
52
|
+
MODAL_REFRESH: "modal:refresh",
|
|
53
|
+
MODAL_CLOSE: "modal:close",
|
|
54
|
+
MODAL_COMPLETE: "modal:complete",
|
|
55
|
+
// LNA actions
|
|
56
|
+
MODAL_LNA_CONNECT: "modal:lna:connect",
|
|
57
|
+
MODAL_LNA_SKIP: "modal:lna:skip",
|
|
58
|
+
// Server confirmation
|
|
59
|
+
MODAL_CONFIRM_SERVER_INSTALL: "modal:confirm-server-install",
|
|
60
|
+
// Connection selection
|
|
61
|
+
MODAL_SELECT_CONNECTION: "modal:select-connection",
|
|
62
|
+
// Parent → Modal events
|
|
63
|
+
PARENT_STATE_UPDATE: "parent:state-update"
|
|
64
|
+
};
|
|
65
|
+
function isMessageType(msg, type) {
|
|
66
|
+
return msg.type === type;
|
|
67
|
+
}
|
|
68
|
+
function isExtensionStateReady(ext) {
|
|
69
|
+
return ext.status === "ready";
|
|
70
|
+
}
|
|
71
|
+
function isExtensionStateNotReady(ext) {
|
|
72
|
+
return ext.status !== "ready";
|
|
73
|
+
}
|
|
74
|
+
function isServerStateReady(server) {
|
|
75
|
+
return server.status === "ready";
|
|
76
|
+
}
|
|
77
|
+
function isServerStateReachable(server) {
|
|
78
|
+
return server.status === "setup" || server.status === "resource-admin";
|
|
79
|
+
}
|
|
80
|
+
function isServerStatePending(server) {
|
|
81
|
+
return server.status === "pending-extension-ready";
|
|
82
|
+
}
|
|
83
|
+
function isServerStateUnreachable(server) {
|
|
84
|
+
return server.status === "unreachable";
|
|
85
|
+
}
|
|
86
|
+
function isServerStateError(server) {
|
|
87
|
+
return server.status === "error";
|
|
88
|
+
}
|
|
89
|
+
function isLnaStatePrompt(lna) {
|
|
90
|
+
return lna.status === "prompt";
|
|
91
|
+
}
|
|
92
|
+
function isLnaStateSkipped(lna) {
|
|
93
|
+
return lna.status === "skipped";
|
|
94
|
+
}
|
|
95
|
+
function isLnaStateGranted(lna) {
|
|
96
|
+
return lna.status === "granted";
|
|
97
|
+
}
|
|
98
|
+
function isLnaStateUnreachable(lna) {
|
|
99
|
+
return lna.status === "unreachable";
|
|
100
|
+
}
|
|
101
|
+
function isLnaStateDenied(lna) {
|
|
102
|
+
return lna.status === "denied";
|
|
103
|
+
}
|
|
104
|
+
function isLnaStateUnsupported(lna) {
|
|
105
|
+
return lna.status === "unsupported";
|
|
106
|
+
}
|
|
107
|
+
function isLnaServerStatePending(server) {
|
|
108
|
+
return server.status === "pending-lna-ready";
|
|
109
|
+
}
|
|
110
|
+
function isLnaServerStateReady(server) {
|
|
111
|
+
return server.status === "ready";
|
|
112
|
+
}
|
|
113
|
+
function isLnaServerStateSetup(server) {
|
|
114
|
+
return server.status === "setup";
|
|
115
|
+
}
|
|
116
|
+
function isLnaServerStateResourceAdmin(server) {
|
|
117
|
+
return server.status === "resource-admin";
|
|
118
|
+
}
|
|
119
|
+
function isLnaServerStateError(server) {
|
|
120
|
+
return server.status === "error";
|
|
121
|
+
}
|
|
122
|
+
function isSupportedBrowser(browser) {
|
|
123
|
+
return browser.status === "supported";
|
|
124
|
+
}
|
|
125
|
+
function isNotSupportedBrowser(browser) {
|
|
126
|
+
return browser.status === "not-supported";
|
|
127
|
+
}
|
|
128
|
+
function isSupportedOS(os) {
|
|
129
|
+
return os.status === "supported";
|
|
130
|
+
}
|
|
131
|
+
function isNotSupportedOS(os) {
|
|
132
|
+
return os.status === "not-supported";
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
DEFAULT_SETUP_STATE,
|
|
136
|
+
DEFAULT_USER_CONFIRMATIONS,
|
|
137
|
+
EXT_CONNECTION_FAILED,
|
|
138
|
+
EXT_NOT_INSTALLED,
|
|
139
|
+
EXT_UNSUPPORTED_VERSION,
|
|
140
|
+
LNA_PERMISSION_DENIED,
|
|
141
|
+
LNA_UNREACHABLE,
|
|
142
|
+
MSG,
|
|
143
|
+
SERVER_CONN_REFUSED,
|
|
144
|
+
SERVER_CONN_TIMEOUT,
|
|
145
|
+
SERVER_IN_ADMIN_STATUS,
|
|
146
|
+
SERVER_IN_SETUP_STATUS,
|
|
147
|
+
SERVER_NETWORK_UNREACHABLE,
|
|
148
|
+
SERVER_NOT_FOUND,
|
|
149
|
+
SERVER_PENDING_EXT_READY,
|
|
150
|
+
SERVER_SERVICE_UNAVAILABLE,
|
|
151
|
+
SERVER_UNEXPECTED_ERROR,
|
|
152
|
+
SetupStep,
|
|
153
|
+
isErrorMessage,
|
|
154
|
+
isEventMessage,
|
|
155
|
+
isExtensionStateNotReady,
|
|
156
|
+
isExtensionStateReady,
|
|
157
|
+
isLnaServerStateError,
|
|
158
|
+
isLnaServerStatePending,
|
|
159
|
+
isLnaServerStateReady,
|
|
160
|
+
isLnaServerStateResourceAdmin,
|
|
161
|
+
isLnaServerStateSetup,
|
|
162
|
+
isLnaStateDenied,
|
|
163
|
+
isLnaStateGranted,
|
|
164
|
+
isLnaStatePrompt,
|
|
165
|
+
isLnaStateSkipped,
|
|
166
|
+
isLnaStateUnreachable,
|
|
167
|
+
isLnaStateUnsupported,
|
|
168
|
+
isMessageType,
|
|
169
|
+
isNotSupportedBrowser,
|
|
170
|
+
isNotSupportedOS,
|
|
171
|
+
isRequestMessage,
|
|
172
|
+
isResponseMessage,
|
|
173
|
+
isServerStateError,
|
|
174
|
+
isServerStatePending,
|
|
175
|
+
isServerStateReachable,
|
|
176
|
+
isServerStateReady,
|
|
177
|
+
isServerStateUnreachable,
|
|
178
|
+
isSupportedBrowser,
|
|
179
|
+
isSupportedOS
|
|
180
|
+
};
|
package/dist/lna.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export type LnaErrorCode = 'lna-unreachable' | 'lna-permission-denied';
|
|
2
|
+
export declare const LNA_UNREACHABLE: LnaErrorCode;
|
|
3
|
+
export declare const LNA_PERMISSION_DENIED: LnaErrorCode;
|
|
4
|
+
export interface LnaStatePrompt {
|
|
5
|
+
status: 'prompt';
|
|
6
|
+
serverUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface LnaStateSkipped {
|
|
9
|
+
status: 'skipped';
|
|
10
|
+
serverUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface LnaStateGranted {
|
|
13
|
+
status: 'granted';
|
|
14
|
+
serverUrl: string;
|
|
15
|
+
}
|
|
16
|
+
export interface LnaStateUnreachable {
|
|
17
|
+
status: 'unreachable';
|
|
18
|
+
serverUrl: string;
|
|
19
|
+
error: {
|
|
20
|
+
message: string;
|
|
21
|
+
code: LnaErrorCode;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface LnaStateDenied {
|
|
25
|
+
status: 'denied';
|
|
26
|
+
error: {
|
|
27
|
+
message: string;
|
|
28
|
+
code: LnaErrorCode;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface LnaStateUnsupported {
|
|
32
|
+
status: 'unsupported';
|
|
33
|
+
}
|
|
34
|
+
export type LnaState = LnaStatePrompt | LnaStateSkipped | LnaStateGranted | LnaStateUnreachable | LnaStateDenied | LnaStateUnsupported;
|
|
35
|
+
export interface LnaServerStatePending {
|
|
36
|
+
status: 'pending-lna-ready';
|
|
37
|
+
}
|
|
38
|
+
export interface LnaServerStateReady {
|
|
39
|
+
status: 'ready';
|
|
40
|
+
version: string;
|
|
41
|
+
}
|
|
42
|
+
export interface LnaServerStateSetup {
|
|
43
|
+
status: 'setup';
|
|
44
|
+
version: string;
|
|
45
|
+
}
|
|
46
|
+
export interface LnaServerStateResourceAdmin {
|
|
47
|
+
status: 'resource-admin';
|
|
48
|
+
version: string;
|
|
49
|
+
}
|
|
50
|
+
export interface LnaServerStateError {
|
|
51
|
+
status: 'error';
|
|
52
|
+
error: {
|
|
53
|
+
message: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export type LnaServerState = LnaServerStatePending | LnaServerStateReady | LnaServerStateSetup | LnaServerStateResourceAdmin | LnaServerStateError;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { SetupState } from './state';
|
|
2
|
+
/**
|
|
3
|
+
* Central registry mapping message types to their payload/response shapes
|
|
4
|
+
* Single source of truth - everything else is inferred!
|
|
5
|
+
*/
|
|
6
|
+
export interface MessageTypeRegistry {
|
|
7
|
+
/**
|
|
8
|
+
* Modal is ready and requesting initial state
|
|
9
|
+
* Sent on modal mount
|
|
10
|
+
*/
|
|
11
|
+
'modal:ready': {
|
|
12
|
+
request: void;
|
|
13
|
+
response: {
|
|
14
|
+
setupState: SetupState;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* User requested to refresh platform detection
|
|
19
|
+
* Triggers re-detection of browser, OS, extension, server
|
|
20
|
+
*/
|
|
21
|
+
'modal:refresh': {
|
|
22
|
+
request: void;
|
|
23
|
+
response: {
|
|
24
|
+
setupState: SetupState;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* User requested to close the modal
|
|
29
|
+
* Parent should hide/destroy modal
|
|
30
|
+
*/
|
|
31
|
+
'modal:close': {
|
|
32
|
+
request: void;
|
|
33
|
+
response: void;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Setup completed successfully
|
|
37
|
+
* Signals parent that user has finished setup
|
|
38
|
+
*/
|
|
39
|
+
'modal:complete': {
|
|
40
|
+
request: void;
|
|
41
|
+
response: void;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* User requested LNA connection to specific server URL
|
|
45
|
+
* Triggers LNA permission request and connection attempt
|
|
46
|
+
*/
|
|
47
|
+
'modal:lna:connect': {
|
|
48
|
+
request: {
|
|
49
|
+
serverUrl: string;
|
|
50
|
+
};
|
|
51
|
+
response: {
|
|
52
|
+
success: boolean;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* User chose to skip LNA setup
|
|
57
|
+
* Falls back to extension-only mode
|
|
58
|
+
*/
|
|
59
|
+
'modal:lna:skip': {
|
|
60
|
+
request: void;
|
|
61
|
+
response: {
|
|
62
|
+
success: boolean;
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* User confirmed server installation status
|
|
67
|
+
* Used when server needs to be installed
|
|
68
|
+
*/
|
|
69
|
+
'modal:confirm-server-install': {
|
|
70
|
+
request: {
|
|
71
|
+
confirmed: boolean;
|
|
72
|
+
};
|
|
73
|
+
response: {
|
|
74
|
+
success: boolean;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* User selected preferred connection method
|
|
79
|
+
* Allows choosing between LNA and Extension paths
|
|
80
|
+
*/
|
|
81
|
+
'modal:select-connection': {
|
|
82
|
+
request: {
|
|
83
|
+
connection: 'lna' | 'extension';
|
|
84
|
+
};
|
|
85
|
+
response: {
|
|
86
|
+
success: boolean;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Parent sending updated state to modal
|
|
91
|
+
* Fired when platform detection results change
|
|
92
|
+
*/
|
|
93
|
+
'parent:state-update': {
|
|
94
|
+
request: {
|
|
95
|
+
setupState: SetupState;
|
|
96
|
+
};
|
|
97
|
+
response: void;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Union of all valid message type strings
|
|
102
|
+
* Derived from MessageTypeRegistry keys
|
|
103
|
+
*/
|
|
104
|
+
export type MessageType = keyof MessageTypeRegistry;
|
|
105
|
+
/**
|
|
106
|
+
* Extract request payload type for a given message type
|
|
107
|
+
* Returns the 'request' field from the registry entry
|
|
108
|
+
*/
|
|
109
|
+
export type RequestPayload<T extends MessageType> = MessageTypeRegistry[T]['request'];
|
|
110
|
+
/**
|
|
111
|
+
* Extract response payload type for a given message type
|
|
112
|
+
* Returns the 'response' field from the registry entry
|
|
113
|
+
*/
|
|
114
|
+
export type ResponsePayload<T extends MessageType> = MessageTypeRegistry[T]['response'];
|
|
115
|
+
/**
|
|
116
|
+
* Message type constants - Type-safe identifiers
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* switch (message.type) {
|
|
120
|
+
* case MSG.MODAL_READY:
|
|
121
|
+
* // Type-safe constant, no typos possible
|
|
122
|
+
* break;
|
|
123
|
+
* }
|
|
124
|
+
*/
|
|
125
|
+
export declare const MSG: {
|
|
126
|
+
readonly MODAL_READY: "modal:ready";
|
|
127
|
+
readonly MODAL_REFRESH: "modal:refresh";
|
|
128
|
+
readonly MODAL_CLOSE: "modal:close";
|
|
129
|
+
readonly MODAL_COMPLETE: "modal:complete";
|
|
130
|
+
readonly MODAL_LNA_CONNECT: "modal:lna:connect";
|
|
131
|
+
readonly MODAL_LNA_SKIP: "modal:lna:skip";
|
|
132
|
+
readonly MODAL_CONFIRM_SERVER_INSTALL: "modal:confirm-server-install";
|
|
133
|
+
readonly MODAL_SELECT_CONNECTION: "modal:select-connection";
|
|
134
|
+
readonly PARENT_STATE_UPDATE: "parent:state-update";
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Type guard that narrows RequestMessage to specific type WITH payload typing
|
|
138
|
+
*
|
|
139
|
+
* Use this for full type safety when you need access to typed payload fields.
|
|
140
|
+
* The guard narrows the generic RequestMessage to RequestMessage<T> where T
|
|
141
|
+
* determines the payload type.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* if (isMessageType(msg, MSG.MODAL_LNA_CONNECT)) {
|
|
145
|
+
* // msg.payload is { serverUrl: string } - fully typed!
|
|
146
|
+
* console.log(msg.payload.serverUrl); // Autocomplete works!
|
|
147
|
+
* }
|
|
148
|
+
*/
|
|
149
|
+
export declare function isMessageType<T extends MessageType>(msg: {
|
|
150
|
+
type: string;
|
|
151
|
+
}, type: T): msg is {
|
|
152
|
+
type: T;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Type-safe request handler map
|
|
156
|
+
* Enforces correct payload access AND correct return type for each message
|
|
157
|
+
*
|
|
158
|
+
* Each handler receives a RequestMessage<K> where K is the specific message type,
|
|
159
|
+
* providing full type safety for payload access. The handler must return the
|
|
160
|
+
* correct ResponsePayload<K> type.
|
|
161
|
+
*/
|
|
162
|
+
export type RequestHandlers = {
|
|
163
|
+
[K in MessageType]?: (msg: {
|
|
164
|
+
type: K;
|
|
165
|
+
requestId: string;
|
|
166
|
+
payload: RequestPayload<K>;
|
|
167
|
+
}) => ResponsePayload<K>;
|
|
168
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type BrowserType = 'chrome' | 'edge' | 'firefox' | 'safari' | 'unknown';
|
|
2
|
+
export type OSType = 'macos' | 'windows' | 'linux' | 'unknown';
|
|
3
|
+
export interface EnvState {
|
|
4
|
+
os: OSType;
|
|
5
|
+
browser: BrowserType;
|
|
6
|
+
}
|
|
7
|
+
export interface SupportedBrowser {
|
|
8
|
+
id: BrowserType;
|
|
9
|
+
status: 'supported';
|
|
10
|
+
name: string;
|
|
11
|
+
extension_url: string;
|
|
12
|
+
}
|
|
13
|
+
export interface NotSupportedBrowser {
|
|
14
|
+
id: BrowserType;
|
|
15
|
+
status: 'not-supported';
|
|
16
|
+
name: string;
|
|
17
|
+
github_issue_url?: string;
|
|
18
|
+
}
|
|
19
|
+
export type Browser = SupportedBrowser | NotSupportedBrowser;
|
|
20
|
+
export interface SupportedOS {
|
|
21
|
+
id: OSType;
|
|
22
|
+
status: 'supported';
|
|
23
|
+
name: string;
|
|
24
|
+
download_url: string;
|
|
25
|
+
}
|
|
26
|
+
export interface NotSupportedOS {
|
|
27
|
+
id: OSType;
|
|
28
|
+
status: 'not-supported';
|
|
29
|
+
name: string;
|
|
30
|
+
github_issue_url?: string;
|
|
31
|
+
}
|
|
32
|
+
export type OS = SupportedOS | NotSupportedOS;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { MessageType, RequestPayload, ResponsePayload } from './message-types';
|
|
2
|
+
/** Branded type for type-safe request IDs */
|
|
3
|
+
export type RequestId = string & {
|
|
4
|
+
readonly __brand: 'RequestId';
|
|
5
|
+
};
|
|
6
|
+
/** Message kind discriminator */
|
|
7
|
+
export type MessageKind = 'request' | 'response' | 'error' | 'event';
|
|
8
|
+
/**
|
|
9
|
+
* Request message - expects a response
|
|
10
|
+
* Sent by either modal or parent to request an action
|
|
11
|
+
*/
|
|
12
|
+
export interface RequestMessage<T extends MessageType = MessageType> {
|
|
13
|
+
readonly kind: 'request';
|
|
14
|
+
readonly type: T;
|
|
15
|
+
readonly requestId: RequestId;
|
|
16
|
+
readonly payload: RequestPayload<T>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Response message - correlates to a request
|
|
20
|
+
* Sent in response to a RequestMessage with matching requestId
|
|
21
|
+
*/
|
|
22
|
+
export interface ResponseMessage<T extends MessageType = MessageType> {
|
|
23
|
+
readonly kind: 'response';
|
|
24
|
+
readonly type: T;
|
|
25
|
+
readonly requestId: RequestId;
|
|
26
|
+
readonly payload: ResponsePayload<T>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Error response - indicates request failure
|
|
30
|
+
* Sent instead of ResponseMessage when request cannot be fulfilled
|
|
31
|
+
*/
|
|
32
|
+
export interface ErrorMessage {
|
|
33
|
+
readonly kind: 'error';
|
|
34
|
+
readonly requestId: RequestId;
|
|
35
|
+
readonly error: {
|
|
36
|
+
code: string;
|
|
37
|
+
message: string;
|
|
38
|
+
details?: unknown;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Event message - fire-and-forget notification
|
|
43
|
+
* No response expected, used for one-way state updates
|
|
44
|
+
*/
|
|
45
|
+
export interface EventMessage<T extends MessageType = MessageType> {
|
|
46
|
+
readonly kind: 'event';
|
|
47
|
+
readonly type: T;
|
|
48
|
+
readonly payload: RequestPayload<T>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Union of all protocol messages
|
|
52
|
+
* Discriminated by 'kind' field for type narrowing
|
|
53
|
+
*/
|
|
54
|
+
export type ProtocolMessage = RequestMessage | ResponseMessage | ErrorMessage | EventMessage;
|
|
55
|
+
/**
|
|
56
|
+
* Type guard to check if message is a request
|
|
57
|
+
*/
|
|
58
|
+
export declare function isRequestMessage(msg: ProtocolMessage): msg is RequestMessage;
|
|
59
|
+
/**
|
|
60
|
+
* Type guard to check if message is a response
|
|
61
|
+
*/
|
|
62
|
+
export declare function isResponseMessage(msg: ProtocolMessage): msg is ResponseMessage;
|
|
63
|
+
/**
|
|
64
|
+
* Type guard to check if message is an error
|
|
65
|
+
*/
|
|
66
|
+
export declare function isErrorMessage(msg: ProtocolMessage): msg is ErrorMessage;
|
|
67
|
+
/**
|
|
68
|
+
* Type guard to check if message is an event
|
|
69
|
+
*/
|
|
70
|
+
export declare function isEventMessage(msg: ProtocolMessage): msg is EventMessage;
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export type ServerErrorCode = 'server-pending-ext-ready' | 'server-conn-refused' | 'server-conn-timeout' | 'server-not-found' | 'server-network-unreachable' | 'server-service-unavailable' | 'server-unexpected-error' | 'server-in-setup-status' | 'server-in-admin-status';
|
|
2
|
+
export declare const SERVER_PENDING_EXT_READY: ServerErrorCode;
|
|
3
|
+
export declare const SERVER_CONN_REFUSED: ServerErrorCode;
|
|
4
|
+
export declare const SERVER_CONN_TIMEOUT: ServerErrorCode;
|
|
5
|
+
export declare const SERVER_NOT_FOUND: ServerErrorCode;
|
|
6
|
+
export declare const SERVER_NETWORK_UNREACHABLE: ServerErrorCode;
|
|
7
|
+
export declare const SERVER_SERVICE_UNAVAILABLE: ServerErrorCode;
|
|
8
|
+
export declare const SERVER_UNEXPECTED_ERROR: ServerErrorCode;
|
|
9
|
+
export declare const SERVER_IN_SETUP_STATUS: ServerErrorCode;
|
|
10
|
+
export declare const SERVER_IN_ADMIN_STATUS: ServerErrorCode;
|
|
11
|
+
export interface ServerStateReady {
|
|
12
|
+
/** Current server status */
|
|
13
|
+
status: 'ready';
|
|
14
|
+
/** Server version */
|
|
15
|
+
version: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ServerStateReachable {
|
|
18
|
+
/** Current server status */
|
|
19
|
+
status: 'setup' | 'resource-admin';
|
|
20
|
+
/** Server version */
|
|
21
|
+
version: string;
|
|
22
|
+
/** Error details */
|
|
23
|
+
error: {
|
|
24
|
+
/** Error message */
|
|
25
|
+
message: string;
|
|
26
|
+
/** Error code */
|
|
27
|
+
code: ServerErrorCode;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface ServerStatePending {
|
|
31
|
+
/** Current server status */
|
|
32
|
+
status: 'pending-extension-ready';
|
|
33
|
+
/** Error details */
|
|
34
|
+
error: {
|
|
35
|
+
/** Error message */
|
|
36
|
+
message: string;
|
|
37
|
+
/** Error code */
|
|
38
|
+
code: ServerErrorCode;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface ServerStateUnreachable {
|
|
42
|
+
/** Current server status */
|
|
43
|
+
status: 'unreachable';
|
|
44
|
+
/** Error details */
|
|
45
|
+
error: {
|
|
46
|
+
/** Error message */
|
|
47
|
+
message: string;
|
|
48
|
+
/** Error code */
|
|
49
|
+
code: ServerErrorCode;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export interface ServerStateError {
|
|
53
|
+
/** Current server status */
|
|
54
|
+
status: 'error';
|
|
55
|
+
/** Error details */
|
|
56
|
+
error: {
|
|
57
|
+
/** Error message */
|
|
58
|
+
message: string;
|
|
59
|
+
/** Error code */
|
|
60
|
+
code: ServerErrorCode;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export type ServerState = ServerStateReady | ServerStateReachable | ServerStatePending | ServerStateUnreachable | ServerStateError;
|