@@ -14,16 +14,23 @@ const converter = new AnsiToHtml({
14
14
/** @type {import('@webcontainer/api').WebContainer } Web container singleton */
15
15
let vm ;
16
16
17
+ export const state = new ( class WCState {
18
+ progress = $state . raw ( { value : 0 , text : 'initialising' } ) ;
19
+ /** @type {string | null } */
20
+ base = $state . raw ( null ) ;
21
+ /** @type {Error | null } */
22
+ error = $state . raw ( null ) ;
23
+ /** @type {string[] } */
24
+ logs = $state . raw ( [ ] ) ;
25
+ /** @type {Record<string, import('$lib/tutorial').Warning[]> } */
26
+ warnings = $state . raw ( { } ) ;
27
+ } ) ( ) ;
28
+
17
29
/**
18
- * @param {import('svelte/store').Writable<string | null> } base
19
- * @param {import('svelte/store').Writable<Error | null> } error
20
- * @param {import('svelte/store').Writable<{ value: number, text: string }> } progress
21
- * @param {import('svelte/store').Writable<string[]> } logs
22
- * @param {import('svelte/store').Writable<Record<string, import('$lib/tutorial').Warning[]>> } warnings
23
30
* @returns {Promise<import('$lib/tutorial').Adapter> }
24
31
*/
25
- export async function create ( base , error , progress , logs , warnings ) {
26
- progress . set ( { value : 0 , text : 'loading files' } ) ;
32
+ export async function create ( ) {
33
+ state . progress = { value : 0 , text : 'loading files' } ;
27
34
28
35
const q = yootils . queue ( 1 ) ;
29
36
/** @type {Map<string, Array<import('$lib/tutorial').FileStub>> } */
@@ -32,10 +39,10 @@ export async function create(base, error, progress, logs, warnings) {
32
39
/** Paths and contents of the currently loaded file stubs */
33
40
let current_stubs = stubs_to_map ( [ ] ) ;
34
41
35
- progress . set ( { value : 1 / 5 , text : 'booting webcontainer' } ) ;
42
+ state . progress = { value : 1 / 5 , text : 'booting webcontainer' } ;
36
43
vm = await WebContainer . boot ( ) ;
37
44
38
- progress . set ( { value : 2 / 5 , text : 'writing virtual files' } ) ;
45
+ state . progress = { value : 2 / 5 , text : 'writing virtual files' } ;
39
46
const common = await ready ;
40
47
await vm . mount ( {
41
48
'common.zip' : {
@@ -47,32 +54,31 @@ export async function create(base, error, progress, logs, warnings) {
47
54
} ) ;
48
55
49
56
/** @type {Record<string, import('$lib/tutorial').Warning[]> } */
50
- let $warnings ;
51
- warnings . subscribe ( ( value ) => ( $warnings = value ) ) ;
57
+ let warnings = { } ;
52
58
53
59
/** @type {any } */
54
60
let timeout ;
55
61
56
62
/** @param {number } msec */
57
63
function schedule_to_update_warning ( msec ) {
58
64
clearTimeout ( timeout ) ;
59
- timeout = setTimeout ( ( ) => warnings . set ( $ warnings) , msec ) ;
65
+ timeout = setTimeout ( ( ) => ( state . warnings = { ... warnings } ) , msec ) ;
60
66
}
61
67
62
68
const log_stream = ( ) =>
63
69
new WritableStream ( {
64
70
write ( chunk ) {
65
71
if ( chunk === '\x1B[1;1H' ) {
66
72
// clear screen
67
- logs . set ( [ ] ) ;
73
+ state . logs = [ ] ;
68
74
} else if ( chunk ?. startsWith ( 'svelte:warnings:' ) ) {
69
75
/** @type {import('$lib/tutorial').Warning } */
70
76
const warn = JSON . parse ( chunk . slice ( 16 ) ) ;
71
77
const filename = warn . filename . startsWith ( '/' ) ? warn . filename : '/' + warn . filename ;
72
- const current = $ warnings[ filename ] ;
78
+ const current = warnings [ filename ] ;
73
79
74
80
if ( ! current ) {
75
- $ warnings[ filename ] = [ warn ] ;
81
+ warnings [ filename ] = [ warn ] ;
76
82
// the exact same warning may be given multiple times in a row
77
83
} else if ( ! current . some ( ( s ) => s . code === warn . code && s . pos === warn . pos ) ) {
78
84
current . push ( warn ) ;
@@ -81,12 +87,12 @@ export async function create(base, error, progress, logs, warnings) {
81
87
schedule_to_update_warning ( 100 ) ;
82
88
} else {
83
89
const log = converter . toHtml ( escape_html ( chunk ) ) . replace ( / \n / g, '<br>' ) ;
84
- logs . update ( ( $ logs) => [ ...$ logs, log ] ) ;
90
+ state . logs = [ ...state . logs , log ] ;
85
91
}
86
92
}
87
93
} ) ;
88
94
89
- progress . set ( { value : 3 / 5 , text : 'unzipping files' } ) ;
95
+ state . progress = { value : 3 / 5 , text : 'unzipping files' } ;
90
96
const unzip = await vm . spawn ( 'node' , [ 'unzip.cjs' ] ) ;
91
97
unzip . output . pipeTo ( log_stream ( ) ) ;
92
98
const code = await unzip . exit ;
@@ -98,11 +104,11 @@ export async function create(base, error, progress, logs, warnings) {
98
104
await vm . spawn ( 'chmod' , [ 'a+x' , 'node_modules/vite/bin/vite.js' ] ) ;
99
105
100
106
vm . on ( 'server-ready' , ( _port , url ) => {
101
- base . set ( url ) ;
107
+ state . base = url ;
102
108
} ) ;
103
109
104
110
vm . on ( 'error' , ( { message } ) => {
105
- error . set ( new Error ( message ) ) ;
111
+ state . error = new Error ( message ) ;
106
112
} ) ;
107
113
108
114
let launched = false ;
@@ -111,7 +117,7 @@ export async function create(base, error, progress, logs, warnings) {
111
117
if ( launched ) return ;
112
118
launched = true ;
113
119
114
- progress . set ( { value : 4 / 5 , text : 'starting dev server' } ) ;
120
+ state . progress = { value : 4 / 5 , text : 'starting dev server' } ;
115
121
116
122
await new Promise ( async ( fulfil , reject ) => {
117
123
const error_unsub = vm . on ( 'error' , ( error ) => {
@@ -121,7 +127,7 @@ export async function create(base, error, progress, logs, warnings) {
121
127
122
128
const ready_unsub = vm . on ( 'server-ready' , ( _port , base ) => {
123
129
ready_unsub ( ) ;
124
- progress . set ( { value : 5 / 5 , text : 'ready' } ) ;
130
+ state . progress = { value : 5 / 5 , text : 'ready' } ;
125
131
fulfil ( base ) ; // this will be the last thing that happens if everything goes well
126
132
} ) ;
127
133
@@ -182,14 +188,14 @@ export async function create(base, error, progress, logs, warnings) {
182
188
183
189
// initialize warnings of written files
184
190
to_write
185
- . filter ( ( stub ) => stub . type === 'file' && $ warnings[ stub . name ] )
186
- . forEach ( ( stub ) => ( $ warnings[ stub . name ] = [ ] ) ) ;
191
+ . filter ( ( stub ) => stub . type === 'file' && warnings [ stub . name ] )
192
+ . forEach ( ( stub ) => ( warnings [ stub . name ] = [ ] ) ) ;
187
193
// remove warnings of deleted files
188
194
to_delete
189
- . filter ( ( stubname ) => $ warnings[ stubname ] )
190
- . forEach ( ( stubname ) => delete $ warnings[ stubname ] ) ;
195
+ . filter ( ( stubname ) => warnings [ stubname ] )
196
+ . forEach ( ( stubname ) => delete warnings [ stubname ] ) ;
191
197
192
- warnings . set ( $ warnings) ;
198
+ state . warnings = { ... warnings } ;
193
199
194
200
current_stubs = stubs_to_map ( stubs ) ;
195
201
@@ -260,7 +266,7 @@ export async function create(base, error, progress, logs, warnings) {
260
266
tree [ basename ] = to_file ( file ) ;
261
267
262
268
// initialize warnings of this file
263
- $ warnings[ file . name ] = [ ] ;
269
+ warnings [ file . name ] = [ ] ;
264
270
schedule_to_update_warning ( 100 ) ;
265
271
266
272
await vm . mount ( root ) ;
0 commit comments