@procedures/fs 0.2.2 → 0.3.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.
Files changed (54) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +73 -1
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/handlers.d.ts +40 -0
  5. package/dist/handlers.d.ts.map +1 -0
  6. package/dist/handlers.js +163 -0
  7. package/dist/handlers.js.map +1 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +2 -0
  11. package/dist/index.js.map +1 -1
  12. package/dist/module.d.ts +23 -2
  13. package/dist/module.d.ts.map +1 -1
  14. package/dist/module.js +94 -3
  15. package/dist/module.js.map +1 -1
  16. package/dist/procedures/fs/hash.d.ts +12 -0
  17. package/dist/procedures/fs/hash.d.ts.map +1 -0
  18. package/dist/procedures/fs/hash.js +23 -0
  19. package/dist/procedures/fs/hash.js.map +1 -0
  20. package/dist/procedures/fs/index.d.ts +4 -0
  21. package/dist/procedures/fs/index.d.ts.map +1 -1
  22. package/dist/procedures/fs/index.js +4 -0
  23. package/dist/procedures/fs/index.js.map +1 -1
  24. package/dist/procedures/fs/temp.d.ts +14 -0
  25. package/dist/procedures/fs/temp.d.ts.map +1 -0
  26. package/dist/procedures/fs/temp.js +20 -0
  27. package/dist/procedures/fs/temp.js.map +1 -0
  28. package/dist/procedures/fs/watch.d.ts +14 -0
  29. package/dist/procedures/fs/watch.d.ts.map +1 -0
  30. package/dist/procedures/fs/watch.js +26 -0
  31. package/dist/procedures/fs/watch.js.map +1 -0
  32. package/dist/procedures/fs/write-json.d.ts +12 -0
  33. package/dist/procedures/fs/write-json.d.ts.map +1 -0
  34. package/dist/procedures/fs/write-json.js +33 -0
  35. package/dist/procedures/fs/write-json.js.map +1 -0
  36. package/dist/root.d.ts +52 -0
  37. package/dist/root.d.ts.map +1 -0
  38. package/dist/root.js +129 -0
  39. package/dist/root.js.map +1 -0
  40. package/dist/types.d.ts +55 -0
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/types.js +37 -0
  43. package/dist/types.js.map +1 -1
  44. package/package.json +2 -2
  45. package/src/handlers.ts +214 -0
  46. package/src/index.ts +2 -0
  47. package/src/module.ts +127 -4
  48. package/src/procedures/fs/hash.ts +25 -0
  49. package/src/procedures/fs/index.ts +4 -0
  50. package/src/procedures/fs/temp.ts +22 -0
  51. package/src/procedures/fs/watch.ts +26 -0
  52. package/src/procedures/fs/write-json.ts +32 -0
  53. package/src/root.ts +139 -0
  54. package/src/types.ts +106 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,57 @@
1
1
  # @procedures/fs
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f23c7ad: Four file procedures (roadmap R44). `fs.write.json` writes a value as JSON through a file that it renames at the end. `fs.hash` gives the hash of a file. `fs.temp` makes a temporary folder. `fs.watch` gives the changes of a file or folder as a stream without an end. With `createFsModule({ root })`, each path stays in the root, and `fs.temp` makes its folders in the folder `.tmp` of the root.
8
+ - bc70357: The file procedures can have a root (roadmap R33). `createFsModule({ root })` gives the procedures of `fsModule`, and each path of each input must be in the root folder. A relative path starts at the root. Without a root, the procedures operate as before.
9
+
10
+ The procedures refuse a path that goes up with `..`, an absolute path outside the root and another drive. They also refuse a symlink or a junction that goes out of the root. The error has the code `FORBIDDEN` and the new reason `outside-root` (the type `ForbiddenReason` of `@procedures/client`). For a path that does not exist, the check uses the real path of the nearest existing folder. `registerFsProcedures(registry, { root })` takes the root too.
11
+
12
+ ### Patch Changes
13
+
14
+ - 3c40d2d: The root of the file procedures accepts a path by its real path. On Windows, a folder can have a short 8.3 name (`RUNNER~1`) and a long real name. A path that used the short name was refused when the root was a link.
15
+ - Updated dependencies [ddea529]
16
+ - Updated dependencies [b2a3e3a]
17
+ - Updated dependencies [a8c47f1]
18
+ - Updated dependencies [381ce3a]
19
+ - Updated dependencies [0c627f8]
20
+ - Updated dependencies [ae7f05f]
21
+ - Updated dependencies [7873940]
22
+ - Updated dependencies [a70d445]
23
+ - Updated dependencies [bc70357]
24
+ - Updated dependencies [07cc998]
25
+ - Updated dependencies [a6b01a9]
26
+ - Updated dependencies [c799cdd]
27
+ - Updated dependencies [540f8d9]
28
+ - Updated dependencies [b6daaec]
29
+ - Updated dependencies [5b9264e]
30
+ - Updated dependencies [956e88b]
31
+ - Updated dependencies [ff62281]
32
+ - Updated dependencies [d81d0ed]
33
+ - Updated dependencies [aa67cc7]
34
+ - Updated dependencies [061fa22]
35
+ - Updated dependencies [cfb9d69]
36
+ - Updated dependencies [43f7de5]
37
+ - Updated dependencies [b07bb50]
38
+ - Updated dependencies [4a3bfa1]
39
+ - Updated dependencies [bd0b626]
40
+ - Updated dependencies [a6be873]
41
+ - Updated dependencies [fb30718]
42
+ - Updated dependencies [c5528e4]
43
+ - Updated dependencies [fee5d9c]
44
+ - Updated dependencies [21f7743]
45
+ - Updated dependencies [31a0b46]
46
+ - @procedures/client@0.3.0
47
+
48
+ ## 0.2.3
49
+
50
+ ### Patch Changes
51
+
52
+ - Updated dependencies [15e48cf]
53
+ - @procedures/client@0.2.3
54
+
3
55
  ## 0.2.2
4
56
 
5
57
  ### Patch Changes
package/README.md CHANGED
@@ -18,7 +18,7 @@ File system operations as RPC procedures. Read, write, copy, move, glob files an
18
18
  - **Zod validation**: Runtime type safety on all inputs
19
19
 
20
20
  The package has 11 procedures. Its register entry (`import "@procedures/fs/register"`) registers them:
21
- `fs.read`, `fs.write`, `fs.exists`, `fs.stat`, `fs.mkdir`, `fs.rm`, `fs.readdir`, `fs.copy`, `fs.move`, `fs.glob`, `fs.read.json`
21
+ `fs.read`, `fs.write`, `fs.exists`, `fs.stat`, `fs.mkdir`, `fs.rm`, `fs.readdir`, `fs.copy`, `fs.move`, `fs.glob`, `fs.read.json`, `fs.write.json`, `fs.hash`, `fs.temp`, `fs.watch`
22
22
 
23
23
  ## Architecture
24
24
 
@@ -102,6 +102,45 @@ Since 0.2.0, an import of the package registers nothing. To register its procedu
102
102
  import "@procedures/fs/register";
103
103
  ```
104
104
 
105
+ ## Confine the paths to a root
106
+
107
+ A host can give the file procedures a root folder. Then each path of each input must be in the root.
108
+
109
+ ```ts
110
+ import { createRegistry } from "@procedures/client";
111
+ import { createFsModule } from "@procedures/fs/module";
112
+ import { bundleDevModule } from "@procedures/bundle-dev/module";
113
+
114
+ // The module with the root comes first: it replaces the fsModule that the bundle requires
115
+ const registry = createRegistry(createFsModule({ root: "/work/project" }), bundleDevModule);
116
+ ```
117
+
118
+ `registerFsProcedures(registry, { root })` registers the procedures with the root in one registry.
119
+
120
+ ### Rules
121
+
122
+ - A relative path starts at the root, not at the working folder of the process.
123
+ - An absolute path in the root is correct.
124
+ - The procedures refuse a path outside the root. The error has the code `FORBIDDEN` and the reason `outside-root`. A server sends the reason in the metadata key `reason`.
125
+ - These paths are outside the root: a path that goes up with `..`, an absolute path in another folder and a path on another drive.
126
+ - The procedures refuse a symlink or a junction that goes out of the root. The check uses the real path of the input (`fs.realpath`).
127
+ - For a path that does not exist, the check uses the real path of the nearest folder above it. Thus a write or `fs.mkdir` cannot go out of the root through a symlinked folder.
128
+ - The check follows a symlink to its target, also when the target does not exist, because a write follows the symlink too.
129
+ - Each path input of each procedure gets the check: `path`, `src`, `dest` and the `cwd` of `fs.glob`.
130
+ - `fs.glob` refuses an absolute pattern, a pattern that starts with a drive and a pattern with a `..` segment. It also removes each match whose real path is outside the root.
131
+ - `fs.readdir` with `includeStats` gives no stats for an entry that goes out of the root.
132
+ - The procedures get the absolute path, so the paths of the output are absolute.
133
+ - On Windows, the check ignores the case of the letters, and `/` and `\` are equal.
134
+ - A relative root starts at the working folder of the process when `createFsModule()` starts.
135
+ - If the root does not exist, each procedure fails with the code `ENOENT`.
136
+ - Without a root, the procedures operate on each path as before. `createFsModule()` gives `fsModule`.
137
+
138
+ ### Limits
139
+
140
+ - The check and the operation are two steps. The check does not see a symlink that a process changes between the two steps.
141
+ - The root applies only to the `fs.*` procedures. A package that uses `node:fs` directly does not get the root. Examples are `git.*` and `lib.*`.
142
+ - The root does not replace the permissions of the operating system.
143
+
105
144
  ## API Reference
106
145
 
107
146
  ### File Operations
@@ -539,6 +578,36 @@ const pkg = result.data as PackageJson;
539
578
  console.log(pkg.name, pkg.version);
540
579
  ```
541
580
 
581
+ #### `fs.write.json`
582
+
583
+ The procedure writes a value as a JSON file, with 2 spaces of indent and a line break at the end. It writes a file next to the target first, then renames it. Thus a reader sees the old file or the whole new file.
584
+
585
+ ```typescript
586
+ await client.exec(["fs", "write.json"], { path: "./data.json", value: { a: 1 }, indent: 2 });
587
+ ```
588
+
589
+ #### `fs.hash`
590
+
591
+ The procedure gives the hash of a file as hexadecimal text: `sha256` (the default), `sha512`, `sha1` or `md5`. It reads the file as a stream.
592
+
593
+ ```typescript
594
+ const { hash, size } = await client.exec(["fs", "hash"], { path: "./archive.tgz" });
595
+ ```
596
+
597
+ #### `fs.temp`
598
+
599
+ The procedure makes a new folder in the temporary folder of the system, and gives its path. With a root, the folder is in the folder `.tmp` of the root. The `prefix` has letters, digits, dots, underscores and hyphens only.
600
+
601
+ #### `fs.watch`
602
+
603
+ The procedure gives the changes of a file or folder as a stream. Each item has the `event` (`rename` or `change`) and the `filename`. The stream has no end: it stops when the reader stops or the call aborts. The platform decides the details, so one change can give two items.
604
+
605
+ ```typescript
606
+ for await (const change of client.execStream(["fs", "watch"], { path: "./src", recursive: true })) {
607
+ console.log(change.event, change.filename);
608
+ }
609
+ ```
610
+
542
611
  ## Usage Examples
543
612
 
544
613
  ### Basic File Operations
@@ -843,6 +912,9 @@ client-fs/
843
912
  │ ├── types.ts # Zod schemas + TypeScript types
844
913
  │ ├── register.ts # Auto-registration
845
914
  │ ├── index.ts # Main entry point
915
+ │ ├── module.ts # fsModule, createFsModule({ root })
916
+ │ ├── root.ts # The check of a path against the root
917
+ │ ├── handlers.ts # The handlers with a root
846
918
  │ ├── procedures/
847
919
  │ │ ├── fs.ts # Barrel export
848
920
  │ │ └── fs/