rspress-plugin-api-extractor 0.18.8 → 0.18.9
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/config-helpers.js +20 -11
- package/model-loader.js +3 -3
- package/observability/sinks/trace-sink.js +4 -4
- package/package.json +3 -2
- package/plugin.js +4 -4
- package/sync-node-fs.js +0 -80
package/config-helpers.js
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
import fsSync from "node:fs";
|
|
1
|
+
import fs from "node:fs";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { normalizeBaseRoute } from "@tsdoctor/pages";
|
|
5
|
-
import { Effect, Result } from "effect";
|
|
4
|
+
import { Effect, Layer, Path, Result } from "effect";
|
|
5
|
+
import { NodeSyncFileSystem } from "@effected/memfs/node-sync";
|
|
6
6
|
import { discoverBundle } from "@tsdoctor/bundle";
|
|
7
7
|
|
|
8
8
|
//#region src/config-helpers.ts
|
|
9
|
+
/**
|
|
10
|
+
* The sync environment bundle discovery runs under from the config helpers:
|
|
11
|
+
* `@effected/memfs`'s read-only synchronous `FileSystem` over `node:fs` plus
|
|
12
|
+
* the (already sync) `Path` service. `@effect/platform-node`'s
|
|
13
|
+
* `NodeFileSystem` is promise-backed, so it cannot serve `Effect.runSync`;
|
|
14
|
+
* `NodeSyncFileSystem` matches its errors tag-for-tag and makes every write
|
|
15
|
+
* member a defect, so a new discovery dependency on a write fails loudly.
|
|
16
|
+
*/
|
|
17
|
+
const SyncDiscoveryLayer = Layer.mergeAll(NodeSyncFileSystem.layer, Path.layer);
|
|
9
18
|
const PREFIX = "[rspress-plugin-api-extractor]";
|
|
10
19
|
/**
|
|
11
20
|
* The adapter's strictness gate over `@tsdoctor/bundle`'s layer-0-only
|
|
@@ -18,14 +27,14 @@ const PREFIX = "[rspress-plugin-api-extractor]";
|
|
|
18
27
|
function requirePackageJson(dir) {
|
|
19
28
|
let stat;
|
|
20
29
|
try {
|
|
21
|
-
stat =
|
|
30
|
+
stat = fs.statSync(dir);
|
|
22
31
|
} catch {
|
|
23
32
|
throw new Error(`${PREFIX} api.fromDir: directory not found: ${dir}`);
|
|
24
33
|
}
|
|
25
34
|
if (!stat.isDirectory()) throw new Error(`${PREFIX} api.fromDir: not a directory: ${dir}`);
|
|
26
35
|
let pkg;
|
|
27
36
|
try {
|
|
28
|
-
pkg = JSON.parse(
|
|
37
|
+
pkg = JSON.parse(fs.readFileSync(path.join(dir, "package.json"), "utf8"));
|
|
29
38
|
} catch {
|
|
30
39
|
throw new Error(`${PREFIX} api.fromDir: missing or unreadable package.json in ${dir}`);
|
|
31
40
|
}
|
|
@@ -36,8 +45,8 @@ function requirePackageJson(dir) {
|
|
|
36
45
|
};
|
|
37
46
|
}
|
|
38
47
|
/**
|
|
39
|
-
* Run `@tsdoctor/bundle`'s `discoverBundle` synchronously (over
|
|
40
|
-
* `
|
|
48
|
+
* Run `@tsdoctor/bundle`'s `discoverBundle` synchronously (over
|
|
49
|
+
* `SyncDiscoveryLayer` above) and translate its typed
|
|
41
50
|
* failures into the plugin's historical error messages.
|
|
42
51
|
*/
|
|
43
52
|
function discoverDescriptor(dir, name, version) {
|
|
@@ -103,9 +112,9 @@ function fromDir(dir, overrides = {}) {
|
|
|
103
112
|
};
|
|
104
113
|
}
|
|
105
114
|
function isModelFolder(dir) {
|
|
106
|
-
if (!
|
|
115
|
+
if (!fs.existsSync(path.join(dir, "package.json"))) return false;
|
|
107
116
|
try {
|
|
108
|
-
return
|
|
117
|
+
return fs.readdirSync(dir).some((f) => f.endsWith(".api.json"));
|
|
109
118
|
} catch {
|
|
110
119
|
return false;
|
|
111
120
|
}
|
|
@@ -124,12 +133,12 @@ function fromParentDir(parentDir, options = {}) {
|
|
|
124
133
|
const absParent = path.resolve(cwd ?? process.cwd(), parentDir);
|
|
125
134
|
let stat;
|
|
126
135
|
try {
|
|
127
|
-
stat =
|
|
136
|
+
stat = fs.statSync(absParent);
|
|
128
137
|
} catch {
|
|
129
138
|
throw new Error(`${PREFIX} apis.fromDir: directory not found: ${absParent}`);
|
|
130
139
|
}
|
|
131
140
|
if (!stat.isDirectory()) throw new Error(`${PREFIX} apis.fromDir: not a directory: ${absParent}`);
|
|
132
|
-
const subdirs =
|
|
141
|
+
const subdirs = fs.readdirSync(absParent, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name).sort();
|
|
133
142
|
const configs = [];
|
|
134
143
|
for (const name of subdirs) {
|
|
135
144
|
const subdir = path.join(absParent, name);
|
package/model-loader.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isLoadedModel, isVersionConfig } from "./config-utils.js";
|
|
2
|
-
import
|
|
2
|
+
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
5
|
import { Model } from "@tsdoctor/model";
|
|
@@ -10,8 +10,8 @@ import { Model } from "@tsdoctor/model";
|
|
|
10
10
|
*/
|
|
11
11
|
async function loadPackageJsonFromPath(pkgPath) {
|
|
12
12
|
const resolvedPath = path.resolve(pkgPath.toString());
|
|
13
|
-
if (!
|
|
14
|
-
const content =
|
|
13
|
+
if (!fs.existsSync(resolvedPath)) throw new Error(`Package.json file not found: ${resolvedPath}`);
|
|
14
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
15
15
|
try {
|
|
16
16
|
return JSON.parse(content);
|
|
17
17
|
} catch (error) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
|
|
4
4
|
//#region src/observability/sinks/trace-sink.ts
|
|
5
5
|
function openTracePath(p) {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
7
|
+
fs.writeFileSync(p, "");
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Create a JSONL trace sink, opening the file eagerly at construction.
|
|
@@ -21,7 +21,7 @@ function makeTraceSink(tracePath) {
|
|
|
21
21
|
minLevel: "trace",
|
|
22
22
|
capturesPayload: true,
|
|
23
23
|
handle: (event) => {
|
|
24
|
-
|
|
24
|
+
fs.appendFileSync(tracePath, `${JSON.stringify(event)}\n`);
|
|
25
25
|
},
|
|
26
26
|
flush: () => {}
|
|
27
27
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rspress-plugin-api-extractor",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.9",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "RSPress plugin for generating API documentation from TypeScript API Extractor models",
|
|
6
6
|
"keywords": [
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"@effected/glob": "^0.9.0",
|
|
43
43
|
"@effected/jsonc": "^0.14.0",
|
|
44
44
|
"@effected/markdown": "^0.14.0",
|
|
45
|
+
"@effected/memfs": "^0.13.0",
|
|
45
46
|
"@effected/npm": "^0.19.0",
|
|
46
47
|
"@effected/package-json": "^0.19.1",
|
|
47
48
|
"@effected/schema-org": "^0.6.0",
|
|
@@ -60,7 +61,7 @@
|
|
|
60
61
|
"@tsdoctor/pages": "0.3.5",
|
|
61
62
|
"@tsdoctor/registry": "0.5.3",
|
|
62
63
|
"@tsdoctor/seo": "0.4.3",
|
|
63
|
-
"@tsdoctor/snapshot": "0.
|
|
64
|
+
"@tsdoctor/snapshot": "0.5.0",
|
|
64
65
|
"@tsdoctor/vfs": "0.4.1",
|
|
65
66
|
"@typescript/vfs": "^1.6.5",
|
|
66
67
|
"clsx": "^2.1.1",
|
package/plugin.js
CHANGED
|
@@ -23,7 +23,7 @@ import { clearTwoslashAccess, installTwoslashAccess, twoslashTransformerFor } fr
|
|
|
23
23
|
import { remarkApiCodeblocks } from "./remark-api-codeblocks.js";
|
|
24
24
|
import { remarkWithApi } from "./remark-with-api.js";
|
|
25
25
|
import { createRequire } from "node:module";
|
|
26
|
-
import
|
|
26
|
+
import fs from "node:fs";
|
|
27
27
|
import os from "node:os";
|
|
28
28
|
import path from "node:path";
|
|
29
29
|
import { fileURLToPath } from "node:url";
|
|
@@ -63,7 +63,7 @@ function ApiExtractorPluginImpl(rawOptions) {
|
|
|
63
63
|
});
|
|
64
64
|
const { layer: eventBusLayer, trace: traceSink, issues: issuesSink, render: renderSink, metrics: metricStore } = buildEventBus(obs);
|
|
65
65
|
const dbPath = path.resolve(process.cwd(), ".api-docs", "snapshot", "api-docs.db");
|
|
66
|
-
|
|
66
|
+
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
|
|
67
67
|
const appLayers = makeAppLayers({
|
|
68
68
|
options,
|
|
69
69
|
obs,
|
|
@@ -163,7 +163,7 @@ function ApiExtractorPluginImpl(rawOptions) {
|
|
|
163
163
|
versions,
|
|
164
164
|
defaultVersion: rspressMultiVersion?.default
|
|
165
165
|
});
|
|
166
|
-
for (const dp of derivedPaths)
|
|
166
|
+
for (const dp of derivedPaths) fs.mkdirSync(dp.outputDir, { recursive: true });
|
|
167
167
|
} else if (options.apis) for (const api of options.apis) {
|
|
168
168
|
const baseRoute = normalizeBaseRoute(api.baseRoute ?? `/${unscopedName(api.packageName)}`);
|
|
169
169
|
const derivedPaths = deriveOutputPaths({
|
|
@@ -176,7 +176,7 @@ function ApiExtractorPluginImpl(rawOptions) {
|
|
|
176
176
|
versions: [],
|
|
177
177
|
defaultVersion: void 0
|
|
178
178
|
});
|
|
179
|
-
for (const dp of derivedPaths)
|
|
179
|
+
for (const dp of derivedPaths) fs.mkdirSync(dp.outputDir, { recursive: true });
|
|
180
180
|
}
|
|
181
181
|
VfsRegistry.clear();
|
|
182
182
|
clearTwoslashAccess();
|
package/sync-node-fs.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import fsSync from "node:fs";
|
|
2
|
-
import { ByteSize, Effect, FileSystem, Layer, Option, Path, PlatformError } from "effect";
|
|
3
|
-
|
|
4
|
-
//#region src/sync-node-fs.ts
|
|
5
|
-
/**
|
|
6
|
-
* A synchronous, read-only `FileSystem` implementation over `node:fs`'s sync
|
|
7
|
-
* API, covering exactly the members `@tsdoctor/bundle`'s discovery walks:
|
|
8
|
-
* `exists`, `stat`, `readFileString`, `readDirectory` and `readLink`.
|
|
9
|
-
*
|
|
10
|
-
* The config helpers (`fromDir`/`fromParentDir`) are a SYNC public API called
|
|
11
|
-
* at rspress.config evaluation time, while bundle discovery is an Effect
|
|
12
|
-
* program over the `FileSystem` service. `@effect/platform-node`'s
|
|
13
|
-
* `NodeFileSystem` is promise-backed, so running discovery under
|
|
14
|
-
* `Effect.runSync` needs this bridge; every other member stays
|
|
15
|
-
* `layerNoop`-denied, which is deliberate — a new discovery dependency on an
|
|
16
|
-
* unimplemented member should fail loudly here, not silently misbehave.
|
|
17
|
-
*/
|
|
18
|
-
const tagOf = (cause) => {
|
|
19
|
-
const code = cause?.code;
|
|
20
|
-
if (code === "ENOENT") return "NotFound";
|
|
21
|
-
if (code === "EACCES" || code === "EPERM") return "PermissionDenied";
|
|
22
|
-
return "Unknown";
|
|
23
|
-
};
|
|
24
|
-
const fail = (method, pathOrDescriptor, cause) => PlatformError.systemError({
|
|
25
|
-
_tag: tagOf(cause),
|
|
26
|
-
module: "FileSystem",
|
|
27
|
-
method,
|
|
28
|
-
pathOrDescriptor,
|
|
29
|
-
cause
|
|
30
|
-
});
|
|
31
|
-
const typeOf = (stats) => {
|
|
32
|
-
if (stats.isDirectory()) return "Directory";
|
|
33
|
-
if (stats.isSymbolicLink()) return "SymbolicLink";
|
|
34
|
-
if (stats.isFile()) return "File";
|
|
35
|
-
return "Unknown";
|
|
36
|
-
};
|
|
37
|
-
const infoFromStats = (stats) => ({
|
|
38
|
-
type: typeOf(stats),
|
|
39
|
-
mtime: Option.some(stats.mtime),
|
|
40
|
-
atime: Option.some(stats.atime),
|
|
41
|
-
birthtime: Option.some(stats.birthtime),
|
|
42
|
-
dev: stats.dev,
|
|
43
|
-
ino: Option.some(stats.ino),
|
|
44
|
-
mode: stats.mode,
|
|
45
|
-
nlink: Option.some(stats.nlink),
|
|
46
|
-
uid: Option.some(stats.uid),
|
|
47
|
-
gid: Option.some(stats.gid),
|
|
48
|
-
rdev: Option.some(stats.rdev),
|
|
49
|
-
size: ByteSize.bytes(stats.size),
|
|
50
|
-
blksize: Option.some(ByteSize.bytes(stats.blksize)),
|
|
51
|
-
blocks: Option.some(stats.blocks)
|
|
52
|
-
});
|
|
53
|
-
const syncFileSystem = FileSystem.layerNoop({
|
|
54
|
-
exists: (path) => Effect.sync(() => fsSync.existsSync(path)),
|
|
55
|
-
stat: (path) => Effect.try({
|
|
56
|
-
try: () => infoFromStats(fsSync.statSync(path)),
|
|
57
|
-
catch: (cause) => fail("stat", path, cause)
|
|
58
|
-
}),
|
|
59
|
-
readFileString: (path) => Effect.try({
|
|
60
|
-
try: () => fsSync.readFileSync(path, "utf8"),
|
|
61
|
-
catch: (cause) => fail("readFileString", path, cause)
|
|
62
|
-
}),
|
|
63
|
-
readDirectory: (path) => Effect.try({
|
|
64
|
-
try: () => fsSync.readdirSync(path),
|
|
65
|
-
catch: (cause) => fail("readDirectory", path, cause)
|
|
66
|
-
}),
|
|
67
|
-
readLink: (path) => Effect.try({
|
|
68
|
-
try: () => fsSync.readlinkSync(path),
|
|
69
|
-
catch: (cause) => fail("readLink", path, cause)
|
|
70
|
-
})
|
|
71
|
-
});
|
|
72
|
-
/**
|
|
73
|
-
* The full sync environment bundle discovery runs under from the config
|
|
74
|
-
* helpers: the sync `FileSystem` bridge plus the (already sync) `Path`
|
|
75
|
-
* service.
|
|
76
|
-
*/
|
|
77
|
-
const SyncDiscoveryLayer = Layer.mergeAll(syncFileSystem, Path.layer);
|
|
78
|
-
|
|
79
|
-
//#endregion
|
|
80
|
-
export { SyncDiscoveryLayer };
|