@theholocron/holocron-plugin-fern 5.0.0-alpha.25 → 5.0.0-alpha.250
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/README.md +2 -2
- package/dist/index.d.mts +38 -18
- package/dist/index.mjs +58 -17
- package/package.json +16 -13
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ pnpm add -D @theholocron/holocron-plugin-fern
|
|
|
42
42
|
| `domain` | No | Base domain (`"wiki.theholocron.dev"`) or full path (`"wiki.theholocron.dev/myrepo"`). When a base domain is given, the repo name is appended automatically as a basepath. |
|
|
43
43
|
| `fernOrg` | No | Fern workspace slug. Defaults to `config.org`. Set this when the Fern workspace name differs from the GitHub org (e.g. workspace `"holocron"`, org `"theholocron"`). |
|
|
44
44
|
|
|
45
|
-
## What `holocron setup` does
|
|
45
|
+
## What `holocron repo setup` does
|
|
46
46
|
|
|
47
47
|
1. **Writes `fern/fern.config.json`** — Fern workspace org name and pinned
|
|
48
48
|
CLI version. Always overwritten.
|
|
@@ -79,7 +79,7 @@ DNS: add one CNAME record — `wiki.theholocron.dev` →
|
|
|
79
79
|
Password protection is configured in the **Fern Dashboard**
|
|
80
80
|
(`dashboard.buildwithfern.com`) — it is not configurable via `docs.yml` or
|
|
81
81
|
any CLI flag. Configure access control manually in the dashboard after
|
|
82
|
-
running `holocron setup`.
|
|
82
|
+
running `holocron repo setup`.
|
|
83
83
|
|
|
84
84
|
## CI secrets
|
|
85
85
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { AuthError, ResolveTokenInput, Wiki,
|
|
2
|
-
|
|
3
|
-
declare const FERN_VERSION = "5.114.1";
|
|
4
|
-
interface FernWikiOptions {
|
|
1
|
+
import { AuthError, DnsRecordRequest, ResolveTokenInput, Wiki, WikiProvisionOpts, WikiProxyConfig } from "@theholocron/cli";
|
|
2
|
+
export declare const resolveToken: (input?: ResolveTokenInput) => string;
|
|
3
|
+
export declare const FERN_VERSION = "5.114.1";
|
|
4
|
+
interface FernWikiOptions extends ResolveTokenInput {
|
|
5
5
|
/** Absolute path to the working repo root. Injected by the loader from RuntimeContext. */
|
|
6
6
|
repoRoot?: string;
|
|
7
7
|
/** Active org name (e.g. "theholocron"). Injected by the loader from RuntimeContext. */
|
|
@@ -36,36 +36,56 @@ interface FernWikiOptions {
|
|
|
36
36
|
/**
|
|
37
37
|
* One-line description shown on the global product switcher card.
|
|
38
38
|
* Falls back to the top-level `description` field in `holocron.config.ts`
|
|
39
|
-
* when omitted. Only used by `holocron sync --steps wiki`.
|
|
39
|
+
* when omitted. Only used by `holocron repo sync --steps wiki`.
|
|
40
40
|
*/
|
|
41
41
|
subtitle?: string;
|
|
42
42
|
/**
|
|
43
43
|
* Font Awesome icon class for the product switcher card (e.g. `"fa-duotone fa-gear"`).
|
|
44
|
-
* Only used by `holocron sync --steps wiki`.
|
|
44
|
+
* Only used by `holocron repo sync --steps wiki`.
|
|
45
45
|
*/
|
|
46
46
|
icon?: string;
|
|
47
47
|
}
|
|
48
|
-
declare class FernWiki implements Wiki {
|
|
48
|
+
export declare class FernWiki implements Wiki {
|
|
49
49
|
private readonly opts;
|
|
50
50
|
readonly key: "wiki";
|
|
51
51
|
readonly providerName = "fern";
|
|
52
52
|
constructor(opts: FernWikiOptions);
|
|
53
53
|
provision(callOpts?: WikiProvisionOpts): Promise<string>;
|
|
54
54
|
proxyConfig(): WikiProxyConfig | null;
|
|
55
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Confirms `HOLOCRON_FERN_TOKEN`/`FERN_TOKEN` resolves, or a Fern token
|
|
57
|
+
* is stored in the keyring — not a live check. Fern exposes no
|
|
58
|
+
* lightweight endpoint to verify a token actually works (the only
|
|
59
|
+
* token-consuming operation is a full `fern generate`, see
|
|
60
|
+
* holocron#1079); this only confirms one is configured, the same way
|
|
61
|
+
* CI's `fern generate --docs` step would find it.
|
|
62
|
+
*
|
|
63
|
+
* Deliberately ignores `cliToken` (`--token`): CI's step only ever sees
|
|
64
|
+
* the env var from a GitHub Actions secret, never a CLI flag — and a
|
|
65
|
+
* bare `--token <value>` meant for some OTHER provider is forwarded to
|
|
66
|
+
* every loaded plugin as a fallback (see AGENTS.md), so honoring it
|
|
67
|
+
* here would report "configured" even when no Fern-specific credential
|
|
68
|
+
* exists anywhere CI would actually look.
|
|
69
|
+
*
|
|
70
|
+
* Only `AuthError` (the specific "no token found" signal) is treated as
|
|
71
|
+
* `ok: false` — any other error (e.g. a real keyring failure) is a
|
|
72
|
+
* genuine problem and must surface as a failure, not get misreported as
|
|
73
|
+
* a missing token.
|
|
74
|
+
*/
|
|
75
|
+
whoami(): Promise<{
|
|
76
|
+
ok: boolean;
|
|
77
|
+
}>;
|
|
78
|
+
dnsRecord(): DnsRecordRequest | null;
|
|
56
79
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
declare
|
|
60
|
-
//#endregion
|
|
61
|
-
//#region src/index.d.ts
|
|
62
|
-
type FernPluginOptions = FernWikiOptions;
|
|
63
|
-
declare function wiki(opts: FernPluginOptions): Wiki;
|
|
64
|
-
declare function createPlugin(options?: FernPluginOptions): {
|
|
80
|
+
export type FernPluginOptions = FernWikiOptions;
|
|
81
|
+
export declare function wiki(opts: FernPluginOptions): Wiki;
|
|
82
|
+
export declare function createPlugin(options?: FernPluginOptions): {
|
|
65
83
|
name: string;
|
|
84
|
+
probes: {
|
|
85
|
+
connection: import("@theholocron/cli").Probe;
|
|
86
|
+
};
|
|
66
87
|
capabilities: {
|
|
67
88
|
wiki: () => Wiki;
|
|
68
89
|
};
|
|
69
90
|
};
|
|
70
|
-
|
|
71
|
-
export { AuthError, FERN_VERSION, FernPluginOptions, FernWiki, type FernWikiOptions, type ResolveTokenInput, createPlugin, resolveToken, wiki };
|
|
91
|
+
export { AuthError, type FernWikiOptions, type ResolveTokenInput };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
import { AuthError, connectionProbe, createResolveToken } from "@theholocron/cli";
|
|
1
2
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
3
|
import { join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
|
|
4
|
+
import { stringifyJson } from "@theholocron/json-utils";
|
|
5
|
+
// src/auth.ts
|
|
6
|
+
const resolveToken = createResolveToken({
|
|
7
|
+
envName: "HOLOCRON_FERN_TOKEN",
|
|
8
|
+
vendorEnvName: "FERN_TOKEN",
|
|
9
|
+
keyringService: "fern",
|
|
10
|
+
errorMessage: "no Fern token found. Set HOLOCRON_FERN_TOKEN / FERN_TOKEN, or run: holocron auth set fern <token>"
|
|
11
|
+
});
|
|
12
|
+
// src/capabilities/wiki.ts
|
|
5
13
|
const FERN_VERSION = "5.114.1";
|
|
6
14
|
var FernWiki = class {
|
|
7
15
|
opts;
|
|
@@ -33,6 +41,38 @@ var FernWiki = class {
|
|
|
33
41
|
headers: { "X-Fern-Host": this.opts.domain.split("/")[0] }
|
|
34
42
|
};
|
|
35
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Confirms `HOLOCRON_FERN_TOKEN`/`FERN_TOKEN` resolves, or a Fern token
|
|
46
|
+
* is stored in the keyring — not a live check. Fern exposes no
|
|
47
|
+
* lightweight endpoint to verify a token actually works (the only
|
|
48
|
+
* token-consuming operation is a full `fern generate`, see
|
|
49
|
+
* holocron#1079); this only confirms one is configured, the same way
|
|
50
|
+
* CI's `fern generate --docs` step would find it.
|
|
51
|
+
*
|
|
52
|
+
* Deliberately ignores `cliToken` (`--token`): CI's step only ever sees
|
|
53
|
+
* the env var from a GitHub Actions secret, never a CLI flag — and a
|
|
54
|
+
* bare `--token <value>` meant for some OTHER provider is forwarded to
|
|
55
|
+
* every loaded plugin as a fallback (see AGENTS.md), so honoring it
|
|
56
|
+
* here would report "configured" even when no Fern-specific credential
|
|
57
|
+
* exists anywhere CI would actually look.
|
|
58
|
+
*
|
|
59
|
+
* Only `AuthError` (the specific "no token found" signal) is treated as
|
|
60
|
+
* `ok: false` — any other error (e.g. a real keyring failure) is a
|
|
61
|
+
* genuine problem and must surface as a failure, not get misreported as
|
|
62
|
+
* a missing token.
|
|
63
|
+
*/
|
|
64
|
+
async whoami() {
|
|
65
|
+
try {
|
|
66
|
+
resolveToken({
|
|
67
|
+
...this.opts,
|
|
68
|
+
cliToken: void 0
|
|
69
|
+
});
|
|
70
|
+
return { ok: true };
|
|
71
|
+
} catch (err) {
|
|
72
|
+
if (err instanceof AuthError) return { ok: false };
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
36
76
|
dnsRecord() {
|
|
37
77
|
const { org, domain, fernOrg } = this.opts;
|
|
38
78
|
if (!domain) return null;
|
|
@@ -40,8 +80,11 @@ var FernWiki = class {
|
|
|
40
80
|
const hostname = domain.split("/")[0];
|
|
41
81
|
return {
|
|
42
82
|
zone: hostname.split(".").slice(-2).join("."),
|
|
43
|
-
|
|
44
|
-
|
|
83
|
+
record: {
|
|
84
|
+
type: "CNAME",
|
|
85
|
+
name: hostname,
|
|
86
|
+
content: `${resolvedFernOrg}.docs.buildwithfern.com`
|
|
87
|
+
}
|
|
45
88
|
};
|
|
46
89
|
}
|
|
47
90
|
};
|
|
@@ -49,10 +92,10 @@ async function writeFernConfig({ repoRoot, fernOrg }) {
|
|
|
49
92
|
const fernDir = join(repoRoot, "fern");
|
|
50
93
|
await mkdir(fernDir, { recursive: true });
|
|
51
94
|
const org = fernOrg ?? "holocron";
|
|
52
|
-
const content =
|
|
95
|
+
const content = stringifyJson({
|
|
53
96
|
organization: org,
|
|
54
97
|
version: FERN_VERSION
|
|
55
|
-
}
|
|
98
|
+
});
|
|
56
99
|
await writeFile(join(fernDir, "fern.config.json"), content, "utf8");
|
|
57
100
|
return `fern.config.json: org=${org}, version=${FERN_VERSION}`;
|
|
58
101
|
}
|
|
@@ -127,24 +170,22 @@ function updateInstancesBlock(content, instanceUrl, customDomain, multiSource, r
|
|
|
127
170
|
if (match[0] === newBlock) return content;
|
|
128
171
|
return content.replace(blockRe, newBlock);
|
|
129
172
|
}
|
|
130
|
-
|
|
131
|
-
//#region src/auth.ts
|
|
132
|
-
const resolveToken = createResolveToken({
|
|
133
|
-
envName: "HOLOCRON_FERN_TOKEN",
|
|
134
|
-
vendorEnvName: "FERN_TOKEN",
|
|
135
|
-
keyringService: "fern",
|
|
136
|
-
errorMessage: "no Fern token found. Set HOLOCRON_FERN_TOKEN / FERN_TOKEN, or run: holocron auth set fern <token>"
|
|
137
|
-
});
|
|
138
|
-
//#endregion
|
|
139
|
-
//#region src/index.ts
|
|
173
|
+
// src/index.ts
|
|
140
174
|
function wiki(opts) {
|
|
141
175
|
return new FernWiki(opts);
|
|
142
176
|
}
|
|
143
177
|
function createPlugin(options = {}) {
|
|
144
178
|
return {
|
|
145
179
|
name: "@theholocron/holocron-plugin-fern",
|
|
180
|
+
probes: { connection: connectionProbe({
|
|
181
|
+
provider: "Fern",
|
|
182
|
+
token: () => resolveToken(options),
|
|
183
|
+
verify: async () => ({
|
|
184
|
+
ok: true,
|
|
185
|
+
subject: "a token is set (Fern cannot check it from here)"
|
|
186
|
+
})
|
|
187
|
+
}) },
|
|
146
188
|
capabilities: { wiki: () => wiki(options) }
|
|
147
189
|
};
|
|
148
190
|
}
|
|
149
|
-
//#endregion
|
|
150
191
|
export { AuthError, FERN_VERSION, FernWiki, createPlugin, resolveToken, wiki };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/holocron-plugin-fern",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.250",
|
|
4
4
|
"description": "Holocron plugin for Fern. Implements the wiki capability for engineering knowledge publishing.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fern",
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"plugin",
|
|
9
9
|
"wiki"
|
|
10
10
|
],
|
|
11
|
-
"homepage": "https://github.com/theholocron/holocron/tree/main/
|
|
11
|
+
"homepage": "https://github.com/theholocron/holocron/tree/main/plugins/holocron-plugin-fern#readme",
|
|
12
12
|
"bugs": "https://github.com/theholocron/holocron/issues",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git+https://github.com/theholocron/holocron.git",
|
|
16
|
-
"directory": "
|
|
16
|
+
"directory": "plugins/holocron-plugin-fern"
|
|
17
17
|
},
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"author": "Newton Koumantzelis",
|
|
@@ -29,25 +29,28 @@
|
|
|
29
29
|
"files": [
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@theholocron/json-utils": "^1.16.0"
|
|
34
|
+
},
|
|
32
35
|
"devDependencies": {
|
|
33
|
-
"@theholocron/eslint-config": "^8.
|
|
34
|
-
"@theholocron/tsconfig": "^8.
|
|
35
|
-
"@theholocron/tsdown-config": "^8.
|
|
36
|
-
"@theholocron/vitest-config": "^8.
|
|
36
|
+
"@theholocron/eslint-config": "^8.8.2",
|
|
37
|
+
"@theholocron/tsconfig": "^8.8.2",
|
|
38
|
+
"@theholocron/tsdown-config": "^8.8.2",
|
|
39
|
+
"@theholocron/vitest-config": "^8.8.2",
|
|
37
40
|
"@types/node": "^26",
|
|
38
|
-
"@vitest/coverage-v8": "^
|
|
41
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
39
42
|
"@vitest/eslint-plugin": "^1.6.27",
|
|
40
43
|
"eslint": "^10.8.1",
|
|
41
44
|
"eslint-plugin-n": "^18.3.0",
|
|
42
45
|
"globals": "^17.11.0",
|
|
43
|
-
"tsdown": "^0.
|
|
44
|
-
"tsx": "4.23.
|
|
46
|
+
"tsdown": "^0.23.3",
|
|
47
|
+
"tsx": "4.23.15",
|
|
45
48
|
"typescript": "^5.9.3",
|
|
46
|
-
"vitest": "^
|
|
47
|
-
"@theholocron/cli": "5.0.0-alpha.
|
|
49
|
+
"vitest": "^5.0.5",
|
|
50
|
+
"@theholocron/cli": "5.0.0-alpha.250"
|
|
48
51
|
},
|
|
49
52
|
"peerDependencies": {
|
|
50
|
-
"@theholocron/cli": "5.0.0-alpha.
|
|
53
|
+
"@theholocron/cli": "5.0.0-alpha.250"
|
|
51
54
|
},
|
|
52
55
|
"engines": {
|
|
53
56
|
"node": ">=22"
|