@reset-framework/sdk 0.2.0 → 0.2.1
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/README.md +27 -2
- package/package.json +1 -1
- package/src/client.js +149 -32
- package/src/errors.js +28 -3
- package/src/index.d.ts +111 -13
- package/src/index.js +12 -2
- package/src/transport.js +162 -0
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Responsibilities:
|
|
6
6
|
|
|
7
|
-
- expose a stable
|
|
7
|
+
- expose a stable typed client for app frontends
|
|
8
8
|
- hide the raw `window.reset` bridge envelope
|
|
9
9
|
- provide runtime availability checks for local browser development
|
|
10
10
|
- centralize the shared browser helpers used by templates and demo apps
|
|
@@ -12,5 +12,30 @@ Responsibilities:
|
|
|
12
12
|
Package layout:
|
|
13
13
|
|
|
14
14
|
- `src/index.js`: public entrypoint
|
|
15
|
-
- `src/client.js`:
|
|
15
|
+
- `src/client.js`: high-level client and namespaced APIs
|
|
16
|
+
- `src/transport.js`: low-level transport and response validation
|
|
16
17
|
- `src/errors.js`: SDK-specific error types
|
|
18
|
+
|
|
19
|
+
Recommended usage:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { reset } from "@reset-framework/sdk"
|
|
23
|
+
|
|
24
|
+
const appInfo = await reset.app.getInfo()
|
|
25
|
+
const runtimeInfo = await reset.runtime.getInfo()
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Available namespaces:
|
|
29
|
+
|
|
30
|
+
- `reset.app.getId()`
|
|
31
|
+
- `reset.app.getName()`
|
|
32
|
+
- `reset.app.getSlug()`
|
|
33
|
+
- `reset.app.getVersion()`
|
|
34
|
+
- `reset.app.getInfo()`
|
|
35
|
+
- `reset.runtime.getPlatform()`
|
|
36
|
+
- `reset.runtime.getArchitecture()`
|
|
37
|
+
- `reset.runtime.getFrameworkVersion()`
|
|
38
|
+
- `reset.runtime.getBridgeVersion()`
|
|
39
|
+
- `reset.runtime.getInfo()`
|
|
40
|
+
- `reset.commands.invoke()`
|
|
41
|
+
- `reset.commands.invokeRaw()`
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -1,53 +1,170 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createResetTransport,
|
|
3
|
+
getResetRuntime,
|
|
4
|
+
invoke,
|
|
5
|
+
invokeRaw,
|
|
6
|
+
isResetRuntimeAvailable
|
|
7
|
+
} from "./transport.js"
|
|
8
|
+
import { ResetProtocolError } from "./errors.js"
|
|
2
9
|
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
10
|
+
function isObjectLike(value) {
|
|
11
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function requireObject(value, command) {
|
|
15
|
+
if (!isObjectLike(value)) {
|
|
16
|
+
throw new ResetProtocolError(
|
|
17
|
+
`Reset runtime returned an invalid payload for '${command}'.`,
|
|
18
|
+
{ command }
|
|
19
|
+
)
|
|
6
20
|
}
|
|
7
21
|
|
|
8
|
-
return
|
|
22
|
+
return value
|
|
9
23
|
}
|
|
10
24
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
target &&
|
|
14
|
-
target.reset &&
|
|
15
|
-
typeof target.reset.invoke === "function"
|
|
16
|
-
)
|
|
17
|
-
}
|
|
25
|
+
function requireStringField(record, field, command) {
|
|
26
|
+
const value = record[field]
|
|
18
27
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
29
|
+
throw new ResetProtocolError(
|
|
30
|
+
`Reset runtime returned an invalid '${field}' field for '${command}'.`,
|
|
31
|
+
{ command }
|
|
32
|
+
)
|
|
22
33
|
}
|
|
23
34
|
|
|
24
|
-
return
|
|
35
|
+
return value
|
|
25
36
|
}
|
|
26
37
|
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
function requireBooleanField(record, field, command) {
|
|
39
|
+
const value = record[field]
|
|
40
|
+
|
|
41
|
+
if (typeof value !== "boolean") {
|
|
42
|
+
throw new ResetProtocolError(
|
|
43
|
+
`Reset runtime returned an invalid '${field}' field for '${command}'.`,
|
|
44
|
+
{ command }
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return value
|
|
29
49
|
}
|
|
30
50
|
|
|
31
|
-
|
|
32
|
-
const
|
|
51
|
+
function normalizeAppInfo(payload, command) {
|
|
52
|
+
const record = requireObject(payload, command)
|
|
33
53
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
54
|
+
return Object.freeze({
|
|
55
|
+
id: requireStringField(record, "id", command),
|
|
56
|
+
name: requireStringField(record, "name", command),
|
|
57
|
+
slug: requireStringField(record, "slug", command),
|
|
58
|
+
version: requireStringField(record, "version", command),
|
|
59
|
+
windowTitle: requireStringField(record, "windowTitle", command)
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function normalizeRuntimeInfo(payload, command) {
|
|
64
|
+
const record = requireObject(payload, command)
|
|
37
65
|
|
|
38
|
-
return
|
|
66
|
+
return Object.freeze({
|
|
67
|
+
platform: requireStringField(record, "platform", command),
|
|
68
|
+
arch: requireStringField(record, "arch", command),
|
|
69
|
+
frameworkVersion: requireStringField(record, "frameworkVersion", command),
|
|
70
|
+
bridgeVersion: requireStringField(record, "bridgeVersion", command),
|
|
71
|
+
debug: requireBooleanField(record, "debug", command)
|
|
72
|
+
})
|
|
39
73
|
}
|
|
40
74
|
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
isAvailable() {
|
|
44
|
-
return isResetRuntimeAvailable(target)
|
|
45
|
-
},
|
|
75
|
+
function createCommandApi(transport) {
|
|
76
|
+
return Object.freeze({
|
|
46
77
|
invoke(command, payload = {}) {
|
|
47
|
-
return invoke(command, payload
|
|
78
|
+
return transport.invoke(command, payload)
|
|
48
79
|
},
|
|
49
80
|
invokeRaw(command, payload = {}) {
|
|
50
|
-
return invokeRaw(command, payload
|
|
81
|
+
return transport.invokeRaw(command, payload)
|
|
51
82
|
}
|
|
52
|
-
}
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function createAppApi(transport) {
|
|
87
|
+
return Object.freeze({
|
|
88
|
+
async getId() {
|
|
89
|
+
const payload = requireObject(await transport.invoke("app.getId"), "app.getId")
|
|
90
|
+
return requireStringField(payload, "id", "app.getId")
|
|
91
|
+
},
|
|
92
|
+
async getName() {
|
|
93
|
+
const payload = requireObject(await transport.invoke("app.getName"), "app.getName")
|
|
94
|
+
return requireStringField(payload, "name", "app.getName")
|
|
95
|
+
},
|
|
96
|
+
async getSlug() {
|
|
97
|
+
const payload = requireObject(await transport.invoke("app.getSlug"), "app.getSlug")
|
|
98
|
+
return requireStringField(payload, "slug", "app.getSlug")
|
|
99
|
+
},
|
|
100
|
+
async getVersion() {
|
|
101
|
+
const payload = requireObject(await transport.invoke("app.getVersion"), "app.getVersion")
|
|
102
|
+
return requireStringField(payload, "version", "app.getVersion")
|
|
103
|
+
},
|
|
104
|
+
async getInfo() {
|
|
105
|
+
return normalizeAppInfo(await transport.invoke("app.getInfo"), "app.getInfo")
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function createRuntimeApi(transport) {
|
|
111
|
+
return Object.freeze({
|
|
112
|
+
async getPlatform() {
|
|
113
|
+
const payload = requireObject(await transport.invoke("runtime.getPlatform"), "runtime.getPlatform")
|
|
114
|
+
return requireStringField(payload, "platform", "runtime.getPlatform")
|
|
115
|
+
},
|
|
116
|
+
async getArchitecture() {
|
|
117
|
+
const payload = requireObject(await transport.invoke("runtime.getArchitecture"), "runtime.getArchitecture")
|
|
118
|
+
return requireStringField(payload, "arch", "runtime.getArchitecture")
|
|
119
|
+
},
|
|
120
|
+
async getFrameworkVersion() {
|
|
121
|
+
const payload = requireObject(
|
|
122
|
+
await transport.invoke("runtime.getFrameworkVersion"),
|
|
123
|
+
"runtime.getFrameworkVersion"
|
|
124
|
+
)
|
|
125
|
+
return requireStringField(payload, "version", "runtime.getFrameworkVersion")
|
|
126
|
+
},
|
|
127
|
+
async getBridgeVersion() {
|
|
128
|
+
const payload = requireObject(
|
|
129
|
+
await transport.invoke("runtime.getBridgeVersion"),
|
|
130
|
+
"runtime.getBridgeVersion"
|
|
131
|
+
)
|
|
132
|
+
return requireStringField(payload, "version", "runtime.getBridgeVersion")
|
|
133
|
+
},
|
|
134
|
+
async getInfo() {
|
|
135
|
+
return normalizeRuntimeInfo(await transport.invoke("runtime.getInfo"), "runtime.getInfo")
|
|
136
|
+
}
|
|
137
|
+
})
|
|
53
138
|
}
|
|
139
|
+
|
|
140
|
+
export function createResetClient(source) {
|
|
141
|
+
const transport = createResetTransport(source)
|
|
142
|
+
const commands = createCommandApi(transport)
|
|
143
|
+
const app = createAppApi(transport)
|
|
144
|
+
const runtime = createRuntimeApi(transport)
|
|
145
|
+
|
|
146
|
+
return Object.freeze({
|
|
147
|
+
isAvailable() {
|
|
148
|
+
return transport.isAvailable()
|
|
149
|
+
},
|
|
150
|
+
getRuntime() {
|
|
151
|
+
return transport.getRuntime()
|
|
152
|
+
},
|
|
153
|
+
commands,
|
|
154
|
+
app,
|
|
155
|
+
runtime
|
|
156
|
+
})
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export {
|
|
160
|
+
createResetTransport,
|
|
161
|
+
getResetRuntime,
|
|
162
|
+
invoke,
|
|
163
|
+
invokeRaw,
|
|
164
|
+
isResetRuntimeAvailable
|
|
165
|
+
} from "./transport.js"
|
|
166
|
+
|
|
167
|
+
export const reset = createResetClient()
|
|
168
|
+
export const commands = reset.commands
|
|
169
|
+
export const app = reset.app
|
|
170
|
+
export const runtime = reset.runtime
|
package/src/errors.js
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
|
-
export class
|
|
2
|
-
constructor(message =
|
|
1
|
+
export class ResetRuntimeError extends Error {
|
|
2
|
+
constructor(message, options = {}) {
|
|
3
3
|
super(message)
|
|
4
|
-
this.name =
|
|
4
|
+
this.name = new.target.name
|
|
5
|
+
|
|
6
|
+
if ("cause" in options) {
|
|
7
|
+
this.cause = options.cause
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class ResetRuntimeUnavailableError extends ResetRuntimeError {
|
|
13
|
+
constructor(message = "Reset runtime is not available in the current environment.") {
|
|
14
|
+
super(message)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class ResetProtocolError extends ResetRuntimeError {
|
|
19
|
+
constructor(message, options = {}) {
|
|
20
|
+
super(message, options)
|
|
21
|
+
this.command = options.command
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class ResetInvocationError extends ResetRuntimeError {
|
|
26
|
+
constructor(command, message, response, options = {}) {
|
|
27
|
+
super(message, options)
|
|
28
|
+
this.command = command
|
|
29
|
+
this.response = response
|
|
5
30
|
}
|
|
6
31
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export type ResetInvokeResponse<T = unknown> =
|
|
|
12
12
|
| ResetInvokeSuccess<T>
|
|
13
13
|
| ResetInvokeError;
|
|
14
14
|
|
|
15
|
+
export type ResetPlatform = "macos" | "windows" | "linux" | "unknown";
|
|
16
|
+
|
|
17
|
+
export type ResetArchitecture = "arm64" | "x64" | "x86" | "unknown";
|
|
18
|
+
|
|
15
19
|
export interface ResetRuntime {
|
|
16
20
|
invoke<T = unknown>(
|
|
17
21
|
command: string,
|
|
@@ -23,39 +27,133 @@ export interface ResetRuntimeWindow {
|
|
|
23
27
|
reset?: ResetRuntime;
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
export interface ResetRuntimeSourceOptions {
|
|
31
|
+
target?: ResetRuntimeWindow;
|
|
32
|
+
runtime?: ResetRuntime;
|
|
33
|
+
resolveRuntime?: () => ResetRuntime | undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type ResetRuntimeSource =
|
|
37
|
+
| ResetRuntime
|
|
38
|
+
| ResetRuntimeWindow
|
|
39
|
+
| ResetRuntimeSourceOptions
|
|
40
|
+
| (() => ResetRuntime | undefined)
|
|
41
|
+
| undefined;
|
|
42
|
+
|
|
43
|
+
export interface ResetTransport {
|
|
44
|
+
isAvailable(): boolean;
|
|
45
|
+
getRuntime(): ResetRuntime;
|
|
46
|
+
invokeRaw<T = unknown>(
|
|
47
|
+
command: string,
|
|
48
|
+
payload?: unknown
|
|
49
|
+
): Promise<ResetInvokeResponse<T>>;
|
|
50
|
+
invoke<T = unknown>(command: string, payload?: unknown): Promise<T>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface ResetCommandApi {
|
|
54
|
+
invoke<T = unknown>(command: string, payload?: unknown): Promise<T>;
|
|
55
|
+
invokeRaw<T = unknown>(
|
|
56
|
+
command: string,
|
|
57
|
+
payload?: unknown
|
|
58
|
+
): Promise<ResetInvokeResponse<T>>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ResetAppInfo {
|
|
62
|
+
id: string;
|
|
63
|
+
name: string;
|
|
64
|
+
slug: string;
|
|
65
|
+
version: string;
|
|
66
|
+
windowTitle: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ResetRuntimeInfo {
|
|
70
|
+
platform: ResetPlatform;
|
|
71
|
+
arch: ResetArchitecture;
|
|
72
|
+
frameworkVersion: string;
|
|
73
|
+
bridgeVersion: string;
|
|
74
|
+
debug: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface ResetAppApi {
|
|
78
|
+
getId(): Promise<string>;
|
|
79
|
+
getName(): Promise<string>;
|
|
80
|
+
getSlug(): Promise<string>;
|
|
81
|
+
getVersion(): Promise<string>;
|
|
82
|
+
getInfo(): Promise<ResetAppInfo>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface ResetRuntimeApi {
|
|
86
|
+
getPlatform(): Promise<ResetPlatform>;
|
|
87
|
+
getArchitecture(): Promise<ResetArchitecture>;
|
|
88
|
+
getFrameworkVersion(): Promise<string>;
|
|
89
|
+
getBridgeVersion(): Promise<string>;
|
|
90
|
+
getInfo(): Promise<ResetRuntimeInfo>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface ResetClient {
|
|
94
|
+
isAvailable(): boolean;
|
|
95
|
+
getRuntime(): ResetRuntime;
|
|
96
|
+
commands: ResetCommandApi;
|
|
97
|
+
app: ResetAppApi;
|
|
98
|
+
runtime: ResetRuntimeApi;
|
|
99
|
+
}
|
|
100
|
+
|
|
26
101
|
declare global {
|
|
27
102
|
interface Window extends ResetRuntimeWindow {}
|
|
28
103
|
}
|
|
29
104
|
|
|
30
|
-
export class
|
|
105
|
+
export class ResetRuntimeError extends Error {
|
|
106
|
+
cause?: unknown;
|
|
107
|
+
constructor(message?: string, options?: { cause?: unknown });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export class ResetRuntimeUnavailableError extends ResetRuntimeError {
|
|
31
111
|
constructor(message?: string);
|
|
32
112
|
}
|
|
33
113
|
|
|
114
|
+
export class ResetProtocolError extends ResetRuntimeError {
|
|
115
|
+
command?: string;
|
|
116
|
+
constructor(message?: string, options?: { command?: string; cause?: unknown });
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export class ResetInvocationError extends ResetRuntimeError {
|
|
120
|
+
command: string;
|
|
121
|
+
response: ResetInvokeError;
|
|
122
|
+
constructor(
|
|
123
|
+
command: string,
|
|
124
|
+
message: string,
|
|
125
|
+
response: ResetInvokeError,
|
|
126
|
+
options?: { cause?: unknown }
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
34
130
|
export function isResetRuntimeAvailable(
|
|
35
|
-
|
|
131
|
+
source?: ResetRuntimeSource
|
|
36
132
|
): boolean;
|
|
37
133
|
|
|
38
134
|
export function getResetRuntime(
|
|
39
|
-
|
|
135
|
+
source?: ResetRuntimeSource
|
|
40
136
|
): ResetRuntime;
|
|
41
137
|
|
|
138
|
+
export function createResetTransport(
|
|
139
|
+
source?: ResetRuntimeSource
|
|
140
|
+
): ResetTransport;
|
|
141
|
+
|
|
42
142
|
export function invokeRaw<T = unknown>(
|
|
43
143
|
command: string,
|
|
44
144
|
payload?: unknown,
|
|
45
|
-
|
|
145
|
+
source?: ResetRuntimeSource
|
|
46
146
|
): Promise<ResetInvokeResponse<T>>;
|
|
47
147
|
|
|
48
148
|
export function invoke<T = unknown>(
|
|
49
149
|
command: string,
|
|
50
150
|
payload?: unknown,
|
|
51
|
-
|
|
151
|
+
source?: ResetRuntimeSource
|
|
52
152
|
): Promise<T>;
|
|
53
153
|
|
|
54
|
-
export function createResetClient(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
): Promise<ResetInvokeResponse<T>>;
|
|
61
|
-
};
|
|
154
|
+
export function createResetClient(source?: ResetRuntimeSource): ResetClient;
|
|
155
|
+
|
|
156
|
+
export const reset: ResetClient;
|
|
157
|
+
export const commands: ResetCommandApi;
|
|
158
|
+
export const app: ResetAppApi;
|
|
159
|
+
export const runtime: ResetRuntimeApi;
|
package/src/index.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
export {
|
|
2
|
+
app,
|
|
3
|
+
commands,
|
|
2
4
|
createResetClient,
|
|
5
|
+
createResetTransport,
|
|
3
6
|
getResetRuntime,
|
|
4
7
|
invoke,
|
|
5
8
|
invokeRaw,
|
|
6
|
-
isResetRuntimeAvailable
|
|
9
|
+
isResetRuntimeAvailable,
|
|
10
|
+
reset,
|
|
11
|
+
runtime
|
|
7
12
|
} from "./client.js"
|
|
8
13
|
|
|
9
|
-
export {
|
|
14
|
+
export {
|
|
15
|
+
ResetInvocationError,
|
|
16
|
+
ResetProtocolError,
|
|
17
|
+
ResetRuntimeError,
|
|
18
|
+
ResetRuntimeUnavailableError
|
|
19
|
+
} from "./errors.js"
|
package/src/transport.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ResetInvocationError,
|
|
3
|
+
ResetProtocolError,
|
|
4
|
+
ResetRuntimeUnavailableError
|
|
5
|
+
} from "./errors.js"
|
|
6
|
+
|
|
7
|
+
function getDefaultWindowTarget() {
|
|
8
|
+
if (typeof window === "undefined") {
|
|
9
|
+
return undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return window
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function hasOwn(object, key) {
|
|
16
|
+
return Object.prototype.hasOwnProperty.call(object, key)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isObjectLike(value) {
|
|
20
|
+
return typeof value === "object" && value !== null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isRuntimeLike(value) {
|
|
24
|
+
return isObjectLike(value) && typeof value.invoke === "function"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function createTargetRuntimeResolver(target) {
|
|
28
|
+
return () => {
|
|
29
|
+
if (!isObjectLike(target) || !isRuntimeLike(target.reset)) {
|
|
30
|
+
return undefined
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return target.reset
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizeRuntimeResolver(source) {
|
|
38
|
+
if (source === undefined) {
|
|
39
|
+
return () => {
|
|
40
|
+
const target = getDefaultWindowTarget()
|
|
41
|
+
return isObjectLike(target) && isRuntimeLike(target.reset) ? target.reset : undefined
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (typeof source === "function") {
|
|
46
|
+
return () => {
|
|
47
|
+
const runtime = source()
|
|
48
|
+
return isRuntimeLike(runtime) ? runtime : undefined
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (isRuntimeLike(source)) {
|
|
53
|
+
return () => source
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (isObjectLike(source) && (hasOwn(source, "runtime") || hasOwn(source, "resolveRuntime") || hasOwn(source, "target"))) {
|
|
57
|
+
if (typeof source.resolveRuntime === "function") {
|
|
58
|
+
return () => {
|
|
59
|
+
const runtime = source.resolveRuntime()
|
|
60
|
+
return isRuntimeLike(runtime) ? runtime : undefined
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (isRuntimeLike(source.runtime)) {
|
|
65
|
+
return () => source.runtime
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return createTargetRuntimeResolver(source.target)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return createTargetRuntimeResolver(source)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function assertCommand(command) {
|
|
75
|
+
if (typeof command !== "string" || command.trim() === "") {
|
|
76
|
+
throw new TypeError("Reset command must be a non-empty string.")
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function normalizeResponse(command, response) {
|
|
81
|
+
if (!isObjectLike(response) || typeof response.ok !== "boolean") {
|
|
82
|
+
throw new ResetProtocolError(
|
|
83
|
+
`Reset runtime returned an invalid response envelope for '${command}'.`,
|
|
84
|
+
{ command }
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (response.ok === false) {
|
|
89
|
+
if (typeof response.error !== "string" || response.error.trim() === "") {
|
|
90
|
+
throw new ResetProtocolError(
|
|
91
|
+
`Reset runtime returned an invalid error response for '${command}'.`,
|
|
92
|
+
{ command }
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return Object.freeze({
|
|
97
|
+
ok: false,
|
|
98
|
+
error: response.error
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return Object.freeze({
|
|
103
|
+
ok: true,
|
|
104
|
+
result: response.result
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function resolveRuntimeOrThrow(resolveRuntime) {
|
|
109
|
+
const runtime = resolveRuntime()
|
|
110
|
+
|
|
111
|
+
if (!isRuntimeLike(runtime)) {
|
|
112
|
+
throw new ResetRuntimeUnavailableError()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return runtime
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function isResetRuntimeAvailable(source) {
|
|
119
|
+
return isRuntimeLike(normalizeRuntimeResolver(source)())
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function getResetRuntime(source) {
|
|
123
|
+
return resolveRuntimeOrThrow(normalizeRuntimeResolver(source))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export async function invokeRaw(command, payload = {}, source) {
|
|
127
|
+
assertCommand(command)
|
|
128
|
+
|
|
129
|
+
const runtime = resolveRuntimeOrThrow(normalizeRuntimeResolver(source))
|
|
130
|
+
const response = await runtime.invoke(command, payload)
|
|
131
|
+
|
|
132
|
+
return normalizeResponse(command, response)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export async function invoke(command, payload = {}, source) {
|
|
136
|
+
const response = await invokeRaw(command, payload, source)
|
|
137
|
+
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
throw new ResetInvocationError(command, response.error, response)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return response.result
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function createResetTransport(source) {
|
|
146
|
+
const resolveRuntime = normalizeRuntimeResolver(source)
|
|
147
|
+
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
isAvailable() {
|
|
150
|
+
return isRuntimeLike(resolveRuntime())
|
|
151
|
+
},
|
|
152
|
+
getRuntime() {
|
|
153
|
+
return resolveRuntimeOrThrow(resolveRuntime)
|
|
154
|
+
},
|
|
155
|
+
invokeRaw(command, payload = {}) {
|
|
156
|
+
return invokeRaw(command, payload, resolveRuntime)
|
|
157
|
+
},
|
|
158
|
+
invoke(command, payload = {}) {
|
|
159
|
+
return invoke(command, payload, resolveRuntime)
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
}
|