@meowpanel/api 0.1.0-alpha.11 → 1.0.0-beta.2

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 (297) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +40 -0
  3. package/esm/mod.d.ts +87 -1
  4. package/esm/mod.d.ts.map +1 -1
  5. package/esm/mod.js +85 -1
  6. package/esm/src/client.d.ts +248 -0
  7. package/esm/src/client.d.ts.map +1 -0
  8. package/esm/src/client.js +235 -0
  9. package/esm/src/emitter.d.ts +53 -0
  10. package/esm/src/emitter.d.ts.map +1 -0
  11. package/esm/src/emitter.js +55 -0
  12. package/esm/src/errors.d.ts +42 -0
  13. package/esm/src/errors.d.ts.map +1 -0
  14. package/esm/src/errors.js +45 -0
  15. package/esm/src/http.d.ts +157 -0
  16. package/esm/src/http.d.ts.map +1 -0
  17. package/esm/src/http.js +317 -0
  18. package/esm/src/namespace.d.ts +59 -0
  19. package/esm/src/namespace.d.ts.map +1 -0
  20. package/esm/src/namespace.js +79 -0
  21. package/esm/src/reactive.d.ts +29 -0
  22. package/esm/src/reactive.d.ts.map +1 -0
  23. package/esm/src/reactive.js +35 -0
  24. package/esm/src/resources/account.d.ts +125 -0
  25. package/esm/src/resources/account.d.ts.map +1 -0
  26. package/esm/src/resources/account.js +151 -0
  27. package/esm/src/resources/api-keys.d.ts +116 -0
  28. package/esm/src/resources/api-keys.d.ts.map +1 -0
  29. package/esm/src/resources/api-keys.js +105 -0
  30. package/esm/src/resources/auth.d.ts +57 -0
  31. package/esm/src/resources/auth.d.ts.map +1 -0
  32. package/esm/src/resources/auth.js +39 -0
  33. package/esm/src/resources/eggs.d.ts +238 -0
  34. package/esm/src/resources/eggs.d.ts.map +1 -0
  35. package/esm/src/resources/eggs.js +187 -0
  36. package/esm/src/resources/hosts.d.ts +62 -0
  37. package/esm/src/resources/hosts.d.ts.map +1 -0
  38. package/esm/src/resources/hosts.js +62 -0
  39. package/esm/src/resources/members.d.ts +138 -0
  40. package/esm/src/resources/members.d.ts.map +1 -0
  41. package/esm/src/resources/members.js +122 -0
  42. package/esm/src/resources/nodes.d.ts +397 -0
  43. package/esm/src/resources/nodes.d.ts.map +1 -0
  44. package/esm/src/resources/nodes.js +352 -0
  45. package/esm/src/resources/server-groups.d.ts +150 -0
  46. package/esm/src/resources/server-groups.d.ts.map +1 -0
  47. package/esm/src/resources/server-groups.js +111 -0
  48. package/esm/src/resources/servers/activity.d.ts +120 -0
  49. package/esm/src/resources/servers/activity.d.ts.map +1 -0
  50. package/esm/src/resources/servers/activity.js +163 -0
  51. package/esm/src/resources/servers/allocations.d.ts +125 -0
  52. package/esm/src/resources/servers/allocations.d.ts.map +1 -0
  53. package/esm/src/resources/servers/allocations.js +137 -0
  54. package/esm/src/resources/servers/connection.d.ts +108 -0
  55. package/esm/src/resources/servers/connection.d.ts.map +1 -0
  56. package/esm/src/resources/servers/connection.js +169 -0
  57. package/esm/src/resources/servers/files.d.ts +164 -0
  58. package/esm/src/resources/servers/files.d.ts.map +1 -0
  59. package/esm/src/resources/servers/files.js +281 -0
  60. package/esm/src/resources/servers/index.d.ts +126 -0
  61. package/esm/src/resources/servers/index.d.ts.map +1 -0
  62. package/esm/src/resources/servers/index.js +135 -0
  63. package/esm/src/resources/servers/profiles.d.ts +138 -0
  64. package/esm/src/resources/servers/profiles.d.ts.map +1 -0
  65. package/esm/src/resources/servers/profiles.js +177 -0
  66. package/esm/src/resources/servers/server.d.ts +136 -0
  67. package/esm/src/resources/servers/server.d.ts.map +1 -0
  68. package/esm/src/resources/servers/server.js +202 -0
  69. package/esm/src/resources/servers/sftp.d.ts +147 -0
  70. package/esm/src/resources/servers/sftp.d.ts.map +1 -0
  71. package/esm/src/resources/servers/sftp.js +153 -0
  72. package/esm/src/resources/servers/types.d.ts +199 -0
  73. package/esm/src/resources/servers/types.d.ts.map +1 -0
  74. package/esm/src/resources/servers/types.js +1 -0
  75. package/esm/src/sse.d.ts +53 -0
  76. package/esm/src/sse.d.ts.map +1 -0
  77. package/esm/src/sse.js +133 -0
  78. package/esm/src/types.d.ts +126 -0
  79. package/esm/src/types.d.ts.map +1 -0
  80. package/esm/src/types.js +21 -0
  81. package/package.json +4 -92
  82. package/script/mod.d.ts +87 -1
  83. package/script/mod.d.ts.map +1 -1
  84. package/script/mod.js +132 -3
  85. package/script/src/client.d.ts +248 -0
  86. package/script/src/client.d.ts.map +1 -0
  87. package/script/src/client.js +239 -0
  88. package/script/src/emitter.d.ts +53 -0
  89. package/script/src/emitter.d.ts.map +1 -0
  90. package/script/src/emitter.js +59 -0
  91. package/script/src/errors.d.ts +42 -0
  92. package/script/src/errors.d.ts.map +1 -0
  93. package/script/src/errors.js +49 -0
  94. package/script/src/http.d.ts +157 -0
  95. package/script/src/http.d.ts.map +1 -0
  96. package/script/src/http.js +321 -0
  97. package/script/src/namespace.d.ts +59 -0
  98. package/script/src/namespace.d.ts.map +1 -0
  99. package/script/src/namespace.js +83 -0
  100. package/script/src/reactive.d.ts +29 -0
  101. package/script/src/reactive.d.ts.map +1 -0
  102. package/script/src/reactive.js +39 -0
  103. package/script/src/resources/account.d.ts +125 -0
  104. package/script/src/resources/account.d.ts.map +1 -0
  105. package/script/src/resources/account.js +158 -0
  106. package/script/src/resources/api-keys.d.ts +116 -0
  107. package/script/src/resources/api-keys.d.ts.map +1 -0
  108. package/script/src/resources/api-keys.js +110 -0
  109. package/script/src/resources/auth.d.ts +57 -0
  110. package/script/src/resources/auth.d.ts.map +1 -0
  111. package/script/src/resources/auth.js +43 -0
  112. package/script/src/resources/eggs.d.ts +238 -0
  113. package/script/src/resources/eggs.d.ts.map +1 -0
  114. package/script/src/resources/eggs.js +193 -0
  115. package/script/src/resources/hosts.d.ts +62 -0
  116. package/script/src/resources/hosts.d.ts.map +1 -0
  117. package/script/src/resources/hosts.js +67 -0
  118. package/script/src/resources/members.d.ts +138 -0
  119. package/script/src/resources/members.d.ts.map +1 -0
  120. package/script/src/resources/members.js +127 -0
  121. package/script/src/resources/nodes.d.ts +397 -0
  122. package/script/src/resources/nodes.d.ts.map +1 -0
  123. package/script/src/resources/nodes.js +362 -0
  124. package/script/src/resources/server-groups.d.ts +150 -0
  125. package/script/src/resources/server-groups.d.ts.map +1 -0
  126. package/script/src/resources/server-groups.js +116 -0
  127. package/script/src/resources/servers/activity.d.ts +120 -0
  128. package/script/src/resources/servers/activity.d.ts.map +1 -0
  129. package/script/src/resources/servers/activity.js +170 -0
  130. package/script/src/resources/servers/allocations.d.ts +125 -0
  131. package/script/src/resources/servers/allocations.d.ts.map +1 -0
  132. package/script/src/resources/servers/allocations.js +142 -0
  133. package/script/src/resources/servers/connection.d.ts +108 -0
  134. package/script/src/resources/servers/connection.d.ts.map +1 -0
  135. package/script/src/resources/servers/connection.js +173 -0
  136. package/script/src/resources/servers/files.d.ts +164 -0
  137. package/script/src/resources/servers/files.d.ts.map +1 -0
  138. package/script/src/resources/servers/files.js +286 -0
  139. package/script/src/resources/servers/index.d.ts +126 -0
  140. package/script/src/resources/servers/index.d.ts.map +1 -0
  141. package/script/src/resources/servers/index.js +139 -0
  142. package/script/src/resources/servers/profiles.d.ts +138 -0
  143. package/script/src/resources/servers/profiles.d.ts.map +1 -0
  144. package/script/src/resources/servers/profiles.js +182 -0
  145. package/script/src/resources/servers/server.d.ts +136 -0
  146. package/script/src/resources/servers/server.d.ts.map +1 -0
  147. package/script/src/resources/servers/server.js +206 -0
  148. package/script/src/resources/servers/sftp.d.ts +147 -0
  149. package/script/src/resources/servers/sftp.d.ts.map +1 -0
  150. package/script/src/resources/servers/sftp.js +158 -0
  151. package/script/src/resources/servers/types.d.ts +199 -0
  152. package/script/src/resources/servers/types.d.ts.map +1 -0
  153. package/script/src/resources/servers/types.js +2 -0
  154. package/script/src/sse.d.ts +53 -0
  155. package/script/src/sse.d.ts.map +1 -0
  156. package/script/src/sse.js +137 -0
  157. package/script/src/types.d.ts +126 -0
  158. package/script/src/types.d.ts.map +1 -0
  159. package/script/src/types.js +25 -0
  160. package/esm/api.d.ts +0 -76
  161. package/esm/api.d.ts.map +0 -1
  162. package/esm/api.js +0 -187
  163. package/esm/components/auth.d.ts +0 -15
  164. package/esm/components/auth.d.ts.map +0 -1
  165. package/esm/components/auth.js +0 -13
  166. package/esm/components/connection/abstract.d.ts +0 -23
  167. package/esm/components/connection/abstract.d.ts.map +0 -1
  168. package/esm/components/connection/abstract.js +0 -43
  169. package/esm/components/connection/sse.d.ts +0 -20
  170. package/esm/components/connection/sse.d.ts.map +0 -1
  171. package/esm/components/connection/sse.js +0 -65
  172. package/esm/components/egg/egg.d.ts +0 -32
  173. package/esm/components/egg/egg.d.ts.map +0 -1
  174. package/esm/components/egg/egg.js +0 -70
  175. package/esm/components/group.d.ts +0 -14
  176. package/esm/components/group.d.ts.map +0 -1
  177. package/esm/components/group.js +0 -33
  178. package/esm/components/member_2.d.ts +0 -69
  179. package/esm/components/member_2.d.ts.map +0 -1
  180. package/esm/components/member_2.js +0 -140
  181. package/esm/components/node.d.ts +0 -78
  182. package/esm/components/node.d.ts.map +0 -1
  183. package/esm/components/node.js +0 -342
  184. package/esm/components/server/activity.d.ts +0 -45
  185. package/esm/components/server/activity.d.ts.map +0 -1
  186. package/esm/components/server/activity.js +0 -158
  187. package/esm/components/server/allocations.d.ts +0 -45
  188. package/esm/components/server/allocations.d.ts.map +0 -1
  189. package/esm/components/server/allocations.js +0 -146
  190. package/esm/components/server/files.d.ts +0 -50
  191. package/esm/components/server/files.d.ts.map +0 -1
  192. package/esm/components/server/files.js +0 -90
  193. package/esm/components/server/power.d.ts +0 -21
  194. package/esm/components/server/power.d.ts.map +0 -1
  195. package/esm/components/server/power.js +0 -43
  196. package/esm/components/server/profiles.d.ts +0 -63
  197. package/esm/components/server/profiles.d.ts.map +0 -1
  198. package/esm/components/server/profiles.js +0 -163
  199. package/esm/components/server/server.d.ts +0 -141
  200. package/esm/components/server/server.d.ts.map +0 -1
  201. package/esm/components/server/server.js +0 -358
  202. package/esm/components/server/sftp.d.ts +0 -31
  203. package/esm/components/server/sftp.d.ts.map +0 -1
  204. package/esm/components/server/sftp.js +0 -84
  205. package/esm/components/server/startup.d.ts +0 -17
  206. package/esm/components/server/startup.d.ts.map +0 -1
  207. package/esm/components/server/startup.js +0 -21
  208. package/esm/components/server/stats.d.ts +0 -19
  209. package/esm/components/server/stats.d.ts.map +0 -1
  210. package/esm/components/server/stats.js +0 -46
  211. package/esm/utils/cache.d.ts +0 -20
  212. package/esm/utils/cache.d.ts.map +0 -1
  213. package/esm/utils/cache.js +0 -66
  214. package/esm/utils/event.d.ts +0 -38
  215. package/esm/utils/event.d.ts.map +0 -1
  216. package/esm/utils/event.js +0 -71
  217. package/esm/utils/object.d.ts +0 -58
  218. package/esm/utils/object.d.ts.map +0 -1
  219. package/esm/utils/object.js +0 -86
  220. package/esm/utils/subscribe.d.ts +0 -37
  221. package/esm/utils/subscribe.d.ts.map +0 -1
  222. package/esm/utils/subscribe.js +0 -29
  223. package/esm/utils/timer.d.ts +0 -13
  224. package/esm/utils/timer.d.ts.map +0 -1
  225. package/esm/utils/timer.js +0 -32
  226. package/esm/utils/units.d.ts +0 -18
  227. package/esm/utils/units.d.ts.map +0 -1
  228. package/esm/utils/units.js +0 -82
  229. package/script/api.d.ts +0 -76
  230. package/script/api.d.ts.map +0 -1
  231. package/script/api.js +0 -192
  232. package/script/components/auth.d.ts +0 -15
  233. package/script/components/auth.d.ts.map +0 -1
  234. package/script/components/auth.js +0 -17
  235. package/script/components/connection/abstract.d.ts +0 -23
  236. package/script/components/connection/abstract.d.ts.map +0 -1
  237. package/script/components/connection/abstract.js +0 -47
  238. package/script/components/connection/sse.d.ts +0 -20
  239. package/script/components/connection/sse.d.ts.map +0 -1
  240. package/script/components/connection/sse.js +0 -69
  241. package/script/components/egg/egg.d.ts +0 -32
  242. package/script/components/egg/egg.d.ts.map +0 -1
  243. package/script/components/egg/egg.js +0 -74
  244. package/script/components/group.d.ts +0 -14
  245. package/script/components/group.d.ts.map +0 -1
  246. package/script/components/group.js +0 -37
  247. package/script/components/member_2.d.ts +0 -69
  248. package/script/components/member_2.d.ts.map +0 -1
  249. package/script/components/member_2.js +0 -146
  250. package/script/components/node.d.ts +0 -78
  251. package/script/components/node.d.ts.map +0 -1
  252. package/script/components/node.js +0 -349
  253. package/script/components/server/activity.d.ts +0 -45
  254. package/script/components/server/activity.d.ts.map +0 -1
  255. package/script/components/server/activity.js +0 -164
  256. package/script/components/server/allocations.d.ts +0 -45
  257. package/script/components/server/allocations.d.ts.map +0 -1
  258. package/script/components/server/allocations.js +0 -152
  259. package/script/components/server/files.d.ts +0 -50
  260. package/script/components/server/files.d.ts.map +0 -1
  261. package/script/components/server/files.js +0 -94
  262. package/script/components/server/power.d.ts +0 -21
  263. package/script/components/server/power.d.ts.map +0 -1
  264. package/script/components/server/power.js +0 -47
  265. package/script/components/server/profiles.d.ts +0 -63
  266. package/script/components/server/profiles.d.ts.map +0 -1
  267. package/script/components/server/profiles.js +0 -168
  268. package/script/components/server/server.d.ts +0 -141
  269. package/script/components/server/server.d.ts.map +0 -1
  270. package/script/components/server/server.js +0 -362
  271. package/script/components/server/sftp.d.ts +0 -31
  272. package/script/components/server/sftp.d.ts.map +0 -1
  273. package/script/components/server/sftp.js +0 -88
  274. package/script/components/server/startup.d.ts +0 -17
  275. package/script/components/server/startup.d.ts.map +0 -1
  276. package/script/components/server/startup.js +0 -25
  277. package/script/components/server/stats.d.ts +0 -19
  278. package/script/components/server/stats.d.ts.map +0 -1
  279. package/script/components/server/stats.js +0 -50
  280. package/script/utils/cache.d.ts +0 -20
  281. package/script/utils/cache.d.ts.map +0 -1
  282. package/script/utils/cache.js +0 -70
  283. package/script/utils/event.d.ts +0 -38
  284. package/script/utils/event.d.ts.map +0 -1
  285. package/script/utils/event.js +0 -75
  286. package/script/utils/object.d.ts +0 -58
  287. package/script/utils/object.d.ts.map +0 -1
  288. package/script/utils/object.js +0 -90
  289. package/script/utils/subscribe.d.ts +0 -37
  290. package/script/utils/subscribe.d.ts.map +0 -1
  291. package/script/utils/subscribe.js +0 -32
  292. package/script/utils/timer.d.ts +0 -13
  293. package/script/utils/timer.d.ts.map +0 -1
  294. package/script/utils/timer.js +0 -36
  295. package/script/utils/units.d.ts +0 -18
  296. package/script/utils/units.d.ts.map +0 -1
  297. package/script/utils/units.js +0 -86
@@ -0,0 +1,169 @@
1
+ import { ReactiveResource } from '../../reactive.js';
2
+ import { SseConnection } from '../../sse.js';
3
+ /**
4
+ * A real-time SSE connection to a specific server on its Whisker node daemon.
5
+ *
6
+ * Emits typed events for console output, power state changes, and resource utilization.
7
+ * Also maintains a rolling buffer of console output lines in {@link output}, pre-populated
8
+ * with recent history fetched from the node on {@link connect}.
9
+ *
10
+ * Obtain a connection via {@link import('./server.ts').Server.connect}.
11
+ *
12
+ * @example
13
+ * ```ts ignore
14
+ * const conn = await server.connect();
15
+ *
16
+ * conn.on('status', (state) => console.log('Power state:', state));
17
+ * conn.on('stats', (stats) => console.log('CPU:', stats.cpuAbsolute + '%'));
18
+ *
19
+ * await conn.connect();
20
+ *
21
+ * // Reactive: $conn.output is the full rolling buffer of console lines
22
+ * // Live lines are appended automatically as they arrive over SSE
23
+ *
24
+ * // Later...
25
+ * conn.disconnect();
26
+ * ```
27
+ */
28
+ export class ServerConnection extends ReactiveResource {
29
+ serverId;
30
+ nodeUrl;
31
+ token;
32
+ /** Maximum number of console output lines retained in {@link ServerConnection.output}. */
33
+ static maxOutputLines = 1024;
34
+ listeners = new Map();
35
+ sse;
36
+ connected = false;
37
+ /**
38
+ * Rolling buffer of console output lines, capped at {@link MAX_OUTPUT_LINES}.
39
+ *
40
+ * Pre-populated with recent history from the node when {@link connect} is called,
41
+ * then appended to live as `console_output` SSE events arrive.
42
+ *
43
+ * Use as a reactive store: `$conn.output`.
44
+ */
45
+ output = [];
46
+ /** @internal */
47
+ constructor(serverId, nodeUrl, token) {
48
+ super();
49
+ this.serverId = serverId;
50
+ this.nodeUrl = nodeUrl;
51
+ this.token = token;
52
+ this.sse = new SseConnection(`${nodeUrl}/api/servers/${serverId}/sse`, token);
53
+ }
54
+ /** `true` if the SSE connection is currently open. */
55
+ get isConnected() {
56
+ return this.connected;
57
+ }
58
+ /**
59
+ * Fetch console history and open the SSE stream.
60
+ *
61
+ * Populates {@link output} with recent history from the node, then begins streaming
62
+ * live events.
63
+ *
64
+ * Maintains only one instances of the stream.
65
+ *
66
+ * @param onError Optional callback invoked if the connection drops unexpectedly.
67
+ */
68
+ async open(onError) {
69
+ this.sse.disconnect(); // close any existing stream
70
+ try {
71
+ const res = await fetch(`${this.nodeUrl}/api/servers/${this.serverId}/logs?size=100`, { headers: { Authorization: `Bearer ${this.token}` } });
72
+ if (res.ok) {
73
+ const json = (await res.json());
74
+ this.output = json.data ?? [];
75
+ this.notify();
76
+ }
77
+ }
78
+ catch {
79
+ // History is best-effort - don't block the SSE connection
80
+ }
81
+ const url = `${this.nodeUrl}/api/servers/${this.serverId}/sse`;
82
+ this.sse = new SseConnection(url, this.token);
83
+ this.connected = true;
84
+ this.sse.connect((event, data) => {
85
+ this.dispatch(event, data);
86
+ }, (err) => {
87
+ this.connected = false;
88
+ this.notify();
89
+ onError?.(err);
90
+ });
91
+ }
92
+ /** Close the SSE stream and stop receiving events. */
93
+ close() {
94
+ this.sse.disconnect();
95
+ this.connected = false;
96
+ }
97
+ /**
98
+ * Register a handler for a typed server event.
99
+ *
100
+ * @param event The event name.
101
+ * @param handler The callback to invoke when the event is received.
102
+ */
103
+ on(event, handler) {
104
+ if (!this.listeners.has(event))
105
+ this.listeners.set(event, new Set());
106
+ this.listeners
107
+ .get(event)
108
+ .add(handler);
109
+ }
110
+ /**
111
+ * Unregister a previously registered event handler.
112
+ *
113
+ * @param event The event name.
114
+ * @param handler The exact handler reference passed to {@link on}.
115
+ */
116
+ off(event, handler) {
117
+ this.listeners
118
+ .get(event)
119
+ ?.delete(handler);
120
+ }
121
+ /** Remove all event handlers for all event types. */
122
+ removeAllListeners() {
123
+ this.listeners.clear();
124
+ }
125
+ /** Parse and dispatch a raw SSE event to registered handlers. */
126
+ dispatch(event, rawData) {
127
+ let payload;
128
+ try {
129
+ if (event === 'console_output') {
130
+ payload = rawData;
131
+ this.output.push(payload);
132
+ if (this.output.length > ServerConnection.maxOutputLines) {
133
+ this.output.shift();
134
+ }
135
+ this.notify();
136
+ }
137
+ else if (event === 'status') {
138
+ const parsed = JSON.parse(rawData);
139
+ if (typeof parsed?.state !== 'string')
140
+ return;
141
+ payload = parsed.state;
142
+ }
143
+ else if (event === 'stats') {
144
+ const raw = JSON.parse(rawData);
145
+ if (typeof raw?.cpu_absolute !== 'number' ||
146
+ typeof raw?.memory_bytes !== 'number') {
147
+ return;
148
+ }
149
+ payload = {
150
+ cpuAbsolute: raw.cpu_absolute,
151
+ memoryBytes: raw.memory_bytes,
152
+ memoryLimitBytes: raw.memory_limit_bytes,
153
+ diskBytes: raw.disk_bytes,
154
+ networkRxBytes: raw.network?.rx_bytes ?? 0,
155
+ networkTxBytes: raw.network?.tx_bytes ?? 0,
156
+ uptimeSeconds: raw.uptime,
157
+ };
158
+ }
159
+ else {
160
+ return;
161
+ }
162
+ }
163
+ catch {
164
+ return;
165
+ }
166
+ const handlers = this.listeners.get(event);
167
+ handlers?.forEach((h) => h(payload));
168
+ }
169
+ }
@@ -0,0 +1,164 @@
1
+ import type { NanoID } from '../../types.js';
2
+ import type { FileEntryData } from './types.js';
3
+ /**
4
+ * A single file or directory entry in a server's file system.
5
+ */
6
+ export declare class FileEntry {
7
+ /** The name of the file or directory. */
8
+ readonly name: string;
9
+ /** Symbolic file mode string, e.g. `"-rw-r--r--"`. */
10
+ readonly mode: string;
11
+ /** Numeric mode bits (octal), e.g. `"644"`. */
12
+ readonly modeBits: string;
13
+ /** Size of the file in bytes. `0` for directories. */
14
+ readonly size: number;
15
+ /** `true` if this entry is a directory. */
16
+ readonly isDirectory: boolean;
17
+ /** MIME type of the file, e.g. `"text/plain"`. */
18
+ readonly mime: string;
19
+ /** `true` if this entry is a symbolic link. */
20
+ readonly isSymlink: boolean;
21
+ /** When this file or directory was created. */
22
+ readonly createdAt: Date;
23
+ /** When this file or directory was last modified. */
24
+ readonly modifiedAt: Date;
25
+ /** @internal */
26
+ constructor(data: FileEntryData);
27
+ }
28
+ /**
29
+ * Manages file system operations for a specific server via the Whisker node daemon API.
30
+ *
31
+ * File operations communicate directly with the node daemon.
32
+ * The node URL is resolved lazily on first use and cached for subsequent calls.
33
+ *
34
+ * @example
35
+ * ```ts ignore
36
+ * const entries = await server.files.list('/');
37
+ * const content = await server.files.read('/server.properties');
38
+ * await server.files.write('/server.properties', 'motd=Hello World\n');
39
+ * await server.files.move({ from: '/old.txt', to: '/new.txt' });
40
+ * await server.files.delete(['/backup.zip']);
41
+ * ```
42
+ */
43
+ export declare class ServerFilesManager {
44
+ private readonly serverId;
45
+ private readonly token;
46
+ private readonly resolveNodeUrl;
47
+ private nodeUrl?;
48
+ /**
49
+ * @param serverId The server's NanoID.
50
+ * @param token Bearer token for node authentication.
51
+ * @param resolveNodeUrl Async function that returns the daemon base URL for this server's node.
52
+ */
53
+ constructor(serverId: NanoID, token: string, resolveNodeUrl: () => Promise<string>);
54
+ /** Lazily resolve and cache the node daemon URL. */
55
+ private getNodeUrl;
56
+ /** Build a full node API URL for a file path endpoint. */
57
+ private buildFileUrl;
58
+ /** Shared auth headers for node requests. */
59
+ private get authHeaders();
60
+ /** Perform a raw fetch to the node and throw on non-2xx. */
61
+ private nodeFetch;
62
+ /**
63
+ * List the contents of a directory.
64
+ *
65
+ * @param path Absolute path to the directory, e.g. `"/"` or `"/plugins"`.
66
+ * @returns An array of {@link FileEntry} objects.
67
+ */
68
+ list(path: string): Promise<FileEntry[]>;
69
+ /**
70
+ * Read the text content of a file.
71
+ *
72
+ * @param path Absolute path to the file, e.g. `"/server.properties"`.
73
+ * @returns The file content as a UTF-8 string.
74
+ */
75
+ read(path: string): Promise<string>;
76
+ /**
77
+ * Read the raw binary content of a file.
78
+ *
79
+ * @param path Absolute path to the file.
80
+ * @returns The file content as an `ArrayBuffer`.
81
+ */
82
+ readBinary(path: string): Promise<ArrayBuffer>;
83
+ /**
84
+ * Write text content to a file, creating it if it doesn't exist.
85
+ *
86
+ * @param path Absolute path to the file.
87
+ * @param content The UTF-8 text content to write.
88
+ */
89
+ write(path: string, content: string): Promise<void>;
90
+ /**
91
+ * Write raw binary content to a file.
92
+ *
93
+ * @param path Absolute path to the file.
94
+ * @param content Binary content to write.
95
+ * @param contentType MIME type of the content.
96
+ */
97
+ writeBinary(path: string, content: ArrayBuffer | Uint8Array, contentType: string): Promise<void>;
98
+ /**
99
+ * Delete one or more files or directories.
100
+ *
101
+ * @param paths An array of absolute paths to delete.
102
+ */
103
+ delete(paths: string[]): Promise<void>;
104
+ /**
105
+ * Move (rename) a file or directory.
106
+ *
107
+ * @param from Absolute source path.
108
+ * @param to Absolute destination path.
109
+ */
110
+ move(from: string, to: string): Promise<void>;
111
+ /**
112
+ * Copy a file or directory to a new location.
113
+ *
114
+ * @param source Absolute path of the source file or directory.
115
+ * @param location Absolute path of the destination directory.
116
+ */
117
+ copy(source: string, location: string): Promise<void>;
118
+ /**
119
+ * Create an empty file or directory.
120
+ *
121
+ * @param path Absolute path of the new file or directory.
122
+ * @param directory When `true`, creates a directory instead of a file.
123
+ */
124
+ create(path: string, directory?: boolean): Promise<void>;
125
+ /**
126
+ * Compress one or more files into an archive.
127
+ *
128
+ * @param files Array of absolute paths to include in the archive.
129
+ * @param name Name of the output archive file, e.g. `"backup.tar.gz"`.
130
+ * @param rootPath Root directory for resolving relative paths. Defaults to `"/"`.
131
+ */
132
+ compress(files: string[], name: string, rootPath?: string): Promise<void>;
133
+ /**
134
+ * Decompress (extract) an archive file.
135
+ *
136
+ * @param file Absolute path to the archive to extract.
137
+ * @param rootPath Directory to extract the archive into. Defaults to `"/"`.
138
+ */
139
+ decompress(file: string, rootPath?: string): Promise<void>;
140
+ /**
141
+ * Change the permissions (chmod) of one or more files.
142
+ *
143
+ * @param entries Array of `{ file, mode }` objects.
144
+ * @param rootPath Root directory for resolving paths. Defaults to `"/"`.
145
+ *
146
+ * @example
147
+ * ```ts ignore
148
+ * await server.files.chmod([{ file: 'start.sh', mode: '755' }]);
149
+ * ```
150
+ */
151
+ chmod(entries: {
152
+ file: string;
153
+ mode: string;
154
+ }[], rootPath?: string): Promise<void>;
155
+ /**
156
+ * Upload a file to the server using multipart form data.
157
+ *
158
+ * @param path Absolute directory path to upload the file into.
159
+ * @param filename The name for the uploaded file.
160
+ * @param content The file content as a `Blob`, `File`, or `ArrayBuffer`.
161
+ */
162
+ upload(path: string, filename: string, content: Blob | File | ArrayBuffer): Promise<void>;
163
+ }
164
+ //# sourceMappingURL=files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../../src/src/resources/servers/files.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,281 @@
1
+ import { ApiError } from '../../errors.js';
2
+ /**
3
+ * A single file or directory entry in a server's file system.
4
+ */
5
+ export class FileEntry {
6
+ /** The name of the file or directory. */
7
+ name;
8
+ /** Symbolic file mode string, e.g. `"-rw-r--r--"`. */
9
+ mode;
10
+ /** Numeric mode bits (octal), e.g. `"644"`. */
11
+ modeBits;
12
+ /** Size of the file in bytes. `0` for directories. */
13
+ size;
14
+ /** `true` if this entry is a directory. */
15
+ isDirectory;
16
+ /** MIME type of the file, e.g. `"text/plain"`. */
17
+ mime;
18
+ /** `true` if this entry is a symbolic link. */
19
+ isSymlink;
20
+ /** When this file or directory was created. */
21
+ createdAt;
22
+ /** When this file or directory was last modified. */
23
+ modifiedAt;
24
+ /** @internal */
25
+ constructor(data) {
26
+ this.name = data.name;
27
+ this.mode = data.mode;
28
+ this.modeBits = data.mode_bits;
29
+ this.size = data.size;
30
+ this.isDirectory = data.type === 'directory';
31
+ this.mime = data.mime;
32
+ this.isSymlink = data.symlink;
33
+ this.createdAt = new Date(data.created);
34
+ this.modifiedAt = new Date(data.modified);
35
+ }
36
+ }
37
+ /**
38
+ * Manages file system operations for a specific server via the Whisker node daemon API.
39
+ *
40
+ * File operations communicate directly with the node daemon.
41
+ * The node URL is resolved lazily on first use and cached for subsequent calls.
42
+ *
43
+ * @example
44
+ * ```ts ignore
45
+ * const entries = await server.files.list('/');
46
+ * const content = await server.files.read('/server.properties');
47
+ * await server.files.write('/server.properties', 'motd=Hello World\n');
48
+ * await server.files.move({ from: '/old.txt', to: '/new.txt' });
49
+ * await server.files.delete(['/backup.zip']);
50
+ * ```
51
+ */
52
+ export class ServerFilesManager {
53
+ serverId;
54
+ token;
55
+ resolveNodeUrl;
56
+ nodeUrl;
57
+ /**
58
+ * @param serverId The server's NanoID.
59
+ * @param token Bearer token for node authentication.
60
+ * @param resolveNodeUrl Async function that returns the daemon base URL for this server's node.
61
+ */
62
+ constructor(serverId, token, resolveNodeUrl) {
63
+ this.serverId = serverId;
64
+ this.token = token;
65
+ this.resolveNodeUrl = resolveNodeUrl;
66
+ }
67
+ /** Lazily resolve and cache the node daemon URL. */
68
+ async getNodeUrl() {
69
+ if (!this.nodeUrl)
70
+ this.nodeUrl = await this.resolveNodeUrl();
71
+ return this.nodeUrl;
72
+ }
73
+ /** Build a full node API URL for a file path endpoint. */
74
+ async buildFileUrl(endpoint) {
75
+ const base = await this.getNodeUrl();
76
+ return `${base}/api/servers/${this.serverId}/files${endpoint}`;
77
+ }
78
+ /** Shared auth headers for node requests. */
79
+ get authHeaders() {
80
+ return { 'Authorization': `Bearer ${this.token}` };
81
+ }
82
+ /** Perform a raw fetch to the node and throw on non-2xx. */
83
+ async nodeFetch(url, init = {}) {
84
+ const res = await globalThis.fetch(url, {
85
+ ...init,
86
+ headers: { ...this.authHeaders, ...init.headers },
87
+ });
88
+ if (!res.ok) {
89
+ let message = `HTTP ${res.status}`;
90
+ try {
91
+ const body = await res.json();
92
+ if (typeof body.error === 'string')
93
+ message = body.error;
94
+ }
95
+ catch { /* ignore */ }
96
+ throw new ApiError({ message, status: res.status });
97
+ }
98
+ return res;
99
+ }
100
+ /**
101
+ * List the contents of a directory.
102
+ *
103
+ * @param path Absolute path to the directory, e.g. `"/"` or `"/plugins"`.
104
+ * @returns An array of {@link FileEntry} objects.
105
+ */
106
+ async list(path) {
107
+ const url = await this.buildFileUrl(path.startsWith('/') ? path : `/${path}`);
108
+ const res = await this.nodeFetch(url);
109
+ const data = await res.json();
110
+ return data.entries.map((e) => new FileEntry(e));
111
+ }
112
+ /**
113
+ * Read the text content of a file.
114
+ *
115
+ * @param path Absolute path to the file, e.g. `"/server.properties"`.
116
+ * @returns The file content as a UTF-8 string.
117
+ */
118
+ async read(path) {
119
+ const url = await this.buildFileUrl(path.startsWith('/') ? path : `/${path}`);
120
+ const res = await this.nodeFetch(url);
121
+ return res.text();
122
+ }
123
+ /**
124
+ * Read the raw binary content of a file.
125
+ *
126
+ * @param path Absolute path to the file.
127
+ * @returns The file content as an `ArrayBuffer`.
128
+ */
129
+ async readBinary(path) {
130
+ const url = await this.buildFileUrl(path.startsWith('/') ? path : `/${path}`);
131
+ const res = await this.nodeFetch(url);
132
+ return res.arrayBuffer();
133
+ }
134
+ /**
135
+ * Write text content to a file, creating it if it doesn't exist.
136
+ *
137
+ * @param path Absolute path to the file.
138
+ * @param content The UTF-8 text content to write.
139
+ */
140
+ async write(path, content) {
141
+ const url = await this.buildFileUrl(path.startsWith('/') ? path : `/${path}`);
142
+ await this.nodeFetch(url, {
143
+ method: 'PUT',
144
+ body: content,
145
+ headers: { 'Content-Type': 'text/plain' },
146
+ });
147
+ }
148
+ /**
149
+ * Write raw binary content to a file.
150
+ *
151
+ * @param path Absolute path to the file.
152
+ * @param content Binary content to write.
153
+ * @param contentType MIME type of the content.
154
+ */
155
+ async writeBinary(path, content, contentType) {
156
+ const url = await this.buildFileUrl(path.startsWith('/') ? path : `/${path}`);
157
+ const body = content instanceof ArrayBuffer ? new Uint8Array(content) : content;
158
+ await this.nodeFetch(url, {
159
+ method: 'PUT',
160
+ body: body,
161
+ headers: { 'Content-Type': contentType },
162
+ });
163
+ }
164
+ /**
165
+ * Delete one or more files or directories.
166
+ *
167
+ * @param paths An array of absolute paths to delete.
168
+ */
169
+ async delete(paths) {
170
+ const url = await this.buildFileUrl('');
171
+ await this.nodeFetch(url, {
172
+ method: 'DELETE',
173
+ body: JSON.stringify({ root: '/', files: paths }),
174
+ headers: { 'Content-Type': 'application/json' },
175
+ });
176
+ }
177
+ /**
178
+ * Move (rename) a file or directory.
179
+ *
180
+ * @param from Absolute source path.
181
+ * @param to Absolute destination path.
182
+ */
183
+ async move(from, to) {
184
+ const url = await this.buildFileUrl('/move');
185
+ await this.nodeFetch(url, {
186
+ method: 'POST',
187
+ body: JSON.stringify({ files: [{ from, to }] }),
188
+ headers: { 'Content-Type': 'application/json' },
189
+ });
190
+ }
191
+ /**
192
+ * Copy a file or directory to a new location.
193
+ *
194
+ * @param source Absolute path of the source file or directory.
195
+ * @param location Absolute path of the destination directory.
196
+ */
197
+ async copy(source, location) {
198
+ const url = await this.buildFileUrl('/copy');
199
+ await this.nodeFetch(url, {
200
+ method: 'POST',
201
+ body: JSON.stringify({ location, files: [source] }),
202
+ headers: { 'Content-Type': 'application/json' },
203
+ });
204
+ }
205
+ /**
206
+ * Create an empty file or directory.
207
+ *
208
+ * @param path Absolute path of the new file or directory.
209
+ * @param directory When `true`, creates a directory instead of a file.
210
+ */
211
+ async create(path, directory = false) {
212
+ const url = await this.buildFileUrl('/create');
213
+ await this.nodeFetch(url, {
214
+ method: 'POST',
215
+ body: JSON.stringify({ name: path, directory }),
216
+ headers: { 'Content-Type': 'application/json' },
217
+ });
218
+ }
219
+ /**
220
+ * Compress one or more files into an archive.
221
+ *
222
+ * @param files Array of absolute paths to include in the archive.
223
+ * @param name Name of the output archive file, e.g. `"backup.tar.gz"`.
224
+ * @param rootPath Root directory for resolving relative paths. Defaults to `"/"`.
225
+ */
226
+ async compress(files, name, rootPath = '/') {
227
+ const url = await this.buildFileUrl('/compress');
228
+ await this.nodeFetch(url, {
229
+ method: 'POST',
230
+ body: JSON.stringify({ root_path: rootPath, files, name }),
231
+ headers: { 'Content-Type': 'application/json' },
232
+ });
233
+ }
234
+ /**
235
+ * Decompress (extract) an archive file.
236
+ *
237
+ * @param file Absolute path to the archive to extract.
238
+ * @param rootPath Directory to extract the archive into. Defaults to `"/"`.
239
+ */
240
+ async decompress(file, rootPath = '/') {
241
+ const url = await this.buildFileUrl('/decompress');
242
+ await this.nodeFetch(url, {
243
+ method: 'POST',
244
+ body: JSON.stringify({ root_path: rootPath, file }),
245
+ headers: { 'Content-Type': 'application/json' },
246
+ });
247
+ }
248
+ /**
249
+ * Change the permissions (chmod) of one or more files.
250
+ *
251
+ * @param entries Array of `{ file, mode }` objects.
252
+ * @param rootPath Root directory for resolving paths. Defaults to `"/"`.
253
+ *
254
+ * @example
255
+ * ```ts ignore
256
+ * await server.files.chmod([{ file: 'start.sh', mode: '755' }]);
257
+ * ```
258
+ */
259
+ async chmod(entries, rootPath = '/') {
260
+ const url = await this.buildFileUrl('/chmod');
261
+ await this.nodeFetch(url, {
262
+ method: 'POST',
263
+ body: JSON.stringify({ root_path: rootPath, files: entries }),
264
+ headers: { 'Content-Type': 'application/json' },
265
+ });
266
+ }
267
+ /**
268
+ * Upload a file to the server using multipart form data.
269
+ *
270
+ * @param path Absolute directory path to upload the file into.
271
+ * @param filename The name for the uploaded file.
272
+ * @param content The file content as a `Blob`, `File`, or `ArrayBuffer`.
273
+ */
274
+ async upload(path, filename, content) {
275
+ const url = await this.buildFileUrl(`/upload?directory=${encodeURIComponent(path)}`);
276
+ const form = new FormData();
277
+ const blob = content instanceof ArrayBuffer ? new Blob([content]) : content;
278
+ form.append('files', blob, filename);
279
+ await this.nodeFetch(url, { method: 'POST', body: form });
280
+ }
281
+ }