@better-fs-tools/cloudflare-computer 0.1.0 → 0.2.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 +5 -5
- package/dist/index.js +1 -1
- package/dist/write.js +0 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -26,15 +26,15 @@ export function computerReadTool(workspace: Workspace) {
|
|
|
26
26
|
}
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
With the write tools. `createFsTools()` from `@better-fs-tools/write` gives them and the read tool one
|
|
29
|
+
With the write tools. `createFsTools()` from `@better-fs-tools/write` gives them and the read tool one digest and one lock manager, and one read store when you pass `state`. Its default digest, `sha256Digest()`, is plain JavaScript, so it runs in a Worker:
|
|
30
30
|
|
|
31
31
|
```ts
|
|
32
32
|
import type { Workspace } from "@cloudflare/computer";
|
|
33
33
|
import { cloudflareComputerFileSystem } from "@better-fs-tools/cloudflare-computer";
|
|
34
34
|
import { createFsTools } from "@better-fs-tools/write";
|
|
35
35
|
|
|
36
|
-
// One
|
|
37
|
-
//
|
|
36
|
+
// One sha256Digest() and one lock manager. createFsTools needs no Node module,
|
|
37
|
+
// so it runs in a Worker.
|
|
38
38
|
export function computerTools(workspace: Workspace) {
|
|
39
39
|
const fs = cloudflareComputerFileSystem(workspace.fs, { allowedRoots: ["/workspace"] });
|
|
40
40
|
const { read, edit, write } = createFsTools({ fs });
|
|
@@ -49,14 +49,14 @@ export function computerTools(workspace: Workspace) {
|
|
|
49
49
|
- The filesystem exposes the resolved `cwd`, `allowedRoots`, `denyRoots`, `symlinks`, and `identity`.
|
|
50
50
|
- It walks each path with `lstat` from `/`, so a symlink above the root, a symlinked root, parent, or file is refused before any byte is read.
|
|
51
51
|
- It streams the file that `readFile` returns. `open()` starts the `readFile` stream, so the request reaches the backend before the read tool's `authorize` runs, but no chunk is read until `authorize` allows it. If a denied read must not reach the backend, deny it in the adapter with `denyRoots` or `allowedRoots`.
|
|
52
|
-
- `verify()` compares size and modification time
|
|
52
|
+
- `verify()` compares size and modification time.
|
|
53
53
|
- `list()` lists directories, so suggestions and `directoryListing()` work.
|
|
54
54
|
|
|
55
55
|
## How it writes
|
|
56
56
|
|
|
57
57
|
- `stat()`, `write()`, and `remove()` use `lstat`, `writeFile`, `mkdir`, and `rm`. They check the roots and refuse every symlink on the path before any write, as `open()` does.
|
|
58
58
|
- `writeFile`, `mkdir`, and `rm` are optional in `CloudflareComputerFileSystemLike`. They are checked when a write runs, not when the filesystem is built. A read-only wrapper backs the read tool, and a write to it gives `unsupported`, which the tools report as `UNSUPPORTED_BACKEND`.
|
|
59
|
-
- `writeCapabilities` is `{
|
|
59
|
+
- `writeCapabilities` is `{ compareAndSwap: false }`. `writeFile` runs in one transaction, so a replace is atomic. It has no version check, so the adapter checks the precondition with a fresh `lstat` just before the write. A create passes `exclusive: true`, so two creators cannot both win.
|
|
60
60
|
- `writeFile` sets the mode to `0o644` unless it gets one, also on a replace. The adapter passes the mode that `lstat` reported, so a replace keeps it. `stat()` reports the mode.
|
|
61
61
|
- There is no `stage()`: Computer has no rename. `apply_patch` writes each file in turn, and undoes them on a failure.
|
|
62
62
|
- The version is the size and the modification time in milliseconds. The write tools also compare the content hash of what the model read, so a same-size change after the read is still `STALE`.
|
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ export function cloudflareComputerFileSystem(workspaceFs, options) {
|
|
|
38
38
|
};
|
|
39
39
|
return Object.freeze({
|
|
40
40
|
id,
|
|
41
|
-
capabilities: Object.freeze({
|
|
41
|
+
capabilities: Object.freeze({ identity: false }),
|
|
42
42
|
paths: posixPaths,
|
|
43
43
|
cwd,
|
|
44
44
|
allowedRoots: roots.allowedRoots,
|
package/dist/write.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { containsPosix } from "@better-fs-tools/fs";
|
|
2
2
|
import { AdapterRefusal, authorize, boundedCode, pathsFromSlashToTarget, displayPath, inspect, mapBackendError, notAFile, refuse, toFileSystemError, } from "./policy.js";
|
|
3
3
|
export const COMPUTER_WRITE_CAPABILITIES = Object.freeze({
|
|
4
|
-
atomic: true,
|
|
5
4
|
compareAndSwap: false,
|
|
6
|
-
preserveMode: true,
|
|
7
5
|
});
|
|
8
6
|
export function computerVersion(entry) {
|
|
9
7
|
return `computer:${entry.size}:${entry.mtime}`;
|
|
@@ -94,7 +92,6 @@ export function computerWrites(workspaceFs, roots) {
|
|
|
94
92
|
identity: null,
|
|
95
93
|
size: entry?.size ?? null,
|
|
96
94
|
createdDirectories: created,
|
|
97
|
-
atomic: COMPUTER_WRITE_CAPABILITIES.atomic,
|
|
98
95
|
});
|
|
99
96
|
return {
|
|
100
97
|
async stat(requested, options = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@better-fs-tools/cloudflare-computer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A readable and writable filesystem over a Cloudflare Computer workspace (experimental).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@better-fs-tools/fs": "^0.
|
|
32
|
+
"@better-fs-tools/fs": "^0.2.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@better-fs-tools/read": "^0.
|
|
36
|
-
"@better-fs-tools/write": "^0.
|
|
35
|
+
"@better-fs-tools/read": "^0.2.0",
|
|
36
|
+
"@better-fs-tools/write": "^0.2.0",
|
|
37
37
|
"@cloudflare/computer": "0.2.1"
|
|
38
38
|
}
|
|
39
39
|
}
|