@muhkoo/connect 0.15.0-alpha.0 → 0.15.0-alpha.1
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/dist/browser/index.js +53 -24
- package/dist/browser/index.js.map +1 -1
- package/dist/connect.d.ts +24 -1
- package/dist/server/index.js +53 -24
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -6675,7 +6675,7 @@ async function parseOrThrow(response, op) {
|
|
|
6675
6675
|
* expect (and isn't serving a stale cached bundle). Keep this in sync with
|
|
6676
6676
|
* `package.json` `version`.
|
|
6677
6677
|
*/
|
|
6678
|
-
const VERSION = "0.15.0-alpha.
|
|
6678
|
+
const VERSION = "0.15.0-alpha.1";
|
|
6679
6679
|
|
|
6680
6680
|
/**
|
|
6681
6681
|
* `HttpClient` — the one place the unified {@link Client} talks to the
|
|
@@ -15458,6 +15458,18 @@ class VfsNamespace {
|
|
|
15458
15458
|
* than by TTL — a stale directory listing shows files that are not there.
|
|
15459
15459
|
*/
|
|
15460
15460
|
cache = new Map();
|
|
15461
|
+
/**
|
|
15462
|
+
* The write of each directory record still in flight, by id.
|
|
15463
|
+
*
|
|
15464
|
+
* Two writes of one record must land in the order they were made. The
|
|
15465
|
+
* personal space has no compare-and-swap: of two writes of one key that
|
|
15466
|
+
* are in flight together it keeps whichever request finishes last, and
|
|
15467
|
+
* that is often the one sent first. Then the earlier write, sealed before
|
|
15468
|
+
* the later edit was made, undoes it. That is how a file deleted forever
|
|
15469
|
+
* from the Trash, while the move that put it there was still being
|
|
15470
|
+
* written, came back. So each write waits for the one before it.
|
|
15471
|
+
*/
|
|
15472
|
+
writing = new Map();
|
|
15461
15473
|
historyLimit;
|
|
15462
15474
|
maxEntries;
|
|
15463
15475
|
maxPathChars;
|
|
@@ -15921,10 +15933,7 @@ class VfsNamespace {
|
|
|
15921
15933
|
const parentPath = dirname(target);
|
|
15922
15934
|
await this.mkdir(parentPath, { recursive: true });
|
|
15923
15935
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
15924
|
-
const { manifest, size } = await this.deps.content.write(bytes, {
|
|
15925
|
-
name,
|
|
15926
|
-
type: opts.type ?? contentTypeFor(name),
|
|
15927
|
-
});
|
|
15936
|
+
const { manifest, size } = await this.deps.content.write(bytes, { name, type: opts.type ?? contentTypeFor(name) }, { onProgress: opts.onProgress });
|
|
15928
15937
|
const parent = await this.openDir(parentPath);
|
|
15929
15938
|
const prior = entryIn(parent.node, name);
|
|
15930
15939
|
if (prior?.kind === "dir")
|
|
@@ -16482,24 +16491,14 @@ class VfsNamespace {
|
|
|
16482
16491
|
if (Object.hasOwn(dir.node.entries, name))
|
|
16483
16492
|
delete dir.hidden[name];
|
|
16484
16493
|
}
|
|
16485
|
-
|
|
16486
|
-
|
|
16487
|
-
|
|
16494
|
+
// Not sent until any earlier write of this record has landed: see
|
|
16495
|
+
// `writing`. Whether that one worked or not, this one still goes.
|
|
16496
|
+
const before = this.writing.get(dir.id);
|
|
16497
|
+
const send = () => this.writeRecord(dir);
|
|
16498
|
+
const write = before ? before.then(send, send) : send();
|
|
16499
|
+
this.writing.set(dir.id, write);
|
|
16488
16500
|
try {
|
|
16489
|
-
|
|
16490
|
-
try {
|
|
16491
|
-
sealed = await seal(dir.key, stored);
|
|
16492
|
-
}
|
|
16493
|
-
catch (err) {
|
|
16494
|
-
// JSON.stringify's own failures: a value too deeply nested to
|
|
16495
|
-
// write. Reading drops those from a stored record, so this is
|
|
16496
|
-
// what the write itself was given.
|
|
16497
|
-
if (!(err instanceof RangeError || err instanceof TypeError))
|
|
16498
|
-
throw err;
|
|
16499
|
-
const where = dir.path ?? `the directory stored as record ${printable(dir.id, 40)}`;
|
|
16500
|
-
throw new VfsConflictError(`cannot write to ${where}: it would hold a value nested too deeply to store`);
|
|
16501
|
-
}
|
|
16502
|
-
await this.deps.store.put(dirKey(dir.id), sealed);
|
|
16501
|
+
await write;
|
|
16503
16502
|
}
|
|
16504
16503
|
catch (err) {
|
|
16505
16504
|
// The edit above was made in place, on the very object the cache
|
|
@@ -16510,8 +16509,38 @@ class VfsNamespace {
|
|
|
16510
16509
|
this.cache.delete(dir.id);
|
|
16511
16510
|
throw err;
|
|
16512
16511
|
}
|
|
16512
|
+
finally {
|
|
16513
|
+
if (this.writing.get(dir.id) === write)
|
|
16514
|
+
this.writing.delete(dir.id);
|
|
16515
|
+
}
|
|
16513
16516
|
this.cache.set(dir.id, Promise.resolve(dir));
|
|
16514
16517
|
}
|
|
16518
|
+
/**
|
|
16519
|
+
* Seal a directory record as it stands NOW and put it in the store.
|
|
16520
|
+
*
|
|
16521
|
+
* Read at the moment of sending, not when the edit was made, so a write
|
|
16522
|
+
* that waited behind another carries every edit made to the record by
|
|
16523
|
+
* then, its own included.
|
|
16524
|
+
*/
|
|
16525
|
+
async writeRecord(dir) {
|
|
16526
|
+
const stored = Object.keys(dir.hidden).length
|
|
16527
|
+
? { ...dir.node, entries: Object.assign(Object.create(null), dir.hidden, dir.node.entries) }
|
|
16528
|
+
: dir.node;
|
|
16529
|
+
let sealed;
|
|
16530
|
+
try {
|
|
16531
|
+
sealed = await seal(dir.key, stored);
|
|
16532
|
+
}
|
|
16533
|
+
catch (err) {
|
|
16534
|
+
// JSON.stringify's own failures: a value too deeply nested to
|
|
16535
|
+
// write. Reading drops those from a stored record, so this is
|
|
16536
|
+
// what the write itself was given.
|
|
16537
|
+
if (!(err instanceof RangeError || err instanceof TypeError))
|
|
16538
|
+
throw err;
|
|
16539
|
+
const where = dir.path ?? `the directory stored as record ${printable(dir.id, 40)}`;
|
|
16540
|
+
throw new VfsConflictError(`cannot write to ${where}: it would hold a value nested too deeply to store`);
|
|
16541
|
+
}
|
|
16542
|
+
await this.deps.store.put(dirKey(dir.id), sealed);
|
|
16543
|
+
}
|
|
16515
16544
|
async createDir(parentPath, name) {
|
|
16516
16545
|
assertValidName(name);
|
|
16517
16546
|
const parent = await this.openDir(parentPath);
|
|
@@ -19488,9 +19517,9 @@ class Client {
|
|
|
19488
19517
|
// GC. `storage.writeFile` would additionally index the manifest
|
|
19489
19518
|
// in the space — a second, diverging source of truth for a file
|
|
19490
19519
|
// whose handle the VFS already holds.
|
|
19491
|
-
write: async (data, meta) => {
|
|
19520
|
+
write: async (data, meta, opts) => {
|
|
19492
19521
|
const space = await resolveContentSpace();
|
|
19493
|
-
const { manifest, stat } = await space.putFile(data, { name: meta.name, type: meta.type });
|
|
19522
|
+
const { manifest, stat } = await space.putFile(data, { name: meta.name, type: meta.type }, { onProgress: opts?.onProgress });
|
|
19494
19523
|
return { manifest, size: stat.size };
|
|
19495
19524
|
},
|
|
19496
19525
|
// Reads go through the manifest alone — no space needed. That is
|