@justai/cuts 0.127.0 → 0.128.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/package.json +1 -1
- package/src/FilePicker.astro +61 -0
package/package.json
CHANGED
package/src/FilePicker.astro
CHANGED
|
@@ -420,11 +420,72 @@ const { id, title = "Choose a file", src = "/files" } = Astro.props;
|
|
|
420
420
|
};
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
+
// queries: write a file without asking · FilePicker write · a persona's own cached asset ·
|
|
424
|
+
// keep a dependency a project points at · write vs save · save asks and I do not want
|
|
425
|
+
// to ask · store a file the person did not make · project dependency from outside files
|
|
426
|
+
//
|
|
427
|
+
// THE SECOND VERB THAT ASKS NOBODY, AND THE ONE THAT WAS MISSING.
|
|
428
|
+
//
|
|
429
|
+
// `save` is deliberately not a friendlier `write`. The kernel's own corpus states the split and
|
|
430
|
+
// it is not about permission — both write the same origin under the same policy:
|
|
431
|
+
//
|
|
432
|
+
// `write` is arithmetic and keeps the PERSONA's things — a cached asset, a draft it will
|
|
433
|
+
// reopen itself. `save` is an interaction and hands a person THEIRS, because the two questions
|
|
434
|
+
// that make a saved document a document — what is it called, where does it go — are the
|
|
435
|
+
// person's to answer.
|
|
436
|
+
//
|
|
437
|
+
// The service has had `write` since the beginning. This door did not expose it, and for fifteen
|
|
438
|
+
// personas that was invisible, because the only project dependency anybody had was `qr`'s logo —
|
|
439
|
+
// which arrives through `pick`, so it is already in files and already has an id.
|
|
440
|
+
//
|
|
441
|
+
// `3dviewer` is the first persona whose dependency comes from OUTSIDE: a model dragged off a
|
|
442
|
+
// desktop. Its project file must point at that model, so the model needs a home — and it is not
|
|
443
|
+
// a document the person made here, it is the asset this persona will reopen itself. Exactly the
|
|
444
|
+
// case the paragraph above describes, with no verb to express it. The persona was left choosing
|
|
445
|
+
// between a doctrine it could not follow and a second Save sheet asking somebody to name a file
|
|
446
|
+
// they did not create.
|
|
447
|
+
//
|
|
448
|
+
// ADDITIVE, and that matters: nothing that exists behaves differently. The policy still answers
|
|
449
|
+
// "who is asking" — same-origin only, exactly as `read` does — so this widens no door.
|
|
450
|
+
//
|
|
451
|
+
// It returns the NODE, because a caller writing a project dependency needs the `id`: a path is
|
|
452
|
+
// what a person renames and an id is what a thing IS.
|
|
453
|
+
async function write(
|
|
454
|
+
path: string,
|
|
455
|
+
bytes: ArrayBuffer | Uint8Array,
|
|
456
|
+
opts: { mime?: string; keepVersions?: number } = {},
|
|
457
|
+
): Promise<{ id: string; name: string; path: string } | null> {
|
|
458
|
+
const bus = await router();
|
|
459
|
+
ensureFrame();
|
|
460
|
+
const body = bytes instanceof Uint8Array
|
|
461
|
+
? (bytes.byteOffset === 0 && bytes.byteLength === bytes.buffer.byteLength
|
|
462
|
+
? bytes.buffer
|
|
463
|
+
: bytes.slice().buffer)
|
|
464
|
+
: bytes;
|
|
465
|
+
const node = await arrived!
|
|
466
|
+
.then(() => bus.proxy({
|
|
467
|
+
service: "files",
|
|
468
|
+
method: "write",
|
|
469
|
+
args: { path, bytes: body, mime: opts.mime, keepVersions: opts.keepVersions },
|
|
470
|
+
// The same 30s ceiling `read` uses. A model is tens of megabytes and a phone's storage is
|
|
471
|
+
// not fast; the default would time out on exactly the files this verb exists for.
|
|
472
|
+
options: { timeout: 30000 },
|
|
473
|
+
}))
|
|
474
|
+
.catch(() => null);
|
|
475
|
+
// A quota that is full, or a path the kernel refused. `null` rather than a throw, for the same
|
|
476
|
+
// reason `read` returns null: a caller must be able to carry on and say so.
|
|
477
|
+
if (!node) return null;
|
|
478
|
+
const n = node as { id: string; name: string };
|
|
479
|
+
return { id: n.id, name: n.name, path };
|
|
480
|
+
}
|
|
481
|
+
|
|
423
482
|
(host as any).pick = pick;
|
|
424
483
|
(sheet as any).pick = pick;
|
|
425
484
|
(host as any).save = save;
|
|
426
485
|
(sheet as any).save = save;
|
|
427
486
|
(host as any).read = read;
|
|
428
487
|
(sheet as any).read = read;
|
|
488
|
+
(host as any).write = write;
|
|
489
|
+
(sheet as any).write = write;
|
|
429
490
|
}
|
|
430
491
|
</script>
|