forked from oraoto/pib
-
-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy pathFilesystem.js
117 lines (95 loc) · 3.87 KB
/
Filesystem.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import './Common.css';
import './InstallDemo.css';
import loader from './tail-spin.svg';
import { PhpWeb } from 'php-wasm/PhpWeb';
import { useEffect, useState } from 'react';
import { sendMessageFor } from 'php-cgi-wasm/msg-bus';
const sendMessage = sendMessageFor((`${window.location.origin}${process.env.PUBLIC_URL}/cgi-worker.mjs`));
const backupSite = async () => {
const persistFile = await sendMessage('readdir', ['/persist']);
const configFiles = await sendMessage('readdir', ['/config']);
if([persistFile, configFiles].flat().length <= 4)
{
throw `Filesystem is empty!`;
}
const php = new PhpWeb({persist: [{mountPath:'/persist'}, {mountPath:'/config'}]});
await php.binary;
const backupPhpCode = await (await fetch(process.env.PUBLIC_URL + '/scripts/backup.php')).text();
window.dispatchEvent(new CustomEvent('install-status', {detail: 'Backing up files...'}));
await php.run(backupPhpCode);
window.dispatchEvent(new CustomEvent('install-status', {detail: 'Refreshing PHP...'}));
await sendMessage('refresh', []);
const zipContents = await sendMessage('readFile', ['/persist/backup.zip']);
const blob = new Blob([zipContents], {type:'application/zip'})
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.click();
URL.revokeObjectURL(link.href);
};
const restoreSite = async ({fileInput}) => {
if(!fileInput.files.length)
{
throw `No file provided.`;
}
const php = new PhpWeb({persist: [{mountPath:'/persist'}, {mountPath:'/config'}]});
const zipContents = await fileInput.files[0].arrayBuffer();
window.dispatchEvent(new CustomEvent('install-status', {detail: 'Uploading zip...'}));
await sendMessage('writeFile', ['/persist/restore.zip', new Uint8Array(zipContents)]);
await php.binary;
const restorePhpCode = await (await fetch(process.env.PUBLIC_URL + '/scripts/restore.php')).text();
window.dispatchEvent(new CustomEvent('install-status', {detail: 'Unpacking files...'}));
await php.run(restorePhpCode);
window.dispatchEvent(new CustomEvent('install-status', {detail: 'Refreshing PHP...'}));
await sendMessage('refresh', []);
};
const clearFilesystem = () => {
const fileDb = indexedDB.open("/persist", 21);
const configDb = indexedDB.open("/config", 21);
window.dispatchEvent(new CustomEvent('install-status', {detail: 'Clearing IDBFS...'}));
const clearDb = openDb => {
let callback;
const promise = new Promise(accept => {
callback = async event => {
const db = openDb.result;
const transaction = db.transaction(["FILE_DATA"], "readwrite");
const objectStore = transaction.objectStore("FILE_DATA");
objectStore.clear();
await sendMessage('refresh', []);
accept();
}
});
return {callback, promise};
};
const fileClear = clearDb(fileDb);
const configClear = clearDb(configDb);
fileDb.onsuccess = fileClear.callback;
configDb.onsuccess = configClear.callback;
return Promise.all([fileClear.promise, configClear.promise]);
};
const makeComponent = (operation) => ({onComplete, onError, onFinally = () => {}, ...args}) => {
const [message, setMessage] = useState('Initializing...');
const onStatus = event => setMessage(event.detail);
useEffect(() => {
window.addEventListener('install-status', onStatus);
window.__operation = window.__operation || operation(args)
.then(() => onComplete())
.catch(error => onError(error))
.finally(() => window.__operation = null);
return () => {
window.removeEventListener('install-status', onStatus);
}
}, []);
return message && ( <div className = "install-demo">
<div className = "center">
<div className = "bevel">
<div className = "inset padded column center">
<img className = "loader-icon" src = {loader} alt = "loading" />
{message}
</div>
</div>
</div>
</div>);
};
export const Restore = makeComponent(restoreSite);
export const Backup = makeComponent(backupSite);
export const Clear = makeComponent(clearFilesystem);