Skip to content

Commit e4e8b2c

Browse files
committed
feat(durable-effects): implement stat method on nodeRuntime
Adds the stat(path) implementation using @effectionx/fs, matching the interface added to DurableRuntime. Re-exports StatResult from durable-effects/runtime.ts and mod.ts. Adds throwing stub and 3 tests covering file, directory, and missing path cases.
1 parent 7d26a69 commit e4e8b2c

5 files changed

Lines changed: 51 additions & 0 deletions

File tree

durable-effects/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type {
1616
DurableRuntime,
1717
ResponseHeaders,
1818
RuntimeFetchResponse,
19+
StatResult,
1920
} from "./runtime.ts";
2021

2122
// ---------------------------------------------------------------------------

durable-effects/node-runtime.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,35 @@ describe("nodeRuntime", () => {
6767
});
6868
});
6969

70+
describe("stat", () => {
71+
it("returns exists and isFile for an existing file", function* () {
72+
const result = yield* runtime.stat("durable-effects/package.json");
73+
expect(result).toEqual({
74+
exists: true,
75+
isFile: true,
76+
isDirectory: false,
77+
});
78+
});
79+
80+
it("returns exists and isDirectory for an existing directory", function* () {
81+
const result = yield* runtime.stat("durable-effects");
82+
expect(result).toEqual({
83+
exists: true,
84+
isFile: false,
85+
isDirectory: true,
86+
});
87+
});
88+
89+
it("returns all false for a missing path", function* () {
90+
const result = yield* runtime.stat("nonexistent-path.txt");
91+
expect(result).toEqual({
92+
exists: false,
93+
isFile: false,
94+
isDirectory: false,
95+
});
96+
});
97+
});
98+
7099
describe("glob", () => {
71100
it("finds files matching a pattern", function* () {
72101
const results = yield* runtime.glob({

durable-effects/node-runtime.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { relative, sep } from "node:path";
1414
import { fetch as effectionFetch } from "@effectionx/fetch";
1515
import {
1616
readTextFile as fsReadTextFile,
17+
stat as fsStat,
1718
globToRegExp,
1819
walk,
1920
} from "@effectionx/fs";
@@ -62,6 +63,22 @@ export function nodeRuntime(): DurableRuntime {
6263
return yield* fsReadTextFile(path);
6364
},
6465

66+
*stat(path) {
67+
try {
68+
const s = yield* fsStat(path);
69+
return {
70+
exists: true,
71+
isFile: s.isFile(),
72+
isDirectory: s.isDirectory(),
73+
};
74+
} catch (err: unknown) {
75+
if ((err as NodeJS.ErrnoException).code === "ENOENT") {
76+
return { exists: false, isFile: false, isDirectory: false };
77+
}
78+
throw err;
79+
}
80+
},
81+
6582
*glob(options) {
6683
const { patterns, root, exclude = [] } = options;
6784
const results: Array<{ path: string; isFile: boolean }> = [];

durable-effects/runtime.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ export type {
1111
DurableRuntime,
1212
ResponseHeaders,
1313
RuntimeFetchResponse,
14+
StatResult,
1415
} from "@effectionx/durable-streams";

durable-effects/stub-runtime.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ export function stubRuntime(
3333
*readTextFile() {
3434
throw new Error("readTextFile not stubbed");
3535
},
36+
*stat() {
37+
throw new Error("stat not stubbed");
38+
},
3639
*glob() {
3740
throw new Error("glob not stubbed");
3841
},

0 commit comments

Comments
 (0)