mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 17:02:17 +00:00
Adds fs.write-file / fs.write-bytes behind a new fs.write:<path> capability (high risk; resolved to the real path, a missing file through its real directory, so a link cannot reach outside the grant; writing doesn't imply reading), and workspace.project.write-file(path, text) behind project.write (medium risk; stays inside the root and creates missing directories). Writes go through the editor's save path: atomic, keeping the file's encoding and BOM (new files are UTF-8), capped at 16 MiB, and refused while an editor holds unsaved changes for the file. Both capabilities need engines.openidea ^1.3. Tested through the real component (misbehave fixture) and the SDK mock. Closes #1823 Closes #1824 Co-authored-by: chaoes <[email protected]>
50 lines
2.2 KiB
Plaintext
50 lines
2.2 KiB
Plaintext
package openidea:[email protected];
|
|
|
|
/// Files outside the open projects: the configuration of the program a
|
|
/// plugin integrates with, a tool installed elsewhere, a licence file.
|
|
///
|
|
/// A plugin's own WASI has no preopened directory, so every path here is
|
|
/// checked against its `fs.read:<path>` (reading) or `fs.write:<path>`
|
|
/// (writing; it doesn't imply reading) grants; without one covering the path a
|
|
/// call returns `denied` naming the capability the manifest has to declare. A
|
|
/// file inside a project is `workspace.project.read-file` / `write-file`.
|
|
/// `path` is absolute, or starts with `~/` for the user's home.
|
|
interface fs {
|
|
use types.{error};
|
|
use workspace.{file-kind, file-stat};
|
|
|
|
/// A text file, decoded as the editor decodes it (BOM and encoding
|
|
/// detection), at most 16 MiB. Unsaved editor contents win, as they do
|
|
/// for `project.read-file`.
|
|
read-file: func(path: string) -> result<string, error>;
|
|
|
|
/// The bytes of a file (images, class files, archives), at most 16 MiB.
|
|
read-bytes: func(path: string) -> result<list<u8>, error>;
|
|
|
|
/// Metadata of an existing path, as `project.stat` reports it; a missing
|
|
/// path is `not-found`.
|
|
stat: func(path: string) -> result<file-stat, error>;
|
|
|
|
/// An entry of a directory.
|
|
record dir-entry {
|
|
/// The entry's name, without its directory.
|
|
name: string,
|
|
kind: file-kind,
|
|
}
|
|
|
|
/// The entries directly under a directory, sorted by name, at most 4096
|
|
/// (like `find-files`); a file is `invalid`.
|
|
read-dir: func(path: string) -> result<list<dir-entry>, error>;
|
|
|
|
/// Replaces the text of a file, or creates it, at most 16 MiB: in one step
|
|
/// (a reader never sees half of it), keeping the file's encoding and BOM;
|
|
/// a new file is UTF-8. `invalid` when the text can't be written in that
|
|
/// encoding, the directory is missing, the path is a directory, or an
|
|
/// editor holds unsaved changes for the file (save them first).
|
|
write-file: func(path: string, text: string) -> result<_, error>;
|
|
|
|
/// Replaces the bytes of a file, or creates it, at most 16 MiB, in one
|
|
/// step; fails like `write-file`.
|
|
write-bytes: func(path: string, bytes: list<u8>) -> result<_, error>;
|
|
}
|