-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathsync-api.ts
More file actions
137 lines (116 loc) · 4.93 KB
/
sync-api.ts
File metadata and controls
137 lines (116 loc) · 4.93 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
* Synchronous API Example
*
* Demonstrates:
* - Connect to sync channel
* - Synchronous file operations
* - Compare with async operations
*
* Note: Requires SharedArrayBuffer support (COOP/COEP headers)
*/
import {
SyncChannel,
isSyncChannelSupported,
mkdirSync,
writeFileSync,
readTextFileSync,
existsSync,
statSync,
removeSync,
isOPFSSupported,
isFileHandleLike,
} from '../src/mod.ts';
const output = document.getElementById('output')!;
function log(message: string, type: 'success' | 'error' | 'info' | 'warning' = 'success'): void {
const line = document.createElement('div');
line.className = type;
line.textContent = message;
output.appendChild(line);
console.log(message);
}
async function runExample(): Promise<void> {
output.textContent = '';
// Check OPFS support
if (!isOPFSSupported()) {
log('OPFS is not supported in this browser!', 'error');
return;
}
// Check SyncChannel support (SharedArrayBuffer + cross-origin isolation)
if (!isSyncChannelSupported()) {
log('SyncChannel is not supported!', 'error');
log('Sync APIs require these HTTP headers:', 'warning');
log(' Cross-Origin-Opener-Policy: same-origin', 'warning');
log(' Cross-Origin-Embedder-Policy: require-corp', 'warning');
return;
}
log('=== Connecting to Sync Channel ===', 'info');
if (SyncChannel.isReady()) {
log('✓ Already connected to sync channel', 'success');
} else {
// Connect to the sync worker (returns AsyncIOResult<SharedArrayBuffer>)
const connectResult = await SyncChannel.connect(
new Worker(new URL('sync-worker.ts', import.meta.url), { type: 'module' }),
{
sharedBufferLength: 10 * 1024 * 1024, // 10MB buffer
opTimeout: 5000, // 5 second timeout
},
);
if (connectResult.isErr()) {
log(`✗ Failed to connect: ${connectResult.unwrapErr().message}`, 'error');
return;
}
log('✓ Connected to sync channel', 'success');
}
// Clean up from previous runs
log('\n=== Cleanup ===', 'info');
removeSync('/sync-example');
log('✓ Cleaned up /sync-example directory', 'success');
// Synchronous operations
log('\n=== Synchronous File Operations ===', 'info');
// Create directory (sync) - mkdir is recursive by default
log('Creating directory...', 'info');
const mkdirResult = mkdirSync('/sync-example/data');
mkdirResult.inspect(() => log('✓ mkdirSync: Created /sync-example/data', 'success'));
mkdirResult.inspectErr((err) => log(`✗ mkdirSync failed: ${err.message}`, 'error'));
// Write file (sync)
log('Writing file...', 'info');
const writeResult = writeFileSync('/sync-example/data/test.txt', 'Hello from sync API!');
writeResult.inspect(() => log('✓ writeFileSync: Wrote test.txt', 'success'));
writeResult.inspectErr((err) => log(`✗ writeFileSync failed: ${err.message}`, 'error'));
// Check existence (sync)
log('Checking existence...', 'info');
const existsResult = existsSync('/sync-example/data/test.txt');
existsResult.inspect((exists) => log(`✓ existsSync: File exists = ${exists}`, 'success'));
existsResult.inspectErr((err) => log(`✗ existsSync failed: ${err.message}`, 'error'));
// Read file (sync)
log('Reading file...', 'info');
const readResult = readTextFileSync('/sync-example/data/test.txt');
readResult.inspect((content) => log(`✓ readTextFileSync: Content = "${content}"`, 'success'));
readResult.inspectErr((err) => log(`✗ readTextFileSync failed: ${err.message}`, 'error'));
// Get stats (sync) - returns FileSystemHandleLike
log('Getting file stats...', 'info');
const statResult = statSync('/sync-example/data/test.txt');
statResult.inspect((handleLike) => {
if (isFileHandleLike(handleLike)) {
log(`✓ statSync: size=${handleLike.size}, kind=${handleLike.kind}`, 'success');
} else {
log(`✓ statSync: kind=${handleLike.kind}`, 'success');
}
});
statResult.inspectErr((err) => log(`✗ statSync failed: ${err.message}`, 'error'));
// Performance comparison
log('\n=== Performance Note ===', 'info');
log('Sync APIs block the main thread and have communication overhead.', 'warning');
log('Use async APIs when possible for better performance.', 'warning');
// Clean up
log('\n=== Final Cleanup ===', 'info');
const removeResult = removeSync('/sync-example');
removeResult.inspect(() => log('✓ removeSync: Removed /sync-example', 'success'));
removeResult.inspectErr((err) => log(`✗ removeSync failed: ${err.message}`, 'error'));
log('\n=== Example Complete ===', 'info');
}
document.getElementById('run')!.addEventListener('click', () => {
runExample().catch((err) => {
log(`Unexpected error: ${err.message}`, 'error');
});
});