@executablemd/runtime 0.9.1 → 0.10.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.
package/esm/apis.js CHANGED
@@ -355,6 +355,18 @@ export const API = {
355
355
  throw err;
356
356
  }
357
357
  },
358
+ *readDirectory(path) {
359
+ const entries = [];
360
+ for (const entry of yield* FsApi.operations.readdirDirents(path)) {
361
+ entries.push({
362
+ name: entry.name,
363
+ isFile: entry.isFile(),
364
+ isDirectory: entry.isDirectory(),
365
+ isSymbolicLink: entry.isSymbolicLink(),
366
+ });
367
+ }
368
+ return entries;
369
+ },
358
370
  *glob(options) {
359
371
  const { patterns, root, exclude = [] } = options;
360
372
  const matched = [];
@@ -477,6 +489,7 @@ export function exec(options) {
477
489
  export const readTextFile = API.Fs.operations.readTextFile;
478
490
  export const stat = API.Fs.operations.stat;
479
491
  export const lstat = API.Fs.operations.lstat;
492
+ export const readDirectory = API.Fs.operations.readDirectory;
480
493
  export const glob = API.Fs.operations.glob;
481
494
  export const writeTextFile = API.Fs.operations.writeTextFile;
482
495
  export const ensureDir = API.Fs.operations.ensureDir;
package/esm/mod.js CHANGED
@@ -8,7 +8,8 @@
8
8
  * Seven domain APIs:
9
9
  * - `API.Process` — subprocess execution (`exec`)
10
10
  * - `API.Fs` — the low-level host filesystem (`readTextFile`, `writeTextFile`,
11
- * `stat`, `lstat`, `glob`, `realpath`, `ensureDir`, `rename`, `remove`)
11
+ * `stat`, `lstat`, `readDirectory`, `glob`, `realpath`, `ensureDir`, `rename`,
12
+ * `remove`)
12
13
  * - `API.Files` — document filesystem access as whole semantic operations,
13
14
  * with no host default. `useHostFiles()` installs the host provider.
14
15
  * - `API.Fetch` — HTTP requests (`fetch`)
@@ -25,7 +26,7 @@
25
26
  */
26
27
  import "./_dnt.polyfills.js";
27
28
  export { API } from "./apis.js";
28
- export { exec, readTextFile, writeTextFile, stat, lstat, glob, realpath, ensureDir, rename, remove, fetch, cwd, env, platform, command, compile, useQuietProcessOutput, } from "./apis.js";
29
+ export { exec, readTextFile, writeTextFile, stat, lstat, readDirectory, glob, realpath, ensureDir, rename, remove, fetch, cwd, env, platform, command, compile, useQuietProcessOutput, } from "./apis.js";
29
30
  export { Service, SERVICE_HOSTNAME, SERVICE_READY_PREFIX, ServiceProcessExitBeforeReadyError, ServiceProtocolDuplicateError, ServiceProtocolHostnameMismatchError, ServiceProtocolIncompatibleError, ServiceProtocolMalformedError, ServiceProtocolTokenMismatchError, ServiceProviderError, ServiceStartupTimeoutError, ServiceTeardownError, ServiceUnexpectedExitError, parseServiceReadyRecord, startService, } from "./service.js";
30
31
  export { Config, timeout, timeoutExec, timeoutFetch } from "./config.js";
31
32
  export { asDuration, durationError, parseDuration } from "./duration.js";
package/esm/test/stubs.js CHANGED
@@ -45,7 +45,10 @@ export function* useStubService(endpoint) {
45
45
  * - `stat` returns `{ exists: true, isFile: true }` for keys in the map.
46
46
  * - `lstat` answers the same, with `isSymbolicLink: false`: an in-memory map
47
47
  * holds file content, so nothing in it is a link to somewhere else.
48
- * - `glob` throws (not stubbed). Install `API.Fs.around()` directly if needed.
48
+ * - `readDirectory` and `glob` throw (not stubbed). An in-memory map of file
49
+ * paths holds no directory structure, so answering either from it would
50
+ * invent one; install `API.Fs.around()` directly when a test needs to
51
+ * enumerate.
49
52
  * - the writing half — `writeTextFile`, `ensureDir`, `rename`, `remove`, and
50
53
  * `realpath` — is not stubbed and reaches the real filesystem. A test that
51
54
  * exercises a document writing files wants a real temporary directory.
@@ -71,6 +74,9 @@ export function* useStubFs(files) {
71
74
  const exists = path in files;
72
75
  return { exists, isFile: exists, isDirectory: false, isSymbolicLink: false };
73
76
  },
77
+ *readDirectory(_args, _next) {
78
+ throw new Error("readDirectory not stubbed");
79
+ },
74
80
  *glob(_args, _next) {
75
81
  throw new Error("glob not stubbed");
76
82
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@executablemd/runtime",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Runtime host APIs for executable.md documents.",
5
5
  "homepage": "https://executable.md",
6
6
  "repository": {
package/types/apis.d.ts CHANGED
@@ -104,6 +104,21 @@ export interface LinkStatResult {
104
104
  isDirectory: boolean;
105
105
  isSymbolicLink: boolean;
106
106
  }
107
+ /**
108
+ * One entry of a directory, as the entry itself rather than as what it leads
109
+ * to.
110
+ *
111
+ * Plain data: a caller reads members, never host methods, so the same values
112
+ * cross a substituted provider and the default adapter. A symbolic link reports
113
+ * `isSymbolicLink: true` with `isFile` and `isDirectory` both false, whatever
114
+ * it points at — the same shape `lstat` answers with.
115
+ */
116
+ export interface DirectoryEntry {
117
+ name: string;
118
+ isFile: boolean;
119
+ isDirectory: boolean;
120
+ isSymbolicLink: boolean;
121
+ }
107
122
  /**
108
123
  * Minimal response headers interface.
109
124
  *
@@ -193,6 +208,17 @@ interface FsHandler {
193
208
  * link is not removing that file. Missing is an answer here too.
194
209
  */
195
210
  lstat(path: string): Operation<LinkStatResult>;
211
+ /**
212
+ * The entries one directory holds directly, in whatever order the host
213
+ * reports them.
214
+ *
215
+ * One level, and nothing more: it does not recurse, does not follow a
216
+ * symbolic link, does not sort, and does not soften a directory that cannot
217
+ * be read into an empty answer. A caller that walks a tree decides for itself
218
+ * which directories are worth reading, which is what lets it skip a subtree
219
+ * entirely rather than filter one it has already walked.
220
+ */
221
+ readDirectory(path: string): Operation<DirectoryEntry[]>;
196
222
  /**
197
223
  * Files and symbolic links beneath `root` whose path relative to it matches
198
224
  * `patterns` and matches none of `exclude`. Paths come back relative and
@@ -288,6 +314,7 @@ export declare function exec(options: ProcessExecOptions & {
288
314
  export declare const readTextFile: typeof API.Fs.operations.readTextFile;
289
315
  export declare const stat: typeof API.Fs.operations.stat;
290
316
  export declare const lstat: typeof API.Fs.operations.lstat;
317
+ export declare const readDirectory: typeof API.Fs.operations.readDirectory;
291
318
  export declare const glob: typeof API.Fs.operations.glob;
292
319
  export declare const writeTextFile: typeof API.Fs.operations.writeTextFile;
293
320
  export declare const ensureDir: typeof API.Fs.operations.ensureDir;
package/types/mod.d.ts CHANGED
@@ -8,7 +8,8 @@
8
8
  * Seven domain APIs:
9
9
  * - `API.Process` — subprocess execution (`exec`)
10
10
  * - `API.Fs` — the low-level host filesystem (`readTextFile`, `writeTextFile`,
11
- * `stat`, `lstat`, `glob`, `realpath`, `ensureDir`, `rename`, `remove`)
11
+ * `stat`, `lstat`, `readDirectory`, `glob`, `realpath`, `ensureDir`, `rename`,
12
+ * `remove`)
12
13
  * - `API.Files` — document filesystem access as whole semantic operations,
13
14
  * with no host default. `useHostFiles()` installs the host provider.
14
15
  * - `API.Fetch` — HTTP requests (`fetch`)
@@ -25,8 +26,8 @@
25
26
  */
26
27
  import "./_dnt.polyfills.js";
27
28
  export { API } from "./apis.js";
28
- export { exec, readTextFile, writeTextFile, stat, lstat, glob, realpath, ensureDir, rename, remove, fetch, cwd, env, platform, command, compile, useQuietProcessOutput, } from "./apis.js";
29
- export type { EvalBlock, FetchInit, FetchOperation, LinkStatResult, ResponseHeaders, RuntimeFetchResponse, StatResult, } from "./apis.js";
29
+ export { exec, readTextFile, writeTextFile, stat, lstat, readDirectory, glob, realpath, ensureDir, rename, remove, fetch, cwd, env, platform, command, compile, useQuietProcessOutput, } from "./apis.js";
30
+ export type { DirectoryEntry, EvalBlock, FetchInit, FetchOperation, LinkStatResult, ResponseHeaders, RuntimeFetchResponse, StatResult, } from "./apis.js";
30
31
  export { Service, SERVICE_HOSTNAME, SERVICE_READY_PREFIX, ServiceProcessExitBeforeReadyError, ServiceProtocolDuplicateError, ServiceProtocolHostnameMismatchError, ServiceProtocolIncompatibleError, ServiceProtocolMalformedError, ServiceProtocolTokenMismatchError, ServiceProviderError, ServiceStartupTimeoutError, ServiceTeardownError, ServiceUnexpectedExitError, parseServiceReadyRecord, startService, } from "./service.js";
31
32
  export type { ServiceEndpoint, ServiceHandler, ServiceAttachment, ServiceStartOptions, } from "./service.js";
32
33
  export { Config, timeout, timeoutExec, timeoutFetch } from "./config.js";
@@ -30,7 +30,10 @@ export declare function useStubService(endpoint: ServiceEndpoint): Operation<voi
30
30
  * - `stat` returns `{ exists: true, isFile: true }` for keys in the map.
31
31
  * - `lstat` answers the same, with `isSymbolicLink: false`: an in-memory map
32
32
  * holds file content, so nothing in it is a link to somewhere else.
33
- * - `glob` throws (not stubbed). Install `API.Fs.around()` directly if needed.
33
+ * - `readDirectory` and `glob` throw (not stubbed). An in-memory map of file
34
+ * paths holds no directory structure, so answering either from it would
35
+ * invent one; install `API.Fs.around()` directly when a test needs to
36
+ * enumerate.
34
37
  * - the writing half — `writeTextFile`, `ensureDir`, `rename`, `remove`, and
35
38
  * `realpath` — is not stubbed and reaches the real filesystem. A test that
36
39
  * exercises a document writing files wants a real temporary directory.