arm64js 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,7 +121,20 @@ A VM can be created either from a base image or your own local snapshot.
121
121
  - `image`: name of an image on the CDN ([all images](https://arm64js.com/images/)): `'alpine'` is the newest version of it, `'alpine:2'` a fixed one, `'alpine@sha256:<hash>'` an exact snapshot.
122
122
  - `snapshotId`: a snapshot id (`snap.id`, 64 hex characters) loads one of your own snapshots made previously.
123
123
 
124
- Additionally, you can specify an `onProgress` callback to track VM loading phases (`resolve → manifest → start → memory (repeats, with counts) → run → done`) and the number of virtual CPUs the VM will have (more is not always better).
124
+ Additionally, you can specify an `onProgress` callback to track VM loading phases and the number of virtual CPUs the VM will have (more is not always better).
125
+
126
+ onProgress gets one argument, a BootProgress object:
127
+
128
+ ```ts
129
+ interface BootProgress {
130
+ stage: 'resolve' | 'manifest' | 'start' | 'memory' | 'run' | 'done';
131
+ done?: number;
132
+ total?: number;
133
+ }
134
+ ```
135
+
136
+ - the stages arrive in the following order: resolve → manifest → start → memory → run → done.
137
+ - done and total are optional, they are filled in during the `memory` stage when the VM data chunks load (the slowers part of the boot for larger VMs).
125
138
 
126
139
  ### Listener: `vm.onOutput(cb)` → unsubscribe
127
140
 
@@ -164,6 +177,24 @@ It works by typing the command into the guest's serial console and reading the b
164
177
 
165
178
  Whatever the command does runs as **root** in the guest.
166
179
 
180
+ #### Streaming the output
181
+
182
+ For longer running commands it can be useful to see output as it's being generated rather waiting for command to finish. To do that you can setup `vm.onOutput` **before** running `vm.exec`:
183
+
184
+ ```ts
185
+ const decoder = new TextDecoder();
186
+ const stop = vm.onOutput((bytes, info) => {
187
+ if (!info.exec) return; // keep only what exec prints
188
+ console.log(decoder.decode(bytes));
189
+ });
190
+
191
+ try {
192
+ const { exitCode } = await vm.exec('apk add --no-cache php');
193
+ } finally {
194
+ stop();
195
+ }
196
+ ```
197
+
167
198
  ### `vm.write(data)`
168
199
 
169
200
  Send data directly into the VM console, lower level than `vm.exec`, allows sending any keyboard sequences including key presses like Ctrl-C ('\x03') or Enter ('\r').
@@ -183,6 +214,16 @@ Copies `data` (a `Blob` or `File`, bytes, or a string) into the VM as the file `
183
214
 
184
215
  The copy is kept in VM memory, so it has to fit there (`alpine` for example has 1 GiB). If you need to use a larger file, use `vm.mount` instead.
185
216
 
217
+ Here's an example how you can load a file from the URL in to the VM:
218
+
219
+ ```ts
220
+ const file = await fetch('./test.txt');
221
+ const fileBlob = await file.blob();
222
+ await vm.writeFile('/tmp/test.txt', fileBlob);
223
+ const { output, exitCode } = await vm.exec('cat /tmp/test.txt');
224
+ console.log(output);
225
+ ```
226
+
186
227
  **Files become part of the VM, so when a snapshot is taken those files will be present in the snapshot.**
187
228
 
188
229
  ### `vm.readFile(path, { maxBytes?, timeoutMs? })` → `Blob`
@@ -215,6 +256,18 @@ Undoes a `mount`. If nothing is mounted at `path` it does nothing. While a progr
215
256
 
216
257
  Saves the VM in browser storage (OPFS) and keeps it running. Use `meta` to store any extra info you'd like to add to the snapshot (any JSON up to 16 KiB); it is returned in `snapshots.list()`.
217
258
 
259
+ For example to save current state and load it when page refreshes:
260
+
261
+ ```ts
262
+ // load from snapshot if previously saved or alpine otherwise
263
+ const snapshotId = localStorage.get('snapshotId');
264
+ await Arm64JS.boot(snapshotId ? snapshotId : 'alpine');
265
+
266
+ // do something to the VM, then save the snapshot again
267
+ const newSnapshot = vm.snapshot();
268
+ localStorage.set('snapshotId', newSnapshot.id);
269
+ ```
270
+
218
271
  ### `vm.dispose()`
219
272
 
220
273
  Stops the VM and frees its workers.
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.4.0";
1
+ export declare const VERSION = "0.6.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by scripts/stamp-version.mjs from package.json. Do not edit.
2
- export const VERSION = "0.4.0";
2
+ export const VERSION = "0.6.0";
package/dist/vm.d.ts CHANGED
@@ -24,8 +24,9 @@ export declare class Vm {
24
24
  /** Run a shell command (one or more lines) in the guest and get its output and
25
25
  * exit code. One at a time per VM. */
26
26
  exec(command: string, opts?: ExecOptions): Promise<ExecResult>;
27
- /** The raw bytes the guest prints on its console. `info.exec` marks what an
28
- * `exec` printed (its command, output and prompts). Returns the unsubscribe. */
27
+ /** The raw bytes the guest prints on its console. While an `exec` runs, only
28
+ * what its command prints comes through, marked `info.exec`. Returns the
29
+ * unsubscribe. */
29
30
  onOutput(cb: (bytes: Uint8Array, info: OutputInfo) => void): () => void;
30
31
  /** Type into the guest's console, as a person at a terminal would. Input
31
32
  * sent while an `exec` or `snapshot` runs is held and delivered after it. */
package/dist/vm.js CHANGED
@@ -29,8 +29,9 @@ export class Vm {
29
29
  this.check();
30
30
  return withSdkErrors(this.host.exec(this.id, command, opts));
31
31
  }
32
- /** The raw bytes the guest prints on its console. `info.exec` marks what an
33
- * `exec` printed (its command, output and prompts). Returns the unsubscribe. */
32
+ /** The raw bytes the guest prints on its console. While an `exec` runs, only
33
+ * what its command prints comes through, marked `info.exec`. Returns the
34
+ * unsubscribe. */
34
35
  onOutput(cb) {
35
36
  this.check();
36
37
  return this.host.onOutput(this.id, cb);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arm64js",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Run a Linux VM inside your web page. Boots Alpine from the arm64js CDN, runs commands, keeps snapshots in the browser.",
5
5
  "type": "module",
6
6
  "license": "MIT",