@poe-platform/safe-fs 0.1.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 (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +290 -0
  3. package/dist/safe-fs/bridge/confinement.d.ts +3 -0
  4. package/dist/safe-fs/bridge/confinement.js +171 -0
  5. package/dist/safe-fs/bridge/filesystem.d.ts +88 -0
  6. package/dist/safe-fs/bridge/filesystem.js +411 -0
  7. package/dist/safe-fs/bridge/index.d.ts +6 -0
  8. package/dist/safe-fs/bridge/index.js +18 -0
  9. package/dist/safe-fs/bridge/stats.d.ts +4 -0
  10. package/dist/safe-fs/bridge/stats.js +37 -0
  11. package/dist/safe-fs/bridge/types.d.ts +75 -0
  12. package/dist/safe-fs/bridge/types.js +1 -0
  13. package/dist/safe-fs/bridge/values.d.ts +6 -0
  14. package/dist/safe-fs/bridge/values.js +65 -0
  15. package/dist/safe-fs/config/memory.d.ts +3 -0
  16. package/dist/safe-fs/config/memory.js +9 -0
  17. package/dist/safe-fs/config/real.d.ts +5 -0
  18. package/dist/safe-fs/config/real.js +16 -0
  19. package/dist/safe-fs/config.d.ts +15 -0
  20. package/dist/safe-fs/config.js +46 -0
  21. package/dist/safe-fs/config.node.d.ts +2 -0
  22. package/dist/safe-fs/config.node.js +22 -0
  23. package/dist/safe-fs/contracts/abort.d.ts +5 -0
  24. package/dist/safe-fs/contracts/abort.js +34 -0
  25. package/dist/safe-fs/contracts/cleanup.d.ts +1 -0
  26. package/dist/safe-fs/contracts/cleanup.js +9 -0
  27. package/dist/safe-fs/contracts/errors.d.ts +50 -0
  28. package/dist/safe-fs/contracts/errors.js +77 -0
  29. package/dist/safe-fs/contracts/filesystem.d.ts +96 -0
  30. package/dist/safe-fs/contracts/filesystem.js +1 -0
  31. package/dist/safe-fs/contracts/index.d.ts +4 -0
  32. package/dist/safe-fs/contracts/index.js +4 -0
  33. package/dist/safe-fs/contracts/io.d.ts +8 -0
  34. package/dist/safe-fs/contracts/io.js +92 -0
  35. package/dist/safe-fs/contracts/path.d.ts +8 -0
  36. package/dist/safe-fs/contracts/path.js +8 -0
  37. package/dist/safe-fs/contracts/portable-path.d.ts +13 -0
  38. package/dist/safe-fs/contracts/portable-path.js +57 -0
  39. package/dist/safe-fs/contracts/virtual-path.d.ts +7 -0
  40. package/dist/safe-fs/contracts/virtual-path.js +66 -0
  41. package/dist/safe-fs/core.d.ts +12 -0
  42. package/dist/safe-fs/core.js +12 -0
  43. package/dist/safe-fs/fs/memory/index.d.ts +58 -0
  44. package/dist/safe-fs/fs/memory/index.js +532 -0
  45. package/dist/safe-fs/fs/mount/comparison.d.ts +19 -0
  46. package/dist/safe-fs/fs/mount/comparison.js +118 -0
  47. package/dist/safe-fs/fs/mount/identity.d.ts +2 -0
  48. package/dist/safe-fs/fs/mount/identity.js +12 -0
  49. package/dist/safe-fs/fs/mount/index.d.ts +44 -0
  50. package/dist/safe-fs/fs/mount/index.js +546 -0
  51. package/dist/safe-fs/fs/overlay/index.d.ts +73 -0
  52. package/dist/safe-fs/fs/overlay/index.js +927 -0
  53. package/dist/safe-fs/fs/readonly/index.d.ts +31 -0
  54. package/dist/safe-fs/fs/readonly/index.js +128 -0
  55. package/dist/safe-fs/fs/real/allocation.d.ts +1 -0
  56. package/dist/safe-fs/fs/real/allocation.js +8 -0
  57. package/dist/safe-fs/fs/real/index.d.ts +76 -0
  58. package/dist/safe-fs/fs/real/index.js +543 -0
  59. package/dist/safe-fs/fs/s3/authority.d.ts +7 -0
  60. package/dist/safe-fs/fs/s3/authority.js +31 -0
  61. package/dist/safe-fs/fs/s3/filesystem.d.ts +93 -0
  62. package/dist/safe-fs/fs/s3/filesystem.js +1024 -0
  63. package/dist/safe-fs/fs/s3/http/index.d.ts +2 -0
  64. package/dist/safe-fs/fs/s3/http/index.js +1 -0
  65. package/dist/safe-fs/fs/s3/http/request.d.ts +16 -0
  66. package/dist/safe-fs/fs/s3/http/request.js +196 -0
  67. package/dist/safe-fs/fs/s3/http/signature.d.ts +20 -0
  68. package/dist/safe-fs/fs/s3/http/signature.js +74 -0
  69. package/dist/safe-fs/fs/s3/http/transport.d.ts +3 -0
  70. package/dist/safe-fs/fs/s3/http/transport.js +455 -0
  71. package/dist/safe-fs/fs/s3/http/types.d.ts +30 -0
  72. package/dist/safe-fs/fs/s3/http/types.js +1 -0
  73. package/dist/safe-fs/fs/s3/http/xml.d.ts +11 -0
  74. package/dist/safe-fs/fs/s3/http/xml.js +188 -0
  75. package/dist/safe-fs/fs/s3/index.d.ts +6 -0
  76. package/dist/safe-fs/fs/s3/index.js +3 -0
  77. package/dist/safe-fs/fs/s3/mock.d.ts +48 -0
  78. package/dist/safe-fs/fs/s3/mock.js +233 -0
  79. package/dist/safe-fs/fs/s3/registry.d.ts +10 -0
  80. package/dist/safe-fs/fs/s3/registry.js +71 -0
  81. package/dist/safe-fs/fs/s3/transport.d.ts +103 -0
  82. package/dist/safe-fs/fs/s3/transport.js +28 -0
  83. package/dist/safe-fs/fs/webdav/index.d.ts +2 -0
  84. package/dist/safe-fs/fs/webdav/index.js +1 -0
  85. package/dist/safe-fs/fs/webdav/resource-id.d.ts +18 -0
  86. package/dist/safe-fs/fs/webdav/resource-id.js +109 -0
  87. package/dist/safe-fs/fs/webdav/webdav.d.ts +101 -0
  88. package/dist/safe-fs/fs/webdav/webdav.js +1226 -0
  89. package/dist/safe-fs/fs/webdav/xml.d.ts +15 -0
  90. package/dist/safe-fs/fs/webdav/xml.js +250 -0
  91. package/dist/safe-fs/index.d.ts +14 -0
  92. package/dist/safe-fs/index.js +12 -0
  93. package/dist/safe-fs/node/filesystem.d.ts +11 -0
  94. package/dist/safe-fs/node/filesystem.js +28 -0
  95. package/dist/safe-fs/node/index.d.ts +2 -0
  96. package/dist/safe-fs/node/index.js +1 -0
  97. package/dist/safe-fs/node/stats.d.ts +1 -0
  98. package/dist/safe-fs/node/stats.js +1 -0
  99. package/dist/safe-fs/node/values.d.ts +1 -0
  100. package/dist/safe-fs/node/values.js +1 -0
  101. package/dist/safe-fs/node-host.d.ts +1 -0
  102. package/dist/safe-fs/node-host.js +1 -0
  103. package/dist/safe-fs/node-unavailable.d.ts +1 -0
  104. package/dist/safe-fs/node-unavailable.js +1 -0
  105. package/dist/safe-fs/platform/browser.d.ts +12 -0
  106. package/dist/safe-fs/platform/browser.js +39 -0
  107. package/dist/safe-fs/platform/node.d.ts +13 -0
  108. package/dist/safe-fs/platform/node.js +26 -0
  109. package/package.json +108 -0
@@ -0,0 +1,31 @@
1
+ import type { ByteSource } from "../../contracts/io.js";
2
+ import type { AppendFileOptions, CopyFileOptions, DirectoryEntry, FileStat, FileSystem, FileSystemCapabilities, FsOptions, MkdirOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions } from "../../contracts/filesystem.js";
3
+ export declare class ReadOnlyFileSystem implements FileSystem {
4
+ #private;
5
+ constructor(filesystem: FileSystem);
6
+ get capabilities(): FileSystemCapabilities;
7
+ readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;
8
+ stat(path: string, options?: FsOptions): Promise<FileStat>;
9
+ lstat(path: string, options?: FsOptions): Promise<FileStat>;
10
+ compareEntry(path: string, peer: FileSystem, peerPath: string, options?: FsOptions): Promise<import("../../contracts/filesystem.js").EntryComparison>;
11
+ readdir(path: string, options?: FsOptions): Promise<DirectoryEntry[]>;
12
+ realpath(path: string, options?: FsOptions): Promise<string>;
13
+ access(path: string, mode?: number, options?: FsOptions): Promise<void>;
14
+ readlink(path: string, options?: FsOptions): Promise<string>;
15
+ readStream(path: string, options?: ReadStreamOptions): ByteSource;
16
+ writeFile(path: string, _data: Uint8Array, _options?: WriteFileOptions): Promise<void>;
17
+ appendFile(path: string, _data: Uint8Array, _options?: AppendFileOptions): Promise<void>;
18
+ writeStream(path: string, _source: ByteSource, _options?: WriteFileOptions): Promise<void>;
19
+ mkdir(path: string, _options?: MkdirOptions): Promise<void>;
20
+ rm(path: string, _options?: RemoveOptions): Promise<void>;
21
+ unlink(path: string, _options?: FsOptions): Promise<void>;
22
+ rmdir(path: string, _options?: FsOptions): Promise<void>;
23
+ rename(source: string, destination: string, _options?: FsOptions): Promise<void>;
24
+ copyFile(source: string, destination: string, _options?: CopyFileOptions): Promise<void>;
25
+ symlink(target: string, path: string, _options?: FsOptions): Promise<void>;
26
+ link(existingPath: string, newPath: string, _options?: FsOptions): Promise<void>;
27
+ chmod(path: string, _mode: number, _options?: FsOptions): Promise<void>;
28
+ utimes(path: string, _atimeMs: number, _mtimeMs: number, _options?: FsOptions): Promise<void>;
29
+ truncate(path: string, _length?: number, _options?: FsOptions): Promise<void>;
30
+ }
31
+ export declare function createReadOnlyFileSystem(filesystem: FileSystem): ReadOnlyFileSystem;
@@ -0,0 +1,128 @@
1
+ import { ACCESS_MODES } from "../../contracts/filesystem.js";
2
+ import { FsError } from "../../contracts/errors.js";
3
+ import { readBytes } from "../../contracts/io.js";
4
+ import { compareEntries, registerEntryView } from "../mount/comparison.js";
5
+ function readOnly(syscall, path, dest) {
6
+ throw new FsError("EROFS", { syscall, path, ...(dest === undefined ? {} : { dest }) });
7
+ }
8
+ function snapshotStat(stat) {
9
+ const { type, size, allocatedBytes, mode, mtimeMs, atimeMs, ctimeMs, birthtimeMs, identityScope, ino, dev, nlink, uid, gid } = stat;
10
+ return {
11
+ type, size, mode, mtimeMs, atimeMs, ctimeMs,
12
+ ...(allocatedBytes === undefined ? {} : { allocatedBytes }),
13
+ ...(birthtimeMs === undefined ? {} : { birthtimeMs }),
14
+ ...(identityScope === undefined ? {} : { identityScope }),
15
+ ...(ino === undefined ? {} : { ino }),
16
+ ...(dev === undefined ? {} : { dev }),
17
+ ...(nlink === undefined ? {} : { nlink }),
18
+ ...(uid === undefined ? {} : { uid }),
19
+ ...(gid === undefined ? {} : { gid }),
20
+ };
21
+ }
22
+ export class ReadOnlyFileSystem {
23
+ #filesystem;
24
+ #capabilities;
25
+ constructor(filesystem) {
26
+ this.#filesystem = filesystem;
27
+ registerEntryView(this, async (path) => ({ filesystem: this.#filesystem, path, readOnly: true }));
28
+ const streamingRead = typeof filesystem.readStream === "function" ? filesystem.capabilities.streamingRead : false;
29
+ this.#capabilities = Object.freeze({
30
+ readOnly: true,
31
+ symlinks: filesystem.capabilities.symlinks === true && typeof filesystem.readlink === "function",
32
+ hardlinks: false,
33
+ permissions: false,
34
+ timestamps: false,
35
+ atomicRename: false,
36
+ ...(streamingRead === undefined ? {} : { streamingRead }),
37
+ streamingWrite: false,
38
+ });
39
+ }
40
+ get capabilities() {
41
+ return this.#capabilities;
42
+ }
43
+ async readFile(path, options) {
44
+ return new Uint8Array(await this.#filesystem.readFile(path, options));
45
+ }
46
+ async stat(path, options) {
47
+ return snapshotStat(await this.#filesystem.stat(path, options));
48
+ }
49
+ async lstat(path, options) {
50
+ return snapshotStat(await this.#filesystem.lstat(path, options));
51
+ }
52
+ compareEntry(path, peer, peerPath, options = {}) {
53
+ return compareEntries(this, path, peer, peerPath, options);
54
+ }
55
+ async readdir(path, options) {
56
+ return (await this.#filesystem.readdir(path, options)).map((entry) => ({ name: entry.name, type: entry.type }));
57
+ }
58
+ async realpath(path, options) {
59
+ return this.#filesystem.realpath(path, options);
60
+ }
61
+ async access(path, mode = ACCESS_MODES.F_OK, options) {
62
+ if (!Number.isInteger(mode) || mode < 0 || mode > 7) {
63
+ throw new FsError("EINVAL", { syscall: "access", path });
64
+ }
65
+ if ((mode & ACCESS_MODES.W_OK) !== 0)
66
+ readOnly("access", path);
67
+ return this.#filesystem.access(path, mode, options);
68
+ }
69
+ async readlink(path, options) {
70
+ if (typeof this.#filesystem.readlink !== "function") {
71
+ throw new FsError("ENOTSUP", { syscall: "readlink", path });
72
+ }
73
+ return this.#filesystem.readlink(path, options);
74
+ }
75
+ async *readStream(path, options) {
76
+ if (typeof this.#filesystem.readStream !== "function") {
77
+ throw new FsError("ENOTSUP", { syscall: "readStream", path });
78
+ }
79
+ for await (const chunk of readBytes(this.#filesystem.readStream(path, options), options?.signal)) {
80
+ yield new Uint8Array(chunk);
81
+ }
82
+ }
83
+ async writeFile(path, _data, _options) {
84
+ readOnly("writeFile", path);
85
+ }
86
+ async appendFile(path, _data, _options) {
87
+ readOnly("appendFile", path);
88
+ }
89
+ async writeStream(path, _source, _options) {
90
+ readOnly("writeStream", path);
91
+ }
92
+ async mkdir(path, _options) {
93
+ readOnly("mkdir", path);
94
+ }
95
+ async rm(path, _options) {
96
+ readOnly("rm", path);
97
+ }
98
+ async unlink(path, _options) {
99
+ readOnly("unlink", path);
100
+ }
101
+ async rmdir(path, _options) {
102
+ readOnly("rmdir", path);
103
+ }
104
+ async rename(source, destination, _options) {
105
+ readOnly("rename", source, destination);
106
+ }
107
+ async copyFile(source, destination, _options) {
108
+ readOnly("copyFile", source, destination);
109
+ }
110
+ async symlink(target, path, _options) {
111
+ readOnly("symlink", target, path);
112
+ }
113
+ async link(existingPath, newPath, _options) {
114
+ readOnly("link", existingPath, newPath);
115
+ }
116
+ async chmod(path, _mode, _options) {
117
+ readOnly("chmod", path);
118
+ }
119
+ async utimes(path, _atimeMs, _mtimeMs, _options) {
120
+ readOnly("utimes", path);
121
+ }
122
+ async truncate(path, _length, _options) {
123
+ readOnly("truncate", path);
124
+ }
125
+ }
126
+ export function createReadOnlyFileSystem(filesystem) {
127
+ return new ReadOnlyFileSystem(filesystem);
128
+ }
@@ -0,0 +1 @@
1
+ export declare function nativeAllocatedBytes(blocks: unknown, platform: string): number | undefined;
@@ -0,0 +1,8 @@
1
+ export function nativeAllocatedBytes(blocks, platform) {
2
+ if (platform !== "darwin" && platform !== "linux")
3
+ return undefined;
4
+ if (typeof blocks !== "number" || !Number.isSafeInteger(blocks) || blocks < 0)
5
+ return undefined;
6
+ const bytes = blocks * 512;
7
+ return Number.isSafeInteger(bytes) ? bytes : undefined;
8
+ }
@@ -0,0 +1,76 @@
1
+ import type { AppendFileOptions, ByteSource, CopyFileOptions, DirectoryEntry, FileStat, FileSystem, FileSystemCapabilities, FsOptions, MkdirOptions, ReadFileOptions, ReadStreamOptions, RemoveOptions, WriteFileOptions } from "../../contracts/index.js";
2
+ export interface RealFileSystemOptions {
3
+ /** An existing, absolute host directory. It is never created implicitly. */
4
+ readonly root: string;
5
+ }
6
+ /**
7
+ * Async byte filesystem for trusted POSIX hosts (Windows is unsupported).
8
+ * Both relative and absolute input paths are virtual POSIX paths rooted at `/`;
9
+ * components resolve in order, following symlinks before subsequent `..` and
10
+ * preserving trailing directory requirements. Empty paths are ENOENT. Excess
11
+ * input `..` clamps at the virtual root; symlink targets may never cross it.
12
+ * There is no process cwd dependency. The configured host root must already
13
+ * exist; its canonical location is pinned on first use or by the async factory.
14
+ *
15
+ * Absolute symlink targets created here are virtual paths, stored as rooted
16
+ * host targets without lexical normalization. Relative targets retain their
17
+ * text; safe dangling, non-directory, and looping targets may be created.
18
+ * Existing host symlinks are
19
+ * followed only when every traversed component remains beneath the root, with
20
+ * a 40-link traversal limit. Existing absolute host targets must start with the
21
+ * canonical root, not a different host alias of that root. lstat, removal, and
22
+ * rename inspect or modify a final symlink itself rather than its target. Absolute readlink results are
23
+ * translated back into virtual paths; external absolute targets are refused.
24
+ *
25
+ * SECURITY LIMIT: containment checks and subsequent Node path operations are
26
+ * not atomic. O_NOFOLLOW narrows final-file open races, but ancestor swaps,
27
+ * concurrent renames, mount changes, and preexisting hardlinks cannot be made
28
+ * safe by these APIs. This is NOT a race-proof sandbox or an isolation boundary
29
+ * against another process modifying the tree. Use an OS sandbox for that.
30
+ *
31
+ * Only regular files, directories, and symlinks are represented. Permissions,
32
+ * ownership, timestamp precision, case sensitivity, umask, and rename behavior
33
+ * are those of the host filesystem. Copy is not atomic; rename can fail EXDEV.
34
+ * Cancellation is cooperative between operations/chunks, not rollback: failed
35
+ * or canceled writes/copies may leave partial data. No native commands execute.
36
+ * Destructive rm/rename operands ending in `.` or `..` are refused with EINVAL,
37
+ * including native recursive-rm edge cases that could otherwise delete content.
38
+ * Public filesystem errors carry only virtual operands; native causes are
39
+ * intentionally omitted so host paths cannot escape through nested errors.
40
+ */
41
+ export declare class RealFileSystem implements FileSystem {
42
+ readonly capabilities: FileSystemCapabilities;
43
+ private readonly configuredRoot;
44
+ private rootPromise;
45
+ constructor(options: RealFileSystemOptions | string);
46
+ private root;
47
+ private absoluteTarget;
48
+ private walk;
49
+ private path;
50
+ private operation;
51
+ private protectRoot;
52
+ private protectTerminal;
53
+ readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;
54
+ writeFile(path: string, data: Uint8Array, options?: WriteFileOptions): Promise<void>;
55
+ appendFile(path: string, data: Uint8Array, options?: AppendFileOptions): Promise<void>;
56
+ stat(path: string, options?: FsOptions): Promise<FileStat>;
57
+ lstat(path: string, options?: FsOptions): Promise<FileStat>;
58
+ readdir(path: string, options?: FsOptions): Promise<DirectoryEntry[]>;
59
+ mkdir(path: string, options?: MkdirOptions): Promise<void>;
60
+ rmdir(path: string, options?: FsOptions): Promise<void>;
61
+ rm(path: string, options?: RemoveOptions): Promise<void>;
62
+ rename(source: string, destination: string, options?: FsOptions): Promise<void>;
63
+ copyFile(source: string, destination: string, options?: CopyFileOptions): Promise<void>;
64
+ realpath(path: string, options?: FsOptions): Promise<string>;
65
+ access(path: string, mode?: number, options?: FsOptions): Promise<void>;
66
+ readlink(path: string, options?: FsOptions): Promise<string>;
67
+ symlink(target: string, path: string, options?: FsOptions): Promise<void>;
68
+ link(existingPath: string, newPath: string, options?: FsOptions): Promise<void>;
69
+ chmod(path: string, mode: number, options?: FsOptions): Promise<void>;
70
+ utimes(path: string, atimeMs: number, mtimeMs: number, options?: FsOptions): Promise<void>;
71
+ truncate(path: string, length?: number, options?: FsOptions): Promise<void>;
72
+ readStream(path: string, options?: ReadStreamOptions): ByteSource;
73
+ writeStream(path: string, source: ByteSource, options?: WriteFileOptions): Promise<void>;
74
+ }
75
+ /** Construct and validate an existing root before returning the backend. */
76
+ export declare function createRealFileSystem(options: RealFileSystemOptions | string): Promise<RealFileSystem>;