Skip to content

Commit e86ea07

Browse files
feat(types): add @opentf/esrun-types TypeScript definitions
Hand-written .d.ts for the runtime: standard modules (runtime:process, runtime:path, runtime:fs) in types/, publishable as @opentf/esrun-types. Ambient `declare module` blocks so editors type `import … from "runtime:fs"`; add via tsconfig `types` or a triple-slash reference. Signatures match the implemented surface; validated with `tsc --strict`. CHANGELOG.
1 parent aea2e3c commit e86ea07

7 files changed

Lines changed: 325 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ pre-`0.1.0` and the public API is unstable.
88

99
### Added
1010

11+
- **`@opentf/esrun-types`** — hand-written TypeScript definitions for the
12+
`runtime:` standard modules (`runtime:process`, `runtime:path`, `runtime:fs`),
13+
in [`types/`](types/), for editor completion and type-checking. Ambient
14+
`declare module` blocks; add via `tsconfig` `types` or a triple-slash
15+
reference. Validated with `tsc --strict`.
16+
1117
- **`runtime:fs`** — modern, Blob-based file I/O, the third `runtime:` standard
1218
module (SPEC §11, DECISIONS D25). `file(path)` is a lazy, Blob-like handle
1319
(`text`/`json`/`bytes`/`arrayBuffer`/`stream`/`exists`/`stat`/`write`/`delete`,

types/README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# @opentf/esrun-types
2+
3+
TypeScript type definitions for [ES Runtime](https://es-runtime.opentechf.org)
4+
(`esrun`) — the `runtime:` standard modules, so your editor gives completion and
5+
type-checking for `import … from "runtime:process" | "runtime:path" | "runtime:fs"`.
6+
7+
## Install
8+
9+
```sh
10+
bun add -d @opentf/esrun-types # or: npm i -D @opentf/esrun-types
11+
```
12+
13+
## Use
14+
15+
Add the package to your `tsconfig.json`:
16+
17+
```json
18+
{ "compilerOptions": { "types": ["@opentf/esrun-types"] } }
19+
```
20+
21+
…or reference it from one file:
22+
23+
```ts
24+
/// <reference types="@opentf/esrun-types" />
25+
```
26+
27+
Then the `runtime:` imports are fully typed:
28+
29+
```ts
30+
import { file, write } from "runtime:fs";
31+
32+
const cfg = await file("./config/app.json").json();
33+
await write("./out/result.txt", "done", { append: true });
34+
```
35+
36+
esrun targets the WinterTC web-platform surface, so web globals (`URL`, `Blob`,
37+
`ReadableStream`, `Response`, …) come from your `lib` (`dom` or `webworker`).
38+
39+
## Covered
40+
41+
- `runtime:process``env`, `args`, `platform`, `arch`, `cwd()`, `exit()`
42+
- `runtime:path``join`, `resolve`, `normalize`, `dirname`, `basename`, `extname`, `parse`, `relative`, `isAbsolute`, `sep`, `delimiter`, `fromFileURL`, `toFileURL`
43+
- `runtime:fs``file()`, `write()`, `readDir`, `stat`, `exists`, `mkdir`, `remove`, `rename`, `Glob`

types/index.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Type definitions for ES Runtime (esrun) — the `runtime:` standard modules.
2+
// Ambient `declare module` blocks: include this package and editors resolve
3+
// `import … from "runtime:fs"` (and process/path) with full completion + types.
4+
//
5+
// Setup (tsconfig.json):
6+
// { "compilerOptions": { "types": ["@opentf/esrun-types"] } }
7+
// or a triple-slash reference in one file:
8+
// /// <reference types="@opentf/esrun-types" />
9+
10+
/// <reference path="./runtime-process.d.ts" />
11+
/// <reference path="./runtime-path.d.ts" />
12+
/// <reference path="./runtime-fs.d.ts" />

types/package.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "@opentf/esrun-types",
3+
"version": "0.1.0",
4+
"description": "TypeScript type definitions for ES Runtime (esrun) — the runtime: standard modules (process, path, fs).",
5+
"types": "index.d.ts",
6+
"files": [
7+
"index.d.ts",
8+
"runtime-process.d.ts",
9+
"runtime-path.d.ts",
10+
"runtime-fs.d.ts"
11+
],
12+
"keywords": ["esrun", "es-runtime", "opentf", "types", "runtime"],
13+
"license": "Apache-2.0",
14+
"repository": {
15+
"type": "git",
16+
"url": "https://github.com/Open-Tech-Foundation/ES-Runtime.git",
17+
"directory": "types"
18+
},
19+
"homepage": "https://es-runtime.opentechf.org/api",
20+
"publishConfig": {
21+
"access": "public"
22+
}
23+
}

types/runtime-fs.d.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
declare module "runtime:fs" {
2+
/** A path: a string, a `file:` URL, or a {@link FsFile} handle. */
3+
export type PathLike = string | URL | FsFile;
4+
5+
/** Anything `write` accepts as the body to write. */
6+
export type WriteInput =
7+
| string
8+
| Blob
9+
| ArrayBuffer
10+
| ArrayBufferView
11+
| Response
12+
| ReadableStream<Uint8Array>
13+
| FsFile;
14+
15+
/** File metadata, from {@link stat} / {@link FsFile.stat} (follows symlinks). */
16+
export interface Stat {
17+
/** Size in bytes. */
18+
size: number;
19+
isFile: boolean;
20+
isDir: boolean;
21+
isSymlink: boolean;
22+
/** Modification time in ms since the Unix epoch, or `null` if unavailable. */
23+
mtimeMs: number | null;
24+
}
25+
26+
/** One entry of a directory listing, from {@link readDir}. */
27+
export interface DirEntry {
28+
name: string;
29+
isFile: boolean;
30+
isDir: boolean;
31+
isSymlink: boolean;
32+
}
33+
34+
/** Options for {@link Glob.scan}. */
35+
export interface GlobScanOptions {
36+
/** Directory to scan (default `"."`). */
37+
cwd?: string;
38+
/** Match dotfiles / dot-directories (default `false`). */
39+
dot?: boolean;
40+
/** Yield absolute paths instead of paths relative to `cwd` (default `false`). */
41+
absolute?: boolean;
42+
/** Yield only files, skipping directories (default `true`). */
43+
onlyFiles?: boolean;
44+
}
45+
46+
/**
47+
* A lazy, Blob-like file handle from {@link file}. Nothing is read until a
48+
* read method is called. **All methods are async.**
49+
*/
50+
export interface FsFile {
51+
/** The path this handle points at. */
52+
readonly path: string;
53+
/** Read the whole file as text (UTF-8). */
54+
text(): Promise<string>;
55+
/** Read and `JSON.parse` the file. */
56+
json(): Promise<any>;
57+
/** Read the whole file as bytes. */
58+
bytes(): Promise<Uint8Array>;
59+
/** Read the whole file as an `ArrayBuffer`. */
60+
arrayBuffer(): Promise<ArrayBuffer>;
61+
/** A `ReadableStream` of the file's bytes. */
62+
stream(): ReadableStream<Uint8Array>;
63+
/** Whether the file exists. */
64+
exists(): Promise<boolean>;
65+
/** File metadata (follows symlinks). */
66+
stat(): Promise<Stat>;
67+
/** Write `data` to this file; resolves to bytes written. */
68+
write(data: WriteInput, options?: { append?: boolean }): Promise<number>;
69+
/** Delete this file. */
70+
delete(): Promise<void>;
71+
/**
72+
* A `WritableStream` sink for incremental / piped writes:
73+
* `await readable.pipeTo(file("out").writable())`. The first chunk
74+
* truncates the file; later chunks append.
75+
*/
76+
writable(): WritableStream<Uint8Array>;
77+
}
78+
79+
/**
80+
* Glob matching and scanning. Patterns support `*`, `**`, `?`, `[classes]`,
81+
* and `{a,b}` alternation; `*` does not cross `/`, `**` does.
82+
*/
83+
export class Glob {
84+
constructor(pattern: string);
85+
/** Pure pattern match against a path (synchronous; no I/O). */
86+
match(path: PathLike): boolean;
87+
/** Walk the (jailed) filesystem, yielding matching paths. Needs `FileRead`. */
88+
scan(options?: string | GlobScanOptions): AsyncIterableIterator<string>;
89+
}
90+
91+
/** A lazy, Blob-like handle for `path`. */
92+
export function file(path: PathLike): FsFile;
93+
94+
/** Write any web body to `dest`; resolves to bytes written. Needs `FileWrite`. */
95+
export function write(
96+
dest: PathLike,
97+
input: WriteInput,
98+
options?: { append?: boolean },
99+
): Promise<number>;
100+
101+
/** List the entries of a directory. Needs `FileRead`. */
102+
export function readDir(path: PathLike): Promise<DirEntry[]>;
103+
104+
/** Metadata for `path` (follows symlinks). Needs `FileRead`. */
105+
export function stat(path: PathLike): Promise<Stat>;
106+
107+
/** Whether `path` exists (missing → `false`). Needs `FileRead`. */
108+
export function exists(path: PathLike): Promise<boolean>;
109+
110+
/** Create a directory (`recursive` creates parents). Needs `FileWrite`. */
111+
export function mkdir(path: PathLike, options?: { recursive?: boolean }): Promise<void>;
112+
113+
/** Remove a file or (with `recursive`) a directory tree. Needs `FileWrite`. */
114+
export function remove(path: PathLike, options?: { recursive?: boolean }): Promise<void>;
115+
116+
/** Rename/move an entry (both jailed). Needs `FileWrite`. */
117+
export function rename(from: PathLike, to: PathLike): Promise<void>;
118+
119+
const fs: {
120+
file: typeof file;
121+
write: typeof write;
122+
readDir: typeof readDir;
123+
stat: typeof stat;
124+
exists: typeof exists;
125+
mkdir: typeof mkdir;
126+
remove: typeof remove;
127+
rename: typeof rename;
128+
Glob: typeof Glob;
129+
};
130+
export default fs;
131+
}

types/runtime-path.d.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
declare module "runtime:path" {
2+
/** The parsed shape of a path, from {@link parse}. */
3+
export interface ParsedPath {
4+
/** The root of the path (`"/"`, `"C:\\"`, or `""`). */
5+
root: string;
6+
/** The directory portion. */
7+
dir: string;
8+
/** The final segment, including any extension. */
9+
base: string;
10+
/** The final segment without its extension. */
11+
name: string;
12+
/** The extension, including the leading dot (or `""`). */
13+
ext: string;
14+
}
15+
16+
/** Path segment separator for the host OS (`"/"` or `"\\"`). */
17+
export const sep: string;
18+
19+
/** Path list delimiter for the host OS (`":"` or `";"`). */
20+
export const delimiter: string;
21+
22+
/** Whether `p` is an absolute path. */
23+
export function isAbsolute(p: string): boolean;
24+
25+
/** Collapses `.`/`..` and redundant separators. */
26+
export function normalize(p: string): string;
27+
28+
/** Joins segments with the separator, then normalizes. */
29+
export function join(...segments: string[]): string;
30+
31+
/** Resolves to an absolute path, anchoring at `cwd()` if no segment is absolute. */
32+
export function resolve(...segments: string[]): string;
33+
34+
/** The directory portion of `p`. */
35+
export function dirname(p: string): string;
36+
37+
/** The final segment of `p`. */
38+
export function basename(p: string): string;
39+
40+
/** The extension of the final segment, including the dot (or `""`). */
41+
export function extname(p: string): string;
42+
43+
/** Splits `p` into `{ root, dir, base, name, ext }`. */
44+
export function parse(p: string): ParsedPath;
45+
46+
/** Relative path from `from` to `to` (both resolved first). */
47+
export function relative(from: string, to: string): string;
48+
49+
/** Converts a `file:` URL to a path. */
50+
export function fromFileURL(url: string | URL): string;
51+
52+
/** Converts a path (resolved to absolute) to a `file:` URL. */
53+
export function toFileURL(p: string): URL;
54+
55+
const path: {
56+
sep: typeof sep;
57+
delimiter: typeof delimiter;
58+
isAbsolute: typeof isAbsolute;
59+
normalize: typeof normalize;
60+
join: typeof join;
61+
resolve: typeof resolve;
62+
dirname: typeof dirname;
63+
basename: typeof basename;
64+
extname: typeof extname;
65+
parse: typeof parse;
66+
relative: typeof relative;
67+
fromFileURL: typeof fromFileURL;
68+
toFileURL: typeof toFileURL;
69+
};
70+
export default path;
71+
}

types/runtime-process.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
declare module "runtime:process" {
2+
/**
3+
* Environment variables as a mutable in-process object, seeded from a host
4+
* snapshot taken when the module is evaluated. Reads, writes, and deletes work
5+
* in-process; they do not propagate to the host process or to child processes.
6+
*/
7+
export const env: Record<string, string>;
8+
9+
/**
10+
* Program arguments after the runtime binary and the script (or `-e` snippet).
11+
* Frozen; excludes the executable and script path.
12+
*/
13+
export const args: readonly string[];
14+
15+
/** Host operating system — the OS-native value (`"linux"`, `"macos"`, `"windows"`, …). */
16+
export const platform: string;
17+
18+
/** Host CPU architecture — the OS-native value (`"x86_64"`, `"aarch64"`, `"arm"`, …). */
19+
export const arch: string;
20+
21+
/** The current working directory (a function — it can change during a run). */
22+
export function cwd(): string;
23+
24+
/**
25+
* Records the exit code and halts execution immediately — code after the call
26+
* does not run.
27+
*/
28+
export function exit(code?: number): never;
29+
30+
const process: {
31+
env: typeof env;
32+
args: typeof args;
33+
platform: typeof platform;
34+
arch: typeof arch;
35+
cwd: typeof cwd;
36+
exit: typeof exit;
37+
};
38+
export default process;
39+
}

0 commit comments

Comments
 (0)