Seregon/zftpd

Zero-copy FTP/HTTP Daemon compatible with all POSIX systems

C/11.0 KB/No license
web/js/api.js
zftpd / web / js / api.js
1/* ══ API LAYER ════════════════════════════════════════════════════════════
2 * Centralized fetch wrappers for all backend endpoints.
3 * ES5 compatible for PS5 browser.
4 * ═════════════════════════════════════════════════════════════════════════ */
5 
6var ZFTPD = ZFTPD || {};
7 
8(function (Z) {
9 'use strict';
10 
11 var api = {};
12 
13 /* ── Internal helpers ── */
14 function get(url) {
15 return fetch(url).then(function (r) {
16 if (!r.ok) throw new Error('HTTP ' + r.status);
17 return r.json();
18 });
19 }
20 
21 function post(url, body) {
22 var opts = {
23 method: 'POST',
24 headers: { 'X-CSRF-Token': Z.csrf() }
25 };
26 if (body !== undefined) {
27 opts.headers['Content-Type'] = 'application/json';
28 opts.body = JSON.stringify(body);
29 }
30 return fetch(url, opts).then(function (r) {
31 if (!r.ok) throw new Error('HTTP ' + r.status);
32 return r.json();
33 });
34 }
35 
36 /* ── Directory listing ── */
37 api.list = function (path) {
38 return get('/api/list?path=' + Z.E(path));
39 };
40 
41 /* ── Directory size (lazy) ── */
42 api.dirsize = function (path) {
43 return get('/api/dirsize?path=' + Z.E(path));
44 };
45 
46 /* ── Stats ── */
47 api.stats = function (path) {
48 return get('/api/stats?path=' + Z.E(path));
49 };
50 
51 api.statsRam = function () {
52 return get('/api/stats/ram');
53 };
54 
55 api.statsSystem = function () {
56 return get('/api/stats/system');
57 };
58 
59 /* ── Disk ── */
60 api.diskInfo = function () {
61 return get('/api/disk/info');
62 };
63 
64 api.diskTree = function (path) {
65 return get('/api/disk/tree?path=' + Z.E(path));
66 };
67 
68 /* ── Processes ── */
69 api.processes = function () {
70 return get('/api/processes');
71 };
72 
73 api.processKill = function (pid) {
74 return post('/api/process/kill', { pid: pid });
75 };
76 
77 /* ── File operations (require ENABLE_WEB_UPLOAD) ── */
78 api.createFile = function (dirPath, name) {
79 return fetch('/api/create_file?path=' + Z.E(dirPath) + '&name=' + Z.E(name), {
80 method: 'POST',
81 headers: { 'Content-Type': 'text/plain', 'X-CSRF-Token': Z.csrf() },
82 body: ''
83 }).then(function (r) {
84 if (!r.ok) throw new Error('HTTP ' + r.status);
85 return r.json();
86 });
87 };
88 
89 api.mkdir = function (dirPath, name) {
90 return post('/api/mkdir?path=' + Z.E(dirPath) + '&name=' + Z.E(name));
91 };
92 
93 api.del = function (path, recursive) {
94 var url = '/api/delete?path=' + Z.E(path);
95 if (recursive) url += '&recursive=1';
96 return post(url);
97 };
98 
99 api.rename = function (path, newName) {
100 return post('/api/rename?path=' + Z.E(path) + '&name=' + Z.E(newName));
101 };
102 
103 api.copy = function (srcPath, dstDir, totalSize) {
104 var url = '/api/copy?path=' + Z.E(srcPath) + '&dst=' + Z.E(dstDir);
105 if (totalSize) url += '&totalsize=' + totalSize;
106 return post(url);
107 };
108 
109 api.copyProgress = function () {
110 return get('/api/copy_progress');
111 };
112 
113 api.copyPause = function () {
114 return post('/api/copy_pause');
115 };
116 
117 api.copyCancel = function () {
118 return post('/api/copy_cancel');
119 };
120 
121 /* ── Network reset ── */
122 api.networkReset = function () {
123 return post('/api/network/reset');
124 };
125 
126 /* ── Upload (XMLHttpRequest for progress tracking) ── */
127 api.upload = function (dirPath, file, onProgress) {
128 return new Promise(function (resolve, reject) {
129 var xhr = new XMLHttpRequest();
130 xhr.open('POST', '/api/upload?path=' + Z.E(dirPath) + '&name=' + Z.E(file.name), true);
131 var token = Z.csrf();
132 if (token) xhr.setRequestHeader('X-CSRF-Token', token);
133 xhr.upload.onprogress = function (e) {
134 if (e.lengthComputable && onProgress) {
135 onProgress(Math.floor(e.loaded / e.total * 100), e.loaded, e.total);
136 }
137 };
138 xhr.onload = function () {
139 if (xhr.status >= 200 && xhr.status < 300) resolve(xhr);
140 else reject(new Error('HTTP ' + xhr.status));
141 };
142 xhr.onerror = function () { reject(new Error('Network error')); };
143 xhr.send(file);
144 /* Return xhr handle for cancellation */
145 resolve._xhr = xhr;
146 });
147 };
148 
149 /* ── Download URL ── */
150 api.downloadUrl = function (path) {
151 return '/api/download?path=' + Z.E(path);
152 };
153 
154 /* ── Game metadata (Phase 4 — stub for now) ── */
155 api.gameMeta = function (path) {
156 return get('/api/game/meta?path=' + Z.E(path));
157 };
158 
159 api.gameIconUrl = function (path) {
160 return '/api/game/icon?path=' + Z.E(path);
161 };
162 
163 /* ── Games management ── */
164 api.gamesInstalled = function () {
165 return get('/api/admin/games/installed');
166 };
167 
168 api.gameInstalledIconUrl = function (id, path) {
169 var u = '/api/admin/games/icon?id=' + Z.E(id || '');
170 if (path) u += '&path=' + Z.E(path);
171 return u;
172 };
173 
174 api.gamesRepairVisibility = function (id) {
175 var u = '/api/admin/games/repair_visibility';
176 if (id) u += '?id=' + Z.E(id);
177 return post(u);
178 };
179 
180 api.gameLaunch = function (id, path) {
181 if (id) {
182 return get('/api/admin/launch?id=' + Z.E(id));
183 }
184 return get('/api/admin/launch?path=' + Z.E(path || ''));
185 };
186 
187 api.gameUninstall = function (id) {
188 return post('/api/admin/games/uninstall?id=' + Z.E(id || ''));
189 };
190 
191 api.gameInstall = function (path) {
192 return post('/api/admin/games/install?path=' + Z.E(path || ''));
193 };
194 
195 api.gameReinstall = function (path) {
196 return post('/api/admin/games/reinstall?path=' + Z.E(path || ''));
197 };
198 
199 api.gameInstallStatus = function () {
200 return get('/api/admin/games/install_status');
201 };
202 
203 /* ── File copy cancel (Phase 5 — stub) ── */
204 api.copyCancel = function () {
205 return post('/api/copy_cancel');
206 };
207 
208 /* ── Archive extraction ── */
209 api.extract = function (archivePath, dstDir) {
210 return post('/api/extract?path=' + Z.E(archivePath) + '&dst=' + Z.E(dstDir));
211 };
212 
213 api.extractProgress = function () {
214 return get('/api/extract_progress');
215 };
216 
217 api.extractCancel = function () {
218 return post('/api/extract_cancel');
219 };
220 
221 /* ── Download Manager (Phase 6 — stub for now) ── */
222 api.downloadStart = function (url, dst) {
223 return post('/api/download/start', { url: url, dst: dst });
224 };
225 
226 api.downloadStatus = function () {
227 return get('/api/download/status');
228 };
229 
230 api.downloadPause = function (id) {
231 return post('/api/download/pause', { id: id });
232 };
233 
234 api.downloadCancel = function (id) {
235 return post('/api/download/cancel', { id: id });
236 };
237 
238 Z.api = api;
239 
240})(ZFTPD);
241