-
Notifications
You must be signed in to change notification settings - Fork 221
/
setup-playground-sync.ts
66 lines (58 loc) · 2.21 KB
/
setup-playground-sync.ts
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
import { PlaygroundClient } from '@wp-playground/remote';
import { installSqlSyncMuPlugin, overrideAutoincrementSequences } from './sql';
import { journalFSOperations } from './fs';
import { SQLJournalEntry, journalSQLQueries, replaySQLJournal } from './sql';
import { PlaygroundSyncTransport, TransportEnvelope } from './transports';
import { FilesystemOperation } from '@php-wasm/fs-journal';
import { SyncMiddleware, marshallSiteURLMiddleware } from './middleware';
import { pruneSQLQueriesMiddleware } from './middleware/prune-sql-queries';
import { hydrateFsWritesMiddleware } from './middleware/hydrate-fs-writes';
export interface SyncOptions {
autoincrementOffset: number;
transport: PlaygroundSyncTransport;
middlewares?: SyncMiddleware[];
}
export async function setupPlaygroundSync(
playground: PlaygroundClient,
{ autoincrementOffset, transport, middlewares = [] }: SyncOptions
) {
middlewares = [
pruneSQLQueriesMiddleware(),
marshallSiteURLMiddleware(await playground.absoluteUrl),
hydrateFsWritesMiddleware(playground),
...middlewares,
];
await installSqlSyncMuPlugin(playground);
await overrideAutoincrementSequences(playground, autoincrementOffset);
transport.onChangesReceived(async (changes) => {
for (const middleware of middlewares) {
changes = await middleware.afterReceive(changes);
}
await playground.replayFSJournal(changes.fs);
await replaySQLJournal(playground, changes.sql);
});
let localChanges: TransportEnvelope = { fs: [], sql: [] };
journalSQLQueries(playground, (query: SQLJournalEntry) => {
localChanges.sql.push(query);
});
journalFSOperations(playground, (op: FilesystemOperation) => {
localChanges.fs.push(op);
});
// Flush the journal at most every 3 seconds
const flushJournal = async () => {
let flushedChanges = localChanges;
localChanges = { fs: [], sql: [] };
for (const middleware of middlewares) {
flushedChanges = await middleware.beforeSend(flushedChanges);
}
if (!flushedChanges.sql.length && !flushedChanges.fs.length) {
return;
}
transport.sendChanges(flushedChanges);
};
const loopAfterInterval = async (f: Function, ms: number) => {
await f();
setTimeout(loopAfterInterval, ms, f, ms);
};
loopAfterInterval(flushJournal, 3000);
}