@floegence/floe-webapp-protocol 0.1.0
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/client.d.ts +50 -0
- package/dist/controlplane.d.ts +13 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +14 -0
- package/dist/index2.js +189 -0
- package/dist/index3.js +56 -0
- package/dist/index4.js +17 -0
- package/dist/index5.js +28 -0
- package/dist/rpc.d.ts +29 -0
- package/dist/types/common.d.ts +99 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +35 -0
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type JSX } from 'solid-js';
|
|
2
|
+
import type { ChannelInitGrant, Client, ClientObserverLike, DirectConnectInfo } from '@floegence/flowersec-core';
|
|
3
|
+
import { type ControlplaneConfig } from './controlplane';
|
|
4
|
+
/**
|
|
5
|
+
* Connection status
|
|
6
|
+
*/
|
|
7
|
+
export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'error';
|
|
8
|
+
interface ProtocolContextValue {
|
|
9
|
+
status: () => ConnectionStatus;
|
|
10
|
+
error: () => Error | null;
|
|
11
|
+
client: () => Client | null;
|
|
12
|
+
connect: (config: ConnectConfig) => Promise<void>;
|
|
13
|
+
disconnect: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for connecting to a flowersec server
|
|
17
|
+
*/
|
|
18
|
+
export interface AutoReconnectConfig {
|
|
19
|
+
/**
|
|
20
|
+
* Enable auto reconnect on failure / unexpected disconnect.
|
|
21
|
+
* Default: false.
|
|
22
|
+
*/
|
|
23
|
+
enabled?: boolean;
|
|
24
|
+
/** Maximum total attempts (including the first). Default: 5. */
|
|
25
|
+
maxAttempts?: number;
|
|
26
|
+
/** Base delay for the first retry. Default: 500ms. */
|
|
27
|
+
initialDelayMs?: number;
|
|
28
|
+
/** Max delay cap. Default: 10s. */
|
|
29
|
+
maxDelayMs?: number;
|
|
30
|
+
/** Exponential backoff factor. Default: 1.8. */
|
|
31
|
+
factor?: number;
|
|
32
|
+
/** Random jitter ratio in [-ratio, +ratio]. Default: 0.2. */
|
|
33
|
+
jitterRatio?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface ConnectConfig {
|
|
36
|
+
mode?: 'tunnel' | 'direct';
|
|
37
|
+
observer?: ClientObserverLike;
|
|
38
|
+
keepaliveIntervalMs?: number;
|
|
39
|
+
connectTimeoutMs?: number;
|
|
40
|
+
handshakeTimeoutMs?: number;
|
|
41
|
+
autoReconnect?: AutoReconnectConfig;
|
|
42
|
+
controlplane?: ControlplaneConfig;
|
|
43
|
+
grant?: ChannelInitGrant;
|
|
44
|
+
directInfo?: DirectConnectInfo;
|
|
45
|
+
}
|
|
46
|
+
export declare function ProtocolProvider(props: {
|
|
47
|
+
children: JSX.Element;
|
|
48
|
+
}): JSX.Element;
|
|
49
|
+
export declare function useProtocol(): ProtocolContextValue;
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ChannelInitGrant } from '@floegence/flowersec-core';
|
|
2
|
+
export interface ControlplaneConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
endpointId: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* 向控制面请求隧道连接凭证(grant)。
|
|
8
|
+
*
|
|
9
|
+
* 说明:
|
|
10
|
+
* - `.design.md` 约定的接口为 POST `${baseUrl}/v1/channel/init`,body: { endpoint_id }
|
|
11
|
+
* - 返回体结构按设计约定:`{ grant_client: ChannelInitGrant }`
|
|
12
|
+
*/
|
|
13
|
+
export declare function requestChannelGrant(config: ControlplaneConfig): Promise<ChannelInitGrant>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ProtocolProvider, useProtocol, type ConnectionStatus, type ConnectConfig, type AutoReconnectConfig } from './client';
|
|
2
|
+
export { useRpc, RpcError, ProtocolNotConnectedError } from './rpc';
|
|
3
|
+
export { requestChannelGrant, type ControlplaneConfig } from './controlplane';
|
|
4
|
+
export * from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ProtocolProvider as e, useProtocol as t } from "./index2.js";
|
|
2
|
+
import { ProtocolNotConnectedError as c, RpcError as s, useRpc as d } from "./index3.js";
|
|
3
|
+
import { requestChannelGrant as f } from "./index4.js";
|
|
4
|
+
import { ReservedTypeIds as m, TypeIds as x } from "./index5.js";
|
|
5
|
+
export {
|
|
6
|
+
c as ProtocolNotConnectedError,
|
|
7
|
+
e as ProtocolProvider,
|
|
8
|
+
m as ReservedTypeIds,
|
|
9
|
+
s as RpcError,
|
|
10
|
+
x as TypeIds,
|
|
11
|
+
f as requestChannelGrant,
|
|
12
|
+
t as useProtocol,
|
|
13
|
+
d as useRpc
|
|
14
|
+
};
|
package/dist/index2.js
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { createContext as T, onCleanup as E, createComponent as P, useContext as k } from "solid-js";
|
|
2
|
+
import { createStore as A } from "solid-js/store";
|
|
3
|
+
import { requestChannelGrant as W } from "./index4.js";
|
|
4
|
+
const R = T();
|
|
5
|
+
function y(a) {
|
|
6
|
+
return a != null && a.enabled ? {
|
|
7
|
+
enabled: !0,
|
|
8
|
+
maxAttempts: Math.max(1, a.maxAttempts ?? 5),
|
|
9
|
+
initialDelayMs: Math.max(0, a.initialDelayMs ?? 500),
|
|
10
|
+
maxDelayMs: Math.max(0, a.maxDelayMs ?? 1e4),
|
|
11
|
+
factor: Math.max(1, a.factor ?? 1.8),
|
|
12
|
+
jitterRatio: Math.max(0, a.jitterRatio ?? 0.2)
|
|
13
|
+
} : {
|
|
14
|
+
enabled: !1,
|
|
15
|
+
maxAttempts: 1,
|
|
16
|
+
initialDelayMs: 500,
|
|
17
|
+
maxDelayMs: 1e4,
|
|
18
|
+
factor: 1.8,
|
|
19
|
+
jitterRatio: 0.2
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function j(a, c) {
|
|
23
|
+
const i = Math.min(c.maxDelayMs, c.initialDelayMs * Math.pow(c.factor, a)), l = c.jitterRatio <= 0 ? 0 : i * c.jitterRatio * (Math.random() * 2 - 1);
|
|
24
|
+
return Math.max(0, Math.round(i + l));
|
|
25
|
+
}
|
|
26
|
+
function H(a) {
|
|
27
|
+
const [c, i] = A({
|
|
28
|
+
status: "disconnected",
|
|
29
|
+
error: null,
|
|
30
|
+
client: null
|
|
31
|
+
});
|
|
32
|
+
let l = 0, u = null, d = null, m = null;
|
|
33
|
+
const h = () => {
|
|
34
|
+
d && (clearTimeout(d), d = null), m == null || m(), m = null;
|
|
35
|
+
}, b = (r) => new Promise((e) => {
|
|
36
|
+
m = e, d = setTimeout(() => {
|
|
37
|
+
d = null, m = null, e();
|
|
38
|
+
}, r);
|
|
39
|
+
}), M = () => {
|
|
40
|
+
h(), u = null, l += 1, c.client && c.client.close(), i({
|
|
41
|
+
status: "disconnected",
|
|
42
|
+
error: null,
|
|
43
|
+
client: null
|
|
44
|
+
});
|
|
45
|
+
}, w = (r, e, t) => {
|
|
46
|
+
if (r !== l || u !== e || c.status !== "connected") return;
|
|
47
|
+
if (!y(e.autoReconnect).enabled) {
|
|
48
|
+
i({
|
|
49
|
+
status: "error",
|
|
50
|
+
error: t,
|
|
51
|
+
client: null
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
h(), l += 1;
|
|
56
|
+
const n = l;
|
|
57
|
+
i({
|
|
58
|
+
status: "connecting",
|
|
59
|
+
error: t,
|
|
60
|
+
client: null
|
|
61
|
+
}), x(n, e).catch(() => {
|
|
62
|
+
});
|
|
63
|
+
}, C = (r, e) => {
|
|
64
|
+
const t = e.observer;
|
|
65
|
+
return {
|
|
66
|
+
onConnect: (...o) => {
|
|
67
|
+
var n;
|
|
68
|
+
return (n = t == null ? void 0 : t.onConnect) == null ? void 0 : n.call(t, ...o);
|
|
69
|
+
},
|
|
70
|
+
onAttach: (...o) => {
|
|
71
|
+
var n;
|
|
72
|
+
return (n = t == null ? void 0 : t.onAttach) == null ? void 0 : n.call(t, ...o);
|
|
73
|
+
},
|
|
74
|
+
onHandshake: (...o) => {
|
|
75
|
+
var n;
|
|
76
|
+
return (n = t == null ? void 0 : t.onHandshake) == null ? void 0 : n.call(t, ...o);
|
|
77
|
+
},
|
|
78
|
+
onWsClose: (o, n) => {
|
|
79
|
+
var s;
|
|
80
|
+
(s = t == null ? void 0 : t.onWsClose) == null || s.call(t, o, n), o === "peer_or_error" && w(r, e, new Error(`WebSocket closed (${n ?? "unknown"})`));
|
|
81
|
+
},
|
|
82
|
+
onWsError: (o) => {
|
|
83
|
+
var n;
|
|
84
|
+
(n = t == null ? void 0 : t.onWsError) == null || n.call(t, o), w(r, e, new Error(`WebSocket error: ${o}`));
|
|
85
|
+
},
|
|
86
|
+
onRpcCall: (...o) => {
|
|
87
|
+
var n;
|
|
88
|
+
return (n = t == null ? void 0 : t.onRpcCall) == null ? void 0 : n.call(t, ...o);
|
|
89
|
+
},
|
|
90
|
+
onRpcNotify: (...o) => {
|
|
91
|
+
var n;
|
|
92
|
+
return (n = t == null ? void 0 : t.onRpcNotify) == null ? void 0 : n.call(t, ...o);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}, f = async (r, e) => {
|
|
96
|
+
const {
|
|
97
|
+
connectTunnelBrowser: t,
|
|
98
|
+
connectDirectBrowser: o
|
|
99
|
+
} = await import("@floegence/flowersec-core/browser"), n = {
|
|
100
|
+
observer: C(r, e),
|
|
101
|
+
keepaliveIntervalMs: e.keepaliveIntervalMs ?? 15e3,
|
|
102
|
+
connectTimeoutMs: e.connectTimeoutMs ?? 1e4,
|
|
103
|
+
handshakeTimeoutMs: e.handshakeTimeoutMs ?? 1e4
|
|
104
|
+
};
|
|
105
|
+
if ((e.mode ?? "tunnel") === "tunnel") {
|
|
106
|
+
const p = e.grant ?? (e.controlplane ? await W(e.controlplane) : null);
|
|
107
|
+
if (!p)
|
|
108
|
+
throw new Error("Tunnel mode requires `grant` or `controlplane` config");
|
|
109
|
+
return t(p, n);
|
|
110
|
+
}
|
|
111
|
+
if (!e.directInfo)
|
|
112
|
+
throw new Error("Direct mode requires `directInfo`");
|
|
113
|
+
return o(e.directInfo, n);
|
|
114
|
+
}, x = async (r, e) => {
|
|
115
|
+
const t = y(e.autoReconnect);
|
|
116
|
+
let o = 0;
|
|
117
|
+
for (; ; ) {
|
|
118
|
+
if (r !== l || u !== e) return;
|
|
119
|
+
o += 1;
|
|
120
|
+
try {
|
|
121
|
+
const n = await f(r, e);
|
|
122
|
+
if (r !== l) {
|
|
123
|
+
n.close();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (u !== e) {
|
|
127
|
+
n.close();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
i({
|
|
131
|
+
status: "connected",
|
|
132
|
+
client: n,
|
|
133
|
+
error: null
|
|
134
|
+
});
|
|
135
|
+
return;
|
|
136
|
+
} catch (n) {
|
|
137
|
+
const s = n instanceof Error ? n : new Error(String(n));
|
|
138
|
+
if (r !== l || u !== e) return;
|
|
139
|
+
if (!(t.enabled && o < t.maxAttempts))
|
|
140
|
+
throw i({
|
|
141
|
+
status: "error",
|
|
142
|
+
error: s,
|
|
143
|
+
client: null
|
|
144
|
+
}), s;
|
|
145
|
+
i({
|
|
146
|
+
status: "connecting",
|
|
147
|
+
error: s,
|
|
148
|
+
client: null
|
|
149
|
+
});
|
|
150
|
+
const D = j(o - 1, t);
|
|
151
|
+
await b(D);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}, v = {
|
|
155
|
+
status: () => c.status,
|
|
156
|
+
error: () => c.error,
|
|
157
|
+
client: () => c.client,
|
|
158
|
+
connect: async (r) => {
|
|
159
|
+
h(), l += 1;
|
|
160
|
+
const e = l;
|
|
161
|
+
u = r, c.client && c.client.close(), i({
|
|
162
|
+
status: "connecting",
|
|
163
|
+
error: null,
|
|
164
|
+
client: null
|
|
165
|
+
}), await x(e, r);
|
|
166
|
+
},
|
|
167
|
+
disconnect: () => {
|
|
168
|
+
M();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
return E(() => {
|
|
172
|
+
M();
|
|
173
|
+
}), P(R.Provider, {
|
|
174
|
+
value: v,
|
|
175
|
+
get children() {
|
|
176
|
+
return a.children;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function N() {
|
|
181
|
+
const a = k(R);
|
|
182
|
+
if (!a)
|
|
183
|
+
throw new Error("useProtocol must be used within a ProtocolProvider");
|
|
184
|
+
return a;
|
|
185
|
+
}
|
|
186
|
+
export {
|
|
187
|
+
H as ProtocolProvider,
|
|
188
|
+
N as useProtocol
|
|
189
|
+
};
|
package/dist/index3.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var i = Object.defineProperty;
|
|
2
|
+
var p = (o, e, r) => e in o ? i(o, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : o[e] = r;
|
|
3
|
+
var s = (o, e, r) => p(o, typeof e != "symbol" ? e + "" : e, r);
|
|
4
|
+
import { useProtocol as E } from "./index2.js";
|
|
5
|
+
import { TypeIds as c } from "./index5.js";
|
|
6
|
+
class u extends Error {
|
|
7
|
+
constructor() {
|
|
8
|
+
super("Not connected"), this.name = "ProtocolNotConnectedError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
class a extends Error {
|
|
12
|
+
constructor(r) {
|
|
13
|
+
super(r.message ?? `RPC error: ${r.code}`, { cause: r.cause });
|
|
14
|
+
s(this, "typeId");
|
|
15
|
+
s(this, "code");
|
|
16
|
+
this.name = "RpcError", this.typeId = r.typeId, this.code = r.code;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function w() {
|
|
20
|
+
const o = E(), e = async (r, d) => {
|
|
21
|
+
const n = o.client();
|
|
22
|
+
if (!n)
|
|
23
|
+
throw new u();
|
|
24
|
+
let t;
|
|
25
|
+
try {
|
|
26
|
+
t = await n.rpc.call(r, d);
|
|
27
|
+
} catch (l) {
|
|
28
|
+
throw new a({ typeId: r, code: -1, message: "RPC transport error", cause: l });
|
|
29
|
+
}
|
|
30
|
+
if (t.error)
|
|
31
|
+
throw new a({
|
|
32
|
+
typeId: r,
|
|
33
|
+
code: t.error.code,
|
|
34
|
+
message: t.error.message ?? `RPC error: ${t.error.code}`,
|
|
35
|
+
cause: t.error
|
|
36
|
+
});
|
|
37
|
+
return t.payload;
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
// File system operations
|
|
41
|
+
fs: {
|
|
42
|
+
list: (r) => e(c.FS_LIST, r),
|
|
43
|
+
readFile: (r) => e(c.FS_READ_FILE, r),
|
|
44
|
+
writeFile: (r) => e(c.FS_WRITE_FILE, r),
|
|
45
|
+
delete: (r) => e(c.FS_DELETE, r),
|
|
46
|
+
getHome: () => e(c.FS_GET_HOME, {})
|
|
47
|
+
},
|
|
48
|
+
// Raw call for custom operations
|
|
49
|
+
call: e
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
u as ProtocolNotConnectedError,
|
|
54
|
+
a as RpcError,
|
|
55
|
+
w as useRpc
|
|
56
|
+
};
|
package/dist/index4.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { assertChannelInitGrant as r } from "@floegence/flowersec-core";
|
|
2
|
+
async function a(e) {
|
|
3
|
+
const t = await fetch(`${e.baseUrl}/v1/channel/init`, {
|
|
4
|
+
method: "POST",
|
|
5
|
+
headers: { "Content-Type": "application/json" },
|
|
6
|
+
body: JSON.stringify({ endpoint_id: e.endpointId })
|
|
7
|
+
});
|
|
8
|
+
if (!t.ok)
|
|
9
|
+
throw new Error(`Failed to get channel grant: ${t.status}`);
|
|
10
|
+
const n = await t.json();
|
|
11
|
+
if (!(n != null && n.grant_client))
|
|
12
|
+
throw new Error("Invalid controlplane response: missing `grant_client`");
|
|
13
|
+
return r(n.grant_client);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
a as requestChannelGrant
|
|
17
|
+
};
|
package/dist/index5.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const E = {
|
|
2
|
+
// File system operations
|
|
3
|
+
FS_LIST: 1001,
|
|
4
|
+
FS_READ_FILE: 1002,
|
|
5
|
+
FS_WRITE_FILE: 1003,
|
|
6
|
+
FS_DELETE: 1006,
|
|
7
|
+
FS_GET_HOME: 1010
|
|
8
|
+
}, S = {
|
|
9
|
+
// File system operations
|
|
10
|
+
FS_CREATE_FILE: 1004,
|
|
11
|
+
FS_CREATE_DIR: 1005,
|
|
12
|
+
FS_RENAME: 1007,
|
|
13
|
+
FS_MOVE: 1008,
|
|
14
|
+
FS_COPY: 1009,
|
|
15
|
+
// Terminal operations
|
|
16
|
+
TERMINAL_SESSION_CREATE: 2001,
|
|
17
|
+
TERMINAL_SESSION_LIST: 2002,
|
|
18
|
+
TERMINAL_SESSION_ATTACH: 2003,
|
|
19
|
+
TERMINAL_DATA: 2004,
|
|
20
|
+
// Bidirectional notification
|
|
21
|
+
// System operations
|
|
22
|
+
SYSTEM_INFO: 3001,
|
|
23
|
+
SYSTEM_EXEC: 3002
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
S as ReservedTypeIds,
|
|
27
|
+
E as TypeIds
|
|
28
|
+
};
|
package/dist/rpc.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type ListRequest, type ListResponse, type ReadFileRequest, type ReadFileResponse, type WriteFileRequest, type WriteFileResponse, type DeleteRequest, type DeleteResponse } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* RPC wrapper for type-safe remote calls
|
|
4
|
+
*/
|
|
5
|
+
export declare class ProtocolNotConnectedError extends Error {
|
|
6
|
+
constructor();
|
|
7
|
+
}
|
|
8
|
+
export declare class RpcError extends Error {
|
|
9
|
+
readonly typeId: number;
|
|
10
|
+
readonly code: number;
|
|
11
|
+
constructor(args: {
|
|
12
|
+
typeId: number;
|
|
13
|
+
code: number;
|
|
14
|
+
message?: string;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export declare function useRpc(): {
|
|
19
|
+
fs: {
|
|
20
|
+
list: (req: ListRequest) => Promise<ListResponse>;
|
|
21
|
+
readFile: (req: ReadFileRequest) => Promise<ReadFileResponse>;
|
|
22
|
+
writeFile: (req: WriteFileRequest) => Promise<WriteFileResponse>;
|
|
23
|
+
delete: (req: DeleteRequest) => Promise<DeleteResponse>;
|
|
24
|
+
getHome: () => Promise<{
|
|
25
|
+
path: string;
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
28
|
+
call: <Req, Res>(typeId: number, request: Req) => Promise<Res>;
|
|
29
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common type definitions for the protocol layer
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Type IDs that are currently implemented by `useRpc()`.
|
|
6
|
+
*
|
|
7
|
+
* Keep this list aligned with `packages/protocol/src/rpc.ts` to avoid misleading downstream users.
|
|
8
|
+
*/
|
|
9
|
+
export declare const TypeIds: {
|
|
10
|
+
readonly FS_LIST: 1001;
|
|
11
|
+
readonly FS_READ_FILE: 1002;
|
|
12
|
+
readonly FS_WRITE_FILE: 1003;
|
|
13
|
+
readonly FS_DELETE: 1006;
|
|
14
|
+
readonly FS_GET_HOME: 1010;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Reserved Type IDs for future protocol domains.
|
|
18
|
+
*
|
|
19
|
+
* These are part of the protocol contract, but are not yet exposed via `useRpc()`.
|
|
20
|
+
*/
|
|
21
|
+
export declare const ReservedTypeIds: {
|
|
22
|
+
readonly FS_CREATE_FILE: 1004;
|
|
23
|
+
readonly FS_CREATE_DIR: 1005;
|
|
24
|
+
readonly FS_RENAME: 1007;
|
|
25
|
+
readonly FS_MOVE: 1008;
|
|
26
|
+
readonly FS_COPY: 1009;
|
|
27
|
+
readonly TERMINAL_SESSION_CREATE: 2001;
|
|
28
|
+
readonly TERMINAL_SESSION_LIST: 2002;
|
|
29
|
+
readonly TERMINAL_SESSION_ATTACH: 2003;
|
|
30
|
+
readonly TERMINAL_DATA: 2004;
|
|
31
|
+
readonly SYSTEM_INFO: 3001;
|
|
32
|
+
readonly SYSTEM_EXEC: 3002;
|
|
33
|
+
};
|
|
34
|
+
export interface FileInfo {
|
|
35
|
+
name: string;
|
|
36
|
+
path: string;
|
|
37
|
+
isDirectory: boolean;
|
|
38
|
+
size: number;
|
|
39
|
+
modifiedAt: number;
|
|
40
|
+
createdAt: number;
|
|
41
|
+
permissions?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ListRequest {
|
|
44
|
+
path: string;
|
|
45
|
+
showHidden?: boolean;
|
|
46
|
+
}
|
|
47
|
+
export interface ListResponse {
|
|
48
|
+
entries: FileInfo[];
|
|
49
|
+
}
|
|
50
|
+
export interface ReadFileRequest {
|
|
51
|
+
path: string;
|
|
52
|
+
encoding?: 'utf8' | 'base64';
|
|
53
|
+
}
|
|
54
|
+
export interface ReadFileResponse {
|
|
55
|
+
content: string;
|
|
56
|
+
encoding: string;
|
|
57
|
+
}
|
|
58
|
+
export interface WriteFileRequest {
|
|
59
|
+
path: string;
|
|
60
|
+
content: string;
|
|
61
|
+
encoding?: 'utf8' | 'base64';
|
|
62
|
+
createDirs?: boolean;
|
|
63
|
+
}
|
|
64
|
+
export interface WriteFileResponse {
|
|
65
|
+
success: boolean;
|
|
66
|
+
}
|
|
67
|
+
export interface DeleteRequest {
|
|
68
|
+
path: string;
|
|
69
|
+
recursive?: boolean;
|
|
70
|
+
}
|
|
71
|
+
export interface DeleteResponse {
|
|
72
|
+
success: boolean;
|
|
73
|
+
}
|
|
74
|
+
export interface TerminalSession {
|
|
75
|
+
id: string;
|
|
76
|
+
name?: string;
|
|
77
|
+
cols: number;
|
|
78
|
+
rows: number;
|
|
79
|
+
pid?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface CreateTerminalRequest {
|
|
82
|
+
name?: string;
|
|
83
|
+
cols: number;
|
|
84
|
+
rows: number;
|
|
85
|
+
cwd?: string;
|
|
86
|
+
env?: Record<string, string>;
|
|
87
|
+
}
|
|
88
|
+
export interface CreateTerminalResponse {
|
|
89
|
+
session: TerminalSession;
|
|
90
|
+
}
|
|
91
|
+
export interface TerminalDataPayload {
|
|
92
|
+
sessionId: string;
|
|
93
|
+
data: Uint8Array;
|
|
94
|
+
}
|
|
95
|
+
export interface TerminalResizePayload {
|
|
96
|
+
sessionId: string;
|
|
97
|
+
cols: number;
|
|
98
|
+
rows: number;
|
|
99
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './common';
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@floegence/floe-webapp-protocol",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"dev": "vite build --watch",
|
|
19
|
+
"build": "pnpm clean && vite build && tsc -p tsconfig.build.json",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
22
|
+
},
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"solid-js": "^1.8.0"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@floegence/flowersec-core": "^0.1.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"solid-js": "^1.9.3",
|
|
31
|
+
"typescript": "^5.7.2",
|
|
32
|
+
"vite": "^6.0.7",
|
|
33
|
+
"vite-plugin-solid": "^2.11.0"
|
|
34
|
+
}
|
|
35
|
+
}
|